graphic violence

posted by tom / April 07, 2006 /

We have to talk, fellow children of the internet. I think that, by and large, you're all doing a bang-up job of building out this new digital commons. It'll soon come to define our planet's culture for the foreseeable future, and we're off to what I would call a solid, monkey-punching start.

But we do have a big problem. The images, people. Many of you abuse them shamelessly, as if you somehow don't know or care about the difference between a GIF and JPEG. I have a hard time even conceiving of this possibility, to be honest. But since I run into this a lot, both with new DCist contributors and with submitted press releases, I thought I might as well write something up explaining how different graphical formats work, and what situations you should use them in.

First, the simplest thing to remember: a graphic is made up of a grid of pixels, each of which has a color assigned to it. You already knew this, but it's where we have to start.

So! Let's start with the simplest and most egregious mistake: using HTML to resize images — i.e., abusing the width and height attributes of the img tag. By way of example, here's a properly resized image of a soundcard from a Flickr user and Creative Commons adopter named whiskymac:

soundcard_small.jpg

And here's the same image, working off of a larger source — one with more information available! — that's been scaled down to the same size using the width and height attributes:

soundcard_large.jpg

See the difference? No? Yeah, neither can I. But that's because I'm using a Mac, and probably because you are, too. OS X takes care of the resampling procedure that I'll discuss in a second. But first, gaze upon the horror that is HTML resizing in Windows Internet Explorer:

soundcard_shitty.jpg

Ugh. Why is this so awful? It's because of the method used to resize the image. The right way to resize an image is to resample it. Basically, you plot each pixel as a point in space — imagine a football field divided into yard-long squares, with an appropriately-colored crayon stuck into the middle of each one to indicate the color. You'd then plot the pixels/crayons of the new image size over the same area — if the new image is larger, the points would be more densely packed-together than the old ones, and if it was smaller, they'd be less dense. To determine the color of each new pixel, you measure its distance from the surrounding original pixels, and use a formula to average them. There are a few different ways to do this averaging operation, but this is the gist of the procedure. It produces good-looking results.

HTML resizing doesn't do this (at least, not on non-Macs). Instead it just skips pixels. Is the new image a quarter the size of the original? Then it just draws every other pixel (in both the vertical and horizontal direction). A ninth of the size? Then it draws every third pixel. That isn't even all that bad — it's the uneven divisions that produce the really awful-looking results. When you make the size larger than the original, it draws every nth pixel twice. It works this way because it's much faster, and because it's easier to program.

So the moral: resize your images in a photo editing program, not in HTML. Besides, if you don't, the user will have to download the original image — if it's just the original, massive JPEG from your digital camera it's going to be pretty large. That's going to take a lot of your bandwidth, and make your users wait a comparatively long time for the image to load.

Now: on to more arcane mistakes. The biggest ones relate to the difference between GIFs and JPEGs, the two most commonly used image formats (PNGs are an up and comer with various advantages over GIF, but in their standard formulation are basically comparable). But first, let's start with their ancestor: the bitmap.

Most people have run into BMPs while screwing around with MS Paint back on Windows 3.1. When the internet came along you probably noticed that they're extremely large. The reason for this has to do with how each pixel in a bitmap records its color information. For most modern displays, each pixel gets 3 bytes of data: one each for the red, green and blue component. A bitmap records this information simply and perfectly for each pixel.

But that takes a lot of space. A GIF improves on this situation by taking a paint-by-numbers approach: there's a color table in the file where each hue gets its full 3 bytes of data, plus an index number that's an additional byte. Then one of those index numbers is assigned to each pixel. Hey! We've already achieved 2/3 improvement in efficiency (if we ignore the color table's overhead, which we ought to 'cuz it's small compared to the pixels). The format also introduces some simple things like run-length encoding, which lets the GIF say to the GIF-reader "there's going to be a block of this color this big" instead of writing down the index for every single pixel. There are some finer details, but this is the basic picture.

The improvements come at a price, though: because only one byte is used for the index numbers, there can only be 256 distinct index numbers — which means our pallette is limited to 256 colors. Your graphics program is good at lumping similar colors together to make maximally efficient use of the pallette, but it's still not enough to reproduce images that use a lot of colors, like photographs. By way of example, here's another Creative Commons photo, this time of some girls going wild and by Flickr user Astros in 06:

girls_going_wild.gif

I've exaggerated the effect, reducing it to 4-bit, rather than a GIF's 8-bit color — there are only 16 distinct colors in this image. But you get the idea. For an image with a wide range of colors, GIF is no good.

JPEG is, though. The reason for this is that it doesn't record each pixel. It doesn't need to — humans aren't that good at telling the difference between 'em. We can see changes in brightness very well, though (this is because our retinas' rods are much more tiny, tightly-packed and sensitive than our cones). So JPEG compression begins by separating an image's brightness from two other components (collectively called "chrominance") that represent the rest of its color. Then it splits the image up into 8x8 blocks of pixels, and, following a zigzag pattern from each block's upper left corner to its lower right, it figures out a mathematical function that describes the change in the component it's describing.

The genius here is that a person can choose how much information this process returns. More information equals a more accurate representation of the original image. This is why you can specify a JPEG's quality setting. More importantly, it lets us spend more bytes on the important brightness information and less on the chrominance, and our puny human eyes can't tell the difference. Then there's some more compression applied, and we're done.

But here's the thing: the way that information is stored is in terms of parameters that are used to jigger a cosine function — you remember, the wavy thing from trig class. It's pretty easy to jigger it to replicate smooth transitions, like a fade into a shadow. It's not so easy to make it handle abrupt changes — hard edges, in other words. It takes a lot more bytes to describe the function well enough to create a sharp drop, and even then it doesn't work all that well.

Here's an example. The first image here is a BMP — a perfect representation of what was on my screen when I composed this image in Photoshop.

artifact_lossless.bmp

And here's a GIF. As you can see, it does a great job, because the image is just black, white, and some gray used to make the letters' edges look smooth:

artifacts_pallettized.gif

And here's a JPEG with the quality turned way down. Ugh.

artifacts_lossy.jpg

Jeez. Look at that crap. Seriously, look at it!

artifacts_zoomed.gif

Yuck. Now obviously you probably won't turn your JPEG settings all the way down. But you should still choose the right format for the right job, because slight problems become big ones when an image is resized, touched up or even just resaved (depending on the program and format).

So, some guidelines:

  • If your image has a wide range of hues and shades, like a photograph, you should use a JPEG.

  • If your image has sharp edges or a limited number of colors, like an icon or a logo, you should use a GIF.

  • If your image really must have both, use a PNG in 24-bit mode. Which I didn't talk about. But it shouldn't come up very often.

That's it. Thank you for your cooperation.

Comments

You'll probably get a lot more readers of the full post if you make it known that there are tits on display.

Posted by: ben wolfson on April 7, 2006 06:11 PM

yeah... I'm afraid I'm being gently encouraged from multiple angles to get rid of that particular graphic. Honestly I only chose it because it was the first thing that popped up in the recent CC stream on Flickr. But the guy's photostream is NSFW, apparently, so I don't wanna leave the link in there. I'll pull it out when I have time to find a new, good graphic.

Posted by: tom on April 7, 2006 06:13 PM

. . . next week.

Posted by: Kriston on April 7, 2006 06:28 PM

The microscopes in my lab save images as .tif files. What's up with that?

Posted by: jeff on April 7, 2006 07:06 PM

Let's not forget to remind everyone that they can use jpeg2000 for all of their lossless archival needs!

Posted by: Fletch on April 7, 2006 11:39 PM

TIFF is another lossless format, although unlike BMP, it also adds a byte that covers transparency for each pixel (aka alpha). I believe it also has some compression (while remaining lossless). But to be honest, I don't know that much about it. I do know that your microscopes are right to export in it: if you don't want to lose any data, you export to TIFF.

As for JPEG2000... yeah, I don't really know anything about it. But I'm sure it's great.

Posted by: tom on April 8, 2006 01:35 AM

nice

Posted by: on September 3, 2006 09:10 PM

Post A Comment

Name


Email Address


URL


Comments


Remember info?



Google Analytics