2

I am trying to create an SVG where black or white squares are overlayed on an image using various blend modes. I'm using a filter with an feImage primitive for the picture, making it partially transparent with feColorMatrix, and blending it with the square with feBlend. The normal blend mode works as I would expect it to, but multiply does not. Here's what I'm getting:

enter image description here

Here's a jsfiddle with the svg code

For multiplying with white (bottom-middle square), I expected it not to lighten the image at all, regardless of opacity, since multiplying with white is basically like multiplying by 1. For black (middle-top square), I expect it to darken the image according to its transparency. These are the things that happen when I play around in GIMP.

The SVG spec has the formulae for various blend modes here, if you're wondering (I can't post more than 2 links with my current reputation, sorry). www.w3.org/TR/SVG/filters.html#feBlendElement

What I think the problem is:

In my filter, I'm actually applying opacity to the feImage, not the SourceGraphic, simply because I couldn't figure out how to do it the other way around, despite much experimentation. Ideally it would be the squares that were partially transparent, and were then overlayed on the image. Setting in="SourceGraphic" for the feColorMatrix doesn't work right, nor does setting the opacity attribute on the rects themselves (they seem to blend with the default white svg background before blending with the image). I'm sure there's some simple solution, but I just can't find it.

Please tell me if anything's unclear. Any assistance is appreciated :)

2 Answers 2

1

For the love of god, add explicit ins and results to your filters. Otherwise it's like trying to push spaghetti. This is what you're looking to do:

    <filter color-interpolation-filters="sRGB" x="-1.0" y="-1.0" width="3.0"
        xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple"
        xlink:actuate="onLoad" height="3.0" 
        xlink:show="other" id="blend-square-multiply">
        <feImage result="raw photo" x="0" y="0" width="522" height="530"
                 xlink:href="http://wallpapersus.com/wallpapers/2012/11/Pirates-Of-The-Caribbean-On-Stranger-Tides-05-2048x2048.jpg"/>
        <feComposite result="photo clip" in="raw photo" in2="SourceGraphic" operator="in"/>
        <feColorMatrix in="SourceGraphic" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 .5 0" type="matrix" result="color-trans"/>
        <feBlend mode="multiply" in="photo clip" in2="color-trans"/>
    </filter>

Fiddle with some edits to make it clear what I was editing: http://jsfiddle.net/Wu96x/

2
  • Whoops, didn't mean to hit enter, here's my actual comment: Thank you, this works for multiplication. However, this filter structure doesn't work for normal blending modes (and I really can't fathom why). For my project I need to be able to swap between "normal" and "multiply" just by switching the "mode" attribute. I changed the fiddle to illustrate: jsfiddle.net/mugwhump/ysXDR/6 It just shows the image and doesn't blend it with the black/white squares. Any ideas?
    – mugwhump
    Commented Aug 13, 2013 at 22:23
  • Blending order matters in "normal" blending (which really isn't blending at all, it's just a simple overlay). You have a semi-opaque color square overlaid with a fully opaque image -> result, the fully opaque image. So just flip the in and the in2, and you're good. Commented Aug 14, 2013 at 21:36
0

Isn't it just appearing lightened because you are placing a partially transparent image over a white background? As you say, the multiply-by-white will be having no effect.

Not the answer you're looking for? Browse other questions tagged or ask your own question.