正如已经指出的那样,这个问题最难的部分是知道给定的颜色是否“更接近”黑色、白色或红色。我把一些可能对你有用的东西放在一起:
Color GetNearestOfBWR(Color c)
{
float redness = Math.Abs(180 - c.GetHue()) / 180;
float brightness = c.GetBrightness();
float saturation = c.GetSaturation();
你现在有三个值,每个值都在 0 和 1 之间,从 0 增加到 1 意味着你越来越接近红色(粗略地说:更多的红色/更少的绿色和蓝色,更多的颜色/更少的黑色,更多的颜色/更少的灰色)。
您现在必须决定颜色在什么时候构成“红色”,老实说,这是一个判断电话。你可以简单地拥有
double brightColourfulRedness = Math.Sqrt(
redness*redness + brightness*brightness + saturation*saturation);
if (brightColourfulRedness > 1)
return Color.FromArgb(255, 0, 0); // red;
(简单的欧几里得范数),但您可能希望对特定属性的权重比另一个更强 - 或者只是修改1
阈值。
然后你必须决定什么映射到黑色或白色;这可能很简单
if (brightness > 0.5)
return Color.FromArgb(255, 255, 255); // white
return Color.FromArgb(0, 0, 0); // black
}
伟大的!所以现在你有一个函数可以根据口味将颜色映射为红色、白色或黑色。剩下的就是将其应用于位图中的每个像素。如果您很高兴覆盖Bitmap
从文件中加载的内容,则不需要该数组;你可以这样做:
int height = imageoriginal.Height;
int width = imageoriginal.Width;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
Color origC = imageoriginal.GetPixel(i, j);
Color newC = GetNearestOfBWR(origC);
imageoriginal.SetPixel(i, j, newC);
}
}
这可能会很慢,因此您也可以使用 DmitryG 的LockBits
代码,但您需要在int
它提供给您的Color
s和GetNearestOfBWR
. (FromArgb
并且ToArgb
这样做,我相信。)