Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

justinwalsh

NeHe Lesson 33 TGA Loading HELP!! please

This topic is 5222 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Well First off i am rewriteing the TGAloader i have the uncompressed loading working very well, but i cant get the compressed TGA loading to work. I am trying to rewrite all the stdio.h functions to the c++ fstream functions. It will load a compressed TGA, but the pixel coloring is all way off. PLease help me. I fear it is something simple, yet i have been codeing for far too long and cant see it. hear is my version of the LoadCompressedTGA function:
//modified by Justin Walsh

bool LoadCompressedTGA(Texture* texture, char* fileName, ifstream* TGAin)  {
//Texture retTexture;

	//TGAin.open(TGAfileName,ios::binary);

	//TGAin.seekg(placeHolder);


	TGAin->read((char*) &tga.header, sizeof(tga.header));//Read Header

	if(TGAin->fail())  {									//If error...

		TGAin->close();			
		return false;										//close file and exit

	}

	texture->width = tga.header[1] * 256 + tga.header[0];
	texture->height = tga.header[3] * 256 + tga.header[2];
	texture->bpp = tga.header[4];
	tga.Width = texture->width;
	tga.Height = texture->height;
	tga.Bpp = texture->bpp;

	if((  texture->width <= 0) || (texture->height <= 0) 
		                       || ((texture->bpp != 24) && (texture->bpp !=32)))  {
		TGAin->close();
		return false;
	}

	if(texture->bpp == 24)
		texture->type = GL_RGB;
	else
		texture->type = GL_RGBA;

	tga.bytesPerPixel = (tga.Bpp / 8);					//Calculate BYTES

	//Calculate memory needed to store TGA

	tga.imageSize = (tga.bytesPerPixel * tga.Width * tga.Height);
	
	texture->imageData = (GLubyte*)malloc(tga.imageSize);
	if(texture->imageData == NULL)  {					//Is there memory?

		TGAin->close();			
		return false;										//close file and exit

	}

	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  {								// Start Loop

		GLubyte chunkheader = 0;			// Variable To Store The Value Of The Id Chunk

		TGAin->read((char*) &chunkheader, sizeof(GLubyte));
		if(TGAin->fail())  {
			if(texture->imageData != NULL)  {	// If there is stored image data

				free(texture->imageData);		// Delete image data

			}
			TGAin->close();
			return false;
		}

		if(chunkheader < 128)  {		// If The Chunk Is A ''RAW'' Chunk							

			chunkheader++;				// Add 1 To The Value To Get Total Number Of Raw Pixels

			for(short counter = 0; counter < chunkheader; counter++)  {
			// Try To Read 1 Pixel

				TGAin->read((char*) &colorBuffer, tga.bytesPerPixel);
				if(TGAin->gcount() != tga.bytesPerPixel)  {
					if(colorBuffer != NULL)  {	// See if colorbuffer has data in it

						free(colorBuffer);		// If so, delete it

					}
					TGAin->close();
					return false;
				}

				texture->imageData[currentByte      ] = colorBuffer[2];		// Write The ''R'' Byte

				texture->imageData[currentByte + 1	] = colorBuffer[1];	// Write The ''G'' Byte

				texture->imageData[currentByte + 2	] = colorBuffer[0];	// Write The ''B'' Byte


				if(tga.bytesPerPixel == 4)  {					// If It''s A 32bpp Image...

			
					texture->imageData[currentByte + 3] = colorBuffer[3];	// Write The ''A'' Byte

				}

				// Increment The Byte Counter By The Number Of Bytes In A Pixel

				currentByte += tga.bytesPerPixel;
				currentPixel++;						// Increment The Number Of Pixels By 1


				if(currentPixel > pixelCount)  {	// Make sure we havent read too many pixels

					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

					TGAin->close();
					return false;
				}

			}
		}  else  {						// If It''s An RLE Header

			chunkheader -= 127;			// Subtract 127 To Get Rid Of The ID Bit

			// Read The Next Pixel

			TGAin->read((char*) &colorBuffer, tga.bytesPerPixel);
			if(TGAin->gcount() != tga.bytesPerPixel)  {
				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

				TGAin->close();
				return false;
			}

			for(short counter = 0; counter < chunkheader; counter++)  {
				// Copy The ''R'' Byte

				texture->imageData[currentByte		] = colorBuffer[2];
				// Copy The ''G'' Byte

				texture->imageData[currentByte + 1	] = colorBuffer[1];
				// Copy The ''B'' Byte

				texture->imageData[currentByte + 2	] = colorBuffer[0];
				if(tga.bytesPerPixel == 4)  {		// If It''s A 32bpp Image

					// Copy The ''A'' Byte

					texture->imageData[currentByte + 3] = colorBuffer[3];
				}
				currentByte += tga.bytesPerPixel;	// Increment The Byte Counter

				currentPixel++;				// Increment The Pixel Counter

				if(currentPixel > pixelCount)  {	// Make sure we havent read too many pixels

					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

					TGAin->close();
					return false;
				}
			}
		}
	}
	while(currentPixel < pixelCount);
	TGAin->close();
	return true;
}
hear is a link to the original project: NeHe Lesson 33 hear is the original function code:
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(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 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

}
I am stuck, i have tried anilizing debugging etc. The only thing i noticed is that my version on the debug returns the pixel color values wrong.

Share this post


Link to post
Share on other sites
Advertisement
Did you really had to rewrite the code with the ifstream class instead off using the FILE var?

No offence or anything. Just wondering.

Oh, the images you see, can you at least make out what it is, even if the colors are wrong?

// Last Attacker \\---=( LA )=---// LA Extreme \\

ICQ Number : 120585863

E-mail: laextr@icqmail.com

[edited by - Last Attacker on March 1, 2004 4:10:36 AM]

Share this post


Link to post
Share on other sites
Yeah the image looks perfect just completely wrong colors, like the green color is purple, and the red color is black. I probably didnt really have to do it, but i figure the best way to lear is to just do it. And i am turning it into a class as well, and i dont feel lie haveing old c code, i want everything to be C++. If you guys need me to post the project i can zip it up if it helps just let me know.

Share this post


Link to post
Share on other sites
Ok, its possible that you havn't swapped the Red and Blue colors when you read the data from the file. You see a TGA and BMP file stores the color data as follows BGR - bytes, instead of RGB - bytes.

I saw that you have used color swapping, but make sure you start at the right place when you read the image data.

Here is a statement to jump right into the image data. Excuse the old C-file vars.

if(fseek(fp, 18 + TGA_Compare[0], SEEK_SET))  


NOTE : That statement above is to check if it couldn't jump there. If it couldn't, then print an error message, etc. else, no problem.

Does your UnCompressed TGA File Loader do the same?

If you want, I can give you my TGA loader code. It uses the C-Files but it can open 8, 16, 24 and 32 bit images, compressed or uncompressed.

// Last Attacker \\---=( LA )=---// LA Extreme \\

ICQ Number : 120585863

E-mail: laextr@icqmail.com

[edited by - Last Attacker on March 1, 2004 6:20:58 AM]

Share this post


Link to post
Share on other sites
ok, i think the error lies inthis line...

original
if(fread(colorbuffer, 1, tga.bytesPerPixel, fTGA) != tga.bytesPerPixel)

how would i convert that statment into the C++ version?

mine is as this right now, and its not reading right.
TGAin->read((char*) &colorBuffer, tga.bytesPerPixel);

ok got it......
i changed it to this.....
TGAin->read((char*) &colorBuffer[0], 1);
TGAin->read((char*) &colorBuffer[1], 1);
TGAin->read((char*) &colorBuffer[2], 1);

anyone know how i could do that in one read line?

Share this post


Link to post
Share on other sites
Use a struct.

For instance :


---header file---
struct RGB_STRUCT
{
char BLUE;
char GREEN;
char RED;
}rgb;

---loading file---
rgb ReadRGB;


TGAin->read((char*) &ReadRGB, sizeof(ReadRGB));


Well, I hope this works for you.

EDIT: If you have an Alpha channel too, just add it into the struct below RED. You can change the char to :
typedef unsigned char UBYTE;

Works for me!

// Last Attacker \\---=( LA )=---// LA Extreme \\

ICQ Number : 120585863

E-mail: laextr@icqmail.com

[edited by - Last Attacker on March 2, 2004 1:11:36 AM]

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!