небезопасное удаление шума изображения в c # (ошибка: область растрового изображения уже заблокирована) - PullRequest
1 голос
/ 11 мая 2011
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 Ответ

5 голосов
/ 11 мая 2011

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.Я сомневаюсь, что это имеет большое значение, но вы можете использовать вместо этого доступ на основе указателя, метод будет таким же.
...