Swap RGB Image to .net IntPtr bgr

hi, is there another opportunity to swap or switch the planes without coping the hole image to get an bgr linear access by an intptr in c#.net?
we tried to swap the planes by the funtion image.FromPlanes(…,image.Planes.Reverse.ToArray()) - after this operation and using the plane[0].ptr to get linear access the color planes are not as expected - see image (original, result)SwappedImage

1 Like


Hi @mariusmherrmann :slight_smile:

I am a bit curious, why the image has the wrong plane order in the first place?
Do you load the image from file, or is it acquired from a camera? If it comes from a camera, maybe the acquisition device isn’t configured correctly.

Anyway, you can use the SwapChannels() method from the :cvb: Foundation package as follows:

var newImg = Stemmer.Cvb.Foundation.ConvertColorSpace.SwapChannels(img, new int[] {2, 1, 0} );

The array defines the new layout. So with the array { 2, 1, 0 }, an RGB image would be rearranged to BGR plane order.

I hope this helps!

Hallo Herr Steinbinder,

die Methode benötigt ca. 37ms bei unserem Bildformat. Es wird also eine Kopie erstellt richtig? Gibt es hier was performanteres?

Vielen Dank!
Marius Herrmann

Hello @mariusmherrmann

please let us know, if you can change the format to BGR in the driver.
We will continue searching until we hear from you.


@parsd any tips on this one?
What I am curious about is, whether any other SDK will interpret the color format as BGR just for the fact that we changed the alignment of the planes in CVB…
If so, any tip to get this done without copying the imagedata would be great.

Hi @mariusmherrmann,

I am not sure if I understand correctly. Therfore a clarification on what the :cvb: Image is might help: The Image is a so called abstract data type, i.e. it only defines behaviour, but not the exact implementation and memory layout. You can think of it as a view on some memory where our plane 0 always represents red, 1 green and 2 blue independent of memory layout. :cvb: Images also have no limitation on memory layouts: so the buffer can be planar (first all reds, then all greens, …) or even not linear at all. The Image just helps you to access these varying buffers and make sense of the actual memory layout. Thus it is not safe to just get the linear access of plane 0 and assume that the memory layout is like an RGB or even BGR array.

So the actual memory layout depends on the image source. Most cameras by default send either Bayer or RGB data. CVB’s default is RGB memory order for conversions and loading files as historically data was (and often still is) sent in this order. The implementation of the Image is done like this to reduce latency when streaming from cameras. We deliver the buffer as is if possible.

So if you use

Image.FromPlanes(MappingOption.LinkPixels, image.Planes.Reverse().ToArray())

only CVB’s view on the buffer is changed. But as no copying is done the memory layout stays RGB. If you require a BGR memory layout for your other SDK there is no way around copying or inline swapping. Inline Swapping can be done like this:

void SwapPlanes(Image image)
  using (var swapped = Image.FromPlanes(MappingOption.LinkPixels, image.Planes.Reverse().ToArray()))

This safes at least memory. But if you do that, then CVB’s convention of plane 0 being red is broken. So e.g. our displays would render the images wrong.

And another caveat: If the image memory layout was not RGBRGB upfront, the resulting memory layout would not be changed to BGRBGR as just the logical memory locations are reused. To be safe you need to analyze the layout via linear access and if it does not match use Foundations SwapChannels.

I hope that clearifies the issue here.


And if you need this for OpenCV interop which uses BGR memory layout by default and has no logical channel association (channel 0 just refers to the first in memory), you can have a look at this post which does the conversion, although always copying: