Tuomas Siipola Articles Projects

Pixelated images in SVG

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:

Sprite from 10 basic RPG enemies by Redshrike licensed under CC-BY 3.0

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.