Using the LibTarga Files

CS 559

Mark Pingel

 

 

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.

 

READING A TARGA IMAGE

 

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);

}

 

WRITING A TARGA IMAGE

 

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.