BGR detection at runtime

Hi,

In one of the examples, the bytes from an image are copied to a bitmap. The way of copying depends on the pixel format of the image (RGB or BGR). In the example, this is done as follows:

#if BGR
              *(pDst++) = *pSrc[2];
              *(pDst++) = *pSrc[1];
              *(pDst++) = *pSrc[0];
#else
              *(pDst++) = *pSrc[0];
              *(pDst++) = *pSrc[1];
              *(pDst++) = *pSrc[2];
#endif

Is there a check for this which can be executed at runtime?

Hi,

do you want to detect whether the memory buffer layout of a :cvb: Image is BGR or do you want to create a BGR bitmap (like e.g. a System.Drawing.Bitmap)?

The latter is simplest: you just need to reference the Stemmer.Cvb.Extensions.dll which adds an extension method to :cvb: Image objects: .ToBitmap(). This produces a BGR8 bitmap:

Image cvbImage = ...;
System.Drawing.Bitmap bitmap = cvbImage.ToBitmap()

To determine whether the Image memory buffer layout is BGR, you need to check the pointers and DataType:

static class ImageExtensions
{
  public static bool IsBgr8(this Image image)
  {
    if (image == null)
      throw new ArgumentNullException(nameof(image));
			
    if (image.Planes.Any(plane => plane.DataType != DataTypes.Int8BppUnsigned))
      return false; // every plane must be of byte type

    if (!TryGetLinearAccessData(image, out var planeData))
      return false; // BGR image must be linear
			
    if (planeData.Length != 3)
      return false; // B-G-R planes
			
    var basePtrs = planeData
      .Select(data => data.BasePtr.ToInt64())
      .ToArray();
		
    // cvb's plane #0 ist red, #1 green and #2 blue
    return (basePtrs[2] == (basePtrs[1] - 1))
      &&   (basePtrs[1] == (basePtrs[0] - 1));
  }
	
  private static bool TryGetLinearAccessData(Image image, out LinearAccessData[] planeData)
  {
    Debug.Assert(image != null);
		
    planeData = new LinearAccessData[image.Planes.Count];
    for (int planeIndex = 0; planeIndex < planeData.Length; planeIndex++)
    {
      var plane = image.Planes[planeIndex];
      if (!plane.TryGetLinearAccess(out planeData[planeIndex]))
        return false;
    }
    return true;
  }
}
1 Like

I need to determine the memory layout. :slight_smile: