我试图通过使用Image和BitmapSource从原始数据创建的位图显示在WPF中:
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;
但是,对BitmapSource.Create的调用将引发ArgumentException,并说“值不在预期范围内”。这不是这样做的方法吗?我打的电话不正确吗?
最佳答案
您的步幅不正确。步幅是分配给扫描线的一条扫描线的字节数
位图。因此,使用以下命令:
int stride = ((RenderWidth * 32 + 31) & ~31) / 8;
并将最后一个参数(当前为
0
)替换为上面定义的stride
。这是神秘的步幅公式的解释:
事实:扫描线必须在32位边界(reference)上对齐。
每条扫描线的字节数的简单公式为:
(width * bpp) / 8
但这可能无法为我们提供在32位边界上对齐的位图,并且(width * bpp)甚至可能无法被8整除。
因此,我们要做的是强制位图连续至少包含32位(我们假设
width > 0
):width * bpp + 31
然后我们说我们不在乎低阶位(0--4位),因为我们试图在32位边界上对齐:
(width * bpp + 31) & ~31
然后除以8以返回字节:
((width * bpp + 31) & ~31) / 8
填充可以通过以下方式计算
int padding = stride - (((width * bpp) + 7) / 8)
天真的公式是
stride - ((width * bpp) / 8)
但是
width * bpp
可能不会在字节边界上对齐,如果不对齐,则此公式会超出字节数。 (考虑使用1 bpp的1像素宽的位图。跨度为4,天真的公式会说padding为4,但实际上为3。)因此,我们添加一点点内容来说明width * bpp
不是a字节边界,然后我们得到上面给出的正确公式。