Question

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?

Was it helpful?

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.

OTHER TIPS

Whilst my answer repeats the same idea, what I have to add is too much for a comment.

I don't know for sure, what is linearRGB in the standard, but I expect it to be, erm, linear. I.e. white color transformed with (darken-twice)

R | ½ 0 0 0 0
G | 0 ½ 0 0 0
B | 0 0 ½ 0 0
A | 0 0 0 1 0

should result in the same color as rgb(50%, 50%, 50%), shouldn't it?

As well as black color transformed with (ligthen-twice)

R | ½ 0 0 0 ½
G | 0 ½ 0 0 ½
B | 0 0 ½ 0 ½
A | 0 0 0 1 0

expected to be the same 50% gray.

But what I actually see as a result is much lighter than expected, color picker shows #BCBCBC instead of #808080. On the other hand, color-interpolation-filters="sRGB" makes the result correct (checked a macbook and a win10 ASUS notebook with default settings).

https://jsfiddle.net/7wvy57fq/2/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top