Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bleed issue rendering images as patterns, or SVG bug? #794

Closed
jermy opened this issue Jul 22, 2024 · 2 comments
Closed

Bleed issue rendering images as patterns, or SVG bug? #794

jermy opened this issue Jul 22, 2024 · 2 comments

Comments

@jermy
Copy link

jermy commented Jul 22, 2024

I've been trying to chase down a rendering quality issue with some example SVG content, where an embedded PNG would exhibit extra pixels that shouldn't be present.

I've generated a test file using the same SVG structure as that file:

<svg width="122" height="190" viewBox="0 0 300 300" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="50" y="0" width="200" height="124" fill="url(#patternId)"/>
<defs>
<pattern id="patternId" patternContentUnits="objectBoundingBox" width="1" height="1">
<use href="#imageId" transform="matrix(0.0033 0 0 0.005 0 0)"/>
</pattern>
<image id="imageId" width="300" height="200" href="data:image/png;base64,
iVBORw0KGgoAAAANSUhEUgAAASwAAADICAYAAABS39xVAAABhGlDQ1BJQ0MgcHJvZmlsZQAAKJF9
kT1Iw0AcxV9TpSItDi0i4pChOtmlijjWKhShQqgVWnUwufQLmrQkKS6OgmvBwY/FqoOLs64OroIg
+AHi7OCk6CIl/i8ptIjx4Lgf7+497t4BQqvKNLMvAWi6ZWRSSTGXXxUDrwhgGCGEEZeZWZ+TpDQ8
x9c9fHy9i/Es73N/jpBaMBngE4kTrG5YxBvEM5tWnfM+cYSVZZX4nHjSoAsSP3JdcfmNc8lhgWdG
jGxmnjhCLJZ6WOlhVjY04mniqKrplC/kXFY5b3HWqg3WuSd/YbCgryxzneYYUljEEiSIUNBABVVY
iNGqk2IiQ/tJD/+o45fIpZCrAkaOBdSgQXb84H/wu1uzOBV3k4JJoP/Ftj/GgcAu0G7a9vexbbdP
AP8zcKV3/bUWMPtJerOrRY+AoW3g4rqrKXvA5Q4w8lSXDdmR/DSFYhF4P6NvygPhW2Bwze2ts4/T
ByBLXaVvgINDYKJE2ese7x7o7e3fM53+fgCy9HLADSd0zAAAAAZiS0dEAP8A/wD/oL2nkwAAAAlw
SFlzAAAuIwAALiMBeKU/dgAAAAd0SU1FB+gHFg0eJ4gC/vsAAAAZdEVYdENvbW1lbnQAQ3JlYXRl
ZCB3aXRoIEdJTVBXgQ4XAAACNUlEQVR42u3WwQkDAQwDQTn996xUENBxec6UIMziC7MmtcLmkrPC
eFd1V6uPCQDBAhAsQLAABAtAsADBAhAsAMECBAtAsAAECxAsAMECECxAsAAEC0CwAMECECwAwQIE
C0CwAAQLECwAwQIQLECwAAQLECwAwQIQLECwAAQLQLAAwQIQLADBAgQLQLAABAsQLADBAhAsQLAA
BAtAsADBAhAsgF8uac0wz3U22LTuar8qd+XDAgQLQLAABAsQLADBAhAsQLAABAtAsADBAhAsAMEC
BAtAsADBAhAsAMECBAtAsAAECxAsAMECECxAsAAEC0CwAMECECwAwQIEC0CwAAQLECwAwQIQLECw
AAQLQLAAwQIQLADBAgQLQLAAwQIQLADBAgQLQLAAXjsTPFITuK3/X1XdlQ8LECwAwQIQLECwAAQL
QLAAwQIQLADBAgQLQLAABAsQLADBAgQLQLAABAsQLADBAhAsQLAABAtAsADBAhAsAMECBAtAsAAE
CxAsAMECECxAsAAEC0CwAMECECwAwQIEC0CwAAQLECwAwQIEC0CwAAQLECwAwQJ469LUDPNaZ4RN
U3e1n5W78mEBggUgWACCBQgWgGABCBYgWACCBSBYgGABCBaAYAGCBSBYgGABCBaAYAGCBSBYAIIF
CBaAYAEIFiBYAIIFIFiAYAEIFoBgAYIFIFgAggUIFoBgAQgWIFgAggUgWIBgAQgWgGABggUgWIBg
AQgWgGABggUgWABvfQF4KRWHEshN6gAAAABJRU5ErkJggg=="/>
</defs>
</svg>

where I wasn't expecting a pixel of the colour on the top/left sides of the image repeated on the bottom/right.
image
(resvg render to PNG then scaled 2x in feh)

I'd assumed I'd broken sampling in relation to a mipmap implementation in tiny-skia I'd added, so was surprised to find it wasn't related to that change at all. I can obviously fix this one render in resvg code, with something like:

--- a/source/crates/resvg/src/path.rs
+++ b/source/crates/resvg/src/path.rs
@@ -61,7 +61,7 @@ pub fn fill_path(
             pattern_pixmap = patt_pix;
             paint.shader = tiny_skia::Pattern::new(
                 pattern_pixmap.as_ref(),
-                tiny_skia::SpreadMode::Repeat,
+                tiny_skia::SpreadMode::Pad,
                 tiny_skia::FilterQuality::Bicubic,
                 fill.opacity().get(),
                 patt_ts,

but patterns are meant to repeat normally, so unless I disable that only for patterns-that-are-actually-images it's clearly not the right answer. The sizes aren't completely arbitrary - the issue will only occur at certain scales, suggesting a rounding/sampling issue depending on if you're lucky or not.

This graphic also fails to render in Firefox and Chromium, so is this actually a bug/feature of SVGs where the use of objectBoundingBox and width/height doesn't actually mean it'll only ever fill that space and sometimes repeated pixels will be visible?

@RazrFalcon
Copy link
Collaborator

Yes, I'm seeing a similar behavior in Chrome and Safari, which suggests that it's perfectly normal.

Also, SVG isn't designed for "precise" rendering. Every library renders it in whatever way it wants.
Moreover, resvg/tiny-skia do not support fractional pattern offsets (#628), which might be one of the reasons for this behavior.

@jermy
Copy link
Author

jermy commented Jul 22, 2024

Thanks, that makes sense. I might see if there's a straightforward way to clamp the sampling for my use-case - perhaps not quite full subpixel offset handling - and otherwise encourage users not to generate graphics like this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants