Skip to main content
gamedev.net
🔒 Locked

basic TGA question

Started by clint8565 14 replies 3.5k views
Original Post
clint8565
clint8565
I'm using lesson 32 and it runs fine, but if I try to edit one of the images it can't load the TGA anymore, can someone please help me
Daaark
Daaark
Make sure you are saving them in the correct format. I'm not sure if lesson 32's tga loader supports compressed TGAs. TGAs have lots of options with how they are saved, like compressed, flipped, color depth, alpha channel.. etc..
clint8565
clint8565
ummm... when I go to save my TGA I don't get any options, it just saves it

I get all kinds of options for PNG, does someone know how to load them in Dev C++?
lc_overlord
lc_overlord
there is a bug in the nehe TGA load code witch makes tga files from PSP8+ not be able to load, but PSP7 saved tga files still work.

It has to do with the idHeader, psp7 doesn't save it but psp8 does(i guess it's the same with other programs to).
the nehe TGA load code asumes that it doesn't exist.

to fix it add
char tgaID[256]; // TGA header

to the beginning of the file right after
TGAHeader tgaheader; // Used To Store Our File Header

and in both LoadCompressedTGA and LoadUncompressedTGA add

	if(tgaheader[0])	{		if(fread(&tgaID, tgaheader[0], 1, fTGA) == 0)					// Read TGA ID		{													if(fTGA != NULL)													// if file is still open			{				fclose(fTGA);													// Close it			}			return false;														// Return failular		}		}


right after

	if((texture->width <= 0) || (texture->height <= 0) || ((texture->bpp != 24) && (texture->bpp !=32)))	// Make sure all information is valid	{		if(fTGA != NULL)													// Check if file is still open		{			fclose(fTGA);													// If so, close it		}		return false;														// Return failed	}


This should fix it, perhaps with a little fiddeling.
clint8565
clint8565
thanks lc_overlord, but I don't know how to fix the errors

TGALoader.cpp In function bool LoadUncompressedTGA(Texture*, char*, FILE*)':
85 TGALoader.cpp no match for 'operator[]' in 'tgaheader[0]'
89 TGALoader.cpp
lg' undeclared (first use this function)
89 TGALoader.cpp `CF_ERROR' undeclared (first use this function)

and the same for LoadCompressedTGA



thanks vampyre_dark, could you tell me how to use the devpak? I can't find a help or any examples

[Edited by - clint8565 on November 25, 2004 2:16:17 PM]
lc_overlord
lc_overlord
Hmm i might have revritten the code just a little bit to mutch.

You can delete line 89 it's just a part of my error logger, so remove it.

the bug on line 85 is a bit tricky, but if you replace tgaheader[0] with a char and take the first byte from the header and put it in that char.

my tga header is just a array of 12 chars, witch makes it more easy to read the compression type.
Perhaps i should just take the lesson 32 code, modify it and put it on the web.
Daaark
Daaark
Quote:
Original post by clint8565

thanks vampyre_dark, could you tell me how to use the devpak? I can't find a help or any examples


I've never used it before. You're going to need to find the header, and the libray file. Read the header (or a readme.txt).
I'm guessing it's

libping.a
libping.h
clint8565
clint8565
lc_overlord, if you want to mod one of the tut's for on the web you could use 33 it's the same, at least for the TGA part, 33's a lot simpler that's all

umm... I got rid of line 89, but I'm not exactly sure what to do with tgaheader[0]

do you mean like make a variable
char something = tgaheader[0]; ?
Pipo DeClown
Pipo DeClown
Is this a crosspost?

These questions a related, so I think one thread would have been enough.
Anyway, glad you found the answer. [wink]
clint8565
clint8565
pipo declown, yes... I did it so that somebody here (working with NeHe) could either help me get the tutorial working or someone else could just tell me a totally different way

PS: the answer is there, but I can't quite reach it just yet ;)
lc_overlord
lc_overlord
ok i modified lessons33 tga load code, and apart from the previous bug i mentioned, this bugfix allso replaces a problem in the header compare code (you only need to compare one byte, why compare the whole thing)
just replace all the content in these files

First we have tga.h

#ifndef __TGA_H__#define __TGA_H__#pragma comment(lib, "Opengl32.lib")					//Link to OpenGL32.lib so we can use OpenGL stuff#include <windows.h>									// Standard windows header#include <stdio.h>										// Standard I/O header #include <gl\gl.h>										// Header for OpenGL32 library#include "texture.h"typedef struct{	GLubyte		header[6];								// First 6 Useful Bytes From The Header	GLuint		bytesPerPixel;							// Holds Number Of Bytes Per Pixel Used In The TGA File	GLuint		imageSize;								// Used To Store The Image Size When Setting Aside Ram	GLuint		temp;									// Temporary Variable	GLuint		type;		GLuint		Height;									//Height of Image	GLuint		Width;									//Width ofImage	GLuint		Bpp;									// Bits Per Pixel} TGA;char tgaheader[12];									// TGA headerchar tgaID[256];									// TGA headerTGA tga;												// TGA image databool LoadUncompressedTGA(Texture *, char *, FILE *);	// Load an Uncompressed filebool LoadCompressedTGA(Texture *, char *, FILE *);		// Load a Compressed file#endif


TGAloader.cpp
/********************************************************************************/Name:		TGA.cpp																*/Header:	tga.h																*/Purpose:	Load Compressed and Uncompressed TGA files							*/Functions:	LoadTGA(Texture * texture, char * filename)							*/			LoadCompressedTGA(Texture * texture, char * filename, FILE * fTGA)	*/			LoadUncompressedTGA(Texture * texture, char * filename, FILE * fTGA)*	/*******************************************************************************/#include "tga.h"/********************************************************************************/name :		LoadTGA(Texture * texture, char * filename)							*/function:  Open and test the file to make sure it is a valid TGA file			*	/parems:	texture, pointer to a Texture structure								*/			filename, string pointing to file to open							*/********************************************************************************/bool LoadTGA(Texture * texture, char * filename)				// Load a TGA file{	FILE * fTGA;												// File pointer to texture file	fTGA = fopen(filename, "rb");								// Open file for reading	if(fTGA == NULL)											// If it didn't open....	{		MessageBox(NULL, "Could not open texture file", "ERROR", MB_OK);	// Display an error message		return false;														// Exit function	}	if(fread(&tgaheader, 12, 1, fTGA) == 0)					// Attempt to read 12 byte header from file	{		MessageBox(NULL, "Could not read file header", "ERROR", MB_OK);		// If it fails, display an error message 		if(fTGA != NULL)													// Check to seeiffile is still open		{			fclose(fTGA);													// If it is, close it		}		return false;														// Exit function	}	if(tgaheader[2]==2)				// See if header matches the predefined header of 	{	// an Uncompressed TGA image		LoadUncompressedTGA(texture, filename, fTGA);						// If so, jump to Uncompressed TGA loading code	}	else if(tgaheader[2]==10)		// See if header matches the predefined header of	{																		// an RLE compressed TGA image		LoadCompressedTGA(texture, filename, fTGA);							// If so, jump to Compressed TGA loading code	}	else																	// If header matches neither type	{		MessageBox(NULL, "TGA file be type 2 or type 10 ", "Invalid Image", MB_OK);	// Display an error		fclose(fTGA);		return false;																// Exit function	}	return true;															// All went well, continue on}bool LoadUncompressedTGA(Texture * texture, char * filename, FILE * fTGA)	// Load an uncompressed TGA (note, much of this code is based on NeHe's {																			// TGA Loading code nehe.gamedev.net)	if(fread(tga.header, sizeof(tga.header), 1, fTGA) == 0)					// Read TGA header	{												MessageBox(NULL, "Could not read info header", "ERROR", MB_OK);		// Display error		if(fTGA != NULL)													// if file is still open		{			fclose(fTGA);													// Close it		}		return false;														// Return failular	}		texture->width  = tga.header[1] * 256 + tga.header[0];					// Determine The TGA Width	(highbyte*256+lowbyte)	texture->height = tga.header[3] * 256 + tga.header[2];					// Determine The TGA Height	(highbyte*256+lowbyte)	texture->bpp	= tga.header[4];										// Determine the bits per pixel	tga.Width		= texture->width;										// Copy width into local structure							tga.Height		= texture->height;										// Copy height into local structure	tga.Bpp			= texture->bpp;											// Copy BPP into local structure	if((texture->width <= 0) || (texture->height <= 0) || ((texture->bpp != 24) && (texture->bpp !=32)))	// Make sure all information is valid	{		MessageBox(NULL, "Invalid texture information", "ERROR", MB_OK);	// Display Error		if(fTGA != NULL)													// Check if file is still open		{			fclose(fTGA);													// If so, close it		}		return false;														// Return failed	}	if(tgaheader[0]!=0)	{		if(fread(&tgaID, tgaheader[0], 1, fTGA) == 0)						// Read TGA Id tag		{				MessageBox(NULL, "Could not read tga ID", "ERROR", MB_OK);				// Display Error			if(fTGA != NULL)												// if file is still open			{				fclose(fTGA);												// Close it			}			return false;													// Return fail		}	}	if(texture->bpp == 24)													//If the BPP of the image is 24...	{		texture->type	= GL_RGB;											// Set Image type to GL_RGB	}	else																	// Else if its 32 BPP	{		texture->type	= GL_RGBA;											// Set image type to GL_RGBA	}	tga.bytesPerPixel	= (tga.Bpp / 8);									// Compute the number of BYTES per pixel	tga.imageSize		= (tga.bytesPerPixel * tga.Width * tga.Height);		// Compute the total amout ofmemory needed to store data	texture->imageData	= (GLubyte *)malloc(tga.imageSize);					// Allocate that much memory	if(texture->imageData == NULL)											// If no space was allocated	{		MessageBox(NULL, "Could not allocate memory for image", "ERROR", MB_OK);	// Display Error		fclose(fTGA);														// Close the file		return false;														// Return failed	}	if(fread(texture->imageData, 1, tga.imageSize, fTGA) != tga.imageSize)	// Attempt to read image data	{		MessageBox(NULL, "Could not read image data", "ERROR", MB_OK);		// Display Error		if(texture->imageData != NULL)										// If imagedata has data in it		{			free(texture->imageData);										// Delete data from memory		}		fclose(fTGA);														// Close file		return false;														// Return failed	}	// Byte Swapping Optimized By Steve Thomas	for(GLuint cswap = 0; cswap < (int)tga.imageSize; cswap += tga.bytesPerPixel)	{		texture->imageData[cswap] ^= texture->imageData[cswap+2] ^=		texture->imageData[cswap] ^= texture->imageData[cswap+2];	}	fclose(fTGA);															// Close file	return true;															// Return success}bool LoadCompressedTGA(Texture * texture, char * filename, FILE * fTGA)		// Load COMPRESSED TGAs{ 	if(fread(tga.header, sizeof(tga.header), 1, fTGA) == 0)					// Attempt to read header	{		MessageBox(NULL, "Could not read info header", "ERROR", MB_OK);		// Display Error		if(fTGA != NULL)													// If file is open		{			fclose(fTGA);													// Close it		}		return false;														// Return failed	}	texture->width  = tga.header[1] * 256 + tga.header[0];					// Determine The TGA Width	(highbyte*256+lowbyte)	texture->height = tga.header[3] * 256 + tga.header[2];					// Determine The TGA Height	(highbyte*256+lowbyte)	texture->bpp	= tga.header[4];										// Determine Bits Per Pixel	tga.Width		= texture->width;										// Copy width to local structure	tga.Height		= texture->height;										// Copy width to local structure	tga.Bpp			= texture->bpp;											// Copy width to local structure	if((texture->width <= 0) || (texture->height <= 0) || ((texture->bpp != 24) && (texture->bpp !=32)))	//Make sure all texture info is ok	{		MessageBox(NULL, "Invalid texture information", "ERROR", MB_OK);	// If it isnt...Display error		if(fTGA != NULL)													// Check if file is open		{			fclose(fTGA);													// Ifit is, close it		}		return false;														// Return failed	}		if(tgaheader[0]!=0)	{		if(fread(&tgaID, tgaheader[0], 1, fTGA) == 0)						// Read TGA Id tag		{				MessageBox(NULL, "Could not read tga ID", "ERROR", MB_OK);				// Display Error			if(fTGA != NULL)												// if file is still open			{				fclose(fTGA);												// Close it			}			return false;													// Return fail		}	}	tga.bytesPerPixel	= (tga.Bpp / 8);									// Compute BYTES per pixel	tga.imageSize		= (tga.bytesPerPixel * tga.Width * tga.Height);		// Compute amout of memory needed to store image	texture->imageData	= (GLubyte *)malloc(tga.imageSize);					// Allocate that much memory	if(texture->imageData == NULL)											// If it wasnt allocated correctly..	{		MessageBox(NULL, "Could not allocate memory for image", "ERROR", MB_OK);	// Display Error		fclose(fTGA);														// Close file		return false;														// Return failed	}	GLuint pixelcount	= tga.Height * tga.Width;							// Nuber of pixels in the image	GLuint currentpixel	= 0;												// Current pixel being read	GLuint currentbyte	= 0;												// Current byte 	GLubyte * colorbuffer = (GLubyte *)malloc(tga.bytesPerPixel);			// Storage for 1 pixel	do	{		GLubyte chunkheader = 0;											// Storage for "chunk" header		if(fread(&chunkheader, sizeof(GLubyte), 1, fTGA) == 0)				// Read in the 1 byte header		{			MessageBox(NULL, "Could not read RLE header", "ERROR", MB_OK);	// Display Error			if(fTGA != NULL)												// If file is open			{				fclose(fTGA);												// Close file			}			if(texture->imageData != NULL)									// If there is stored image data			{				free(texture->imageData);									// Delete image data			}			return false;													// Return failed		}		if(chunkheader < 128)												// If the ehader is < 128, it means the that is the number of RAW color packets minus 1		{																	// that follow the header			chunkheader++;													// add 1 to get number of following color values			for(short counter = 0; counter < chunkheader; counter++)		// Read RAW color values			{				if(fread(colorbuffer, 1, tga.bytesPerPixel, fTGA) != tga.bytesPerPixel) // Try to read 1 pixel				{					MessageBox(NULL, "Could not read image data", "ERROR", MB_OK);		// IF we cant, display an error					if(fTGA != NULL)													// See if file is open					{						fclose(fTGA);													// If so, close file					}					if(colorbuffer != NULL)												// See if colorbuffer has data in it					{						free(colorbuffer);												// If so, delete it					}					if(texture->imageData != NULL)										// See if there is stored Image data					{						free(texture->imageData);										// If so, delete it too					}					return false;														// Return failed				}																						// write to memory				texture->imageData[currentbyte		] = colorbuffer[2];				    // Flip R and B vcolor values around in the process 				texture->imageData[currentbyte + 1	] = colorbuffer[1];				texture->imageData[currentbyte + 2	] = colorbuffer[0];				if(tga.bytesPerPixel == 4)												// if its a 32 bpp image				{					texture->imageData[currentbyte + 3] = colorbuffer[3];				// copy the 4th byte				}				currentbyte += tga.bytesPerPixel;										// Increase thecurrent byte by the number of bytes per pixel				currentpixel++;															// Increase current pixel by 1				if(currentpixel > pixelcount)											// Make sure we havent read too many pixels				{					MessageBox(NULL, "Too many pixels read", "ERROR", NULL);			// if there is too many... Display an error!					if(fTGA != NULL)													// If there is a file open					{						fclose(fTGA);													// Close file					}						if(colorbuffer != NULL)												// If there is data in colorbuffer					{						free(colorbuffer);												// Delete it					}					if(texture->imageData != NULL)										// If there is Image data					{						free(texture->imageData);										// delete it					}					return false;														// Return failed				}			}		}		else																			// chunkheader > 128 RLE data, next color reapeated chunkheader - 127 times		{			chunkheader -= 127;															// Subteact 127 to get rid of the ID bit			if(fread(colorbuffer, 1, tga.bytesPerPixel, fTGA) != tga.bytesPerPixel)		// Attempt to read following color values			{					MessageBox(NULL, "Could not read from file", "ERROR", MB_OK);			// If attempt fails.. Display error (again)				if(fTGA != NULL)														// If thereis a file open				{					fclose(fTGA);														// Close it				}				if(colorbuffer != NULL)													// If there is data in the colorbuffer				{					free(colorbuffer);													// delete it				}				if(texture->imageData != NULL)											// If thereis image data				{					free(texture->imageData);											// delete it				}				return false;															// return failed			}			for(short counter = 0; counter < chunkheader; counter++)					// copy the color into the image data as many times as dictated 			{																			// by the header				texture->imageData[currentbyte		] = colorbuffer[2];					// switch R and B bytes areound while copying				texture->imageData[currentbyte + 1	] = colorbuffer[1];				texture->imageData[currentbyte + 2	] = colorbuffer[0];				if(tga.bytesPerPixel == 4)												// If TGA images is 32 bpp				{					texture->imageData[currentbyte + 3] = colorbuffer[3];				// Copy 4th byte				}				currentbyte += tga.bytesPerPixel;										// Increase current byte by the number of bytes per pixel				currentpixel++;															// Increase pixel count by 1				if(currentpixel > pixelcount)											// Make sure we havent written too many pixels				{					MessageBox(NULL, "Too many pixels read", "ERROR", NULL);			// if there is too many... Display an error!					if(fTGA != NULL)													// If there is a file open					{						fclose(fTGA);													// Close file					}						if(colorbuffer != NULL)												// If there is data in colorbuffer					{						free(colorbuffer);												// Delete it					}					if(texture->imageData != NULL)										// If there is Image data					{						free(texture->imageData);										// delete it					}					return false;														// Return failed				}			}		}	}	while(currentpixel < pixelcount);													// Loop while there are still pixels left	fclose(fTGA);																		// Close the file	return true;																		// return success}
clint8565
clint8565
ok... it works with their TGAs now for the big test, mine

hmmm... it works kind of, it may be the image editor though I'm currently trying to get a better one, but at least I can make non-transparent TGAs now thanks!!!
clint8565
clint8565
Quote:
Original post by lc_overlord
ok i modified lessons33 tga load code, and apart from the previous bug i mentioned, this bugfix allso replaces a problem in the header compare code (you only need to compare one byte, why compare the whole thing)
just replace all the content in these files

First we have tga.h

*** Source Snippet Removed ***

TGAloader.cpp
*** Source Snippet Removed ***


I'm using Dev C++ with the modified lesson 33, but I can't get transparent TGAs, can someone help please

[Edited by - clint8565 on November 28, 2004 1:34:24 PM]
lc_overlord
lc_overlord
Yea, it's not just the tga load code, because it works just fine.
You have to create the texture as a GL_RGBA instead of GL_RGB

i made parts of the uncompressed image transparent and modified the LoadGLTextures function like this.

int LoadGLTextures()											// Load Bitmaps And Convert To Textures{	int Status=FALSE;											// Status Indicator	// Load The Bitmap, Check For Errors.	if (LoadTGA(&texture[0], "Data/Uncompressed.tga") &&		LoadTGA(&texture[1], "Data/Compressed.tga"))	{		Status=TRUE;											// Set The Status To TRUE			glGenTextures(1, &texture[0].texID);				// Create The Texture ( CHANGE )			glBindTexture(GL_TEXTURE_2D, texture[0].texID);			glTexImage2D(GL_TEXTURE_2D, 0, 4, texture[0].width, texture[0].height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture[0].imageData);			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);			if (texture[0].imageData)						// If Texture Image Exists ( CHANGE )			{				free(texture[0].imageData);					// Free The Texture Image Memory ( CHANGE )			}			// Typical Texture Generation Using Data From The TGA ( CHANGE )			glGenTextures(1, &texture[1].texID);				// Create The Texture ( CHANGE )			glBindTexture(GL_TEXTURE_2D, texture[1].texID);			glTexImage2D(GL_TEXTURE_2D, 0, 3, texture[1].width, texture[1].height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture[1].imageData);			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);			if (texture[1].imageData)						// If Texture Image Exists ( CHANGE )			{				free(texture[1].imageData);					// Free The Texture Image Memory ( CHANGE )			}			}	return Status;												// Return The Status}


then i added

glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);

before the first gl_Begin in the DrawGLScene function.

clint8565
clint8565
thank you so much, it took me a bit to figure out the program I'm using to get transparencies, but it's finally working :D, now I can make games without everything looking like they live in a box

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.