Question

I'm using an SVG filter to create a blurred "dropshadow" type effect on some complex paths.

<defs>
    <filter id="dropshadow" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
        <feColorMatrix result="hueOut" in="SourceAlpha" type="hueRotate" values="340"/>
        <feColorMatrix result="satOut" in="hueOut" type="saturate" values="3"/>
        <feGaussianBlur in="satOut" stdDeviation="8"/> 
        <feMerge> 
           <feMergeNode/>
           <feMergeNode in="SourceGraphic"/> 
        </feMerge>
    </filter>
</defs>

I arrived at the above feColorMatrix values purely through trial and error. (There is a peculiarly beautiful hue shift from dark to light that I never would have come up with if I were working with the matrix math alone.) Basically, I'm spinning the color wheel 340 degrees, and then I'm saturating the color using a value of 3, just before blurring it. (The spec used to be somewhat unclear on this, but trial and error has shown that values over 1 for type="saturate" saturate the image and values below 1 desaturate the image.)

Here's the problem: I'm iterating over a massive quantity of paths, and the double matrix operation slows my machine to a halt. It crashes way too often.

Can some matrix math guru help me work out the number for me to combine the two feColorMatrix filters above into one more efficient feColorMatrix filter primitive of type="matrix"? I get the gist of the spec, but I'm in over my head here on the math side of things.

Was it helpful?

Solution

In my experience ColorMatrix operations are very fast, and blurs are incredibly slow, so I'm guessing that combining these won't get you very far. But FWIW, here's the combined matrix. (This is not hard to do - there are lots of online matrix multipliers:)

2.5537  -0.61224    0.52246 0   0
-0.4163 1.30776 -0.10754    0   0
0.3037  -0.88224    2.3546  0   0
0   0   0   1   0
0   0   0   0   1

Update:

Ok step by step. According to the svg filters spec the matrix equivalent of a saturate is:

| R' |     |0.213+0.787s  0.715-0.715s  0.072-0.072s 0  0 |   | R |
| G' |     |0.213-0.213s  0.715+0.285s  0.072-0.072s 0  0 |   | G |
| B' |  =  |0.213-0.213s  0.715-0.715s  0.072+0.928s 0  0 | * | B |
| A' |     |           0            0             0  1  0 |   | A |
| 1  |     |           0            0             0  0  1 |   | 1 |

So all you have to do is build a little excel table that multiples this out for you.

Then you look at the spec for hue rotate and you find that the matrix equivalent for huerotate is:

| R' |     | a00  a01  a02  0  0 |   | R |
| G' |     | a10  a11  a12  0  0 |   | G |
| B' |  =  | a20  a21  a22  0  0 | * | B |
| A' |     | 0    0    0    1  0 |   | A |
| 1  |     | 0    0    0    0  1 |   | 1 |

where the terms a00, a01, etc. are calculated as follows:

| a00 a01 a02 |    [+0.213 +0.715 +0.072]
| a10 a11 a12 | =  [+0.213 +0.715 +0.072] +
| a20 a21 a22 |    [+0.213 +0.715 +0.072]
                        [+0.787 -0.715 -0.072]
cos(hueRotate value) *  [-0.213 +0.285 -0.072] +
                        [-0.213 -0.715 +0.928]
                        [-0.213 -0.715+0.928]
sin(hueRotate value) *  [+0.143 +0.140-0.283]
                        [-0.787 +0.715+0.072]

Since radians are expected inputs to Excel trig formulae, you do a degree to radian conversion (340deg is about 5.9 radians - or just less than 2* pi) and then build the resulting matrix in Excel. You could hand multiply the matrices, but frankly I don't have a huge desire to relive linear algebra class. So you google "matrix multiply online" and pop the two matrices into any of the matrix multiply tools on page 1 of results. And there you go. A consolidated matrix.

Easy :-)

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