// HACKER NEWS — CYBERSECURITY
Why Tiny JPEGs Look Different in Chrome
What looked like a rendering bug turned out to be a clever JPEG decoding optimization in Chrome.
A while back, when chatting with a colleague over their computer, I noticed that a logo did not look exactly the same as it did on mine. It looked thinner on theirs and more faithful to the original image. It was rendered at 15px; here is an upscaled version.
Note: this was not the original image. It happened a while ago, so I made a new image to demonstrate the issue.
If you squint, or take a step back, the one from Chrome looks thicker. A bit weird, but swapping the image for an SVG fixed it. Still, I was curious: why was it rendering like this in the first place?
I did some digging and found a nifty optimization that Chrome uses when rendering JPEGs at small scales.
The intuitive way to render a small image from a JPEG is to fully decompress it in memory and then scale it down.
Imagine a 2000 × 2000 JPEG that needs to be displayed at 20 × 20. Once uncompressed, the image takes far more memory than the final result. A bitmap of the full image uses roughly 12 MB, while the final 20 × 20 image needs only about 1.2 KB. Most of the information in the large version is lost when scaling down.
An interesting insight is that the information lost is not random.
When an image is scaled down heavily, the information that disappears is mostly the high-frequency detail. This is easy to see intuitively. Think of a tree with lots of leaves and rough bark: those fine details change quickly from pixel to pixel, so they count as high-frequency information.
If you scale that tree down to something tiny, like 20 × 10, you end up with just a green blob at the top for the foliage and a brown stick at the bottom for the trunk. The scaled-down version has thrown away the fine detail, the high-frequency information.