Why does my TGA appear upside down?!?

Started by
2 comments, last by Viscous-Flow 22 years, 6 months ago
Hello, I got my TGA class to properly load TARGA (TGA) image files. The program will work fine if I use TGA's I find on the Internet. But, I downloaded the program GIMP for Windows which was reccommended as an image editor on one of Gamedev.net's recent articles since I don't have enough spare $$ to buy Paint Shop Pro 7. When I save a TGA and attempt to display it, the picture is UPSIDE DOWN! You can imagine how painful this is . It may have something to do with how I draw it one screen with the glTexCoord2f(). Anyways if you have any suggestions they would be very helpful. Here is the code for the Image class (I'll add bitmap support later on):
      
#ifndef GLIMAGE
#define GLIMAGE

//  Define the universal bitmap id

#define BITMAP_ID 0x4D42

#include <stdio.h>		//  Holds the file manipulation routines
#include <stdlib.h>		//  Holds other routines
#include <gl\gl.h>		//  Header file for the OpenGL32 library


//  Structure that holds pertinent information about image formats

typedef struct
{
	short int		width;		//  Width of the image

	short int		height;		//  Height of the image

	unsigned char	*data;		//  Data of the image

} IMAGE;

//  The definition fo the GLImage class

class GLImage
{
	//  Variables

	private:
		FILE	*file;				//  The file pointer


		//  Texture format (GL_RGBA, GL_RGB, GL_ALPHA)

		GLenum	textureFormat;			

		//  Windows Bitmap variables


		//  Targa image format variables

		unsigned char	tgaType[4];		//  Holds colormap information and the image type - byte 0 ignored

		unsigned char	tgaInfo[7];		//  Holds information such as the image width, height, and number of bits

		unsigned char*	tgaImageData;	//  Holds the image data

		int				tgaImageWidth;	//  Holds the image width

		int				tgaImageHeight;	//  Holds the image height

		int				tgaImageBits;	//  Holds the image number of bits

		int				tgaImageSize;	//  Holds the image size


	//  Functions

	public:

		//  Loads a Windows bitmap file

		int LoadBMPFile(char *filename, int idNum);

		//  Loads a Targa image format file - supports 8, 24, and 32 uncompressed images

		//	The texture to bind this image too is idNum

		int LoadTGAFile(char *filename, int idNum);

	//  Utility functions

	private:
		
		//  Reads in a RGBA for a 32bit tga image

		int tgaRGBA();

		//  Reads in a RGB for a 24bit tga image

		int tgaRGB();

		//  Reads in a grayscale 8bit tga image

		int tgaGray();

		//  Gets the tga data based on the number of bits of the image

		int tgaData();
};

#endif
  
Here is the function definitions for the GLImage class:
  
//  Include neccessary header files

#include "stdafx.h"		//  Header file for Windows
#include "GLImage.h"	//  Header file for the GLImage class


//  Loads a Windows bitmap file

int GLImage::LoadBMPFile(char *filename, int idNum)
{
	return 1;
}

//  Loads a Targa image format file - supports 8, 24, and 32 uncompressed images

//	The texture to bind this image too is idNum

int GLImage::LoadTGAFile(char *filename, int idNum)
{
	//  Open the file and checked to see if it was a success

	if((file = fopen(filename, "r+bt")) == NULL)
		return 0;

	fread(tgaType, sizeof(char), 3, file);	//  Read in the colormap information and the image type - byte 0 ignored

	fseek(file, 12, SEEK_SET);				//  Seek past the tga header and the other useless information

	fread(&tgaInfo, sizeof(char), 6, file);	//  Read in the vital information


	//  Load only the image types we support

	if(tgaType[1] != 0 || (tgaType[2] != 2 && tgaType[2] != 3))
	{
		fclose(file);
		return 0;
	}

	tgaImageWidth	= tgaInfo[0] + tgaInfo[1] * 256;	//  Get the image width

	tgaImageHeight	= tgaInfo[2] + tgaInfo[3] * 256;	//  Get the image height

	tgaImageBits	= tgaInfo[4];						//  Get the number of bits in the image


	tgaImageSize	= tgaImageWidth * tgaImageHeight * (tgaImageBits / 8);	//  Get the image size


	//  Make sure we are loading a supported type

	if(tgaImageBits != 32 && tgaImageBits != 24 && tgaImageBits != 8)
	{
		fclose(file);
		return 0;
	}

	//  Get the image data and check for a success

	if(tgaData() == NULL)
	{
		fclose(file);
		return 0;
	}

	//  If there was an error or there was no image data return 0

	if(tgaImageData == NULL)
	{
		fclose(file);
		return 0;
	}

	//  Close the file

	fclose(file);

	//  Set up texture with OpenGL

	glBindTexture(GL_TEXTURE_2D, idNum);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glTexImage2D(GL_TEXTURE_2D, 0, textureFormat, tgaImageWidth, tgaImageHeight, 0, textureFormat, GL_UNSIGNED_BYTE, tgaImageData);

	//  Free the tga image data since it was already uploaded

	free(tgaImageData);

	return 1;
}

//  Reads in a RGBA for a 32bit tga image

