Gradients, blurs and other filters producing smooth color transitions often result in visible banding in RGBA8888, due to the limited precision of the format. But some parts of the internal resvg pipeline appear to compound these issues with repeated rounding. I've compiled a small torture test that demonstrates the issue and included it below. I have also submitted PRs for resvg and tiny-skia that introduce an optional 16bpc pipeline that largely eliminates the issue:
I realise that formats other than RGBA8888 are explicitly out of scope for tiny-skia, and the sheer size and AI-assisted origin of these PRs may make them seem like a hostile act! But I have tried to remain respectful of the design goals and performance of the existing 8bpc pipeline, and keep the binary as clean and performant as possible when the 16bpc pipeline is disabled.
This was mostly an itch I wanted to scratch, since there are currently very few tools to render a SVG file with end-to-end 16bpc precision so that RGBA8888 banding can be minimised via dithering. I'm not here to argue that the project scope should be changed to include it!
(all images below are designed to be viewed full size at native 1:1 resolution)
Torture test SVG (will be rendered by your browser's SVG engine):
Torture test SVG rendered with resvg 8pbc pipeline:
Torture test SVG rendered with resvg 16pbc pipeline and truncated to 8bpc - still has inherent RGBA8888 banding, but removes the compounded internal rounding:
Torture test SVG rendered with resvg 16pbc pipeline and dithered to 8bpc, which trades RGBA8888 banding for dithering noise (which may be exacerbated if displayed at sizes other than 1:1):

Gradients, blurs and other filters producing smooth color transitions often result in visible banding in RGBA8888, due to the limited precision of the format. But some parts of the internal resvg pipeline appear to compound these issues with repeated rounding. I've compiled a small torture test that demonstrates the issue and included it below. I have also submitted PRs for resvg and tiny-skia that introduce an optional 16bpc pipeline that largely eliminates the issue:
I realise that formats other than RGBA8888 are explicitly out of scope for tiny-skia, and the sheer size and AI-assisted origin of these PRs may make them seem like a hostile act! But I have tried to remain respectful of the design goals and performance of the existing 8bpc pipeline, and keep the binary as clean and performant as possible when the 16bpc pipeline is disabled.
This was mostly an itch I wanted to scratch, since there are currently very few tools to render a SVG file with end-to-end 16bpc precision so that RGBA8888 banding can be minimised via dithering. I'm not here to argue that the project scope should be changed to include it!
(all images below are designed to be viewed full size at native 1:1 resolution)
Torture test SVG (will be rendered by your browser's SVG engine):
Torture test SVG rendered with resvg 8pbc pipeline:
Torture test SVG rendered with resvg 16pbc pipeline and truncated to 8bpc - still has inherent RGBA8888 banding, but removes the compounded internal rounding:
Torture test SVG rendered with resvg 16pbc pipeline and dithered to 8bpc, which trades RGBA8888 banding for dithering noise (which may be exacerbated if displayed at sizes other than 1:1):