Friday, February 03, 2006

As promised, here are some details on the OpenNETCF.Drawing.Imaging namespace. I'm going to demonstrate how to accomplish several tasks listed in the previous post as not supported by the CF Bitmap class.

0. Preface. helper classes

In the wrapper we introduce 2 helper classes - StreamOnFile and ImageUtils. The latter is simply a collection of high-level image proverssing methods. The former is an IStream implemented over .NET Stream (including FileStream). The implementation is not complete, but sufficient for the Imaging API methods that expect an IStream parameter.

1. Thumbnails, loading parts of the large image

Loading an image in Imaging API is achieved via calls to decoders - COM objects implementing IImageDecoder interface. The basic imaging interface IImage uses decoders to load image data. Most of the decoders support loading partial image, dicarding the unnecessary data. E.g. if you need to load a 3000x2000 image into a 300x200 PictureBox control, it is obvious that you don't need all 6MP of data taking a whopping 18 MB of RAM (24bpp). Moreover, most devices will simply throw an OutOfMemoryException fi you try something like this. Decoder can be instructed to load an image of the required size so that it will skip over those pixels that don't make it (or factor them into interpolation process to scale the image more smoothly). Here is how we achieve it.


        static public IBitmapImage CreateThumbnail(Stream stream, Size size)
        {
            IBitmapImage imageBitmap;
            ImageInfo ii;
            IImage image;

            ImagingFactory factory = new ImagingFactoryClass();
            factory.CreateImageFromStream(new StreamOnFile(stream), out image);
            image.GetImageInfo(out ii);
            factory.CreateBitmapFromImage(image, (uint)size.Width, (uint)size.Height, 
          ii.PixelFormat, InterpolationHint.InterpolationHintDefault, out imageBitmap);
            return imageBitmap;
        }

After we got IBitmapImage object, we can convert it to the .NET Bitmap:

             Bitmap bm = ImageUtils.IBitmapImageToBitmap(imageBitmap);

2. Image transformation (flip, rotate, gamma/brightness/contrast controls)

Imaging library offers a limited set of the image operations exposed via interface IBasicBitmapOps. These are also wrapped in the ImageUtils class so that you get the following methods:

public Bitmap RotateFlip(Bitmap bitmap, RotateFlipType type)
public Bitmap Rotate(Bitmap bitmap, float angle)
public Bitmap Flip(Bitmap bitmap, bool flipX, bool flipY)

Of course you are welcome to use the IBasicBitmapOps directly.

3. Image tags

TBD

4. Transparency and alpha blending

If you have a PNG image with alpha channel information and you load it into a Bitmap object, the transparency is immediately lost. Not so, if using IImage class.

ImagingFactory factory = new ImagingFactoryClass();
IImage
img;
factory.CreateImageFromFile(
"rgba8.png", out img);

Bitmap imageBackground = new Bitmap(“MyImage.bmp“);
Graphics
g = Graphics.FromImage(imageBackground);

IntPtr hDC = g.GetHdc();

RECT rc = RECT.FromXYWH(200, 200, width, h
eight);
img.Draw(hDC, rc,
null
);
g.ReleaseHdc(hDC);

The above code will transparently draw rgba8.png over the specified bitmap.

2/3/2006 5:13:30 PM (Pacific Standard Time, UTC-08:00)  #    Comments [7]  | 
 Saturday, January 28, 2006

I've been encouraged to blog about a new feature available as a part of newly released beta 1 of OpenNETCF SDF - the Imaging API wrapper.

The Imaging API is an attempt to bring Image codec support from the desktop GDI+ to mobile devices. It is implemented as a set of COM interfaces available to C/C++ applications. There is a cocreatable class ImagingFactory and a bunch of interfaces that allow loading, saving and manipulating the images. Effective 1.0 SP2 Compact Framework uses this API internally to load (and in 2.0 to save) images instead of imgdecmp.dll used in CF1 SP1 and before.

In CF2 it became possible to wrap COM interfaces for use in the managed applications. The Bitmap class is also significantly richer than before. Given this, one would ask what would be the reason to try using Imaging API directly. Here is a brief list of things that are not part of the CF2 Bitmap class:

  • Access to image tags (EXIF header etc)
  • Image transformation (flip, rotate, gamma/brightness/contrast controls)
  • Thumbnails, loading parts of the large image

The Imaging wrapper is located inside OpenNetCF.Drawing components as OpenNetCF.Drawing.Imaging namespace. On top of the basic interfaces it offers a small utility layer presented as ImageUtils class. ImageUtils has the following high-level methods:

  • Bitmap RotateFlip(Bitmap bitmap, RotateFlipType type)
  • Bitmap Flip(Bitmap bitmap, bool flipX, bool flipY)
  • Bitmap IBitmapImageToBitmap(IBitmapImage imageBitmap)
  • IBitmapImage BitmapToIImageBitmap(Bitmap bitmap)
  • IBitmapImage CreateThumbnail(Stream stream, Size size)

