65.9K
CodeProject 正在变化。 阅读更多。
Home

颜色替换器

2009 年 10 月 6 日

CPOL

2分钟阅读

viewsIcon

47311

downloadIcon

4408

一个示例,展示了如何替换图像中特定颜色范围内的一种颜色。

引言

我记得以前很喜欢 MS Office 2000 中包含的 MS PhotoEditor,因为它是一个简单有效的工具,可以在您想要通过消除图像中的特定颜色来创建具有透明部分的图像时使用。 好吧,这篇文章将向您展示这是如何实现的。

背景

这个过程背后的思想是逐像素读取图像,对于每个像素,进一步分解为每个颜色的三个基本组成部分(ARGB):Alpha、Red、Green、Blue。 在本示例中,我们不太关心读取 Alpha,但在写回图像像素时会用到。 读取像素并获取其 RGB 分量后,我们现在通过添加容差值来设置每个颜色的上限,并从原始值中减去它来得出下限颜色。 最终,我们决定颜色是否位于我们先前设置的范围内,如果是,则将新颜色应用于该像素。 在透明度的情况下,三个颜色分量不再重要,所以无论它们是什么,我们只需将 Alpha 系数提高到其最大值,即 255 十进制或 FF 十六进制。

Using the Code

根据容差值,我们首先定义传递到我们函数的原始颜色的每个颜色的限制。

//Defining Tolerance
//R
iR_Min = Math.Max((int)_colorOld.R - _tolerance, 0);
iR_Max = Math.Min((int)_colorOld.R + _tolerance, 255);

//G
iG_Min = Math.Max((int)_colorOld.G - _tolerance, 0);
iG_Max = Math.Min((int)_colorOld.G + _tolerance, 255);

//B
iB_Min = Math.Max((int)_colorOld.B - _tolerance, 0);
iB_Max = Math.Min((int)_colorOld.B + _tolerance, 255);

然后,我们按行、列的方式循环遍历图像像素

for (int x = 0; x < bmap.Width; x++)
{
    for (int y = 0; y < bmap.Height; y++)
    {
        c = bmap.GetPixel(x, y);
        ...

读取像素后,我们检查它是否位于我们先前定义的原始颜色值范围内

//Determinig Color Match
if(
    (c.R >= iR_Min && c.R <= iR_Max) &&
    (c.G >= iG_Min && c.G <= iG_Max) &&
    (c.B >= iB_Min && c.B <= iB_Max) 
  )

如果是匹配项,那么我们进行另一个检查,但这次,是关于写入像素的检查,现在检查的是替换颜色是否透明。

if(_colorNew == Color.Transparent)
  bmap.SetPixel(x, y, Color.FromArgb(0,
       _colorNew.R,
       _colorNew.G,
       _colorNew.B));

else
  bmap.SetPixel(x, y, Color.FromArgb(c.A,
       _colorNew.R,
       _colorNew.G,
       _colorNew.B));

如您所见,如果新颜色是透明的,我们只需将 alpha 降低到 0;否则,我们使用从原始图像获取的 alpha 值 c.A

关注点

在尝试从 PictureBox 中选择颜色时,MouseEventArgs 坐标不是很准确,并且在本文章中仍然没有解决,我希望我们能够一起找到解决方案。 目前的实现方式如下...

private void pbPreview_MouseMove(object sender, MouseEventArgs e)
{
    if (bPicking)
    {
        Bitmap bmTemp = (Bitmap)((PictureBox)sender).Image;
        pnlOldColor.BackColor = bmTemp.GetPixel(e.X,e.Y);
    }
}
© . All rights reserved.