c#中的不安全图像噪声消除(错误:位图区域已被锁定)

时间:2011-05-11 11:22:17

标签: c# image-processing filtering

public unsafe Bitmap  MedianFilter(Bitmap Img)
     {
        int Size =2;

        List<byte> R = new List<byte>();
        List<byte> G = new List<byte>();
        List<byte> B = new List<byte>();

        int ApetureMin = -(Size / 2);
        int ApetureMax = (Size / 2);

        BitmapData imageData = Img.LockBits(new Rectangle(0, 0, Img.Width, Img.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);

        byte* start = (byte*)imageData.Scan0.ToPointer ();
        for (int x = 0; x < imageData.Width; x++)
        {
            for (int y = 0; y < imageData.Height; y++)
            {
                for (int x1 = ApetureMin; x1 < ApetureMax; x1++)
                {
                    int valx = x + x1;
                    if (valx >= 0 && valx < imageData.Width)
                    {
                        for (int y1 = ApetureMin; y1 < ApetureMax; y1++)
                        {
                            int valy = y + y1;
                            if (valy >= 0 && valy < imageData.Height)
                            {
                                Color tempColor = Img.GetPixel(valx, valy);// error come from here
                                R.Add(tempColor.R);
                                G.Add(tempColor.G);
                                B.Add(tempColor.B);
                            }
                        }
                    }
                }
            }
        }

        R.Sort();
        G.Sort();
        B.Sort();

        Img.UnlockBits(imageData);
        return Img;
     }

我试着这样做。但我得到一个错误调用“位图区域已被锁定”任何人都可以帮助如何解决这个问题。 (错误位置突出显示)

1 个答案:

答案 0 :(得分:5)

GetPixel是访问图像的懒散方式,如果其他人开始直接弄乱图像缓冲区,则不再工作(正如您所注意到的)。你为什么要那样做?

检查http://www.bobpowell.net/lockingbits.htm,了解对快速图像处理的一些了解。

在这种情况下,请改用以下内容:

int pixelSize = 4 /* Check below or the site I linked to and make sure this is correct */
byte* color =(byte *)imageData .Scan0+(y*imageData .Stride) + x * pixelSize;

请注意,这会为您提供该像素的第一个字节。根据您正在查看的颜色格式(ARGB?RGB?..),您还需要访问以下字节。似乎无论如何都要套用你的用例,因为你只关心字节值,而不是Color值。


所以,在有了一些闲暇时间之后,这就是我想出来的(请花时间去理解并检查它,我确保它已编译完毕):

    public void SomeStuff(Bitmap image)
    {
        var imageWidth = image.Width;
        var imageHeight = image.Height;
        var imageData = image.LockBits(new Rectangle(0, 0, imageWidth, imageHeight), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);

        var imageByteCount = imageData.Stride*imageData.Height;
        var imageBuffer = new byte[imageByteCount];
        Marshal.Copy(imageData.Scan0, imageBuffer, 0, imageByteCount);

        for (int x = 0; x < imageWidth; x++)
        {
            for (int y = 0; y < imageHeight; y++)
            {
                var pixelColor = GetPixel(imageBuffer, imageData.Stride, x, y);

                // Do your stuff
            }
        }
    }

    private static Color GetPixel(byte[] imageBuffer, int imageStride, int x, int y)
    {

        int pixelBase = y*imageStride + x*3;
        byte blue = imageBuffer[pixelBase];
        byte green = imageBuffer[pixelBase + 1];
        byte red = imageBuffer[pixelBase + 2];

        return Color.FromArgb(red, green, blue);
    }

  • 依赖于样本中使用的PixelFormat(关于每像素的像素大小/字节数和值的顺序)。如果您更改PixelFormat,则会中断。
  • 不需要unsafe关键字。我怀疑它有很大的不同,但你可以自由地使用基于指针的访问,方法也是一样的。