Friday, 24 August 2012

Squirrel's Guide to Image Formats

(last updated: 30/08/11)

Image formats, there's a fun subject. We've all seen our fair share of blurry or distorted images on the web - some of it can't be avoided, but a lot of it can, and here's a guide explaining how.

Which is better, the JPG or the PNG? Find out this and much more after the jump.

Things to Note

This guide may not be aimed at you. If to you "web images" means uploading a photo of yourself to Facebook, not much of what I'm about to say will make sense. Furthermore if you're not fussy about image formats and neither are the people you aim to please, that's perfectly fine (though it does raise questions as to why you came to this page in the first place). However, if you're frequently taking video game screenshots or attempting to design websites, I'd like to think there's a lot that can be learned here. I don't claim to be an expert, but I know how to avoid tackiness.

The aim of this guide isn't to demand that you follow a standard set of rules, but just to raise awareness of the pros and cons of certain types of files. It's aimed more towards the people who frequently take screenshots from emulators, or are fans of sprite sheets, web design or anything that you're likely to produce for use on the internet. Professional photographers and artists may have their own laws. There may be some factual inaccuracies so take everything with a pinch of salt. Detailed information can be found on the likes of Wikipedia - this guide is an attempts to be simplistic.

It also assumes you have a basic understanding of files on a computer. Image files store information about images. The computer then renders the contents of said file how it sees fit. Formats differ not by how they're rendered in real-time, but how they're stored on the computer. Some methods of storage are better than others, but there are multiple methods and it's good to know which ones work best.

Browser Standards

This guide was last updated in July 2011 and things may have changed since it was written, however, at the present time web browsers cannot render every type of image format out there. Straight away you've reduced the pool of choices from hundreds (if not thousands) to just a handful. In theory, all image formats can be hosted on the internet, but not necessarily rendered within a browser window. It would also assume the end user has a compatible image viewer on his/her end to view the image. Unless you're a HARDCORE artist or something, it's best to stick with the set below.

Fairly popular image formats that are work avoiding for internet use are the likes of PSD, PDN, TIFF, JPEG 2000, TGA, PCX etc.. Most of these can be converted into the types listed below, and some are legacy formats that shouldn't be used at all.

Formats to care about are as follows:

Bitmap (not to be confused with the term meaning raster graphics) (BMP)
Graphics Interchange Format (GIF)
Joint Photographic Experts Group (JPEG (or JPG))
Portable Network Graphics (PNG)
Scalable Vector Graphics (SVG)

NOTE: just because your browser supports them does not mean they're all good at the same tasks. If they were, we wouldn't have five of them.

"Web Safe" Myth Debugging

The internet has been around for many years now, but when it was first made available to the public, several restrictions were in place when it came to images. The most common restriction, which is still referenced quite a bit today on older websites, is the idea that all images have to be "web safe". "Web safe" suggests that these images never stray past the default Microsoft Windows 256 colour palette (a.k.a. 8-bit colour). Why? Because back in the mid-1990s many computer monitors couldn't handle higher colour depths, and would therefore may have struggled to render your image properly. A hardware restriction, basically.

This is not an issue in the present day. Almost every home or business computer built in the 21st century runs in 16 or 32-bit colour, as to the phones and tablets, and pretty much anything with a screen. To put this into perspective, back in 1995 you may have had only 256 possible colours on screen (28). By 2000 that would have likely been raised to something like 65,536 (216), and at the time of writing it's 16,777,216 (224). Those extra eight bits in the last example are used for alpha transparency... but we're getting off topic the point is COLOUR IS NOT AN ISSUE.

Having said that, there still are some "web safe" standards that are worth following. When I design websites, I still like to make sure the person running with a 1024x768 monitor is happy for example, so you shouldn't be aiming to make images ridiculously big. Many are still held back by poor internet connections, so minimising bandwidth through smaller file sizes is a good way to make everyone happy. At the end of the day, though you can easily blame someone for keeping slow, outdated kit, you can't blame them for having a poor telephone line. That's the internet provider's problem.

It's also not worth caring for older browsers. Smart people ignore Internet Explorer 6 or anything older and since 2004 images haven't generally been a problem for browsers. Unless we're talking SVGs... I don't plan to talk about those much today. APNG is also a nice one not many browsers support - it may see more widespread adoption in the years that follow, but again, that's for another day.

"Lossy" vs. "Lossless"

I'll be using these terms a lot in a bit, so let's get acquainted with them.

Most of the time, images are "compressed". The data used to render the image on screen (e.g. THIS PIXEL IS RED, THIS PIXEL IS BLUE) is simplified in such a way that it results in a smaller file size.

Small file sizes are an extremely good thing. They can help the user in a number of ways, the most obvious thing being that smaller files equals more room for other stuff. Even today, an uncompressed image could potentially take up a pretty hefty chunk of your hard drive, and that's not particularly helpful to anyone.

