Блокировка битов не может обнаружить пиксели - PullRequest
0 голосов
/ 17 сентября 2011

Я создаю программу, которая сканирует все пиксели изображения и всякий раз, когда находит пиксель, который содержит розовый цвет.Это делает пиксель черным.Но кажется, что розового пикселя не видно, когда на изображении их два.Я не знаю, правильно ли я использую LockBits, возможно я использую это неправильно.Может кто-нибудь, пожалуйста, помогите мне решить эту проблему, я был бы очень признателен.

Вот код ниже:

            Bitmap bitmap = pictureBox1.Image as Bitmap;
            System.Drawing.Imaging.BitmapData d = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);
            IntPtr ptr = d.Scan0;
            byte[] rgbs = new byte[Math.Abs(d.Stride) * bitmap.Height];
            Marshal.Copy(ptr, rgbs, 0, rgbs.Length);
            Graphics g = pictureBox1.CreateGraphics();
            for (int index = 2; index < rgbs.Length; index += 3)
            {


                if (rgbs[index] == 255 &&  rgbs[index - 1] == 0 && rgbs[index - 2] == 255) // If color = RGB(255, 0, 255) Then ...
                {
                     // This never gets executed!
                     rgbs[index] = 0;
                     rgbs[index - 1] = 0;
                     rgbs[index - 2] = 0;

                }
            }
            Marshal.Copy(rgbs, 0, ptr, rgbs.Length); // Copy rgb values back to the memory location of the bitmap.
            pictureBox1.Image = bitmap;
            bitmap.UnlockBits(d); 

1 Ответ

1 голос
/ 17 сентября 2011

Вам не нужно копировать данные пикселей в массив.Смысл LockBits в том, что он дает вам прямой (небезопасный) доступ к памяти.Вы можете просто перебирать пиксели и изменять их по мере их нахождения.Вам нужно знать формат изображения, чтобы сделать это успешно.

  BitmapData bmd=bm.LockBits(new Rectangle(0, 0, 10, 10), 
                       ImageLockMode.ReadOnly, bm.PixelFormat);
  // Blue, Green, Red, Alpha (Format32BppArgb)
  int pixelSize=4;

  for(int y=0; y<bmd.Height; y++)
  {
    byte* row=(byte *)bmd.Scan0+(y*bmd.Stride);
    for(int x=0; x<bmd.Width; x++) 
    {
      int offSet = x*pixelSize;
      // read pixels
      byte blue = row[offSet];
      byte green = row[offSet+1];
      byte red = row[offSet+2];
      byte alpha = row[offSet+3];

      // set blue pixel
      row[x*pixelSize]=255;
    }
  }

Это немного сложнее в VB, чем в C #, так как VB не знает указателей и требует использования класса маршала для доступанеуправляемые данные.Вот пример кода.(Почему-то я изначально думал, что это вопрос VB).

  Dim x As Integer
  Dim y As Integer
  ' Blue, Green, Red, Alpha (Format32BppArgb)
  Dim PixelSize As Integer = 4 
  Dim bmd As BitmapData = bm.LockBits(new Rectangle(0, 0, 10, 10),
                                      ImageLockMode.ReadOnly, bm.PixelFormat)

  For y = 0 To bmd.Height - 1
    For x = 0 To bmd.Width - 1
      Dim offSet As Int32 = (bmd.Stride * y) + (4 * x)
      ' read pixel data
      Dim blue As Byte = Marshal.ReadByte(bmd.Scan0, offSet)
      Dim green As Byte = Marshal.ReadByte(bmd.Scan0, offSet + 1)
      Dim red As Byte = Marshal.ReadByte(bmd.Scan0, offSet + 2)
      Dim alpha As Byte = Marshal.ReadByte(bmd.Scan0, offSet + 3)
      ' set blue pixel
      Marshal.WriteByte(bmd.Scan0, offSet , 255)
    Next
  Next
...