I grew up with Targa; this probably had something to do with my dad having a Truevision Vista card when I was a kid. Targa is my favorite image format. This is my second attempt at writing a proper, generalized, stable, error-handling Targa reader/writer. I worked from the official Targa 2.0 specification.
Quick feature list:
I have successfully tested this code on the following platforms:
I haven't had the chance to test it with other Win32 compilers or any older DOS compilers. If you get the chance to do this, please mail me with your results.
Apparently, Truevision (the company that created the Targa format) was acquired by Pinnacle at some point. For some reason, I can't find the TGA Format Specs on ftp.truevision.com anymore.
Copyright © 2001-2004 Emil Mikulic.
Source and binary redistribution of this code, with or without changes, for free or for profit, is allowed as long as this copyright notice is kept intact. Modified versions have to be clearly marked as modified.
This code is provided without any warranty. The copyright holder is not liable for anything bad that might happen as a result of the code.
targa-1.tar.gz (8KB)
Or separately:
targa.c (30KB)
targa.h (6KB)
A 400x300 grayscale image drawn into an array of bytes. Use tga_write_mono to write it to a top-down oriented Targa file:
#include "targa.h" int main() { uint8_t image[300][400]; /* draw to image */ tga_write_mono("output.tga", image, 400, 300); return 0; }
How you go about handling errors is up to you, but the following example should at least demonstrate how to catch an error and format it into a humanly-readable error string:
tga_result result; result = tga_write_mono("output.tga", image, 400, 300); if (result != TGA_NOERR) { fprintf(stderr, "Error writing targa: %s\n", tga_error(result)); exit(EXIT_FAILURE); }
A quick run-down of all the convenience writing functions:
Depth is given in bits. Be aware that the RGB writing functions will modify your image data, flipping the red and blue components.
A reading example. The following code will read an image, convert it into top-down and left-to-right stored order, make it grayscale and write it to another file:
tga_image img; tga_read(&img, "input.tga"); if (!tga_is_top_to_bottom(&img)) tga_flip_vert(&img); if (tga_is_right_to_left(&img)) tga_flip_horiz(&img); if (tga_is_colormapped(&img)) tga_color_unmap(&img); if (!tga_is_mono(&img)) tga_desaturate_avg(&img); tga_write("output.tga", &img);
Every manipulation and loading/saving function used above could potentially return an error. In a more mission-critical application, you would probably want to handle these errors.
The Targa reading and writing code consists of two files: targa.c and targa.h. Both are released under a BSD equivalent license. I don't really expect this code to become a shared library. It's quite small and any program that uses it should assimilate (bwahahaha) the Targa code into its own source tree. I won't feel bad if you decide to make a shared library out of it, it's just not the way I envisioned this code would be used.
Returns the number of bits per pixel allocated to the attribute field. (the alpha component) This is pretty useless; included for completeness only.
tga_image img; tga_read(&img, "input.tga"); printf("%d attribute bits\n", tga_get_attribute_bits(&img));
Returns 1 if the Targa is stored in right-to-left order, or 0 if left-to-right order. Be aware that some Targa readers don't honor right-to-left storage order.
tga_image img; tga_read(&img, "input.tga"); if (tga_is_right_to_left(&img)) tga_flip_horiz(&img);
Returns 1 if the Targa is stored in top-to-bottom order, or 0 if bottom-to-top order. By default, Targa images are stored in bottom-to-top order so that the positive y-axis points upwards as it usually does in mathematics.
tga_image img; tga_read(&img, "input.tga"); if (!tga_is_top_to_bottom(&img)) tga_flip_vert(&img);
Returns 1 if the Targa is colormapped, or 0 if it's grayscale or truecolor.
tga_image img; tga_read(&img, "input.tga"); if (tga_is_colormapped(&img)) tga_color_unmap(&img);
Returns 1 if the image_type field of the tga_image struct is of an RLE type, 0 otherwise. Targa images which have been read from a file will have this set if the file was RLE. If the image_type is set to an RLE type before writing a Targa to a file, it will be written as a compressed targa.
tga_image img; tga_read(&img, "input.tga"); if (tga_is_rle(&img)) printf("input file is compressed.\n");
Returns 1 if the Targe is an 8-bit grayscale image, or 0 otherwise.
tga_image img; tga_read(&img, "input.tga"); if (!tga_is_mono(&img)) tga_desaturate_avg(&img);
Formats errcode into a humanly readable error code.
tga_image img; tga_result result; result = tga_read(&img, "input.tga"); if (result != TGA_NOERR) { fprintf(stderr, "Error writing targa: %s\n", tga_error(result)); exit(EXIT_FAILURE); }
Reads filename into a tga_image structure pointed to by dest. Returns TGA_NOERR if successful, or an appropriate error code if not.
tga_image img; tga_result result; result = tga_read(&img, "input.tga"); if (result != TGA_NOERR) printf("error!\n");
Reads from fp into dest. Refer to tga_read().
Writes a Targa image specified by src to filename. Returns TGA_NOERR if successful, or an appropriate error code if not.
uint8_t image[300][400]; tga_image img; tga_result result; img.image_id_length = 0; img.image_id = NULL; img.color_map_type = TGA_COLOR_MAP_ABSENT; img.color_map_origin = 0; img.color_map_length = 0; img.color_map_depth = 0; img.color_map_data = NULL; img.image_type = TGA_IMAGE_TYPE_MONO_RLE; img.origin_x = 0; img.origin_y = 0; img.width = 400; img.height = 300; img.pixel_depth = 8; /* image array is in top-to-bottom order */ img.image_descriptor = TGA_T_TO_B_BIT; img.image_data = image; result = tga_write("output.tga", &img); if (result != TGA_NOERR) printf("error!\n");
Writes a Targa image, src, to fp. Refer to tga_write().
Write to filename a plain memory array, image, of dimensions <width>x<height>. The array is taken to be in top-down, left-to-right order. This is a convenience function that sets up a tga_image struct for you and writes it using tga_write. Returns TGA_NOERR if successful, or an appropriate error code if not.
uint8_t image[300][400]; tga_write_mono("output.tga", image, 400, 300);
Same as tga_write_mono() but uses RLE compression.
Same as tga_write_mono() but writes out a truecolor (BGR) image. You must specify the depth in bits - 16, 24, or 32.
uint8_t image[300][400][3]; tga_write_bgr("output.tga", image, 400, 300, 24);
Same as tga_write_bgr() but uses RLE compression.
Same as tga_write_bgr() but flips red and blue components in the image. Be aware that calling this function will modify the image data you pass to it.
Same as tga_write_rgb() but uses RLE compression.
Horizontally flips the internal storage order of img.image_data and also flips the horizontal order flag in img.image_descriptor. The flipping is done in place; no working memory is allocated. Be aware that some Targa readers don't honor right-to-left order. This function returns TGA_NOERR on success or an error code if the img fields are in error.
/* given: tga_image img; */ tga_flip_horiz(&img);
Vertically flips the internal storage order of img.image_data and also flips the vertical order flag in img.image_descriptor. The flipping is done in place; no working memory is allocated. By default, Targa images are stored in bottom-to-top order so that the positive y-axis points upwards as it usually does in mathematics. This function returns TGA_NOERR on success or an appropriate error code if the img fields are in error.
/* given: tga_image img; */ tga_flip_vert(&img);
Converts a color-mapped Targa into a truecolor one. The image_data field is reallocated to fit the truecolor image, then unmapping is done backwards so that the process can be done in place. No working memory beyond the final size of the image data will be allocated. This function returns TGA_NOERR on success or an appropriate error code if it runs out of memory or the img fields are in error.
/* given: tga_image img; */ tga_color_unmap(&img);
Returns a pointer to the pixel (x, y) in image img or NULL if the specified pixel is outside of the range (0, 0) - (width-1, height-1).
Positive x is right, positive y is down. This function accounts for the internal storage order of the image data given in the image_descriptor field of img.
/* given: tga_image img; */ uint8_t *p = tga_find_pixel(&img, 18, 64);
Unpacks the pixel pointed at by src (refer to tga_find_pixel()) into bytes pointed to by b, g, r, a. If you are uninterested in any one of these four components, you can set it to NULL. You must specify the pixel depth of the image; there is a pixel_depth field in the tga_image struct which can supply this value for you.
Returns TGA_NOERR if successful, or TGAERR_PIXEL_DEPTH if you pass it an illegal bit depth.
/* given: tga_image img; */ uint8_t b, g, r; uint8_t *p = tga_find_pixel(&img, 18, 64); tga_unpack_pixel(p, img.pixel_depth, &b, &g, &r, NULL);
Packs b, g, r, a into the pixel pointed at by dest. (refer to tga_find_pixel()) You must specify the pixel depth of the image; there is a pixel_depth field in the tga_image struct which can supply this value for you.
Returns TGA_NOERR if successful, or TGAERR_PIXEL_DEPTH if you pass it an illegal bit depth.
/* given: tga_image img; */ uint8_t *p = tga_find_pixel(&img, 18, 64); tga_pack_pixel(p, img.pixel_depth, 200, 100, 50, 0);
Desaturates a truecolor image into a grayscale one. The conversion is done in-place, then img.image_data is reallocated to the new, smaller size. Returns TGA_NOERR if successful, or an appropriate error code if the img fields are in error.
The desaturation formula is:
out = (
r * cr +
g * cg +
b * cb ) / dv
/* given: tga_image img; */ tga_desaturate(&img, 2, 3, 4, 9);
Wrapper around tga_desaturate() using the weighting given in
Rec.601-1:
y = 0.2989r + 0.5866g + 0.1145b
Wrapper around tga_desaturate() using the weighting given in
Rec.709:
y = 0.2126r + 0.7152g + 0.0722b
Wrapper around tga_desaturate() using the ITU weighting:
y = 0.2220r + 0.7067g + 0.0713b
Wrapper around tga_desaturate() using equal weights:
y = (r + g + b) / 3
Converts any type of image (colormapped, grayscale, truecolor) into a truecolor image with the given bit depth, bits. The conversion is done in place as far as that is possible. The function avoids allocating working memory.
Returns TGA_NOERR on success, or an appropriate error code on failure.
/* given: tga_image img; */ tga_convert_depth(&img, 24);
Swaps the red and blue components of a truecolor image. Returns TGA_NOERR on success, or TGAERR_PIXEL_DEPTH if img.pixel_depth is set to an illegal value.
/* given: tga_image img; */ tga_swap_red_blue(&img);
Frees the image_id, color_map_data and image_data fields of img and sets them to NULL. If any of the fields are already NULL, the function will not try to free them.
tga_image img; /* set up header */ img.image_data = (uint8_t*)malloc(400*300*3); /* draw image */ /* write targa */ tga_free_buffers(&img);
Valid XHTML 1.1
copyright © 2001-2004 Emil Mikulic
$Date: 2006/04/22 08:27:56 $