c# - 如何使用 LockBits 将位图中非黑色的像素着色为黄色?

标签 c# .net winforms lockbits

使用 GetPixel 和 SetPixel 很简单,但速度很慢,因此我尝试使用 LockBits。

我很久以前就用过这个方法来比较两个图像:

public static Bitmap FastComparison(Bitmap bmp1,Bitmap bmp2)
    {
       tolerancenumeric = 15;
       int tolerance = tolerancenumeric * tolerancenumeric + 
                       tolerancenumeric * tolerancenumeric + 
                       tolerancenumeric * tolerancenumeric; //dr * dr + dg * dg + db * db;
       bmp3 = new Bitmap(512,512);  
       PixelFormat pxf = PixelFormat.Format24bppRgb;
       Rectangle rect = new Rectangle(0, 0, bmp1.Width, bmp1.Height);
       BitmapData bmpData1 = bmp1.LockBits(rect, ImageLockMode.ReadWrite, pxf);
       BitmapData bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadWrite, pxf);
       BitmapData bmpData3 = bmp3.LockBits(rect, ImageLockMode.ReadWrite, pxf);

       IntPtr ptr1 = bmpData1.Scan0;
       IntPtr ptr2 = bmpData2.Scan0;
       IntPtr ptr3 = bmpData3.Scan0;

       int numBytes = bmpData1.Stride * bmp1.Height;
       byte[] rgbValues1 = new byte[numBytes];
       Marshal.Copy(ptr1, rgbValues1, 0, numBytes);
       bmp1.UnlockBits(bmpData1);

       byte[] rgbValues2 = new byte[numBytes];
       Marshal.Copy(ptr2, rgbValues2, 0, numBytes);
       bmp2.UnlockBits(bmpData2);


       for (int counter = 0; counter < rgbValues1.Length; counter += 3)
       {
          int  dr, dg, db;
          dr = (int)rgbValues2[counter] - (int)rgbValues1[counter];
          dg = (int)rgbValues2[counter + 1] - (int)rgbValues1[counter + 1];
          db = (int)rgbValues2[counter + 2] - (int)rgbValues1[counter + 2];
          int error = dr * dr + dg * dg + db * db;

          int y, x;
          y = (counter / 3) / 512;
          x = (counter - y * 512 * 3)/3;
          if ((x == 479) && (y == 474))
          {
             Byte r1, g1, b1, r2, g2, b2;
             r1 = rgbValues1[counter];
             b1 = rgbValues1[counter+1];
             g1 = rgbValues1[counter+2];
             r2 = rgbValues2[counter];
             b2 = rgbValues2[counter+1];
             g2 = rgbValues2[counter+2];
           }

           if (error < tolerance)
           {
             rgbValues1[counter] = 0; 
             rgbValues1[counter + 1] = 0;
             rgbValues1[counter + 2] = 0;
           }
         }
         Marshal.Copy(rgbValues1, 0, ptr3, numBytes);
         bmp3.UnlockBits(bmpData3);
         return bmp3;
       }

但现在我想也使用 LockBits,但只使用一张图像,并将所有非黑色像素着色为黄色。

我开始了新方法:

public Bitmap ChangeColors(Bitmap bmp1)
        {
            bmpColors = new Bitmap(512, 512);
            PixelFormat pxf = PixelFormat.Format24bppRgb;
            Rectangle rect = new Rectangle(0, 0, bmp1.Width, bmp1.Height);
            BitmapData bmpData1 = bmp1.LockBits(rect, ImageLockMode.ReadWrite, pxf);

            IntPtr ptr1 = bmpData1.Scan0;

            int numBytes = bmpData1.Stride * bmp1.Height;
            byte[] rgbValues1 = new byte[numBytes];
            Marshal.Copy(ptr1, rgbValues1, 0, numBytes);
            bmp1.UnlockBits(bmpData1);

            for (int counter = 0; counter < rgbValues1.Length; counter += 3)
            {
                int y, x;
                y = (counter / 3) / 512;
                x = (counter - y * 512 * 3) / 3;

                Byte r1, g1, b1;
                r1 = rgbValues1[counter];
                b1 = rgbValues1[counter + 1];
                g1 = rgbValues1[counter + 2];
            }

            return bmpColors;
        }

但不知道如何制作,以便位图 bmpColors 将是原始的,但所有像素不是黑色的,而是黄色的。

最佳答案

简单地测试字节并相应地设置它们怎么样?

Byte r1, g1, b1;
r1 = rgbValues1[counter];         // should be + 2 !!
b1 = rgbValues1[counter + 1];     // should be + 0 !!
g1 = rgbValues1[counter + 2];     // should be + 1 !!

if (r1 + b1 + g1 == 0 ) 
{
    r1 = 255;
    g1 = 255;
}

当然,这假设您可以接受真正的黑色和基本的黄色。

如果您需要更多控制,则需要更多代码,例如

if (r1 + b1 + g1 < threshold)

对于黑色阴影,对于黄色可能:

    r1 = myYellow_R;
    g1 = myYellow_G;
    b1 = myYellow_B;

顺便说一句:您需要检查这些索引;上次我查看 LockBits 数组中的数据时,反转了:不是 RGB(更不用说 RBG 了),而是 >BGR! (对于 32bpp BGRA!)

由于您使用的是旧方法,因此还请确保您的像素格式没问题;如果是 32bpp,您将需要进行一些简单的修改。

关于c# - 如何使用 LockBits 将位图中非黑色的像素着色为黄色?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25976620/

相关文章:

c# - 如何在 C# 中打印 KeyValuePair<K,T> 中的信息?

C# 向 COM 公开 - 接口(interface)继承

c# - Task.WaitAll 和异常

c# - ListView 中的图像质量差

c# - 维护多个设置文件

c# - 在导航时再次调用 ViewModel 的构造函数,因此再次订阅 Messenger 订阅

c# - 在单元测试中链接 resx 文件

当从 python 调用时,c# 需要额外的参数(.net 和 ironpython)

C# - 基本问题 : What is '?' ?

.net - WndProc 重载时抛出异常