csssvgvector-graphicscolormatrixsvg-filters

Matching a color in SVG with feColorMatrix


I created a drop shadow in SVG using SourceAlpha for the shadow, so its plain black. Using feColorMatrix I reduced the opacity a bit, but still it wasn't looking as I wanted - I want the color of the shadow to match a specific color value. So I took a more in depth look at feColorMatrix.

Now I don't use SourceAlpha as source for the shadow, but SourceGraphic. As my vector image is plain white aka rgba(255, 255, 255, 1), I can calculate the color of the shadow like that:

<feColorMatrix in="the-shadow" result="color-out" type="matrix"
                values="0.0157 0      0      0 0
                        0      0.3059 0      0 0 
                        0      0      0.7765 0 0 
                        0      0      0      1 0  "/>

The outcome should be a dark blue shadow aka rgba(4, 78, 198, 1).

Actually this is working and I believe the calculations are all correct, but when creating a shadow with CSS3 using the same color, there is a noticeable difference: The SVG filter seems to render the color a bit too light. Is there any way to fix that?


Solution

  • feColorMatrix like most filters operates in the linearRGB colour space. If you want an sRGB colour, Try setting color-interpolation-filters="sRGB" as an attribute on the feColorMatrix.

        <svg width="100%" xmlns:xlink="http://www.w3.org/1999/xlink"
        
        viewBox="0 0 640 480" height="100%"
        xmlns="http://www.w3.org/2000/svg">
        
        <filter id="cm">
        
        <feColorMatrix in="SourceGraphic" type="matrix"
                        values="0.0157 0      0      0 0
                                0      0.3059 0      0 0 
                                0      0      0.7765 0 0 
                                0      0      0      1 0  "/>
        
        </filter>
        
        <filter id="cmRGB">
        
        <feColorMatrix color-interpolation-filters="sRGB" in="SourceGraphic" type="matrix"
                        values="0.0157 0      0      0 0
                                0      0.3059 0      0 0 
                                0      0      0.7765 0 0 
                                0      0      0      1 0  "/>
        
        </filter>
        
        <rect width="100%" height="50%" fill="white" filter="url(#cm)"/>
        
        <rect y="50%" width="100%" height="100%" fill="white" filter="url(#cmRGB)"/>
        
        </svg>

    It sure looks different to me on Firefox.