Colorizing grayscale image

2019-05-26 18:36发布

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:

original grayscale http://crawdad.cornell.edu/test/1.png red foreground http://crawdad.cornell.edu/test/2.png red foreground, yellow background http://crawdad.cornell.edu/test/3.png

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).

For those having experience with Adobe Director, the effect I want is the same as Director's color and bgColor properties. (I'm converting a project from Director to html5/javascript.)

3条回答
狗以群分
2楼-- · 2019-05-26 19:07

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"/>

and then use JavaScript to set the 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 tableValues for feFuncR, feFuncG, and feFuncB are "1 1", "0 1", and "0 0", respectively. (Map the rgb range of 0-255 to 0-1.)

Setting 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!

查看更多
3楼-- · 2019-05-26 19:18

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>

The feBlend element has a few more modes that you can try. Also the feComposite and feColorMatrix elements might be of interest to you.

查看更多
倾城 Initia
4楼-- · 2019-05-26 19:20

Maybe you can just pick the nodes and change their properties.

In example:

document.querySelector('#g2161').setAttribute('style','fill:blue');
查看更多
登录 后发表回答