It is even more important when dealing with the internet. Most of the time, a web server is licensed out to a customer for use, and in a lot of cases, the provider only gives the user a limited amount of server bandwidth. Bandwidth in terms of internet servers is a measurement of how much information is being processed. How much information the server is taking in, and how much it's dishing out to other users. Some providers don't like you overloading their servers by giving them lots of work to do, and reducing the sizes of files (thus reducing the work load) is the best way to keep a server happy. Some providers put a bandwidth limit on their servers, meaning that if they're used too much, the whole thing will be turned off until the owner throws more cash at it.

It's all about efficiency. The world works better if things are efficient, and in terms of images, the difference between "efficient" and "inefficient" is literally a click away.

But how do you get a smaller file size? Well, that depends on the image format. Each uses its own algorithm in an attempt to deliver the best possible result. If you're lucky, the algorithm won't damage your image (i.e. it will be LOSSLESS), though sometimes in order to get a small file, it will (LOSSY). The logical conclusion is to not accept any sort of damage at all, however it's a balancing act - do you want a small file that's slightly distorted, or a massive one that isn't?

The big example is the difference between an old video game screenshot and a high quality photograph. An old video game may only be capable of outputting a handful of colours on screen, so for example:

This is Commander Keen 4, released in 1991. It's running in CGA mode, which in this example has an on-screen palette of four. That means a pixel here can only be BLACK, CYAN, MAGENTA or WHITE. If you think there's more colours involved, look closer - there isn't. Artists of the day used a concept known as "dithering" to trick the human eye into believing more colours were there. Again, more on that later.

If in like this example, there are only four colours (palette entries) involved, it might be wise to use an image format whose compression algorithm can understand we're only dealing with four of the sixteen million possible colours and do something useful with that information.

A different example. Here there are clearly more than four colours, so the same trick might not work as well, hence the need for a different algorithm. If you were dealing with these sorts of images professionally (i.e. not for internet use) you probably wouldn't compress stuff at all unless you could guarantee that it was both lossless and would make a difference. Once you go lossy, there's no going back. You can't "undo" the damage, because the editor won't know how.

Like here. Four blocks containing four (resized) pixels, three blue, one red. If a lossy algorithm decides to average each block out, you get the same purple block. Try and reverse the process and in this case there's four possible solutions.

The Comparison

So, we know our candidates by name, let's get to know them a little better.


Bitmaps are one of the oldest and most well known image formats you can find on the web today. They're the default image format for older versions of MSPaint, and chances are if you've used a Windows computer for more than ten years, you've probably ran into one at some stage. There are several different types based on standard colour depths. Most of the time, BMPs are lossless.


GIFs are the most common image format on the net, and once upon a time, were the best format out there. One of the reasons for this is the fact they can handle transparency. In the 1990s, they were all the rage, and can contain up to 256 colours. They're lossless assuming you're using a competent image editor and less than 256 colours to play with. They can also do animation.


JPEGs are perhaps the most known image format in the world, as they're the default type for digital cameras, scanners and anything that usually deals with the term "photo". Again, there are many types, lossless JPEGs and JPEG 2000s aren't going to be covered in this guide as they don't tend to get on well with web browsers. JPEGs are a lossy image format.


PNGs are the new default for MSPaint and are usually a lossless format. They support alpha transparency, or "partial" transparency which the others tend to lack.


SVGs are vectors, meaning they're entirely different to the other four and won't be covered in this guide. They work via relative co-ordinates as opposed to defined pixels. An entirely different (but useful) kettle of fish.


Now to see which fares best. I'm going to use a test image - a screenshot from a relatively complex but still old video game, which fits into the category of images I described above.

This is the base image. It's an unfinished Chemical Plant Zone from the "Nick Arcade" build of Sonic the Hedgehog 2 (for the Sega Mega Drive). It is to be saved in a number of different formats to see what happens. The image has a resolution of 320x224 and contains 35 on-screen colours.

I'll be measuring in file size in BYTES (and converting it to kiloBYTES (kB)). Bytes differ from BITS (there are eight bits in a byte), which would be used in transfer rates (usually kb/s or mb/s). Bytes are generally used for storage, and I don't make the rules as to why the computing world keeps switching from bits to bytes.

So first...

24-bit Bitmap - 215,094 bytes ~ 210.05kB, LOSSLESS

This is your bog standard BMP. BMPs are largely uncompressed, so this can be considered the "raw" version of the image. As you can see, 210kB is quite a lot... and if you can't see that, let me remind you that the entire game was housed in a 1MB ROM chip back in 1992. That means this image is about one fifth the size of the entire game. Why 24-bit? Because chances are that's the limit of your monitor. 8-bits for red, 8-bits for green, 8-bits for blue, resulting in 16 million possible combinations.