The last method - CreateThumbnail - allows loading a small thumbnail instead of a large image. Most Pocket PC devices won't be able to load and display a 5-6 megapixel image produced by most digital cameras. At the same time one can easily load 640x480 thumbnail that will let one implement basic zoomable view.

In the next couple of days I'm going to provide a few code samples. Stay tuned.

1/28/2006 1:53:31 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]  | 
 Wednesday, January 04, 2006

Alex Y sent me a link to the digg.com, where ISO Recorder is being discussed. I'm not sure what to make of it, but I know it's better to be “digged” than to be /.ed

1/4/2006 6:08:53 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]  | 
 Tuesday, November 01, 2005

Few days ago (Oct 26) in San Francisco I spotted what must be a part of the upcoming Visual Studio/SQL Server/Biztalk launch event. The picture is a bit grainy, but then whatever JAM is, a great camera it is not.

These are TX1s from London Taxi Company

11/1/2005 2:55:33 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [0]  | 
 Thursday, October 27, 2005

In what is widely regarded as a shrewd move a popular low-cost brokerage firm Charles Schwab started a new advertising campaign clamoring for customers to “Talk to Chuck”. I think not. This is if you ask me a clear case of sheer idiocy. “Charles Schwab” sounded respectable, somewhat European. Now, why would I want to have a broker whose name is Chuck? Why not Billy Bob?

In entirely unrelated news: a popular low-cost chain of kiddie restaurants in an attempt to bolster its image has renamed itself to “Charles E. Cheese”

10/27/2005 11:58:24 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [0]  | 
 Wednesday, October 12, 2005

I've been reading about the new Microsoft Streets and Trips 2006 and came across a feature comparison chart

This reminded me of one of the reasons why I dislike marketing people. Here are 10 rules “How to create a favorable comparison chart“

  1. Pick your competition wisely. If possible, compare to unrelated products
    or products marketed for a different niche
  2. Try limiting your comparison to only those features that exist in your
    product. Never mind the competition has something that you don't - you are
    playing on the home field and you are setting the rules.
  3. Never hesitate to use meaningless "features" as sales points. "Only our
    product is built on the powerful XYZ technology". So if the competitor used ZYX
    technology, that's his problem. We are not here to discuss whose technology
    is better. Suffice it to say that they did not use ours.
  4. Be charitable. If you can throw in a few features that exist in all
    competing products do it, but do it sparingly. You are not going to look
    good if there are too many of those.
  5. "New!" next to the feature description works very well. It is especially
    good when done in red bold font with a little star ornament. And no, you do
    not have to explain that "new" refers to something that is new to this
    release of *your* product, even if competition had it for ages.
  6. It really helps to compare your almost released product to competitor's
    last year release even if they just announced a new version. After all you
    haven't seen it - it may very well not exist. Remember, other people create
    vaporware - we have bold plans and imminent upcoming releases.
  7. If you can't think of 10 rules, make it 6.
10/12/2005 5:55:39 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [0]  | 
 Monday, September 12, 2005

Update: I'm getting reports that this build of ISO Recorder crashes on the recent Vista builds. I pulled the download for now. Expect a new drop for the Vista Beta 2 timeframe

With certain amount of help from other Vista beta testers I have released an early build of ISO Recorder for Windows Vista.

I want to thank David Smith and Jonathan Rosenberg for their assistance with testing and willingnes to help prove that 3rd time is indeed a charm. Apparently working with beta OS (Vista) and beta compiler (VS2005) can be ... tricky sometimes

9/12/2005 12:56:36 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [0]  | 
 Friday, September 09, 2005

If you have tried to install VS2005 August CTP on Windows Vista 64-bit edition you probably found out that it is not possible to do because 64-bit .Net framework fails to install. The reason it fails to install is quite silly. It's a bug in the launch condition in the installation package.

Here is how to get around this. You will need the msidb.exe tool found in the bin directory of the Platform SDK

  1. Create a temporary directory and copy \VS\WCU\dotnetframework\x64\NetFX64.exe from the Visual Studio DVD into this directory. Copy msidb.exe into the same directory (or ensure that it is in the path)
  2. Explode it using a command
    NetFx64.exe /Q /C /T:%CD%
  3. Extract the LaunchCondition decriptor by running:
    msidb -e -dnetfx.msi -f%CD% LaunchCondition
  4. Use notepad to edit LaunchCondtion.idt. Add OR (VersionNT=600) to the condition as shown below:
    (Version9X >= 410) OR ((VersionNT = 500) AND (ServicePackLevel >= 3)) OR (VersionNT = 501) OR ((VersionNT = 502) AND (ServicePackLevel >= 1)) OR (VersionNT=600) [LocProductName] is not supported on Windows 95, Windows NT, Windows 2000 without Service Pack 3 or greater, and Windows Server 2003 without Service Pack 1 or greater.
  5. Use MSIDB again to import the updated launch condition:
    msidb -i -dnetfx.msi -f%CD% LaunchCondition.idt
  6. Now launch install.exe and complete the framework installation. At this point you can relaunch Studio setup and successfully complete it.
9/9/2005 12:33:53 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [0]  |