2

While trying to better understand all the properties of Bitmap and locked bits, I created a 10x1px image, with the following properties:

Pixel format:Format24bppRgb

Specifies that the format is 24 bits per pixel; 8 bits each are used for the red, green, and blue components.

Color depth in bits: 24 (3 bytes)

So that means I got 10 pixels that each need 3 bytes which means I need to create a byte array of length 30 to copy in all the image data using: Marshal.Copy(lockedBitmapData.Scan0, bytesArray, 0, 30);

The stride is the width of a single row of pixels (a scan line), rounded up to a four-byte boundary.

Does that mean that when I access BitmapData.Stride, it will always return an integer as if the PixelFormat was one of the 32bit variations?

Why the code below causes 2 additional bytes that are 0, instead of 10 that are 0? Or is it 2 because it is rounding up 30 bytes to 32 as the closest byte length that is divisible by 4 as the doc says? I think I misunderstood documentation and expected it to count 4 bytes for every pixel when calculating stride.

byte[] bytesArray = new byte[lockedBitmapData.Stride];
Marshal.Copy(lockedBitmapData.Scan0, bytesArray, 0, lockedBitmapData.Stride);
miran80
  • 945
  • 7
  • 22

1 Answers1

3

Stride is understood to be the distance from line to line, not from pixel to pixel. The difference to the expected pixels_per_line * bytes_per_pixel is due to the padding at the end of each logical line. Thus your second interpretation is mostly correct,

32 as the closest byte length that is divisible by 4 as the doc says

I would just add "are padded to ensure complete 4-byte boundaries" since 16 and 24 are as well divisible by 4. This article contains a picture, this answer contains supplementary information.

The underlying reason is hardware related. If a 2-D data structure is memory-aligned (as in this case, DWORD aligned), lookups (indexing) and bulk operations on that data run significantly faster.

Cee McSharpface
  • 8,493
  • 3
  • 36
  • 77
  • The count of all pixel lines in across the width of the image, right? So, if my image was taller than 1px, I would need to multiply my byte array with the height. And each of those lines would be padded by 2 bytes that would be zero (in my 24bit image case). – miran80 Feb 09 '20 at 17:22
  • 1
    the count of all pixel *columns* across the width of the image. yes. in fact the actual value of the padding bytes should not matter as they are always skipped and never interpreted, but it is likely that any sensible implementation would initialize them to zero. – Cee McSharpface Feb 09 '20 at 17:23