Using the LibTarga Files
This document is meant to give you an introduction to the libtarga files that were written by Alex Mohr. In order to be able to use the libtarga code in your projects, you are going to have to make a few changes in your project settings.
Now that the new project is created, we are going to configure it to be a LibTarga project.
1.Select Project->Settings...
2.Choose "All Configurations" option in "Settings For:" menu.
3.Click "C/C++" tab, this should bring up the C/C++ compiler page up.
4.Choose "Preprocessor" page from "Category" menu
5.In the field "Additional include directories:", type in:
p:\graphics\public\html\Gallery\LibTarga
Note: If you already have something there, s:\fltk\include for instance, use a
comma as a separator.
This tells the compiler where the header files for the library are.
6.Click "Link" tab, this should bring up the linker page.
7.Under "Category" menu, select "Input"
8.In the "Additional library path:" field, type in:
p:\graphics\public\html\Gallery\LibTarga,
Note: If you already have something there, s:\fltk\lib for instance, use a
comma as a separator.
This allows the linker to find FLTK library binary files.
The following steps will set the project, so that correct output format is used when generating
object files.
Then we need to tell the linker to use the essential libraries when creating the executable file. Notice that we must change the settings for both "Debug" and "Release" versions. For debug, we need to specify the debug version of the libtarga library. Also, notice that we are adding the libraries to our program, so we must be careful not to remove any others.
1.Click "Link" tab
2.Select "Win32 Release" item, in the "Setting For:" menu
3.Add WITHOUT replacing anything else in the "Object/library modules:" field the
following text:
libtarga_mt.lib
4.Select "Win32 Debug" item, in the "Setting For:" menu
5.Add WITHOUT replacing anything else in the "Object/library modules:" field the
following text:
libtarga_dmt.lib
6.Then click "Ok".
Now that we have set up our project, we are free to use the libtarga code to read and/or write targa images.
The function used for reading images is
void* tga_load( const char * file, int * width, int * height, unsigned int format );
const char* file : The filename of the .tga image we wish to read in
int* width : We pass in a pointer to an integer because the tga_load function will fill in
this value with the appropriate width for the image.
int* height : We pass in a pointer to an integer because the tga_load function will fill in
this value with the appropriate height for the image.
unsigned int format : There are two values that you can use for this :
TGA_TRUECOLOR_32 – RGBA
TGA_TRUECOLOR_24 – RGB
Note that only TGA_TRUECOLOR_32 supports an alpha channel.
If there is an error, there are several functions available to help you debug the problem:
int tga_get_last_error();
const char * tga_error_string( int error_code );
So, if you want to debug a problem in the targa code, you could use a statement such
printf(tga_error_string(tga_get_last_error()));
So, how can we actually load an image.
Here is some sample code for loading in an image
unsigned char* targaimage;
int wdt,hgt;
targaimage = (unsigned char *)tga_load(imgname,&wdt,&hgt,TGA_TRUECOLOR_32);
Remember to deallocate the memory that tga_load allocates. You could use:
free ( targaimage );
to accomplish this.
Now, let’s say we have a window that we wish to use to draw our image. If we subclass the Fl_Window class, we can override the draw() method to do just this. The draw method could look something like this ( Note, this example assumes that your class is called TargaWindow and that you are storing the image in an array called targaimage. It also assumes that you’re storing the height and width of the image in uint32 variables imgHeight and imgWidth):
void TargaWindow::draw()
{
// Assign the height and width of the targa image to temporary signed
// variables to use in the fl_draw_image function call
int H = imgHeight;
int W = imgWidth;
fl_draw_image( targaimage,0,0,W,H,4);
}
The fl_draw_image function will draw the image passed in the array. The 4 tells FLTK that the array passed in is using 4 bits ( RGBA ) per pixel.
IMPORTANT: the tga_load function loads in an image using the lower-left hand corner as location 0,0. The image array is loaded left to right from bottom to top. However, FLTK uses the upper left-hand corner as 0,0, not the lower left-hand corner. Therefore, you’ll want to reverse the ordering of the pixels values so that when you call fl_draw_image the image is not drawn upside-down.
Here is a row reversing function that you could use:
// The following function reverses the row ordering for the
// targaimage. This makes the call to draw the targa image on
// to the screen easier in that it doesn't have to adjust
// for it being stored in reverse order.
void TargaWindow::rvrsRow()
{
unsigned char *tmp=new unsigned char[imgWidth*imgHeight*4];
for (uint32 i=0; i<imgHeight; i++)
{
for (uint32 j=0; j<imgWidth; j++)
{
tmp[(i*imgWidth+j)*4]=targaimage[((imgHeight-i-1)*imgWidth+j)*4];
tmp[(i*imgWidth+j)*4+1]=targaimage[((imgHeight-i-1)*imgWidth+j)*4+1];
tmp[(i*imgWidth+j)*4+2]=targaimage[((imgHeight-i-1)*imgWidth+j)*4+2];
tmp[(i*imgWidth+j)*4+3]=targaimage[((imgHeight-i-1)*imgWidth+j)*4+3];
}
}
delete [] targaimage;
targaimage=tmp;
}
So, how can all this fit together to read in an image? You could use the following function to read in an image:
Assumes you have declared a class called TargaWin that has the following data members:
unsigned char *targaimage; // Holds the R,G,B,A data of the targa image
// we are going to draw
uint32 imgWidth; // The width of the targa image
uint32 imgHeight; // The height of the targa image
int xCoordinate; // The X Cartesian Coordinate of the upper left
// corner of the targa
int yCoordinate; // The Y Cartesian Coordinate of the upper left
// corner of the targa
// Grabs the targa image passed in as an argument and stores its
// values in my pixel array called targaimage.
void TargaWindow::setImage(char * imgname) {
int wdt,hgt;
targaimage = (unsigned char *)
tga_load(imgname,&wdt,&hgt,TGA_TRUECOLOR_32);
if (targaimage) { // If the targa is a valid image
imgWidth = (uint32)wdt;
imgHeight = (uint32)hgt;
size_t npixels; // total number of pixels in image
resize(0,0,((int)imgWidth), ((int)imgHeight)); // Resize the Window
// to be the
// dimensions of the
// image
npixels = imgWidth * imgHeight; // Assign the total number of pixels
// Reverse the ordering of the pixel values in the
// targaimage array so that the fl_draw_image function
// won't have to take this into account
rvrsRow();
}
else {
printf("Error trying to set image!\n");
printf(tga_error_string(tga_get_last_error()));
}
damage(1);
}
The following function may be used to write a targa file:
int tga_write_raw( const char * file, int width, int height, unsigned char * dat, unsigned
int format );
The function returns a 1 if successful and a 0 if not successful.
const char* file : The name of the targa file we wish to write
int width : The known width of the targa image.
int height : The known height of the targa image.
unsigned char* dat : The array holding the image information
unsigned int format: Same formats as before, only this time it should be whatever format
is being stored, not which we wish to load.
Using the code examples defined before, the following could be employed to write the image to a file.
// This function takes the targa image being shown on the screen
// and writes the image out to a file designated by the argument
// name specified
void TargaWindow::writeImage(char *name) {
// Remember to reverse the rows, otherwise we'd be writing an
// upside-down image!!
rvrsRow();
if(!(tga_write_raw(name,(int)imgWidth,(int)imgHeight,targaimage,
TGA_TRUECOLOR_32))) {
printf("Couldn't write TGA image!\n");
printf(tga_error_string(tga_get_last_error()));
}
rvrsRow();
}
Remember that you have to reverse the rows back after writing the image to a file, otherwise you’d be displaying an upside-down image the next time you displayed this window.