我有一个灰度图像。我想过滤white -> color1
和black -> color2
。两种颜色都是十六进制CSS语法。我需要做什么数学才能产生这种效果?
我正在使用这种语法:
<!-- just an example -->
<filter id="colorMeMatrix">
<feColorMatrix in="SourceGraphic"
type="matrix"
values="0 0 0 0 0
1 1 1 1 0
0 0 0 0 0
0 0 0 1 0" />
答案 0 :(得分:48)
要了解您需要的矩阵,您必须明确定义您的起点,最终想要的内容以及colour matrix filter的工作原理。
矩阵有五列四行。每行代表一个输出数字:R,G,B,A。列表示输入RGBA和常量1.您可以通过将行中的每个值与相应的输入值相乘来计算每行的输出值。
输入和输出数字都标准化为0-1范围,因此您不必担心将所有内容乘以256.
所以对于你的例子中的矩阵:
/*R G B A 1 */
0 0 0 0 0 // R = 0*R + 0*G + 0*B + 0*A + 0
1 1 1 1 0 // G = 1*R + 1*G + 1*B + 1*A + 0
0 0 0 0 0 // B = 0*R + 0*G + 0*B + 0*A + 0
0 0 0 1 0 // A = 0*R + 0*G + 0*B + 1*A + 0
它采用输入颜色,将所有四个通道(RGBA)相加,并使结果成为绿色通道。红色和蓝色通道为零,Alpha通道不会更改。因此,您的照片最终会出现黑色区域,但所有彩色/灰色/白色/透明区域都会转换为绿色阴影。
当然,这不是你想要的。您希望黑色区域为一种颜色,白色区域为另一种颜色,所有灰色区域位于两者之间。
要使黑色区域成为某种颜色,您必须设置矩阵的常数因子参数。对于黑色,输入RGB值将为零,因此此时它们不会考虑因素。
如果你的colour2,你想在单色图像中用作黑色的值是(r2,g2,b2),那么这就是你的常数因子必须是:
/*R G B A 1 */
? ? ? 0 r2 // R = ?*0 + ?*0 + ?*0 + 0*0 + r2 = r2
? ? ? 0 g2 // G = ?*0 + ?*0 + ?*0 + 0*0 + g2 = g2
? ? ? 0 b2 // B = ?*0 + ?*0 + ?*0 + 0*0 + b2 = b2
0 0 0 1 0 // A = 1*A
当然,上面的矩阵会将任何输入颜色转换为该输出颜色,因为它不会影响输入RGBA值。要获得所需的渐变,您需要白色区域 - 对于R,G和B输入值为1的区域,最终得到colour1,我将写为(r1,g1,b1)。
现在,为了使事情变得更容易,请记住,对于灰度图像,任何点的R,G和B值都是相等的。所以我们可以使用这些值中的任何一个作为输入而忽略其他值。因此,如果我们只设置每个通道的R因子,当输入值为白色时,输入R等于1,方程式为
/*R G B A 1 */
? 0 0 0 r2 // R = ?*1 + r2 = r1
? 0 0 0 g2 // G = ?*1 + g2 = g1
? 0 0 0 b2 // B = ?*1 + b2 = b1
0 0 0 1 0 // A = 1*A
简单代数告诉您,为了使这些方程有效,您需要用colour1和colour2值之间的差异替换问号:
/* R G B A 1 */
(r1-r2) 0 0 0 r2 // R = (r1-r2)*1 + r2 = r1
(g1-g2) 0 0 0 g2 // G = (g1-g2)*1 + g2 = g1
(b1-b2) 0 0 0 b2 // B = (b1-b2)*1 + b2 = b1
0 0 0 1 0 // A = 1*A
例如,如果您希望输入图像的白色区域映射到青色(r = 0,g = 1,b = 1)并且您的黑色输入区域映射到深紫色(r = 0.1,g = 0,b = 0.2),你会使用像
这样的矩阵 /*R G B A 1 */
-0.1 0 0 0 0.1 // R = (-0.1)*R + 0.1
1 0 0 0 0 // G = 1*R + 0
0.8 0 0 0 0.2 // B = 0.8*R + 0.2
0 0 0 1 0 // A = 1*A
Using that matrix in a filter已应用于this original image。
请注意,这实际上与我在评论中链接的示例完全不同;在那个过滤器中,我试图保持白色为白色,黑色为黑色,但将灰色改为颜色。为此我使用了伽马校正滤镜,而不是颜色矩阵。