Optimizing textured graphics

From rgba colors to the box-shadow attribute, the CSS standard tends to evolve in response to designers’ ingenuity. Two years ago, implementing rounded corners meant saving an image sprite, applying an appropriate PNGFix for IE, and serving both the graphic and javascript hack up as static assets. Now that border-radius is enshrined in spec, however, that sought-after design element is accessible to everyone with a stylesheet.

Luke Wroblewski got me to thinking, though:

Textures are the new rounded corners.

Just like rounded corners, textures have been around for a while. But throwing texture at a design without thinking can lead to unacceptable loading times—a major no-no in the ultralight business of mobile development. Some very clever people are experimenting with CSS3′s linear-gradient to create patterns, but until filters like perlin, gaussian, and weave how found their way into a future spec, it’s worth considering how textured graphics can be prepared for use on the web.

The contenders

Right now, 98% of texturing is done graphically, either as part of large composite graphics or as small tileable sprites. The conventional wisdom isn’t anything new:

Best forPhotosIllustrationsTransparencyNoYesLossyYesNoSupported byYesIE>6
What doesn’t get as much air-time, is how the addition of randomized textures (think noise) can have on compression ratios. Got tiles? Use a PNG—my de-facto choice for sprites, but a format that isn’t well suited for storing images with lots of colors or color borders.

So how bad is it?

Photoshop’s web optimizer (File > Save for web & devices) is one of my favorite tools for fine-tuning graphics for the real world. It offers reasonably good control over the compression used by each format as well as a quantitative assessment of the results. In other words, a convenient tool for testing the efficacy of various compression algorithms.

I constructed a test image that emphasized PNG’s strengths, figuring that a two-tone image (4 after anti-aliasing down the middle) would give the format its best change to deliver favorable results. It started at 256 pixels a side. For all the bitmap fans in the crowd, that’s 192KB. Nowhere to go from here but down.

Unsurprisingly, PNG delivered. A 24-bit export weighed in at 1.037KB, while an 8-bit version with lighter headers arrived at a mere 623B. JPEGs weren’t bad, either. An export at 20% delivered a 990B file and an unacceptable volume of compression artifacts, but a second attempt at 70% clocked in at 2.165KB. Small differences, but over twice the size recorded for either PNG.

Now, with noise

For the second round, I simulated the addition of a random texture by throwing noise (about as random as it gets) across the test graphic. Noise is probably the worst-case scenario where lossless compression is concerned, but hey—after the opening round, it was JPEG’s turn to face off with a creampuff.

It wasn’t pretty.

Using the same optimizations as before, I was able to produce PNG files ranging from 60.45KB for a full-palette PNG-8 to a whopping 90.48KB for a true color PNG. Even adjustments to the palette only produced minor reductions in filesize before image quality degraded noticeably.

JPEG, on the other hand, did much better. The “noisy” test at 70% quality brought the size down to 38.24KB, but compression all the way down to 0% quality did not significantly hurt the quality of the image or its textures. At 11.39KB this version was still an order of magnitude heavier than the untextured images, but a fraction of the weight of any of the other contenders.

We have a winner.

An alternative

There’s one more option: rather than texturing graphics individually, it might be possible (but not advisable) to deliver tileable textures as transparent 24-bit PNGs placed directly over untextured graphics. Though a layered-texture approach might help to reduce the overall page weight of very specific graphics, the headaches that accompany it—in creating and maintaining texture layers, in ceding artistic control to the browser, in having to justify the amount of resources consumed by a single browser thread—just aren’t worth the cost.


  • PNG compression is a better choice for images with broad, homogenous swaths or images where crispness (e.g., around type) is a significant consideration
  • JPEG compression is superior in situations with many colors or many color-borders
  • Noise might be helpful in hiding compression artifacts