I'm trying to get an bitmap created from raw data to show in WPF, by using an Image and a BitmapSource:
Int32[] data = new Int32[RenderHeight * RenderWidth];
for (Int32 i = 0; i < RenderHeight; i++)
{
for (Int32 j = 0; j < RenderWidth; j++)
{
Int32 index = j + (i * RenderHeight);
if (i + j % 2 == 0)
data[index] = 0xFF0000;
else
data[index] = 0x00FF00;
}
}
BitmapSource source = BitmapSource.Create(RenderWidth, RenderHeight, 96.0, 96.0, PixelFormats.Bgr32, null, data, 0);
RenderImage.Source = source;
However the call to BitmapSource.Create throws an ArgumentException, saying "Value does not fall within the expected range". Is this not the way to do this? Am I not making that call properly?
Your stride is incorrect. Stride is the number of bytes allocated for one scanline of the bitmap. Thus, use the following:
int stride = ((RenderWidth * 32 + 31) & ~31) / 8;
and replace the last parameter (currently 0
) with stride
as defined above.
Here is an explanation for the mysterious stride formula:
Fact: Scanlines must be aligned on 32-bit boundaries (reference).
The naive formula for the number of bytes per scanline would be:
(width * bpp) / 8
But this might not give us a bitmap aligned on a 32-bit boundary and (width * bpp) might not even have been divisible by 8.
So, what we do is we force our bitmap to have at least 32 bits in a row (we assume that width > 0
):
width * bpp + 31
and then we say that we don't care about the low-order bits (bits 0--4) because we are trying to align on 32-bit boundaries:
(width * bpp + 31) & ~31
and then divide by 8 to get back to bytes:
((width * bpp + 31) & ~31) / 8
The padding can be computed by
int padding = stride - (((width * bpp) + 7) / 8)
The naive formula would be
stride - ((width * bpp) / 8)
But width * bpp
might not align on a byte boundary and when it doesn't this formula would over count the padding by a byte. (Think of a 1 pixel wide bitmap using 1 bpp. The stride is 4 and the naive formula would say that the padding is 4 but in reality it is 3.) So we add a little bit to cover the case that width * bpp
is not a byte boundary and then we get the correct formula given above.