SVG opacity mask resolution and scaling - html

I'm trying to reduce the download size of transparent PNGs by decomposing them into color and alpha images. This approach works fine, for my customer's images the size is reduced by over 50%.
To recompose the images I'm experimenting with both SVG and canvas.
The SVG solution uses an opacity mask, and the canvas uses the globalCompositeOperation.
The problem is, the SVG incorrectly shows dark edges when down-scaling (either by specifying the size in CSS or directly on the SVG). These dark edges do not appear when rendering the SVG at the same size of the input images. The canvas works fine. This happens in all browsers I tested (Chrome, IE11, Firefox)
The problem I believe, is that the SVG will independently resize the alpha-image and color-image, and then apply the opacity mask. However this approach does not work. In image processing it is well known that to resize a transparent image, one either has to pre-multiply the color components by the alpha, and then use a standard resizing algorithm, or one has to perform a weighted average (since mostly transparent pixels have less impact on the final color). See for example this discussion
When applying SVG filter effects, one could initially tweak the intermediate resolution that is used, but I can't figure out how to do this when using the SVG mask property (Robert Longson correctly pointed out to me that the filter effects do not support this anymore, since the filterRes attribute was deprecated)
Here's the SVG code (our run it directly from my website in any HTML5 compliant browser)
<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='1000' height='454' viewBox='0 0 2560 1162'>
<defs>
<mask id='mask'>
<image color-interpolation='sRGB' image-rendering='optimizeQuality' width='2560px' height='1162px' xlink:href='first-A.png'></image>
</mask>
</defs>
<image color-interpolation='sRGB' image-rendering='optimizeQuality' mask='url(#mask)' width='2560px' height='1162px' xlink:href='first-RGB.png'></image>
</svg>
Does anyone know how to tweak the SVG mask effect so that these edge artifacts do not appear?
Thanks a lot,
Peter

Related

Rendering upscaled SVG with vector-effect: non-scaling-stroke on JS canvas in chrome results in border being too thick

I am trying to render a small SVG (width="3.0202789" height="2.5201435") on a canvas.
SVG file was created by importing some CAD render result into Inkscape, removing all unnecessary parts and clipping to the content so it contains weird transforms.
All paths have stroke-width of 1px and vector-effect set to non-scaling-stroke. As far as I understand SVG specs that shuould instruct the renderer to always keep stroke width at 1px in screen space units no matter of scale.
SVG is loaded into an element then the the element's width and height are set to some sensible values.
It renders as intended in Firefox and using Node Canvas though in Chrome it looks like the ctx.drawImage method completely ignores the vector-effect="non-scaling-stroke" instruction and computes stroke-width in viewbox units. The upscaled element is rendered as intended though:
Rendering results:
Firefox rendering (img on the left, canvas on the right)
Chrome rendering (img on the left, canvas on the right)
JSFiddle with a minimal example: https://jsfiddle.net/ucojz62n/
Chrome version used: Chromium 108.0.5359.124 (though the issue has been around for more than two years)
Firefox version used: 108.0 (though it worked great 2+ years ago as well)

Very large SVG rendered blurry in Firefox

I'm trying to render a very large SVG image inside an img tag.
This works fine in Chrome, but Firefox (both Windows and Linux) renders the image blurry as if it was a raster image with much lower resolution.
The problem can be broken down to a simple example:
SVG image with a view box of 30,000x30,000, showing a diagonal line
The SVG is displayed in an img tag that has a width and height of 30,000px each
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30000 30000'%3E%3Cpath d='M 0,0 L30000,30000' stroke-width='1' stroke='%23000' /%3E%3C/svg%3E" width="30000" height="30000" />
This renders as follows (cropped but not scaled):
What I already tried unsuccessfully:
different view box sizes
smaller img dimensions but scaled up with CSS transforms (2D/3D)
image-rendering: crisp-edges on the img
shape-rendering: crispEdges on the SVG content
Using an <object> instead of an <img> actually renders the image crisp, but the <object> element comes with its own shortcomings and pitfalls. If possible I'd like to keep using the <img> element.
Does anybody have hints what might be the problem or ideas for possible solutions?

How can I avoid overlapping stroks cancelling each other? (Defect?)

I have the following SVG in an HTML page.
<svg preserveAspectRatio='none' xmlns='http://www.w3.org/2000/svg' viewBox="0 0 1 1">
<circle class='spath' cx="0.5" cy="0.5" r="0.02" stroke="green" stroke-width="0.08" fill="none"/>
</svg>
The stroke-width is more than enough to cover the entire width of the circle. Instead of a solid circle though I get the following rendering:
Wherever the stroke overlaps itself from the other side it gets cancelled -- it draws nothing on the overlapping parts.
Is there some CSS/SVG setting to avoid this, or is it a Firefox rendering defect? (On Linux)
For reference, here is a stroke-width="0.05", which should not be filling less of the circle (like 0.08, it should completely fill it).
And this is 0.4, the size required to fill the circle. Since it lacks any overlap it appears to draw correctly.
Note: I'm unable to workaround the problem by calculating the exact size required. This is just a reduced example with a simple path. My full SVG has many curves and different points of overlap.

Base64 svg on ie11 not rendering when resized

I have a particular svg file encoded in base64 that I'm trying to display with an img tag.
My problem is; for this particular svg only the image is not rendered when resized on internet explorer only
You can try it yourself (I'm on windows7 with ie11): CodePen
Do you have any explanation/workaround for this ?
Best regards
If you look very close when playing with the size, we can see parts of the SVG are actually displayed. It seems that IE resizes the canvas but not the actual shape.
Decoding your SVG file, here is what we get:
<svg height="361.5" width="361.5" xmlns="http://www.w3.org/2000/svg"><path d="m-110.25-20.25h582v402h-582z" fill="none"/>...</svg>
The height and width are fixed. Changing these properties with a viewBox property like this allows IE to resize the shape:
<svg viewBox="0 0 361.5 361.5" xmlns="http://www.w3.org/2000/svg"><path d="m-110.25-20.25h582v402h-582z" fill="none"/>...</svg>
Kind regards!

SVG 1px Sliver Showing Randomly

Designing a site and having an issue with an inline SVG graphic. On the homepage , the big red angled block that sits behind the text for the event slide seems to have a 1pm thin sliver to the left of it. The area that would normally be an edge if it was a full on square.
This appears on mobile phones (as it's responsive), and also in browser windows when resizing smaller to simulate a mobile width. All attempts by me and my people to resolve this strange issue haven't worked yet. Can anyone lend a hand?
Link
It's an artifact of rounding the size of the image to an integer number of pixels, and it's coming from the following element in the SVG
<use xmlns="http://www.w3.org/2000/svg" fill="#7F0000"
sketch:type="MSShapeGroup"
xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"
xlink:href="#path-1" xmlns:xlink="http://www.w3.org/1999/xlink"/>
I'm not familiar enough with Sketch's SVG export to say how to eliminate it.