Posts Tagged ‘ formats

Using 24 bit uncompressed TARGA files

Every time I have a coding rage, I always end up needing some sort of image buffer I can blit directly into and saving it to a file. My favorite file format is the good ol’ TARGA file format, better known as the file with the *.tga extension. You can find this format in games, namely Quake 3 for saving screenshots.

I’m not going to give a detailed view of the TARGA specs. I just want to use the lossless, true-color (24 bit colors) storing option the format provides.

TARGA’s are easy to implement but are little tricky: easy because they simply have an 18 byte header and the rest that follows are mere groups of 3 bytes representing each of the 24 bit pixels. But there are also options regarding color palettes and compression, and that’s always tricky.

Let me just rapidly point, for my own needs, the most important parts of the specs:

In my latest implementation, this is the TGA header I created in C/C++:

   wh = width >> 8;
   hh = height >> 8;

   char header[18] = { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
      width - (wh << 8), wh,
      height - (hh << 8), hh,
      24, 0x20
   };

I first set the third byte to 2, indicating that I want a true-color, uncompressed image.

I then need to encode 2 byte values representing the width and height of the image. Those dimensions are stored in little endian format, which means that the lower part of the number comes first, then the higher part.

Since numbers are stored on 8 bit values, I isolate the higher part of the width and height like so:

   wh = width >> 8;
   hh = height >> 8;

It's then easy to get the lower part by shifting back 8 bits and substracting those values from the original dimensions.

   width - ( wh << 8 ), height - ( hh << 8 )

The 17th element is the bit per pixel (bpp) and I want the 24 bit version.

Finally, the final 18th element is more complicated as information about alpha depth is stored here. I'm not using alpha at this point so I can ignore this.

But there is also something about a "direction" and that cannot be ignored. In fact, lost into these 8 remaining bits is a special feature that determine whether the image is stored with the first line on top (which we all assume as normal) or with the first line at the bottom! The original format wrote the images upside-down. Setting this value to 0, my image will be mirorred upside-down but still aligned to the left. Lighting up that bit at the 6th position of this field sets it right (hence the hexadecimal value 0x20).

All of this can be verified with the Gimp - our favorite graphics package : when first saving a TARGA file, it will ask whether you want RLE compression uncheck this) and where you want the origin to start (select Top left).

One final note concerns the encoding of the 24 bit pixels themselves. While we are all used to the red-green-blue (RGB) encoding order, TARGAs uses blue-green-red (BGR). So don't forget to swap, or else weird things will show up in your program.

Happy hacking.

return top