0

我有这个代码;

BitmapData bdBackground = Background.LockBits(new Rectangle(0, 0, Background.Width,
    Background.Height), ImageLockMode.ReadWrite, Background.PixelFormat);
BitmapData bdForeground = videoFrame.LockBits(new Rectangle(0, 0, videoFrame.Width,
    videoFrame.Height), ImageLockMode.ReadWrite, videoFrame.PixelFormat);

unsafe
{
    for (int x = 0; x < videoFrame.Width; x++)
    {
        byte* columnBackground = (byte*)bdBackground.Scan0 + (x * bdBackground.Stride);
        byte* columnForeground = (byte*)bdForeground.Scan0 + (x * bdForeground.Stride);

        for (int y = 0; y < videoFrame.Height; y++)
        {
             if (columnBackground[x * pixelSize] == columnForeground[x * pixelSize])
             {
                  columnForeground[x] = 0;
             }
        }
    }
}
Background.UnlockBits(bdBackground);
videoFrame.UnlockBits(bdForeground);

它给了我错误;

尝试读取或写入受保护的内存。这通常表明其他内存已损坏。

if (columnBackground[x * pixelSize] == columnForeground[x * pixelSize])

这是什么原因?我从这里获取此代码

4

2 回答 2

3

首先,您需要了解图像如何存储在数组中。“通常在大多数 API 中”的图像是行主要的,这意味着它们是逐行存储的(通常在一维数组中)。要遍历一行主要图像(遍历像素),外部循环通常从 0 到高度,内部循环从 0 到宽度。这使循环更易于阅读,并增加了缓存命中。步幅是一个非常重要的概念,它表示每行所需的字节数,不一定等于每像素的宽度*字节数,因为通常存在对齐原因的填充。

stride 用于访问新行,例如,如果我想访问第三行: third_Row = 3 * image_stride; 如果要访问第三行的第 10 个像素,只需将 ( 10 * bytes per pixel) 添加到third_Row: third_Row_Tenth_Pixel = 3 * image_stride + 10 * Bytes_per_pixel

注意:请注意上述不适用于每像素位数低于 8 的任何图像,通常使用 4、2 或 1。

您正在做的是相反的事情,您将列号乘以步幅,而不是行号,有效地超出了图像的范围。

简而言之,反转 x 和 y 循环,使 y 1 包含 x 1(出于增加缓存命中的原因):

unsafe
{
    for (int y = 0; y < videoFrame.Height; y++)
    {
        byte* columnBackground = (byte*)bdBackground.Scan0 + (y * bdBackground.Stride);
        byte* columnForeground = (byte*)bdForeground.Scan0 + (y * bdForeground.Stride);

        for (int x = 0; x < videoFrame.Width; x++)
        {
             if (columnBackground[x * pixelSize] == columnForeground[x * pixelSize])
             {
                  columnForeground[x] = 0;
             }
        }
    }
}
Background.UnlockBits(bdBackground);
videoFrame.UnlockBits(bdForeground);
于 2013-11-13T20:17:42.607 回答
1

y访问位图数组时从不使用该变量。你应该乘以yStride不是x。然后x * pixelSize像你一样添加。

于 2013-11-13T18:40:47.230 回答