A BMP basically does nothing to compress the file size. It doesn't take note that most of those 16 million colour combinations aren't being used, and thus the image is huge.

8-bit Bitmap - 72,758 bytes ~ 71.05kB, LOSSLESS

But the BMP standard allows you to define the colour depth. MSPaint for example, allows you to save it as an 8-bit BMP. The only reason we can do this is because we know that 256 (8-bit) is more than 35. It's built me a custom-made 256 colour palette, though 221 palette entries won't be used. As you can see though, we've improved things significantly, but I'm sure we can do better. We're still not really compressing anything.

4-bit Bitmap - 35,958 bytes ~ 35.12kB, LOSSY

1-bit Bitmap - 9,022 bytes ~ 8.81kB, LOSSY

MSPaint can do 4-bit and 1-bit BMPs too, but this time, it won't generate a suitable palette. Instead, it will just use the "default" one, which Windows provides. The BMP standard actually allows for 16-bit, 32-bit, 48-bit and 64-bit varieties too, but I'm not listing them all because that would require me to find a new image editor. 4-bit (16 colours) is less than 35, and thus there's a loss in picture quality. MSPaint chooses to use "nearest neighbour" for bitmaps, so the only distortion that occurs is when palettes are merged. The image is otherwise untouched.

GIF - 14,043 bytes ~ 13.71kB, LOSSLESS

MSPAINT-COMPRESSED GIF - 24,773 bytes ~ 24.12kB, LOSSY

These are the two most common forms of GIF format you're likely to see. By definition, a GIF cannot exceed more than 256 palette entries - the top defines 256 palette entries though again, does not use all of them, the bottom also defines 256 palette entries, but rather than base the palette from the colours in the image, it seeks advice from Windows, which gives it the default palette once more. The colours in Sonic 2 do not match those of the windows palette and therefore in order to compensate, the MSPaint version applies dithering in a pathetic attempt to preserve the image. I've no idea why it doesn't use nearest neighbour like the BMP example - it just does. Thus the top is lossless, bottom is lossy.

This is risky business. Some image editors follow the rules of the former GIF, others (such as MSPaint), the latter. You won't know unless you test for yourself. If your image exceeds 256 colours, saving as a GIF will cause a loss of quality regardless. GIFs use other methods to actually compress things. It finds quicker ways of storing the data, and there'll be a detailed specification stating how.

Why dither? Well, it's an old idea that comes from the days of CRT displays:

Here we have four colours, white, black, blue and red. Some pixels are arranged in a cross-hatch manner.

On a blurry display, the cross-hatched parts start to look like a whole new colour. There is no purple in our palette, but yet there is a purple colour. MAGIC. I've resized this up so you can see what's going on, obviously. Different methods produce different shades, but as sharp, crisp LCD screens became a standard... this doesn't work as well as it once did.

As you can see though, MSPaint's dithering has actually made the issue worse, because many of the compression tricks struggle if the colours keep changing. "The next four pixels are red" is easier to say than "the next two pixels are red, then there's a blue one, then there's a red one", for example.

GIF (128 colours) - 13,479 bytes ~ 13.16kB, LOSSLESS

GIF (64 colours) - 13,143 bytes ~ 12.83kB, LOSSLESS

GIFs can be optimised to some degree though! Our first GIF defined 256 palette entries... and I know for a fact we don't need them all. So I can set it to define just 128, 64, 32, 16, 8, 4 or 2 instead. My image contains 35 colours in total, so the best I can do without losing image quality is to define 64 palette entries. Sadly this means 29 palette entries go unused - there may be ways to compress this stuff further but for now, I'm just going to accept it as a restriction of the format. In theory you can do this with BMPs too, though it's not widely seen.

GIF (32 colours) - 12,957 bytes ~ 12.65kB, LOSSY

Of course, 35 is very close to 32. Some of the colours in that image are very similar, so we could generate a new palette without the bad stuff being as noticeable. Because we're only losing three colours here it's very difficult to notice the change, however this still counts as lossy compression. But it may just be a pointless extra mile - we've shaved off 186 bytes between 64 and 32 colours and it's barely worth it. I could demonstrate the rest of the family but we're just going to see more distortions from here on out.

JPEG, "100%" - 94,823 bytes ~ 92.60kB, A BIT LOSSY

JPEG, "50%"- 20,646 bytes ~ 20.16kB, LOSSY

JPEG, "0%"- 5,387 bytes ~ 5.26kB, GOOD GOD

This is JPEG family, or at least, three members of it. The percentages measure image quality, but all you need to know is we're dealing with the WEAKEST, AVERAGE, and STRONGEST compression values, from top to bottom.

JPEGs are rubbish at this sort of thing. There's the proof. The compression based around averaging blocks of 8x8 rather than using palettes and that can lead to some dodgy results. Steer clear from JPEGs if you're dealing with images of this nature, as even the weakest compression distorts things a bit.

