“着色” .NET 中的位图

发布于 2024-08-06 10:05:32 字数 132 浏览 8 评论 0原文

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

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

If you have a System.Drawing.Bitmap instance that contains a greyscale image, is there a built in way to "colourize" it with the influence of another colour?

For example, if you had a black and white (greyscale) picture of a coffee mug and you wanted to create separate images of red, green and purple versions programmatically.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

混吃等死 2024-08-13 10:05:33

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

If it's an 8 bit image, you can just use a different the palette (Image.Palette). That's essentially a lookup table that assigns a Color value to each possible pixel byte value. Much faster than changing all pixels in a loop.

流星番茄 2024-08-13 10:05:33

请参阅此处

我过去曾使用过此方法。您想专门查看 ToSepia。
您可能需要稍微解构它,但它对我有用。

See here

I have used this in the past. You are wanting to look specifically at ToSepia.
You may need to deconstruct this a bit but it has worked for me.

奢华的一滴泪 2024-08-13 10:05:33

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

更新:请参阅 http://www.codeproject 处的示例。 com/KB/cs/Merge_Images_in_C_.aspx

I'd create a copy of the original image and them put a separate semi transparent image of the desired color of the top.

Update: see example at http://www.codeproject.com/KB/cs/Merge_Images_in_C_.aspx

东走西顾 2024-08-13 10:05:33

我不确定内置的方式,但是,如果您将每种颜色表示为浮点而不是字节(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"

不过,您确实需要对每个像素应用此功能。

I am unsure of a built in way but, if you represent each colour as a float rather than a byte (255 becomes 1 - full intensity), multiplying the each channel with your desired colour should give the effect you are talking about.

(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"

You do need to apply this per pixel though.

凉风有信 2024-08-13 10:05:32

我没有提供代码示例,但这里有一种方法可以做到这一点。将每个像素从 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();

    }

I don't have a code example to give but here's a way to do this. Convert each pixel from RGB to HSV and change the Hue and Saturation component on each pixel. The Hue controls the Color. The Value should stay the same. The result will be a Bitmap with the same lightness and darkness but with a different color.

Edit: here's an example. Notice the Hue and Saturation update.

        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();

    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文