如何使用GDI +仅转换特定颜色的像素?

时间:2013-03-26 12:25:46

标签: c# .net gdi+

假设我有一个由黑白RGB像素组成的图像,具有不同的透明度。然后,我想使用GDI +来维持所有像素的透明度级别,并将黑色像素转换为红色,使白色像素不受影响。

我认为色彩图看起来像是:

 |0 0 0 0 0|
 |0 0 0 0 0|
 |0 0 0 0 0|
 |0 0 0 1 0|
 |1 0 0 0 1|

但是,如果不依次循环每个像素并测试其颜色,我可以将该地图仅应用于黑色像素吗?

3 个答案:

答案 0 :(得分:7)

回答主要问题: 没有方式使用矩阵替换特定颜色,因为矩阵只是无条件的转换

解决您的问题:由于您使用的组合(黑白),可以使用矩阵 !请参阅下面的详细答案......

非常好的参考资料: Color Transformations and the Color Matrix


你的矩阵猜测非常接近,但是,你并没有保持所有RGBA值完好无损。看看这里:

  R   G   B   A   W
 ___________________
| 1 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 0 | 0 |
| 0 | 0 | 1 | 0 | 0 |
| 0 | 0 | 0 | 1 | 0 |
| 1 | 0 | 0 | 0 | 1 |
 ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

通过对角线1,您 维持当前的RGBA值。通过在1上指定[4][0],您也表示您希望 最大值

在您使用黑白的特定情况下,仅替换黑色将起作用,因为白色的RGB值已经达到最大值(255,255,255)。

因此,通过以上矩阵,您基本上是在说:将所有RGB保持为当前值,我还希望红色始终为255!< / em>的


使用序列(R,G,B,A)并应用上述规则的详细示例:红色最大值= 255,其他一切都相同。

  • 找到(0,0,0,128)=结果(255,0,0,128);
  • 找到(0,0,0,192)=结果(255,0,0,192);
  • 找到(255,255,255,128)=结果(255,255,255,128);
  • 找到(255,255,255,255)=结果(255,255,255,255);

如您所见,红色组件始终设置为最大值,其余组件保持不变。


示例图片:

Sample color transformation

左侧包含指定了alpha值的原始颜色,而右侧包含应用了上述转换的相同图像。左侧的圆圈按以下方式组织:

                  R    G    B    A   |   R    G    B    A
               ______________________|_______________________
circle[0,0] = | (255,   0,   0,   0) | (255,   0,   0,  64) | = circle[0,1]
      [1,0] = | (  0,   0,   0,   0) | (  0,   0,   0,  64) | =       [1,1]
      [2,0] = | (255, 255, 255,   0) | (255, 255, 255,  64) | =       [2,1]
      [3,0] = | (255,   0,   0, 128) | (255,   0,   0, 255) | =       [3,1]
      [4,0] = | (  0,   0,   0, 128) | (  0,   0,   0, 255) | =       [4,1]
      [5,0] = | (255, 255, 255, 128) | (255, 255, 255, 255) | =       [5,1]
               ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

用于生成样本图像的C#代码:

using (Bitmap myBitmap = new Bitmap(102, 302))
{
    Graphics g = Graphics.FromImage(myBitmap);
    g.Clear(Color.Transparent);
    g.FillEllipse(new SolidBrush(Color.FromArgb(0, Color.Red)), new Rectangle(1, 1, 50, 50));
    g.FillEllipse(new SolidBrush(Color.FromArgb(0, Color.Black)), new Rectangle(1, 51, 50, 50));
    g.FillEllipse(new SolidBrush(Color.FromArgb(0, Color.White)), new Rectangle(1, 101, 50, 50));

    g.FillEllipse(new SolidBrush(Color.FromArgb(64, Color.Red)), new Rectangle(51, 1, 50, 50));
    g.FillEllipse(new SolidBrush(Color.FromArgb(64, Color.Black)), new Rectangle(51, 51, 50, 50));
    g.FillEllipse(new SolidBrush(Color.FromArgb(64, Color.White)), new Rectangle(51, 101, 50, 50));

    g.FillEllipse(new SolidBrush(Color.FromArgb(128, Color.Red)), new Rectangle(1, 151, 50, 50));
    g.FillEllipse(new SolidBrush(Color.FromArgb(128, Color.Black)), new Rectangle(1, 201, 50, 50));
    g.FillEllipse(new SolidBrush(Color.FromArgb(128, Color.White)), new Rectangle(1, 251, 50, 50));

    g.FillEllipse(new SolidBrush(Color.FromArgb(255, Color.Red)), new Rectangle(51, 151, 50, 50));
    g.FillEllipse(new SolidBrush(Color.FromArgb(255, Color.Black)), new Rectangle(51, 201, 50, 50));
    g.FillEllipse(new SolidBrush(Color.FromArgb(255, Color.White)), new Rectangle(51, 251, 50, 50));
    g.DrawRectangle(Pens.Black, 0, 0, myBitmap.Width - 1, myBitmap.Height - 1);

    e.Graphics.DrawImage(myBitmap, 0, 0);

    ColorMatrix colorMatrix = new ColorMatrix(
        new Single[][]
        {
            new [] { 1f, 0, 0, 0, 0 },
            new [] { 0f, 1, 0, 0, 0 },
            new [] { 0f, 0, 1, 0, 0 },
            new [] { 0f, 0, 0, 1, 0 },
            new [] { 1f, 0, 0, 0, 1 }
        });

    using (ImageAttributes imageAttr = new ImageAttributes())
    {
        imageAttr.SetColorMatrix(colorMatrix);

        Rectangle rect = new Rectangle(150, 0, myBitmap.Width, myBitmap.Height);
        e.Graphics.DrawImage(myBitmap, rect, 0, 0, myBitmap.Width, myBitmap.Height, GraphicsUnit.Pixel, imageAttr);
    }
}

答案 1 :(得分:3)

黑色用0表示, 白色表示为1

要使用黑色像素 使您的数学工作,您应该执行以下操作:

  1. 反转图像的颜色(不会失去透明度)。
  2. 将白色(原始黑色)转换为Aqua(红色反转)。
  3. 将颜色反转回原始颜色。
  4. 步骤2中的色彩映射将如下所示:

    |0 0 0 0 0|
    |0 1 0 0 0|
    |0 0 1 0 0|
    |0 0 0 1 0|
    |0 0 0 0 1|
    

    结果现在应该如下:

    1. 黑色是红色。
    2. 白色仍然是白色。

答案 2 :(得分:2)

除了描述的其他技术之外,Color Remap Table可用于转换图像中特定单个颜色(的简短列表)。重映射表是传递给Graphics对象的DrawImage方法的ImageAttributes对象的一部分。从MSDN文档:

  

当GDI +绘制图像时,图像的每个像素都与图像进行比较   一系列旧颜色。如果像素的颜色与旧颜色匹配,则为   颜色更改为相应的新颜色。颜色是   仅为渲染而更改 - 图像本身的颜色值   (存储在Image或Bitmap对象中)不会更改。