Now you could say the weak compression isn't doing the game much harm, but you'd be an idiot for saying that because you generally want the strongest compression possible with the minimum amount of damage. JPEG doesn't offer that. Weak compression equals large file sizes, and though we've moved on from BMPs... we can still do better.

STANDARD PNG - 13,430 bytes ~ 13.12kB, LOSSLESS

PNGs are my favourite choice. They took the best parts of the BMP and GIF standards and produced something magical. They are lossless, support alpha transparency, and support up to 32-bit colour, serving all of your needs. Basically, you'd pick PNG every time in this test case.

The PNG format is fancy and again, the details won't be described here, however, there is one thing slightly wrong about this image. It's ever so slightly darker than the rest, or at least, it is in Firefox browsers. It's a nasty business called gamma correction, applied for god knows what reasons by certain image editors. HOWEVER, the image has still not lost any information, it's just gained some. Gamma correction is applied "on top" of the image, and is easily removed, not making much of a difference to the file size. Some browsers don't even show the gamma stuff. It's generally not a concern but it's something that the likes of MSPaint likes to do.

OPTIMISED PNG - 6,535 bytes ~ 6.38kB, LOSSLESS

PNGs can (and should) be optimised. This was done via Ken Silverman's PNGOut and uses even more fancy tricks to knock the size down even more. Again, no loss to the image. And here it's actually removed the gamma correction, so all's well again.

Results, Conclusions etc.

Type  Subtype     Size (B)  Quality    Compression
BMP | 24-bit    | 215,094 | LOSSLESS | 0%
JPG | 100%      | 94,823  | LOSSY    | 55.92%
BMP | 8-bit     | 72,758  | LOSSLESS | 66.17%
BMP | 4-bit     | 35,958  | LOSSY    | 83.28%
GIF | MSPaint   | 24,773  | LOSSY    | 88.48%
JPG | 50%       | 20,646  | LOSSY    | 90.40%
GIF | Standard  | 14,043  | LOSSLESS | 93.47%
GIF | 128       | 13,479  | LOSSLESS | 93.73%
PNG | Standard  | 13,430  | LOSSLESS | 93.76%
GIF | 64        | 13,143  | LOSSLESS | 93.89%
GIF | 32        | 12,957  | LOSSY    | 93.98%
BMP | 1-bit     | 9,022   | LOSSY    | 95.81%
PNG | Optimised | 6,535   | LOSSLESS | 96.96% <-- BEST
JPG | 0%        | 5,387   | LOSSY    | 97.50%

So what does all this mean then? Well, as you can see, the majority of formats compress this image to at least 90% of its original size. Even the best looking JPG can knock off hundreds of bytes, so the obvious point to make is image compression is a good idea.

Three of the four BMPs lie at the top of the list, which again shows the BMP format it's not a great choice. In this example the screenshot contained less than 64 colours, so the 8-bit BMP didn't damage it. In different circumstances, it would, so in the BMP world, the only "sub-type" you can truly rely on is the 24-bit variety, a.k.a. the uncompressed version. A BMP does steal third place in this test, but in order to do so it had to reduce the number of colours to two. That's just stupid, and would have been out-done had I'd included more types of GIF.

JPGs lie across the field. Under extremely heavy compression they win out-right, but look at the cost - the image is barely recognisable. On the weakest setting, the JPG comes in second-last in terms of file size, and the image is still distorted. In these situations, you simply would not use JPGs. Ever.

The GIFs have a good showing - even the standard 256 colour option manages to losslessly compress things by about 93% and I'd say that's pretty damned good. But observe the 256 colour GIF handled by MSPaint - that fairs a lot worse and the image is distorted. In this case, a carefully saved GIF is a reasonably good idea, but had the image contained more than 256 colours you'd have run into problems. As said, in some very rare cases a GIF can out-perform a PNG, however most of the time, GIFs aren't worth caring for. You should only use GIFs if you know your image well - I know this image contains less than 64 colours in total, so I can compress accordingly without fear of losing detail. In other examples, that can't happen.

The PNGs carry no concerns with them when it comes to files of this nature. They outperform the GIFs and BMPs and lose no data while doing so. In this case, PNGs are the best choice, and is why so many of us favour the format. However again, with different images comes different hurdles - a PNG would not necessarily be suitable for a high quality photograph. I didn't want any distortion at all, you might not be as bothered. If alpha transparency was needed it is the only option out there for internet use.

So, I hope this has been educational. Now of course, different types of image will vary, especially if you start exceeding a couple thousand colours. However, as far as lossless images go, most of the time, a PNG works best. Even if you're only scraping a tiny bit off, there's never really a reason to save as a BMP or a GIF. They're both redundant formats.

And I can't believe I wrote all of this out just to prove that point. Oh well.

No comments:

Post a Comment