Pixelated images in SVG
- Published
- Last updated
- Revisions
SVG, as its name suggests, is designed for scalable vector graphics.
However, the format also supports raster graphics with image
element.
By default, the raster images are usually upscaled smoothly which is unsuitable for pixel art and close-ups of image data.
In this article we're checking out how this behavior can be changed in different SVG renderers.
There's a promising attribute called image-rendering
which hints whether the rendered should optimize for rendering speed or quality.
Below you can see how different values of this attribute work in your browser on a simple 2 × 2 image:
Based on my tests only Firefox and Inkscape give out the desired output with optimizeSpeed
option.
So we cannot rely on the image-rendering
attribute which is, after all, only a hint.
SVG also supports CSS which has a similarly named image-rendering
property.
Option pixelated
looks exactly like what we need as it should preserve the pixelated look.
There's also crisp-edges
which could, at least in theory, use a pixel-art scaling algorithm.
Test your browser below:
It seems that Chrome supports pixelated
but Firefox doesn't.
To support both these browsers, we can use both the image-rendering
attribute and property:
<image image-rendering="optimizeSpeed" style="image-rendering:pixelated" />
Unfortunately, controlling image rendering doesn't seem to possible at all in Safari and SVG renderers like librsvg.
There are two workarounds: upscaling the image in advance and recreating the image with vector shapes.
Let's compare image-rendering
option against the workarounds on an image at 4x scaling:
The above file sizes are calculated after optimizing the embedded images with oxipng, running svgcleaner and gzipping everything. As we can see, file sizes of the workarounds are a bit larger than the original. To keep the upscaled image sharp on all displays, 16x scaling is used instead of 4x scaling, because the display may have a pixel ratio up to 4 and 4 × 4 = 16. Additionally, gaps between pixels can be visible in the vectorized image especially when displayed at different zoom levels.
Overall upscaling seems to be the better workaround in terms of file size and clean rendering. However, you might be able to handcraft a much smaller SVG depending on the style and complexity of your image.