I'd like to show an image and apply a mask on top of that that would make the entire image darker, except for a number of regions that would keep the original content of the image. Something like using a mask with holes in it.
I've been trying a lot of options, but I couldn't make it work. That's the closest I've got:
<image id="image1" xlink:href="image.png" height="100%" width="100%" />
<g if="image1mask" >
<circle id="image1maskhole" cx="160" cy="120" r="80" fill="black" fill-opacity="100%" />
<rect id="image1maskbase" x="0" y="0" width="100%" height="100%" fill="rgb(100, 100, 100)" fill-opacity="30%" comp-op="dst-out"/>
</g>
However, the circle is filled (black) in the mask. I'd like it to be totally transparent. I tried using white instead, but the result is also wrong. I also tried playing with the fill-opacity values, but I couldn't make it work either.
I'm testing on chrome, but I'm going to run it in an embedded browser that doesn't handle masks very well. That's why I'm avoiding this possible solution (that works perfectly on chrome):
<defs>
<mask id="image1mask" >
<rect x="0" y="0" width="100%" height="100%" fill="white" fill-opacity="30%" />
<polygon points="30,30, 80,30, 50,120, 80,210, 30,210" fill="white" />
<circle cx="160" cy="120" r="80" fill="white" />
<rect x="250" y="30" width="50" height="180" fill="white" />
</mask>
</defs>
<image id="image1" xlink:href="image.png" height="100%" width="100%" mask="url(#image1mask)" />
Can anyone help, please?
Thanks very much.
---- Possible solution:
I found a way to do that. It is actually a workaround, and I'm a bit concerned about performance. I'm embedding this into a JavaFX2 application. And unfortunelly it doesn't work very well. The mask will actually be interpreted as a rectangle that encloses all items of mask1 in it. So back to the beginning.
<svg class="svg-graphic" width="320" height="240" >
<defs>
<clipPath id="mask1">
<polygon points="30,30, 80,30, 50,120, 80,210, 30,210" fill="white" />
<circle cx="160" cy="120" r="80" fill="white" />
<rect x="250" y="30" width="50" height="180" fill="white" />
</clipPath>
</defs>
<image id="backimage" xlink:href="image.png" height="100%" width="100%" style="opacity:0.3" />
<image id="imagemask" xlink:href="image.png" height="100%" width="100%" clip-path="url(#mask1)"/>
</svg>
-- Another possible solution: This one works in the embedded browser.
The only drawback is that it uses a lot of "fake" images. One for the background (shaded) and one for each hole in the mask (non shaded parts). Once again, performance may suffer.
<svg class="svg-graphic" width="320" height="240" >
<image id="image1back" xlink:href="image.png" height="100%" width="100%" style="opacity:0.3" />
<g id="mask4" visibility="visible">
<defs>
<clipPath id="mask4def-1"><polygon points="30,30, 80,30, 50,120, 80,210, 30,210" /></clipPath>
<clipPath id="mask4def-2"><circle cx="160" cy="120" r="50" /></clipPath>
<clipPath id="mask4def-3"><rect x="250" y="30" width="50" height="180" /></clipPath>
</defs>
<image xlink:href="image.png" height="100%" width="100%" clip-path="url(#mask4def-1)"/>
<image xlink:href="image.png" height="100%" width="100%" clip-path="url(#mask4def-2)"/>
<image xlink:href="image.png" height="100%" width="100%" clip-path="url(#mask4def-3)"/>
</g>
</svg>
It will result in the same result as the Masking approach I give in above (that won't work in my embedded browser). Does anyone knows whether it is a problematic approach or not? Anyone with better ideas?