I'm trying to colorize grayscale images on the fly with user-selected foreground and background colors (limited to red, green, blue, cyan, magenta, yellow, black, and white). The effect I want is as follows:
From left to right, these show the original grayscale image, that image where the user selected red as background color, and the same image with red background/yellow foreground.
Redrawing the images in a canvas every time the user selects a color is not practical (images will be 800x800px and I need to create 30 frames for animation).
I am only targeting the most recent version of WebKit, Firefox, and Internet Explorer, so html5, css3, and svg effects are fine. Images can be straight html
<img> tag or can be
<image> within an
<svg> tag (the latter is actually preferable).
An ideal solution might involve svg filters (which I have no experience with, can they do this?). Another possibility might treat my grayscale image as an alpha channel with a solid color above it and a solid color below it (not sure how I'd do that on the fly).
Welcome to the wonderful world of SVG filter effects, where anything's possible but it takes forever to figure it out. Below is an example of how to do what you want with red and blue. The blending might not be exactly what you're looking for, and you might benefit from adding some transparency to the color.
<svg> <defs> <filter x="0%" y="0%" width="100%" height="100%" id="mk"> <feImage xlink:href="http://crawdad.cornell.edu/test/1.png" result="img"/> <feBlend in="img" in2="SourceGraphic" mode="multiply"> </feBlend> </filter> </defs> <rect width="100" height="100" fill="red" filter="url(#mk)" /> <rect x="110" width="100" height="100" fill="blue" filter="url(#mk)" /> </svg>
OK, I have a solution using SVG filters.
<defs> <filter id="colorize"> <feComponentTransfer color-interpolation-filters="sRGB"> <feFuncR id="fR" type="table" tableValues="0 1"/> <feFuncG id="fG" type="table" tableValues="0 1"/> <feFuncB id="fB" type="table" tableValues="0 1"/> </feComponentTransfer> </filter> </defs> <image filter="url(#colorize)" x="0" y="0" width="100" height="100" xlink:href="urlOfGrayscaleImage"/>
tableValues (to simplify that, I gave
feFuncR et al
ids) as follows. The first number in each
tableValues is the value that should replace black in the image, the second number is the value that should replace white. Thus to change black/white to red/yellow, the
feFuncB are "1 1", "0 1", and "0 0", respectively. (Map the rgb range of 0-255 to 0-1.)
color-interpolation-filters="sRGB" is critical. I was going nuts trying to work this out yesterday before someone else pointed it out to me.
Note: As of 12/27/12, Safari ignores
color-interpolation-filters="sRGB", while Chrome and Firefox use it. I hope Safari releases a version using a more recent WebKit; this isn't the only lingering SVG bug in Safari that has long since been fixed in Chrome.
I hope this is useful to someone!
Maybe you can just pick the nodes and change their properties.
©2020 All rights reserved.