位图Scan0,Stride off

时间:2014-08-29 14:35:27

标签: c# bitmap unsafe

我正在编写一个将xored delta应用于现有位图的程序。我遇到的问题是在第一次迭代中似乎关闭了5个像素,导致了一些有趣的色彩效果

private void ApplyDelta(ref Bitmap bitmapA, Bitmap bitmapB, Rectangle bounds)
    {
        if (bounds.Width != bitmapB.Width || bounds.Height != bitmapB.Height || bitmapA.PixelFormat != bitmapB.PixelFormat)
        {
            return;
        }

        BitmapData bmdA = bitmapA.LockBits(bounds, ImageLockMode.ReadWrite, bitmapA.PixelFormat);
        BitmapData bmdB = bitmapB.LockBits(new Rectangle(0, 0, bitmapB.Width, bitmapB.Height), ImageLockMode.ReadOnly, bitmapB.PixelFormat);
        unsafe
        {
            int bytesPerPixel = Image.GetPixelFormatSize(bitmapA.PixelFormat) / 8;
            for (int y = 0; y < bmdA.Height; y++)
            {
                byte* rowA = (byte*)bmdA.Scan0 + (y * bmdA.Stride);
                byte* rowB = (byte*)bmdB.Scan0 + (y * bmdB.Stride);
                for (int x = 0; x < bmdA.Width * bytesPerPixel; x++)
                {
                    rowA[x] ^= rowB[x];
                }
            }
        }

        bitmapA.UnlockBits(bmdA);
        bitmapB.UnlockBits(bmdB);
    }

结果:

Picture Error

1 个答案:

答案 0 :(得分:1)

Stride是一行像素的宽度加上一些填充,因此每行开始于4字节边界以提高效率。来自BobPowell.net:

  

Stride属性...以字节为单位保存一行的宽度。然而,行的大小可能不是像素大小的精确倍数,因为为了提高效率,系统确保将数据打包成以四字节边界开始并填充为四个字节的倍数的行。这意味着例如每像素宽24像素的图像将具有52的步幅。每行中使用的数据将占用3 * 17 = 51字节,并且1字节的填充将每行扩展为52字节或13 * 4字节。一个宽度为17像素的4BppIndexed图像的步幅为12.其中9个字节,或者更恰当的是8个半字节,将包含数据,并且该行将用另外3个字节填充到4字节边界。

有关详细信息,请参阅this article

编辑:重新阅读您的问题,我不确定这是否适用于您的情况。但请在计算中确保记住填充。