Images often account for most of the downloaded bytes on a web page and also often occupy a significant amount of visual space. As a result, optimizing images can often yield some of the largest byte savings and performance improvements for your website: the fewer bytes the browser has to download, the less competition there is for the client’s bandwidth and the faster the browser can download and render useful content on the screen.
Image optimization is both an art and science: an art because there is no one definitive answer for how best to compress an individual image, and a science because there are many well developed techniques and algorithms that can significantly reduce the size of an image. Finding the optimal settings for your image requires careful analysis along many dimensions: format capabilities, content of encoded data, quality, pixel dimensions, and more.
Optimizing vector images #
All modern browsers support Scalable Vector Graphics (SVG), which is an XML-based image format for two-dimensional graphics. You can embed the SVG markup directly on the page or as an external resource. Most vector-based drawing software can create SVG files or you can write them by hand directly in your favorite text editor.
svg version="1.2" baseProfile="tiny" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 612 792" xml:space="preserve">
circle fill="red" stroke="black" stroke-width="2" stroke-miterlimit="10" cx="50" cy="50" r="40"/>
The above example renders the below simple circle shape with a black outline and red background and was exported from Adobe Illustrator.
As you can tell, it contains a lot of metadata, such as layer information, comments, and XML namespaces that are often unnecessary to render the asset in the browser. As a result, it is always a good idea to minify your SVG files by running through a tool like SVGO.
Case in point, SVGO reduces the size of the above SVG file generated by Illustrator by 58%, taking it from 470 to 199 bytes.
svg version="1.2" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 612 792">circle fill="red" stroke="#000" stroke-width="2" stroke-miterlimit="10" cx="50" cy="50" r="40"/>svg>
Because SVG is an XML-based format, you can also apply GZIP compression to reduce its transfer size—make sure your server is configured to compress SVG assets!
A raster image is simply a two-dimensional grid of individual “pixels”—for example, a 100×100 pixel image is a sequence of 10,000 pixels. In turn, each pixel stores the “RGBA” values: (R) red channel, (G) green channel, (B) blue channel, and (A) alpha (transparency) channel.
Internally, the browser allocates 256 values (shades) for each channel, which translates to 8 bits per channel (2 ^ 8 = 256), and 4 bytes per pixel (4 channels x 8 bits = 32 bits = 4 bytes). As a result, if we know the dimensions of the grid we can easily calculate the filesize:
- 100×100 pixel image is composed of 10,000 pixels
- 10,000 pixels x 4 bytes = 40,000 bytes
- 40,000 bytes / 1024 = 39 KB
As an aside, regardless of the image format used to transfer the data from the server to the client, when the image is decoded by the browser, each pixel always occupies 4 bytes of memory. This can be an important constraint for large images and devices which do not have a lot of available memory —for example, low-end mobile devices.
|100 x 100||10,000||39 KB|
|200 x 200||40,000||156 KB|
|300 x 300||90,000||351 KB|
|500 x 500||250,000||977 KB|
|800 x 800||640,000||2500 KB|
39 KB for a 100×100 pixel image may not seem like a big deal, but the filesize quickly explodes for larger images and makes image assets both slow and expensive to download. This post has so far only focused on the “uncompressed” image format. Thankfully, a lot can be done to reduce the image file size.
One simple strategy is to reduce the “bit-depth” of the image from 8 bits per channel to a smaller color palette: 8 bits per channel gives us 256 values per channel and 16,777,216 (256 ^ 3) colors in total. What if you reduce the palette to 256 colors? Then you would only need 8 bits in total for the RGB channels and immediately save two bytes per pixel—that’s 50% compression savings over the original 4 bytes per pixel format!
Complex scenes with gradual color transitions (for example, gradients or sky) require larger color palettes to avoid visual artifacts such as the pixelated sky in the 5-bit asset. On the other hand, if the image only uses a few colors, then a large palette is simply wasting precious bits!
Next, once you’ve optimized the data stored in individual pixels you could get more clever and look at nearby pixels as well: turns out, many images, and especially photos, have many nearby pixels with similar colors— for example, the sky, repeating textures, and so on. Using this information to your advantage the compressor can apply delta encoding where instead of storing the individual values for each pixel, you can store the difference between nearby pixels: if the adjacent pixels are the same, then the delta is “zero” and you only need to store a single bit! But why stop there…
The human eye has different level of sensitivity to different colors: you can optimize your color encoding to account for this by reducing or increasing the palette for those colors. “Nearby” pixels form a two-dimensional grid. This means that each pixel has multiple neighbors: you can use this fact to further improve delta encoding. Instead of looking at just the immediate neighbors for each pixel, you can look at larger blocks of nearby pixels and encode different blocks with different settings.
As you can tell, image optimization gets complicated quickly (or fun, depending on your perspective), and is an active area of academic and commercial research. Images occupy a lot of bytes and there is a lot of value in developing better image compression techniques! If you’re curious to learn more, head to the Wikipedia page, or check out the WebP compression techniques whitepaper for a hands-on example.
So, once again, this is all great, but also very academic: how does it help you to optimize images on your site? Well, it’s important to understand the shape of the problem: RGBA pixels, bit-depth, and various optimization techniques. All of these concepts are critical to understand and keep in mind before you dive into the discussions of various raster image formats.
Lossless versus lossy image compression #
For certain types of data, such as source code for a page, or an executable file, it is critical that a compressor does not alter or lose any of the original information: a single missing or wrong bit of data could completely change the meaning of the contents of the file, or worse, break it entirely. For some other types of data, such as images, audio, and video, it may be perfectly acceptable to deliver an “approximate” representation of the original data.
In fact, due to how the eye works, we can often get away with discarding some information about each pixel in order to reduce the filesize of an image— for example, our eyes have different sensitivity to different colors, which means that we can use fewer bits to encode some colors. As a result, a typical image optimization pipeline consists of two high level steps:
- Image is processed with a lossy filter that eliminates some pixel data.
- Image is processed with a lossless filter that compresses the pixel data.
The first step is optional, and the exact algorithm will depend on the particular image format, but it is important to understand that any image can undergo a lossy compression step to reduce its size. In fact, the difference between various image formats, such as GIF, PNG, JPEG, and others, is in the combination of the specific algorithms they use (or omit) when applying the lossy and lossless steps.
So, what is the “optimal” configuration of lossy and lossless optimization? The answer depends on the image contents and your own criteria such as the tradeoff between filesize and artifacts introduced by lossy compression: In some cases, you may want to skip lossy optimization to communicate intricate detail in its full fidelity. In other cases, you may be able to apply aggressive lossy optimization to reduce the filesize of the image asset. This is where your own judgment and context need to come into play—there is no one universal setting.
As a hands-on example, when using a lossy format such as JPEG, the compressor will typically expose a customizable “quality” setting (for example, the quality slider provided by the “Save for Web” functionality in Adobe Photoshop), which is typically a number between 1 and 100 that controls the inner workings of the specific collection of lossy and lossless algorithms. For best results, experiment with various quality settings for your images, and don’t be afraid to dial down the quality—the visual results are often very good and the filesize savings can be quite large.
Note that quality levels for different image formats are not directly comparable due to differences in algorithms used to encode the image: quality 90 JPEG will produce a very different result than a quality 90 WebP. In fact, even quality levels for the same image format may produce visibly different output based on implementation of the compressor!
Image optimization checklist #
Some tips and techniques to keep in mind as you work on optimizing your images:
- Prefer vector formats: vector images are resolution and scale independent, which makes them a perfect fit for the multi-device and high-resolution world.
- Minify and compress SVG assets: XML markup produced by most drawing applications often contains unnecessary metadata which can be removed; Ensure that your servers are configured to apply GZIP compression for SVG assets.
- Prefer WebP over older raster formats: WebP images will usually be far smaller than older images.
- Pick best raster image format: determine your functional requirements and select the one that suits each particular asset.
- Experiment with optimal quality settings for raster formats: don’t be afraid to dial down the “quality” settings, the results are often very good and byte savings are significant.
- Remove unnecessary image metadata: many raster images contain unnecessary metadata about the asset: geo information, camera information, and so on. Use appropriate tools to strip this data.
- Serve scaled images: resize images and ensure that the “display” size is as close as possible to the “natural” size of the image. Pay close attention to large images in particular, as they account for largest overhead when resized!
- Automate, automate, automate: invest into automated tools and infrastructure that will ensure that all of your image assets are always optimized.