int GLImage::tgaRGBA()
{
	//  Allocate memory for the image data

	tgaImageData = (unsigned char*)malloc(tgaImageSize);

	//  Check to make sure the allocation of memory was a success

	if(tgaImageData == NULL)
		return 0;

	//  Make sure the number of bytes read is equal to the size of the image

	if(fread(tgaImageData, sizeof(unsigned char), tgaImageSize, file) != (size_t)tgaImageSize)
	{
		free(tgaImageData);
		return 0;
	}

	//  A utility variable

	unsigned char temp;

	//  Since the tga image is in BGR we need to change it to RGB so OpenGL can read it

	for (int i = 0; i < tgaImageSize; i += 4)
    {
		//  Swap the appropriate letters

        temp = tgaImageData[i];
        tgaImageData[i] = tgaImageData[i + 2];
        tgaImageData[i + 2] = temp;
    }

	//  Set the texture format to  a 32bit RGBA image

    textureFormat = GL_RGBA;
	
	return 1;
}

//  Reads in a RGB for a 24bit tga image

int GLImage::tgaRGB()
{
	//  Allocate memory for the image data

	tgaImageData = (unsigned char*)malloc(tgaImageSize);

	//  Check to make sure the allocation of memory was a success

	if(tgaImageData == NULL)
		return 0;

	//  Make sure the number of bytes read is equal to the size of the image

	if(fread(tgaImageData, sizeof(unsigned char), tgaImageSize, file) != (size_t)tgaImageSize)
	{
		free(tgaImageData);
		return 0;
	}

	//  A utility variable

	unsigned char temp;

	//  Since the tga image is in BGR we need to change it to RGB so OpenGL can read it

	for (int i = 0; i < tgaImageSize; i += 3)
    {
		//  Swap the appropriate letters

        temp = tgaImageData[i];
        tgaImageData[i] = tgaImageData[i + 2];
        tgaImageData[i + 2] = temp;
    }

	//  Set the texture format to  a 24bit RGB image

    textureFormat = GL_RGB;

	return 1;
}

//  Reads in a grayscale 8bit tga image

int GLImage::tgaGray()
{
	//  Allocate memory for the image data

	tgaImageData = (unsigned char*)malloc(tgaImageSize);

	//  Check to make sure the allocation of memory was a success

	if(tgaImageData == NULL)
		return 0;

	//  Make sure the number of bytes read is equal to the size of the image

	if(fread(tgaImageData, sizeof(unsigned char), tgaImageSize, file) != (size_t)tgaImageSize)
	{
		free(tgaImageData);
		return 0;
	}

	//  Set the texture format to  a 8bit grayscale image

    textureFormat = GL_ALPHA;

	return 1;
}

//  Gets the tga data based on the number of bits of the image

int GLImage::tgaData()
{
	if (tgaImageBits == 32)
        return tgaRGBA();
    else if (tgaImageBits == 24)
        return tgaRGB();	
    else if (tgaImageBits == 8)
        return tgaGray();

	return 0;
}
    
  
Here is how I implemented it where image is an object of the GLImage class and these functions are a part of a seperate GLMain class:
      
//  Initialize the OpenGL scene

void GLMain::Initialize(GLWindow* wnd)
{
	//  Initialze the variables

	window = wnd;	//  Get the vital information about the window

	angle = 0.0f;

	//  Enable OpenGL specific abilities

	InitGLScene();

	if(image.LoadTGAFile("texture.tga", 13) == NULL)
	{
		//  Send an error message

		MessageBox(HWND_DESKTOP, "Error loading textures", "Error", MB_OK | MB_ICONEXCLAMATION);
		window->isDone = TRUE;
	}
}

I'm skipping a few other irrelevant functions....

//  Render the scene

void GLMain::Render()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	//  Clear the screen

	glLoadIdentity();									//  Reset the origin back to the center


	glTranslatef(0.0f, 0.0f, -30.0f);

	glEnable (GL_TEXTURE_2D);			//  Enable texture mapping

    glBindTexture (GL_TEXTURE_2D, 13);	//  Bind the texture 13 so we can use it


    glBegin (GL_QUADS);
        glTexCoord2f (0.0f,0.0f);			//  Lower left corner of image

        glVertex3f (-10.0f, -10.0f, 0.0f);
        glTexCoord2f (1.0f, 0.0f);			//  Lower right corner of image

        glVertex3f (10.0f, -10.0f, 0.0f);
        glTexCoord2f (1.0f, 1.0f);			//  Upper right corner of image

        glVertex3f (10.0f, 10.0f, 0.0f);
        glTexCoord2f (0.0f, 1.0f);			//  Upper left corner of image

        glVertex3f (-10.0f, 10.0f, 0.0f);
    glEnd ();

    glDisable (GL_TEXTURE_2D); //  Disable texture mapping

}
    
Thank you!! Edited by - Viscous-Flow on October 18, 2001 6:39:57 PM
Advertisement
All you have to do is rotate it 180 degrees, like this:

glRotatef();

and make sure you use 180.
------------------------------Put THAT in your smoke and pipe it
The last byte of the header will have bit 5 set to 1 the image''s vertical origin is the top. So, if it''s 0, flip the image vertically.

[Resist Windows XP''s Invasive Production Activation Technology!]
Thanks Null and Void! I figured out where the bit is by looking up at the TGA Image specs and got it to work. Thanks again!

This topic is closed to new replies.

Advertisement