1

Is there a way to access the underlying memory of a BitmapImage object with c# pointers?

I know that there's a CopyPixels method but it makes a copy of the pixels array into a new array (duplicating memory requirements). If you open a large image (2gb) it allocates a lot of un-useful stuff. And if you want to operate some sort of elaboration, like CCLA, it takes a huge amount of memory.

I need only to read the pixel array.

Is it possible to address pixels directly like you can do in System.Drawing.Bitmap?

I wrote a fast bitmap access for System.Drawing.Bitmap, but as I'm using WPF, I need the same functionality for BitmapSource. Otherwise I have to duplicate the image loading (Bitmap for my old method and BitmapSource to show the image in WPF) taking a lot of memory and time.

Thank you Lorenzo

Mitch
  • 21,223
  • 6
  • 63
  • 86
LoxLox
  • 977
  • 9
  • 16

1 Answers1

2

A bitmap source does not necessarily have backing memory for the entire image. An example of when it does not would be an image file on disk which is lazy loaded.

The only access you have with WIC, and therefore WPF, is the CopyPixels method. Certain subclasses of BitmapSource will allow access to a buffer, but they are internally just allocating memory and calling CopyPixels themselves.

I would assume that whatever operation does not require access to the entire image at a time. If so, you can call CopyPixels to a smaller buffer, and window your access to the image. Most decoders, when a single pixel is requested, will buffer the entire stride, or in the case of JPEG, then entire block.

I am not sure what CCLA is, and cannot find a definition that seems to fit, but if it is some sort of transform on the source image, you can implement it as a BitmapSource. That way, you can compose a full chain which will

With careful attention to the CacheOption used on the source image, as well as the order of transforms, you should be able to access an arbitrarily large image without significant memory impact.

If you already have a performant algorithm for GDI (System.Drawing), there is no sense re-implementing it. You can still display your final bitmap using Imaging.CreateBitmapSourceFromHBitmap or by using a WindowsFormsHost to host the control you previously built.

Community
  • 1
  • 1
Mitch
  • 21,223
  • 6
  • 63
  • 86
  • CCLA stands for Connected component labelling algorithm [HERE](http://en.wikipedia.org/wiki/Connected-component_labeling). For working it needs the entire image allocation. Yes, I have an algo just written in System.Drawing. When I load an image of 2-4gb, using your suggested method it creates a COPY of the bitmap to render the image (CreateBitmapSourceForHBitmap). As also the CCLA needs an int array to label the image I need about 14~15gb of ram to do the job. Whithout the image conversion i need only ~9gb of ram. – LoxLox Jan 27 '14 at 12:45
  • What about using the WriteableBitmap.BackBuffer to access the image directly? Do you think is a good idea? Do you think that writeable bitmap creates a copy of the original bitmap? – LoxLox Jan 27 '14 at 12:49
  • The writable bitmap can do nothing but call `CopyPixels`. If you make that the only copy which exists, then I think that accessing the `BackBuffer` of a `WritableBitmap` is an excellent idea. I would also just continue to use the GDI algorithm via `CreateBitmapSourceForHBitmap` after windowing or use `WindowsFormsHost`, but that is just me. – Mitch Jan 27 '14 at 22:47