【问题标题】:Changing the tint of a bitmap while preserving the overall brightness在保持整体亮度的同时更改位图的色调
【发布时间】:2010-02-27 15:29:32
【问题描述】:

我正在尝试编写一个函数,它可以让我对位图进行红移或蓝移,同时保持图像的整体亮度。基本上,完全红移的位图将具有与原始位图相同的亮度,但会被完全染成红色(即所有像素的 G 值和 B 值都相同)。蓝色着色相同(但 R 和 G 相等)。频谱偏移的程度需要在 0 到 1 之间变化。

提前致谢。

【问题讨论】:

  • 将颜色空间更改为 HSV,然后改变色调是否符合您的要求?
  • HSV 会起作用,但不完全是。
  • 听起来你想要的是特定颜色的“灰度”图像,对吗?
  • @emddudley:是的,这正是我想要的,您的评论触发了我下面的解决方案。谢谢。

标签: c# .net bitmap rgb


【解决方案1】:

这是我一直在寻找的效果(糟糕的 JPEG,抱歉):

alt text http://www.freeimagehosting.net/uploads/d15ff241ca.jpg

中间的图片是原图,侧面的图片分别是全红移、部分红移、部分蓝移和全蓝移。

这是产生这种效果的函数:

public void RedBlueShift(Bitmap bmp, double factor)
{
    byte R = 0;
    byte G = 0;
    byte B = 0;
    byte Rmax = 0;
    byte Gmax = 0;
    byte Bmax = 0;
    double avg = 0;
    double normal = 0;
    if (factor > 1)
    {
        factor = 1;
    }
    else if (factor < -1)
    {
        factor = -1;
    }
    for (int x = 0; x < bmp.Width; x++)
    {
        for (int y = 0; y < bmp.Height; y++)
        {
            Color color = bmp.GetPixel(x, y);
            R = color.R;
            G = color.G;
            B = color.B;
            avg = (double)(R + G + B) / 3;
            normal = avg / 255.0; // to preserve overall intensity
            if (factor < 0) // red-tinted:
            {
                if (normal < .5)
                {
                    Rmax = (byte)((normal / .5) * 255);
                    Gmax = 0;
                    Bmax = 0;
                }
                else
                {
                    Rmax = 255;
                    Gmax = (byte)(((normal - .5) * 2) * 255);
                    Bmax = Gmax;
                }
                R = (byte)((double)R - ((double)(R - Rmax) * -factor));
                G = (byte)((double)G - ((double)(G - Gmax) * -factor));
                B = (byte)((double)B - ((double)(B - Bmax) * -factor));
            }
            else if (factor > 0) // blue-tinted:
            {
                if (normal < .5)
                {
                    Rmax = 0;
                    Gmax = 0;
                    Bmax = (byte)((normal / .5) * 255);
                }
                else
                {
                    Rmax = (byte)(((normal - .5) * 2) * 255);
                    Gmax = Rmax;
                    Bmax = 255;
                }
                R = (byte)((double)R - ((double)(R - Rmax) * factor));
                G = (byte)((double)G - ((double)(G - Gmax) * factor));
                B = (byte)((double)B - ((double)(B - Bmax) * factor));
            }
            color = Color.FromArgb(R, G, B);
            bmp.SetPixel(x, y, color);
        }
    }
}

【讨论】:

  • 我可以想象这段代码会非常慢,因为它使用的是逐像素操作。我会按照 Hans Passant 的建议研究 ColorMatrix 类。
  • @Will Kru:是的,由于GetPixelSetPixel,我发布的代码会超级慢。但是,ColorMatrix 对我不起作用,因为我的“位图”并不是真正的 .NET 位图——它们是 2D int 数组。我包含的函数使用 .NET 位图和 GetPixel/SetPixel,以便对其他人更有用。
【解决方案2】:

您将为此使用 ColorMatrix 类。 this project 有一个很好的教程。

【讨论】:

  • 我还没有看到任何使用 ColorMatrix 的颜色偏移 + 保持亮度的示例(即色调)。我仔细看了你提供的那个链接不是。有例子吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-27
  • 2016-12-08
  • 1970-01-01
相关资源
最近更新 更多