如何在linearRGB颜色空间中计算feComponentTransfer离散函数中的步长

时间:2018-06-20 15:36:05

标签: svg-filters

我正在尝试使用feComponentTransfer函数创建离散梯度:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg x="0" y="0" width="500px" height="120px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
   <title>A discrete gradient</title> 
   <defs>
    <linearGradient id="inputImage" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%">
       <stop offset="0" stop-color="black"/>
       <stop offset="1" stop-color="white"/>
    </linearGradient>
    <filter id="discrete" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%" color-interpolation-filters="linearRGB">     
       <feComponentTransfer>
          <feFuncR type="discrete" tableValues=".666667 .6      .533333 .466667 .4      .333333 .266667 .2      .133333 .066667"/>
          <feFuncG type="discrete" tableValues=".666667 .6      .533333 .466667 .4      .333333 .266667 .2      .133333 .066667"/>
          <feFuncB type="discrete" tableValues=".933333 .866667 .8      .733333 .666667 .6      .533333 .466667 .4      .333333"/>      
       </feComponentTransfer>       
    </filter>   
   </defs>
   <rect x="10px" y="10px" width="480px" height="100px" fill="url(#inputImage)" filter="url(#discrete)"/>
</svg>
  1. 我希望看到这些颜色:#AAAAEE,#9999DD,#8888CC,#7777BB,#6666AA,#555599,#444488,#333377,#222266,#111155,但显示的是Firefox *这些:#D5D5F7,#CBCBEF,#C1C1E7,#B6B6DE,#AAAAD5,#9C9CCB,#8D8DC1,#7C7CB6,#6666AA,#49499C,它们给出了类似的混合效果,但音调更亮一些。我知道该滤镜的工作是调整亮度,对比度等。但是,我不了解这种情况下滤镜的工作原理。因此,这里的问题是我应该如何计算tableValues中的步骤-在linearRGB颜色空间内-以便准确显示我想要的颜色。

  2. 我注意到,大多数显示(输出)颜色的分量值都完全映射到给定范围之外,我想知道-如果我错了,请更正我-这与规范。

  3. 由于我不了解这些功能如何在linearRGB色彩空间中工作,因此我决定手动获取所需的颜色。我尝试了随机值,并经过数千次尝试,终于找到了前6种所需颜色(#AAAAEE,#9999DD,#8888CC,#7777BB,#6666AA,#555599)和第九种颜色(#222266)的步骤。对于所需的第七种颜色(#444488,R:68 | 0.266667,G:68 | 0.266667,B:136 | 0.533333),我很容易找到feFuncB步骤,但找不到红色和绿色函数的值来精确输出68 |。 0.266667。因此,最接近所需的#444488为我提供的红色和绿色值为0.058823,它输出的是附近的#454588。我也遇到了同样的问题,即所需的第8种(#333377)和第10种(#111155)颜色,我可以实现的最接近输出分别为#353577和#0D0D55。 这是以一种输出(几乎)我想要的所有颜色的方式编写的tableValues *:

  <feFuncR type="discrete" tableValues=".4    .317647 .247058 .184313 .133333 .09     .058823 .0353   .015686 .0039"/>
  <feFuncG type="discrete" tableValues=".4    .317647 .247058 .184313 .133333 .09     .058823 .0353   .015686 .0039"/>
  <feFuncB type="discrete" tableValues=".8588 .721568 .603921 .498039 .4      .317647 .247    .184313 .13333  .09"/>

现在,我重复一个问题:是否有一种简便的方法(数学类型,乘数或其他方法)用于显示指定的颜色,而不会浪费时间测试随机小数?

  • 结果来自于Ubuntu 16.4 64位Gnome上的Firefox 60.0.2,使用Gpick工具进行了检查,并且您已经知道,该结果不同于同一操作系统或其他OS上的其他渲染引擎。目前,我只对它的工作方式感兴趣,或者更好的是对它的工作方式感兴趣。

预先感谢

Spyros Andredakis

1 个答案:

答案 0 :(得分:0)

在我回答之前,您需要非常注意滴管告诉您的颜色值。如果要在标准sRGB或linearRGB空间中获得特定颜色,请确保将吸管设置为该空间。

也就是说,如果要在linearRGB中进行转换,但是要在sRGB中获得特定颜色作为结果,则需要以linearRGB术语指定等效的目标sRGB颜色。您可以使用伽玛校正公式来完成此操作。

例如,如果您希望渐变中的第一个颜色是sRGB中的#AAAAEE,则必须对数组输入进行以下校正(十进制):

linearRGB中的颜色=((sRGB + 0.055中的颜色)/1.055)^ 2.4

例如,您的组件传输数组中的第一个R / G / B值应为

R:0.402 =((.6667 + 0.055)/1.055)^ 2.4

G:0.402 =((.6667 + 0.055)/1.055)^ 2.4

B:0.855 =((.9333 + 0.055)/1.055)^ 2.4

此公式通常不能精确到100%-当sRGB单位值小于0.04045(L = S / 12.92)时,您需要使用其他公式。但是您所有的目标值都高于0.04,因此我们无需担心。

完整结果:

    <svg x="0" y="0" width="500px" height="120px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
       <title>A discrete gradient</title> 
       <defs>
        <linearGradient id="inputImage" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%">
           <stop offset="0" stop-color="black"/>
           <stop offset="1" stop-color="white"/>
        </linearGradient>

        <filter id="discrete" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%">        
       <feComponentTransfer>
          <feFuncR type="discrete" tableValues="0.4020	0.3185	0.2462	0.1845	0.1329	0.0908	0.0578	0.0331	0.0160	0.0056"/>
          <feFuncG type="discrete" tableValues="0.4020	0.3185	0.2462	0.1845	0.1329	0.0908	0.0578	0.0331	0.0160	0.0056"/>
          <feFuncB type="discrete" tableValues="0.8550	0.7231	0.6038	0.4969	0.4020	0.3185	0.2462	0.1845	0.1329	0.0908"/>        
       </feComponentTransfer>     
           </feComponentTransfer>      
        </filter>   
       </defs>
       <rect x="10px" y="10px" width="480px" height="100px" fill="url(#inputImage)" filter="url(#discrete)"/>
    </svg>