Css 在feColorMatrix过滤器中匹配颜色

Css 在feColorMatrix过滤器中匹配颜色,css,svg,svg-filters,Css,Svg,Svg Filters,我有一个灰度图像。我想对它进行过滤,以便白色->彩色1和黑色->彩色2。这两种颜色都是十六进制CSS语法。我需要做什么数学才能得到这个效果 我使用以下语法: <!-- just an example --> <filter id="colorMeMatrix"> <feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 0 1 1 1 1 0

我有一个灰度图像。我想对它进行过滤,以便
白色->彩色1
黑色->彩色2
。这两种颜色都是十六进制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" />


要理解您需要的矩阵,您必须清楚地定义开始的内容、结束的内容以及矩阵的工作方式

矩阵有五列四行。每行表示一个输出数字: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值将为零,因此此时不考虑它们

如果单色图像中黑色的颜色2为(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的区域,以你的颜色1结束,我将把它写成(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 
简单代数告诉您,为了使这些方程起作用,您需要用color1和color2值之间的差值替换问号:

      /*   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 
适用于


请注意,这实际上与我在评论中链接的示例大不相同;在那个滤镜里,我试着把白色保持为白色,黑色保持为黑色,但把灰色改为彩色。为此,我使用了伽马校正过滤器,而不是颜色矩阵。

我现在没有时间写出来,但这可能会让你开始:解释得很好!!你可能想在你的过滤器中添加一个color interpolation filters=“sRGB”属性-它为图像提供了更多的自然颜色插值(它是伽马校正的)@MichaelMullany,我还没有尝试过它-它确实有很大的不同,尽管我不知道sRGB版本一定更好。你只需要知道你想要什么,并确保你在正确的颜色空间中计算颜色的RGB值。我已经更新了要比较的颜色。好吧,如果你从灰度开始,那么开始的颜色配置文件是不相关的。但是,如果你想在另一张图片中匹配颜色,那么肯定是这样。如果sRGB规范在跨浏览器中定义得更清晰、更一致,这将是一个有利于它的大论据。@MichaelMullany建议添加
color interpolation filters=“sRGB”
达到了我想要的效果。基本上,我有一个理想的目标颜色(#002A78),下面的过滤器现在将完整的源代码正确地映射到所述目标: