试图读取或写入受保护的内存 - 图像处理

时间:2013-11-13 18:32:51

标签: c# image-processing

我有这段代码;

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])

中的

原因是什么?我从here

获取此代码

2 个答案:

答案 0 :(得分:3)

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

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包含x一个(出于增加缓存命中的原因):

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);

答案 1 :(得分:1)

访问位图数组时,永远不会使用y变量。您应该将y乘以Stride而不是x。然后像你一样添加x * pixelSize