DCSIMG
WPF Official Image Interop - Essential WPF

WPF Official Image Interop

As I wrote my few last posts about how to access the BitmapSource WIC image pixels, I have found a post in the MSDN forum, which exposes a static class called Imaging. This amazing class which somehow was very hard to find, can do a great work with image-interop. Looking inside the MSDN for the Imaging class, I found the following methods:

The CreateBitmapSourceFromMemorySection is the best match for creating a BitmapSource from a memory section. Looking further inside the updated MSDN it said that "CreateBitmapSourceFromMemorySection - Returns a managed BitmapSource, based on the provided unmanaged memory location".

When I tried to pass an address of a memory, allocated by the Marshal.AllocHGlobal method, to the CreateBitmapSourceFromMemorySection method, it threw a COM exception!

Digging inside this method using Reflector, it seems that it calls the WICCreateBitmapFromSection, which is a WIC unmanaged function defined in the windowscodecs.dll (The MSDN didn't give any clue of what happened, or how to use this function!).

So I turned to the MSDN post again. It figured out that this method must be used with a file-mapping (too weird).

The code snippet bellow demonstrates the use of this method:

// Create a new file mapping object to back the bitmap
IntPtr section = CreateFileMapping(
                INVALID_HANDLE_VALUE,
                IntPtr.Zero,
                PAGE_READWRITE,
                0,
                numBytes,
                null);

IntPtr pixels = MapViewOfFile(
                section,
                FILE_MAP_ALL_ACCESS,
                0,
                0,
                numBytes);
// Manipulate the pixels using the pixels pointer 
// Create a bitmap source using the memory section
BitmapSource source = Imaging.CreateBitmapSourceFromMemorySection(
                section,
                _pixelWidth,
                _pixelHeight,
                _pixelFormat,
                _stride,
                0);
 

What does this method do?

This method encapsulates the memory provided by the section-pointer with a WPF BitmapSource instance. Now we can set this BitmapSource instance as a source of an Image.

 

Disadvantages:

There is no option to manipulate the pixels and reuse the same BitmapSource (calling the Image.InvalidateVisual method is not working). The only way is to call the CreateBitmapSourceFromMemorySection again (this creates a new BitmapSource), and set the Image.Source property again). Since the BitmapSource only encapsulates this memory, no copy is made, but a new managed instance of a BitmapSource is still created in the managed heap. If we use this method to display a series of images (such as the Video solution), we causes the CPU and the garbage collector to work, and the Virtual Memory/Page Faults to increase (and decrease after a while of course).

Comparing this solution to my previous unofficial one: The unofficial solution performs a little better, but at the same time presents a versioning risk.

Download the code from here.

Published Sunday, October 14, 2007 9:34 PM by Tomer Shamam
תגים:, , ,

Comments

# re: WPF Official Image Interop

Thursday, December 20, 2007 8:38 PM by nick bridger

After reading this "Official Image Interop" post it doesnt seem quite as useful as the unofficial way. The aspect of the unofficial method I need is the speed. I want to create an image (either from a bmp file or to a coded format) and then operate on this image multiple times, each time producing a "processed" copy of the image. Again to save time, the processed image(s) would be created once and then simply overwritten next time round. Thats where I was trying to use the unofficial method to lock the source image and then copy over and process source pixels into a locked destination image.

Currently I do all processing in native unmanaged code and use GDI to Bitblt the results. Maybe I need to find a (fast) way of converting a HBITMAP to a BitmapSource that I can render.

# re: WPF Official Image Interop

Friday, December 21, 2007 10:04 PM by Tomer Shamam

Hi Nick,

If you look at the Imaging class you will find that it has a method called CreateBitmapSourceFromHBitmap, for creating a BitmapSource from an HBITMAP. This method returns a BitmapSource as a return value, but if you dig inside you will see that the actual return value is an InteropBitmap which has an Invalidate method for rendering the Visual host after a change (.NET 3.0 SP1 or later).

If you will dig further, you will find that the InteropBitmap doesn’t copy the pixels, rather it calls the WIC IWICImagingFactory::CreateBitmapFromHBITMAP API (read about WIC here, you may find it very useful especially if you have custom a codec).

To overcome your problem, just create the first image using the CreateBitmapSourceFromHBitmap (call it from C++/CLI and pass it the HBITMAP), then alter the pixels and call Invalidate after you cast down the BitmapSource to  InteropBitmap.

I will be glad to hear if it helped.

# re: WPF Official Image Interop

Monday, February 04, 2008 3:05 PM by mms

Hello,

I'm wondering if there is a way for Interop.Imaging.CreateBitmapSourceFromHIcon to create a bitmap source of the proper (current) DPI. It always uses 96 and hence in 120 DPI the bitmaps render larger than intended. I realize its working with raw pixels but there should be a way to tell it the DPI to use.

As a side question what would be the most efficient way to create at 120DPI bitmap from the returned 96DPI bitmap?

thanks,

marek

# re: WPF Official Image Interop

Monday, February 11, 2008 9:30 PM by Tomer Shamam

IMHO, neither HICON nor HBITMAP supports 120 dpi (only 96). This is the reason you can't select a different DPI than 96.

To overcome the sizing problem when working with 120dpi, you can use my markup extesnsion described here:

blogs.microsoft.co.il/.../wpf-is-dpi-depended.aspx

# re: WPF Official Image Interop

Tuesday, May 19, 2009 7:00 PM by Reinhard

also the CreateBitmapSourceFromMemorySection returns an InteropBitmap, and the Invalidate method works as well.

Leave a Comment

(required) 
(required) 
(optional)
(required) 

Enter the numbers above:
Powered by Community Server (Commercial Edition), by Telligent Systems