resvg icon indicating copy to clipboard operation
resvg copied to clipboard

Low image quality when downscaling

Open dleisner opened this issue 1 year ago • 10 comments

The use case is a PNG image which is base64-encoded and embedded in the SVG in an <image> tag. In the attached example, the original image is 160x160, and scaled down to 49x49 in the SVG markup. emoji-49px-base64

The rendered image (resvg-rendered-49px.png) quality is degraded, especially on the curves. resvg-rendered-49px

When defining the dimensions as 160x160 in the SVG markup, the rendered image (resvg-rendered-160px.png) quality is great. And when including that image on an HTML page and re-scaling in the HTML markup, <img src="resvg-rendered-160px.png" width="49" height="49">, the image quality remains crisp. resvg-rendered-160px

We also tried setting the image-rendering attribute for OptimizeQuality, but the improvement was negligible. https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/image-rendering

Is is correct that Bicubic interpolation is being used? Do you have any guidance for improving image quality, and/or are there plans for other interpolation options?

Processing this same image with various interpolation filters in ImageSharp (e.g. Lanczos, MitchellNetravali, etc.) does produce a high quality result.

dleisner avatar Aug 10 '23 23:08 dleisner

resvg does use bicubic scaling, but I guess something goes wrong. Will see.

RazrFalcon avatar Aug 11 '23 10:08 RazrFalcon

Also ran into this issue. The SVG below has an embedded PNG in 1024 * 1024 size, which looks really aliased when rendered at 100 * 100 size.

SVG

instagram

resvg output

instagram

Chromium output

Screenshot 2023-08-24 at 4 35 31 pm

romanzes avatar Aug 24 '23 06:08 romanzes

I also tried explicitly passing FilterQuality::Bicubic here, but the result was the same. Could it be a problem with tiny-skia then?

romanzes avatar Aug 24 '23 06:08 romanzes

@romanzes It most definitely is.

RazrFalcon avatar Aug 24 '23 14:08 RazrFalcon

Any updates on this issue?

incetarik avatar Sep 28 '23 18:09 incetarik

It will be done when it will be done.

RazrFalcon avatar Sep 29 '23 03:09 RazrFalcon

modify the pipeline in tiny-skia to slightly expand the sparsity of the neighboring 4x4 for bicubic, then average them. This might yield some improvement.

ZhouXiaolin avatar Nov 23 '23 01:11 ZhouXiaolin

I don't think this is the case. It works fine in Skia, meaning the bug is somewhere else.

RazrFalcon avatar Nov 23 '23 09:11 RazrFalcon

I don't think this is the case. It works fine in Skia, meaning the bug is somewhere else.

Actually, Skia has the same problem, embedded rasters look aliased when downscaled. I was able to fix it in my fork of Skia by changing this line to:

ctx.canvas()->drawImageRect(
            imgInfo.fImage, imgInfo.fDst, SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear));

However, as far as I understand, tiny-skia doesn't support mipmapping, so this workaround wouldn't help here.

romanzes avatar Nov 23 '23 09:11 romanzes

@romanzes That's surprising. I will double check later. If Skia fails in the same way as tiny-skia then there is nothing we can do, sort of. We would have to find a workaround.

And no, tiny-skia doesn't support mipmapping. Afaik it was a lot of work to implement and Skia uses some sort of shared cashing for them. Too much complexity for now.

RazrFalcon avatar Nov 23 '23 10:11 RazrFalcon