【问题标题】:Attempted to read or write protected memory - image manipulation试图读取或写入受保护的内存 - 图像处理
【发布时间】:2013-11-13 18:32:51
【问题描述】:

我有这个代码;

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获取此代码

【问题讨论】:

    标签: c# image-processing


    【解决方案1】:

    首先,您需要了解图像是如何存储在数组中的。 “通常在大多数 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);
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-08
        • 2012-09-21
        • 2012-04-16
        • 2020-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多