2

如果您有一个System.Drawing.Bitmap包含灰度图像的实例,是否有一种内置方法可以在另一种颜色的影响下“着色”它?

例如,如果您有一张咖啡杯的黑白(灰度)图片,并且您想以编程方式创建红色、绿色和紫色版本的单独图像。

4

5 回答 5

5

我没有要给出的代码示例,但这是一种方法。将每个像素从 RGB 转换为 HSV,并更改每个像素上的色相和饱和度分量。色调控制颜色。价值应该保持不变。结果将是一个具有相同明暗但颜色不同的位图。

编辑:这是一个例子。注意色相和饱和度更新。

        public static Color ColorFromAhsb(int a, float h, float s, float b)
    {

        if (0 > a || 255 < a)
        {
            throw new Exception("a");
        }
        if (0f > h || 360f < h)
        {
            throw new Exception("h");
        }
        if (0f > s || 1f < s)
        {
            throw new Exception("s");
        }
        if (0f > b || 1f < b)
        {
            throw new Exception("b");
        }

        if (0 == s)
        {
            return Color.FromArgb(a, Convert.ToInt32(b * 255),
              Convert.ToInt32(b * 255), Convert.ToInt32(b * 255));
        }

        float fMax, fMid, fMin;
        int iSextant, iMax, iMid, iMin;

        if (0.5 < b)
        {
            fMax = b - (b * s) + s;
            fMin = b + (b * s) - s;
        }
        else
        {
            fMax = b + (b * s);
            fMin = b - (b * s);
        }

        iSextant = (int)Math.Floor(h / 60f);
        if (300f <= h)
        {
            h -= 360f;
        }
        h /= 60f;
        h -= 2f * (float)Math.Floor(((iSextant + 1f) % 6f) / 2f);
        if (0 == iSextant % 2)
        {
            fMid = h * (fMax - fMin) + fMin;
        }
        else
        {
            fMid = fMin - h * (fMax - fMin);
        }

        iMax = Convert.ToInt32(fMax * 255);
        iMid = Convert.ToInt32(fMid * 255);
        iMin = Convert.ToInt32(fMin * 255);

        switch (iSextant)
        {
            case 1:
                return Color.FromArgb(a, iMid, iMax, iMin);
            case 2:
                return Color.FromArgb(a, iMin, iMax, iMid);
            case 3:
                return Color.FromArgb(a, iMin, iMid, iMax);
            case 4:
                return Color.FromArgb(a, iMid, iMin, iMax);
            case 5:
                return Color.FromArgb(a, iMax, iMin, iMid);
            default:
                return Color.FromArgb(a, iMax, iMid, iMin);
        }

    }

    private void Form1_Load(object sender, EventArgs e)
    {
        var bmp = new Bitmap("c:\\bw.bmp");

        foreach (int y in Enumerable.Range(0, bmp.Height))
        { 
            foreach (int x in Enumerable.Range(0,bmp.Width))
            {
                var p = bmp.GetPixel(x, y);
                var h = p.GetHue();

                var c = ColorFromAhsb(p.A, p.GetHue() + 200, p.GetSaturation() + 0.5f, p.GetBrightness());
                bmp.SetPixel(x, y, c);                    
            }
        }
        pictureBox1.Image = bmp;
        //bmp.Dispose();

    }
于 2009-09-30T21:50:35.323 回答
2

如果是 8 位图像,您可以使用不同的调色板 (Image.Palette)。这本质上是一个查找表,它为每个可能的像素字节值分配一个颜色值。比在循环中更改所有像素要快得多。

于 2009-10-01T11:19:48.770 回答
1

我会创建原始图像的副本,然后他们将顶部所需颜色的单独半透明图像放置。

更新:参见http://www.codeproject.com/KB/cs/Merge_Images_in_C_.aspx的示例

于 2009-09-30T15:25:18.440 回答
1

这里

我过去用过这个。您想专门查看 ToSepia。您可能需要稍微解构它,但它对我有用。

于 2009-09-30T15:29:27.137 回答
1

我不确定内置方式,但是,如果您将每种颜色表示为浮点数而不是字节(255 变为 1 - 全强度),则将每个通道与您想要的颜色相乘应该会产生您正在谈论的效果。

(1,1,1) "white" * (1,0,0) "red" = (1,0,0) "red"

(0.5,0.5, 0.5) "grey" * (0,1,0) "green" = (0,0.5,0) "dark green"

不过,您确实需要按像素应用它。

于 2009-10-01T00:21:56.187 回答