Hacking Image Interpolation for Fun and Profit

13 Jan 2019

Raster images normally look distorted or pixelated when enlarged—especially if they contain graphics or text. The technique below is about blowing up tiny images, and the results might surprise you.

Let’s say you want to use this image as a full page background on your website:

1920x1080.jpg (22 KB)

Using SVG or CSS gradients would be ideal for reducing the file size and providing resolution-independent scaling. Sadly, neither technology supports mesh gradients at this time.

Fortunately, there’s another way to achieve both a tiny file size and vector-like scaling using a raster image.

Here’s how it works:

  1. Downsample the image so its dimensions are 32x18.
  2. Export the image as a PNG. The resulting file should be around 1 KB.
  3. Use the 32x18 image as a CSS background that covers its container:
    .my-background {
      width: 1920px;
      height: 1080px;
      background: url(32x18.png);
      background-size: cover;
    }
    

    or as an <img> element:

    <img src="32x18.png" style="width: 100%; height: auto;" />
    

Here is the result:

32x18.png (1443 bytes)

Can you tell the difference? The stretched image looks almost identical to the original. It scales up infinitely without noticeable distortion. Better yet, the new image is only 1.4KB—a 93.6% reduction 🎉. Click here for a side-by-side comparison.

Here is another example:

1920x1080-2.jpg (143 KB)

This image has more detail than the previous one. In this case, the small image needs to be a bit larger (128x72) to capture the detail. Finding the right size takes some experimenting.

128x72.png (7 KB)

This technique is also suitable for blurred background photos—the kind you typically see behind a text overlay. In this case, saving the image as a JPEG yields a smaller file size.

1920x1080-4.jpg (199 KB)

256x144-4.jpg (10 KB)

Limitations

Before you get too excited, this technique does have one limitation. It works well for smooth gradients and images with less contrast, but look what happens if you blow up this image:

1920x1080-3.jpg (337 KB)

128x72-2.png (21 KB)

What’s going on here?

When the downsampled image is enlarged, the browser uses an interpolation algorithm to fill in the missing data. Smooth images with less contrast can be upsampled without noticeable distortion because the interpolated pixels blend in with the originals.

How is this useful?

This technique is great for reducing the file size of background images that often contain less detail. It’s also great for rendering lightweight, scalable mesh gradients—something you can’t currently do with SVG or CSS. Mesh gradients were planned for SVG 2.0 but the feature has since been removed from the spec.

So the next time you’re about to export a big background image from Photoshop or Sketch, give this technique a try. You might be surprised how well it works.

Discuss on TwitterEdit on GitHub


Keep Reading