使用透明背景更改图像颜色

时间:2017-01-21 08:09:11

标签: c# gdi+ system.drawing

我需要使用c#(System.Drawings)将透明背景上带绿色圆圈的图像加载到位图图像中。

这很容易。但是,我需要在将圆形颜色添加到更大的图像之前更改圆形的颜色,而不会影响周围的透明度。在我的情况下,我需要将圆形颜色更改为黄色并将其添加为太阳。

我无法使用固定的黄色圆圈图像,因为所需的颜色是动态的。

所以在下面的代码中,如何在将图像添加到位图之前更改图像的颜色?

Image i = Image.FromFile(greenCircleFile);
Bitmap b = new Bitmap(500, 500);

using(Graphics g = Graphics.FromImage(b))
{
    //--> Here I need to change the color of the green circle to yellow
    //afterwards I can add it to the bitmap image
    g.DrawImage(i, 0, 0, 500, 500);
}

请注意,需要考虑两件事:保持形状(圆圈)的抗锯齿,并且用户需要选择颜色并按原样使用以覆盖圆的原始颜色。

修正:

感谢@TaW,他提供了正确的答案。然而,有一个小故障,这是最适合我的版本:

Image i = Image.FromFile(greenCircleFile);
Bitmap b = new Bitmap(500, 500);

using(Graphics g = Graphics.FromImage(b))
{
    //Here I need to change the color of the green circle to yellow
    i = ChangeToColor(b, Color.Gold)
    //afterwards I can add it to the bitmap image
    g.DrawImage(i, 0, 0, 500, 500);
}

ChangeToColor功能如下:

Bitmap ChangeToColor(Bitmap bmp, Color c)
{
    Bitmap bmp2 = new Bitmap(bmp.Width, bmp.Height);
    using (Graphics g = Graphics.FromImage(bmp2))
    {
        float tr = c.R / 255f;
        float tg = c.G / 255f;
        float tb = c.B / 255f;

        ColorMatrix colorMatrix = new ColorMatrix(new float[][]
          {
            new float[] {0, 0, 0, 0, 0},
            new float[] {0, 0, 0, 0, 0},
            new float[] {0, 0, 0, 0, 0},
            new float[] {0, 0, 0, 1, 0},
            new float[] {tr, tg, tb, 0, 1}
          });

        ImageAttributes attributes = new ImageAttributes();
        attributes.SetColorMatrix(colorMatrix);

        g.DrawImage(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height),
            0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, attributes);
    }
    return bmp2;
}

2 个答案:

答案 0 :(得分:4)

这将创建一个新的位图,所有非透明像素都强烈地向新颜色移动:

    Bitmap ChangeToColor(Bitmap bmp, Color c)
    {
        Bitmap bmp2 = new Bitmap(bmp.Width, bmp.Height);
        using (Graphics g = Graphics.FromImage(bmp2))
        {
            float tr = c.R / 255f;
            float tg = c.G / 255f;
            float tb = c.B / 255f;

            ColorMatrix colorMatrix = new ColorMatrix(new float[][]
              {
                 new float[] {0, 0, 0, 0, 0},
                 new float[] {0, 0, 0, 0, 0},
                 new float[] {0, 0, 0, 0, 0},
                 new float[] {0, 0, 0, 1, 0},
                 new float[] {tr, tg, tb, 0, 1}  // kudos to OP!
              });

            ImageAttributes attributes = new ImageAttributes();
            attributes.SetColorMatrix(colorMatrix);

            g.DrawImage(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height),
                0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, attributes);
        }
        return bmp2;
    }

确保不要泄漏您创建的位图!

请注意,还有其他方法。 Here是指向使用ColorMapping的方法的链接。这允许一系列颜色被另一个范围替换,因此它可以保持渐变像你在反对称图形中获得的渐变。

答案 1 :(得分:-2)

这是我只需要创建一个新控件的解决方案

然后继承Picturebox检查出来。

let interval = CMTime(value: 1, timescale: 1)
self.audioPlayer?.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main, using: { (progressTime) in

let secondsProgress = CMTimeGetSeconds(progressTime)

    let secondsStringProgress = String(format: "%02d", Int((secondsProgress.truncatingRemainder(dividingBy: 60))))
    let minuitesStringProgress = String(format: "%02d", Int(secondsProgress) / 60)
    //self.countDownLabel.text = "\(minuitesStringProgress):\(secondsStringProgress)"

    if let duration = self.audioPlayer?.currentItem!.asset.duration {

        let secondsDuration = CMTimeGetSeconds(duration)

            let secondsStringDuration = String(format: "%02d", Int((secondsDuration.truncatingRemainder(dividingBy: 60))))
            let minuitesStringDuration = String(format: "%02d", Int(secondsDuration) / 60)

                let secondsString = String(format: "%02d", Int(secondsStringDuration)! - Int(secondsStringProgress)!)
                let minuitesString = String(format: "%02d", Int(minuitesStringDuration)! - Int(minuitesStringProgress)!)

            self.countDownLabel.isHidden = false
            self.countDownLabel.text = "\(minuitesString):\(secondsString)"

        self.horizontalSlider.value = Float(secondsProgress / secondsDuration)
        self.circleSlider.value = Float(secondsProgress / secondsDuration)

    }
})