8

我正在尝试通过使用 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,说“值不在预期范围内”。这不是这样做的方法吗?我没有正确拨打电话吗?

4

1 回答 1

39

你的步幅不正确。步幅是为位图的一个扫描线分配的字节数。因此,请使用以下内容:

int stride = ((RenderWidth * 32 + 31) & ~31) / 8;

并将最后一个参数(当前0)替换stride为上面定义的。

下面是对神秘步幅公式的解释:

事实:扫描线必须在 32 位边界上对齐(参考)。

每个扫描线的字节数的简单公式是:

(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,简单的公式会说填充是 4,但实际上它是 3。)所以我们添加一点点来覆盖width * bpp不是字节的情况边界,然后我们得到上面给出的正确公式。

于 2009-12-31T04:10:39.923 回答