我希望能够混合两个或多个颜色对象。假设我从半透明的红色开始:
var 红色 = Color.FromArgb(140, 255, 0, 0);
然后我想将半透明的绿色混合到其中:
var 绿色 = Color.FromArgb(140, 0, 255, 0);
我遇到的颜色混合代码片段通常会产生棕色的阴影,但我真正想要的是一种效果,就像你在(比如说)中将一种颜色绘制在另一种颜色上时所得到的效果)Paint.Net,产生更多的深绿色:-
然后我想混合第三种颜色,比如半透明的蓝色:
var 蓝色 = Color.FromArgb(140, 0, 0, 255);
这一次,我想最终得到图像中心看到的青色:
(同样,如果我尝试使用常用的代码片段,那么我通常会得到灰色或棕色)。
顺便说一句,可能值得一提的是,以下代码几乎实现了我所追求的目标:
using (var bitmap = new Bitmap(300, 300))
{
using (var g = Graphics.FromImage(bitmap))
{
var c1 = Color.FromArgb(alpha: 128, red: 255, green: 0, blue: 0);
var c2 = Color.FromArgb(alpha: 200, red: 0, green: 255, blue: 0);
var c3 = Color.FromArgb(alpha: 100, red: 0, green: 0, blue: 255);
g.FillRectangle(new SolidBrush(c1), 100, 0, 100, 100);
g.FillRectangle(new SolidBrush(c2), 125, 75, 100, 100);
g.FillRectangle(new SolidBrush(c3), 75, 50, 100, 100);
}
}
我猜这代码相当于我的 Paint.Net 步骤,在另一个半透明彩色矩形上绘制一个半透明彩色矩形。但是我希望能够计算最终的混合颜色,并在一次调用
g.FillRectangle()
中使用它,而不是调用该方法三次来实现混合效果。
最后,这是我之前提到的颜色混合代码片段的示例,当我将它们用于我的颜色时,通常会产生棕色阴影:-
private Color Blend(Color c1, Color c2)
{
var aOut = c1.A + (c1.A * (255 - c1.A) / 255);
var rOut = (c1.R * c1.A + c2.R * c2.A * (255 - c1.A) / 255) / aOut;
var gOut = (c1.G * c1.A + c2.G * c2.A * (255 - c1.A) / 255) / aOut;
var bOut = (c1.B * c1.A + c2.B * c2.A * (255 - c1.A) / 255) / aOut;
return Color.FromArgb(aOut, rOut, gOut, bOut);
}
感谢 @TaW 的早期评论(否则我永远无法解决这个问题!),我能够编写一种以 Paint.net、Paintshop 等风格混合两种颜色的方法:-
var r = Color.FromArgb(140, 255, 0, 0);
var g = Color.FromArgb(140, 0, 255, 0);
var b = Color.FromArgb(140, 0, 0, 255);
// How to use:
var rg= AlphaComposite(r, g);
var rb= AlphaComposite(r, b);
var gb= AlphaComposite(g, b);
var rgb= AlphaComposite(AlphaComposite(r, g), b);
...
// A cache of all opacity values (0-255) scaled down to 0-1 for performance
private readonly float[] _opacities = Enumerable.Range(0, 256)
.Select(o => o / 255f)
.ToArray();
private Color AlphaComposite(Color c1, Color c2)
{
var opa1 = _opacities[c1.A];
var opa2 = _opacities[c2.A];
var ar = opa1 + opa2 - (opa1 * opa2);
var asr = opa2 / ar;
var a1 = 1 - asr;
var a2 = asr * (1 - opa1);
var ab = asr * opa1;
var r = (byte)(c1.R * a1 + c2.R * a2 + c2.R * ab);
var g = (byte)(c1.G * a1 + c2.G * a2 + c2.G * ab);
var b = (byte)(c1.B * a1 + c2.B * a2 + c2.B * ab);
return Color.FromArgb((byte)(ar * 255), r, g, b);
}
自 Chrome/Edge 111+、Safari 16.2+、或 Firefox 113+、Opera 97+ 您可以使用 color-mix() 来添加不透明度:
.my-element{
--my-opacity: 20%;
--my-color: rgb(52 201 235);
background-color: color-mix(in srgb-linear, var(--my-color), transparent calc(100% - var(--my-opacity)))
}
<div class="my-element">my-element</div>