Welcome! Log In Create A New Profile

Advanced

Targa (TGA) loading

Posted by dancinninja 
Targa (TGA) loading
December 08, 2010 06:54AM
Howdy all. I'm trying to load in my texture files from the SD card, and I'm having a bit of trouble. The targa loading function is based on the Nehe OpenGL lession #24.

I have run some tests and if I load in the textures via tpl files and have the textures be part of the binary, everything works as it should. The trouble is in the tga file loading. I get, for lack of a better term, "pink garbage". Not only are the colors all wrong, but the actual picture looks like static. Pink static. With transparent stripes. Here is my converted function:

(Note, I have a define in there, NEW_TEXTURE_ALLOCATION, which is my attempt to "correct" the information read in. The original, from the Nehe tutorials, is included below that).

bool LoadTextureFromTGA(char * fileName, GXTexObj &textureObj){
	const u8 TGAheader[12] = {0,0,2,0,0,0,0,0,0,0,0,0};      // Uncompressed TGA header
	u8 TGAcompare[12];               // Used to compare TGA header
	u8 header[6];                    // First 6 useful bytes from the header
	u32 bytesPerPixel;               // Holds number of bytes per pixel used in the TGA file
	u32 bpp;                         // Image color depth in bits per pixel
	u32 imageSize;                   // Used to store the image size when setting aside ram
	u8 *imageData = 0;	             // Image data (Up To 32 Bits)
	u32 temp;                        // Temporary variable
	//u32 type = GL_RGBA;            // Set the default GL mode to RBGA (32 BPP)
	u32 width;                       // Image width
	u32 height;                      // Image height

	FILE *file = fopen(fileName, "rb");            // Open the TGA file

	if( !file || fread(TGAcompare,1,sizeof(TGAcompare),file)!=sizeof(TGAcompare) ||  
		memcmp(TGAheader,TGAcompare,sizeof(TGAheader))!=0 ||                
		fread(header,1,sizeof(header),file)!=sizeof(header)){             

		if (!file){
			fprintf(stderr,"Error: Cannot load %s\n", fileName);
			return false;
		}else{
			fprintf(stderr,"Error: %s is an invalid TGA texture\n", fileName);
			fclose(file);                // If anything failed, close the file
			return false;
		}
	}

	width  = header[1] * 256 + header[0];        // Determine the TGA width (highbyte*256+lowbyte)
	height = header[3] * 256 + header[2];        // Determine the TGA height (highbyte*256+lowbyte)

	if(width <= 0 || height <= 0 || (header[4]!=24 && header[4]!=32)){ // Is the TGA 24 or 32 bit?

		fprintf(stderr,"Error: %s is an invalid TGA texture\n", fileName);
		fclose(file);                    // If anything failed, close the file
		return false;
	}

	bpp = header[4];                           // Grab the TGA's bits per pixel (24 or 32)
	bytesPerPixel = bpp/8;                     // Divide by 8 to get the bytes per pixel
	imageSize = width*height*bytesPerPixel;    // Calculate the memory required for the TGA data


#ifdef NEW_TEXTURE_ALLOCATION

	// We add in an alpha channel if there isn't one, since there is no texture format: GX_RGB 

	u8* tempData = new u8 [imageSize];       

	if(!tempData || fread(tempData, 1, imageSize, file) != imageSize){
		delete[] tempData;
		fprintf(stderr,"Error: cannot load %s\n", fileName);
		fclose(file);                       // Close the file
		return false;
	} 
	fclose (file);                            // Close the file

	imageData = new u8 [width*height*4];   //This will always be 32 bits

	if(bytesPerPixel == 4){
		// We have an alpha channel
		for(u32 i = 0; i < imageSize; i += bytesPerPixel){
	                                    
			imageData   = tempData[i+2];               
			imageData[i+1] = tempData[i+1];  
			imageData[i+2] = tempData[i+0]; 
			imageData[i+3] = tempData[i+3]; 
		}
	}else{
		// We do NOT have an alpha channel; add our own.
		u32 j = 0;
		for(u32 i = 0; i < imageSize; i += bytesPerPixel){
	                                       
			imageData[j+0] = tempData[i+2];               
			imageData[j+1] = tempData[i+1];  
			imageData[j+2] = tempData[i+0]; 
			imageData[j+3] = 0xff; 

			j += 4;		// 4 bytes per pixel

		}

	}

	#else

	 // This is the original:
	imageData = new u8 [imageSize];        // Reserve memory to hold the TGA data

	if(!imageData ||                        // Does the storage memory exist?
		fread(imageData, 1, imageSize, file)!=imageSize){    // Does the image size match the memory reserved?
		delete[] imageData;            // If so, release the image data
		fprintf(stderr,"Error: cannot load %s\n", fileName);
		fclose(file);                       // Close the file
		return false;
	}

	fclose (file);                            // Close the file

	for(u32 i = 0; i < imageSize; i += bytesPerPixel){         // Loop through the image data
											// Swaps the 1st and 3rd bytes ('R'ed and 'B'lue)
		temp=imageData;                  // Temporarily store the value at image data 'i'
		imageData = imageData[i + 2];    // Set the 1st byte to the value of the 3rd byte
		imageData[i + 2] = temp;            // Set the 3rd byte to the value in 'temp' (1st byte value)
	}

	#endif


	GX_InitTexObj(&textureObj, imageData, width, height, GX_TF_RGBA8, 
		GX_CLAMP, GX_CLAMP, GX_FALSE);

	// Mipmaping... maybe later.
	//GX_InitTexObjLOD(&textureObj, GX_LIN_MIP_LIN, GX_LINEAR, 0, 5, 0, GX_DISABLE, GX_DISABLE, GX_ANISO_1);
	// I also made up values for min LOD, max LOD, and the LOD bias.

	delete[] imageData;

	return true;            // Texture building went Ok, return true
}
What am I doing wrong?
Re: Targa (TGA) loading
December 08, 2010 11:14AM
I think what is going wrong is that the Wii RGBA format is not what you think it is. It's not the same as the OpenGL RGBA format (also caught me offguard)

OpenGL RGBA is just a linear array of 32 bit values containing the pixel data.
Wii RGBA is 4x4 RGBA, it contains 4x4 pixel blocks in 32x 16 bit values, where the first 16x 16 bit values are red+alpha and the next 16x 16bit are green+blue.

PNG files can be loaded with the PNGU library, which contains a 4x4RGBA loader. You can adapt that code to read TGA files instead of PNG files.
PNGU: [wiibrew.org]
Re: Targa (TGA) loading
December 08, 2010 09:28PM
Of course! How silly of me.

Looking at the code for pngu, maybe I should just switch to pngs. Yikes. I'm not sure what the differences between pngs and tgas are. If I just plopped the code into the tga reader, it probably wouldn't work, would it?
Re: Targa (TGA) loading
December 08, 2010 09:33PM
Well, I would just go for PNG files unless you have a special reason to need to support TGA.
PNG can do everything that TGA can do, at a smaller file size.
Re: Targa (TGA) loading
December 09, 2010 02:28AM
You sure the values you're calculating are correct? TGA is little-endian I'm surprised it's not code dumped it's probably calculating massive width/height and bpp values?
Re: Targa (TGA) loading
December 09, 2010 03:32AM
Looks to me like he's already byte-swapping the width and height, and bpp is only one byte long.
Re: Targa (TGA) loading
December 09, 2010 06:48PM
You're correct I missed that. Never seen it done by multiplication before.
Sorry, only registered users may post in this forum.

Click here to login