Match colors in feColorMatrix filter
To understand the matrix you need, you have to clearly define what you're starting with, what you want to end up with, and how the colour matrix filter works.
The matrix has five columns and four rows. Each row represents one of the output numbers: R,G,B,A. The columns represent your input RGBA and a constant 1. You calculate the output value for each row by adding up each of the values in the row multiplied by the corresponding input value.
Both the input and the output numbers are standardized to the range 0-1, so you don't have to worry about multiplying everything by 256.
So for the matrix in your example:
/*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
It takes the input color, adds up all four channels (RGBA) and makes the result the green channel. The red and blue channels are zero and the alpha channel isn't changed. So your picture ends up with black areas still black, but all coloured/gray/white/transparent areas are converted into shades of green.
That's not what you wanted, of course. You wanted to have black areas one colour and white areas another colour, and all gray areas somewhere in between the two.
To make black areas a certain colour, you have to set the constant-factor parameters of your matrix. The input RGB values are going to be zero for black, so they don't factor in at this point.
If your colour2, the value you want to use for black in your monochrome image, is (r2, g2, b2), then that's what your constant factors have to be:
/*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
Of course, the above matrix will turn any input colour into that output colour, because it doesn't factor in anything from the input RGBA values. To get the gradient you want, you need white areas -- those with input values of 1 for R, G, and B, to end up with your colour1, which I'm going to write as (r1, g1, b1).
Now, to make things a little easier, remember that for a grayscale image the R, G and B values for any point will be equal. So we can just use any one of those values as the input and ignore the others. So if we just set the R-factor for each channel, when the input value is white the input R equals 1 and the equations are
/*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
Simple algebra tells you that in order to make those equations work, you need to replace the question marks with the difference between the colour1 and colour2 values:
/* 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
For example, if you want white areas of the input image to map to cyan (r=0,g=1,b=1) and your black input areas to map to a deep purple (r=0.1, g=0, b=0.2), you would use a matrix like
/*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
Using that matrix in a filter applied to this original image.
Note that this is actually quite different from the example I linked to in a comment; in that filter, I was trying to maintain white as white and black as black, but change the grays to colour. For that I used a gamma correction filter, not a colour matrix.
Matching a color in SVG with feColorMatrix
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>
SVG Filter - feColorMatrix has non-linear color
So, firstly, don't believe everything you read in the specs - especially when they're not
at least a Candidate Recommendation. That filter spec has been worked on for years and many things that are different than the SVG 1.1 spec have not been implemented.
In SVG 1.1 (the current cross browser baseline) - filters operate in the linearRGB space. From the SVG spec (15.1)
(‘color-interpolation-filters’ has an initial value of linearRGB
(187, 187, 187) is what happens when you do 50% in the linearRGB space and then measure the result using an sRGB eye-dropper. In order to over-ride it, you must put color-interpolation-filters="sRGB" in your filter element.
This is a perfectly fine way to convert colors. As Robert mentioned in the comment - you can also use a flood & a composite to do it.
<filter id="flood-recolor">
<feFlood flood-color="grey"/>
<feComposite operator="in" in2="SourceGraphic"/>
</filter>
Consolidate two SVG feColorMatrix filter effects into one matrix?
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 :-)
Related Topics
Is There Any IE8 Only CSS Hack
Center Twitter Bootstrap 3 Glyphicons in Buttons
What Does the Selector [Class^="Span"] Do
Tweaking Bootstrap 2.0 for Semantic Markup
Styling Not Applying to Child Component
iOS CSS Opacity + Visibility Transition
How to Apply My CSS Stylesheet to an Rss Feed
Set Dot Color of 'Text-Overflow: Ellipsis'
Css3 Transformation Blurry Borders
How to Pass !Important as Parameter/Option for Lesscss Mixins
Pixel Density, Retina Display and Font-Size in CSS
Is It Bad Practice to Use Negative Margins or Padding in CSS
How to Remove Letter-Spacing for the Last Letter of an Element in CSS
Change Color of Select Component's Border and Arrow Icon Material Ui
What Is the Current State of Sub-Pixel Accuracy in the Major Browsers
Blur Effect on the Entire Webpage
Responsive Layout - Px, Em, or %
Override Jquery UI Datepicker Div Visible Strangely on First Page Load