Skip to main content

Simple targa image file TGA loader C++

What is a tga file? TGA Targa is a specific file specification that is use to store and load image data. Image data that is store in binary. Chances are if you are here, viewing this blog you know what a TGA image is. But just in case you don't know, you can educate your self more about this at the following link wikipedia.

To begin writing your tag image loader, you will need to first create a tga header structure. You will do so with the following code.


struct TGA_Header
{
    unsigned char  ID_Length;
    unsigned char  ColorMapType;
    unsigned char  ImageType;
    unsigned char  ColorMapSpecification[5];
    unsigned short xOrigin;
    unsigned short yOrigin;
    unsigned short ImageWidth;
    unsigned short ImageHeight;
    unsigned char  PixelDepth;
};

The relevant data we require from the header is the ImageHeight, ImageWidth, and the PixelDepth which is the bpp bits-per-pixel. The rest of information in the header we won't need. The next step is to create a couple of variables to so your image info. You can do so with the following variables.

    unsigned int bpp;
    unsigned int width;
    unsigned int height;
    unsigned int type;
    unsigned int imageSize;
    unsigned char * imageData = nullptr;

Now, we are ready to begin the loading process. The first thing to do is create a TGA_Header object. like so...

    TGA_Header TGAHeader;
    
Next create a FILE pointer and set it to null. Then on the next line open the file using fopen and set the filename and specify the reading format as binary "rb"

    FILE * file = nullptr;
    file = fopen(filename, "rb");
    
If the file open successfully, then our file pointer will have an address and will no longer be equal to nullptr. To check if the file was open successfully we need to do the following. Which is to check if the file pointer is equal to nullptr. if it is equal to nullptr then it was not successful on opening the given filename. If that happen we can print an error, and return some kind of value letting us know that the file was not successful on attempting to open it.

    if (file == nullptr)
    {
        width  = 0;
        height = 0;
        bpp    = 0;
        printf("file ('%s') not be found!\n", filename);
        return 0;
    }

However if the file was successfully opened. Then we need to read in the TGA_Header info portion of the file. This is done with the following line.

    fread(&TGAHeader, 1, sizeof(TGA_Header), file);

    if (TGAHeader.ImageType != 2){
        printf("unsupoted image type %s", filename);
        width  = 0;
        height = 0;
        bpp    = 0;
        return 0;
    }
    
Once the Header portion of the file is read into TGAHeader we can take the info we want from it and store the into the variables we created above.

    width  = TGAHeader.ImageWidth;
    height = TGAHeader.ImageHeight;
    bpp    = TGAHeader.PixelDepth;

Then we'll just check to make sure our variables have the valid data.

    if (width <= 0 || height <= 0 || (bpp != 24 && bpp != 32))
    {
        printf("file data curruption or data not valid \n");
        width  = 0;
        height = 0;
        bpp    = 0;
        return 0;
    }
    
    
    const unsigned int RGB = 0x1907;
    const unsigned int RGBA = 0x1908;
    
The we need to set the image type.

    type = RGBA;// GL_RGBA;
    
    if (bpp == 24)
        type = RGB;// GL_RGB;
  
After setting the image type we need to allocate some space to store our image data. You will do so with the following.

    int bytesPerPixel = *bpp / 8;
    imageSize = *width * *height * bytesPerPixel;
    imageData = new unsigned char[imageSize];
    
    if (imageData == NULL)
        return 0;
    
Once we have allocated some memory to store our image data we can begin store that data by calling the fread() function, and passing the imageData the size of that data type which is char, and the size of the buffer which is imageSize, then finally the file we are reading the image data from.

    fread(imageData, sizeof(char), imageSize, file);

Once reading the done. We should check to for any errors while reading image data. To do so we will pass the file as a parameter to  the ferror() function. like so...

    if ( ferror(file) )
    {
        printf("error occured while reading file (%s).\n", filename);
        width  = 0;
        height = 0;
        bpp    = 0;
        delete [] imageData;
        return 0;
    }
  
Finally convert the image data to RGB because it is stored backwards as BGR.

    for (int i=0; i<(int)imageSize; i += bytesPerPixel)
    {
        unsigned int tmp = imageData[i];
        imageData[i]     = imageData[i+2];
        imageData[i+2]   = tmp;
    }
    
And, finally we are done. We have our imageData and the size of that imageData via imageSize. we have our image width, height, bytes per pixel via bpp, and our image type via type. Stay tuned to this blog. I will be using these data to load and create Textures in OpenGL. See u next time, and have fun coding.
  

Saving a Targa image via Photoshop.

save as

Note the file format select when saving a .tga image