【问题标题】:Why does BitmapSource.Create throw an ArgumentException?为什么 BitmapSource.Create 会抛出 ArgumentException?
【发布时间】:2009-12-31 03:19:26
【问题描述】:

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

【问题讨论】:

    标签: c# bitmapsource stride


    【解决方案1】:

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

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

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

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

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

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

    (width * bpp) / 8
    

    但这可能不会为我们提供在 32 位边界上对齐的位图,并且 (width * bpp) 甚至可能无法被 8 整除。

    所以,我们要做的是强制位图连续至少有 32 位(我们假设 width &gt; 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 是不是字节边界,然后我们得到上面给出的正确公式。

    【讨论】:

    • 谢谢你,但你到底是怎么想出这个表达方式的?为什么不是简单的 RenderWidth * 4?这不是一行的字节数吗?
    • 抱歉,我应该提供详细信息。在您的情况下,您有bpp = 32,所以是的,公式简化为RenderWidth * 4。但也有一些奇怪的情况(便宜的 LCD 使用 18 bpp)以及扫描线必须在 32 位边界上对齐的事实。我在上面提供了通用公式和如何提出它的解释。希望它能说明问题。
    • 谢谢。还有一个问题。波浪号对这样的整数有什么作用?
    • @Mike Pateras:它是按位非运算符。这意味着它将翻转整数二进制表示中的位(因此0 变为11 变为0)。我说我们要忽略width * bpp + 31 的最低五位(并隐式保留其余位)。一个简单的方法是在这五个位中创建一个具有0 并且在其余位中具有1 的数字;这称为位掩码。如果我们用这个位掩码(~31)取逻辑和width * bpp + 31,我们已经屏蔽掉了我们不关心的五个低位。如果不清楚,请告诉我。
    • 我整天都在搞这个,你的帖子帮助我在 30 秒内修复了我的代码。非常感谢你!!!如果有人需要知道,((width * 24 + 23) &amp; ~23) / 8;PixelFormats.Rgb24; 一起使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-02
    • 1970-01-01
    • 2012-08-10
    • 2018-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多