www.pudn.com > Gimcrack-v0.0051-Source.zip > targa.cpp


#include  
#include  
#include  
#include "targa.h" 
#include "tgaformat.h" 
using namespace std; 
 
/////////////////////////////////////////////////////////////////////////// 
 
GcTarga::GcTarga(): 
imageTypeCode(0), 
imageWidth(0), 
imageHeight(0), 
bitCount(0), 
imageData(NULL) 
{ 
	// Constructing the targa object 
} 
 
/////////////////////////////////////////////////////////////////////////// 
 
GcTarga::~GcTarga() 
{ 
	// Free memmory 
	Destroy(); 
} 
 
/////////////////////////////////////////////////////////////////////////// 
 
bool GcTarga::Load(char *fileName) 
{ 
	TGAHeader	header; 
 
	// Open the TGA file 
	ifstream file(fileName, ios::in | ios::binary); 
 
	// Check to see if opened 
	if(!file) { 
		MessageBox(NULL, "Failed to open TGA file.", "ERROR", MB_OK); 
		return false; 
	} 
 
	// Read the header 
	file.read((char*)&header, sizeof(TGAHeader)); 
 
	// Sasve neccessary data 
	imageTypeCode	= header.imageTypeCode; 
	imageWidth		= header.imageWidth; 
	imageHeight		= header.imageHeight; 
	bitCount		= header.bitCount; 
 
	// Check that it's the corect type 
	if((imageTypeCode != 2) && (imageTypeCode != 3) && (imageTypeCode != 10)) { 
		file.close(); 
		MessageBox(NULL, "The TGA file is not of a suported format", "ERROR", MB_OK); 
		return false; 
	} 
 
	if(imageTypeCode != 10)  
	{ 
		// Load a normal, non compressed tga 
		if(!LoadNormal(file)) { 
			file.close(); 
			return false; 
		}	 
	} 
	else 
	{ 
		// Load a RLE compressed tga 
		if(!LoadRLE(file)) { 
			file.close(); 
			return false; 
		}	 
	} 
 
	// Close the file 
	file.close(); 
 
	return true; 
} 
 
/////////////////////////////////////////////////////////////////////////// 
 
bool GcTarga::Write(char *fileName, uint width, uint height, uint screenBpp) 
{ 
	TGAHeader	header; 
	int			colorMode; 
	byte		colorSwap; 
	long		imageSize; 
 
	// Create file ofr writing 
	ofstream file(fileName, ios::out | ios::binary); 
 
	// Check to make sure it's opened corectly 
	if(!file) { 
		file.close(); 
		return false; 
	} 
	 
	// Clear the header 
	memset(&header, 0, sizeof(TGAHeader)); 
 
	// Fill the header with correct data 
	header.bitCount = screenBpp; 
	header.colorMapEntrySize = 0; 
	header.colorMapLenght = 0; 
	header.colorMapOrgin = 0; 
	header.colorMapType = 0; 
	header.imageDescriptor = 0; 
	header.imageHeight = height; 
	header.imageIDLenght = 0; 
	header.imageTypeCode = 2; 
	header.imageWidth = width; 
	header.imageXOrgin = 0; 
	header.imageYOrgin = 0; 
 
	// Get the color mode 
	colorMode = screenBpp / 8; 
 
	// Write the header data to the file 
	file.write((char*)&header, sizeof(TGAHeader)); 
 
	// Calculate the image size 
	imageSize = width * height * colorMode; 
 
	// Change image data from RGB to BGR 
	for(int i = 0; i < imageSize; i += colorMode) 
	{ 
		colorSwap = imageData[i]; 
		imageData[i] = imageData[i + 2]; 
		imageData[i + 2] = colorSwap; 
	} 
 
	// Write the image data 
	file.write((char*)imageData, imageSize); 
 
	// Close the file 
	file.close(); 
 
	return true; 
} 
 
/////////////////////////////////////////////////////////////////////////// 
 
void GcTarga::Screenshot(char *fileName, uint winWidth, uint winHeight, uint screenBpp) 
{ 
	/* WARNING! DO NOT USE THIS IF THE BITMAP ARE TO BE USED FURTHER ON */ 
 
	// Make sure that the memmory is freed 
	if(imageData != NULL) { 
		delete [] imageData; 
		imageData = NULL; 
	} 
 
	// Allocate and reset the memory 
	imageData = new byte[winWidth * winHeight * (screenBpp / 8)]; 
	memset(imageData, 0, sizeof(winWidth * winHeight * (screenBpp / 8))); 
 
	// Check for format 
	if(screenBpp == 32)  
	{ 
		// Read the image data from the window 
		glReadPixels(0, 0, winWidth, winHeight, GL_RGBA, GL_UNSIGNED_BYTE, imageData); 
	} 
	else  
	{ 
		// Read the image data from the window 
		glReadPixels(0, 0, winWidth, winHeight, GL_RGB, GL_UNSIGNED_BYTE, imageData); 
	} 
 
	// Write to TGA file 
	Write(fileName, winWidth, winHeight, screenBpp); 
 
	// Make sure that the memmory is freed 
	if(imageData != NULL) { 
		delete [] imageData; 
		imageData = NULL; 
	} 
} 
 
/////////////////////////////////////////////////////////////////////////// 
 
void GcTarga::Draw(uint xPos, uint yPos) 
{ 
	// Bind a null texture to "disable texturing 
	glBindTexture(GL_TEXTURE_2D, NULL); 
 
	// Set the correct drawing options 
	glPixelStorei(GL_UNPACK_ALIGNMENT, 4); 
 
	// Set the position 
	glRasterPos2i(xPos, yPos); 
	 
	// Draw the TGA 
	if(bitCount == 32) { 
		glDrawPixels(imageWidth, imageHeight, GL_RGBA, GL_UNSIGNED_BYTE, imageData); 
	} 
	else { 
		glDrawPixels(imageWidth, imageHeight, GL_RGB, GL_UNSIGNED_BYTE, imageData); 
	} 
} 
 
/////////////////////////////////////////////////////////////////////////// 
 
void GcTarga::Destroy() 
{ 
	if(imageData != NULL) {  
		delete [] imageData;  
		imageData = NULL;  
	}  
} 
 
/////////////////////////////////////////////////////////////////////////// 
 
bool GcTarga::LoadNormal(ifstream &file) 
{ 
	byte		colorMode; 
	byte		colorSwap; 
 
	// Check for depth 
	if((bitCount == 24) || (bitCount == 32)) 
	{ 
		// Get the color mode 
		colorMode = bitCount / 8; 
 
		// Calculate the size of the image 
		imageSize = imageWidth * imageHeight * colorMode; 
 
		// Allocate memory for image data 
		imageData = new byte[imageSize]; 
 
		// Read image data 
		file.read((char*)imageData, imageSize); 
 
		// Change BGR to RGB (BGRA to RGBA) 
		for(int i = 0; i < imageSize; i += colorMode) 
		{ 
			colorSwap = imageData[i]; 
			imageData[i] = imageData[i + 2]; 
			imageData[i + 2] = colorSwap; 
		} 
	} 
	else if(bitCount == 16) 
	{ 
		ushort *pixels; 
		int r = 0, g = 0, b = 0; 
 
		// RGB color mode (after conversion) 
		imageSize = imageWidth * imageHeight * 3; 
 
		// Allocate memory for image data 
		imageData = new byte[imageSize]; 
		byte *buffer = new byte[imageSize]; 
 
		// Read the image data 
		file.read((char*)buffer, imageSize); 
 
		// Set pointer to first group of pixles 
		pixels = (ushort*)buffer; 
 
		// Convert to 24 bit RGB 
		for(int i = 0; i < imageWidth * imageHeight; i++) 
		{ 
			// Change the pixel to 24 bit 
			b = (pixels[i] & 0x1f) << 3; 
			g = ((pixels[i] >> 5) & 0x1f) << 3; 
			r = ((pixels[i] >> 10) & 0x1f) << 3; 
			 
			// Swap to RGB and save in array 
			imageData[i * 3 + 0] = r; 
			imageData[i * 3 + 1] = g; 
			imageData[i * 3 + 2] = b; 
		} 
 
		// Free upp the memory 
		delete [] buffer; 
	} 
	else 
	{ 
		MessageBox(NULL, "TGA file of a not suported bpp", "Error", MB_OK); 
		return false; 
	} 
 
	return true; 
} 
 
/////////////////////////////////////////////////////////////////////////// 
 
bool GcTarga::LoadRLE(ifstream &file) 
{ 
	/* This code is based on gametutorials.com's tutorial */ 
	/* on loading a RLE TGA file.						  */								 
	byte	rleID = 0; 
	byte	colorCount = 0; 
	byte	colorMode = bitCount / 8; 
	int		colorsRead = 0; 
	int		stride = colorMode * imageWidth; 
	int		pixels = 0, j = 0; 
	int		counter = 0; 
	int		dataSize; 
 
 
	// Find the size of the image data 
	file.seekg(0, ios::end); 
	dataSize = file.tellg(); 
	dataSize -= sizeof(TGAHeader); 
 
	// Set position for data reading 
	file.seekg(sizeof(TGAHeader), ios::beg); 
 
	// Allocate memory for image data 
	imageData		= new byte[stride * imageHeight]; 
	byte *color		= new byte[colorMode]; 
	byte *buffer	= new byte[dataSize]; 
 
	// Read all image data to the buffer 
	file.read((char*)buffer, dataSize); 
 
	// Read the image data 
	while(pixels < imageWidth * imageHeight) 
	{ 
		// Read in the current color count + 1 
		rleID = buffer[counter++]; 
		 
		if(rleID < 128) 
		{ 
			/* The colroCount number of colors are uniqe */ 
 
			// Calculate the number of colors to be read 
			colorCount = rleID + 1; 
 
			// Go through and read all the unique colors found 
			while(colorCount) 
			{ 
				// Read in the current color 
				for(j = 0; j < colorMode; j++) { 
					color[j] = buffer[counter++]; 
				} 
 
				// Store the current pixel in our image array 
				imageData[colorsRead + 0] = color[2]; 
				imageData[colorsRead + 1] = color[1]; 
				imageData[colorsRead + 2] = color[0]; 
 
				// Is this a RGBA file? 
				if(bitCount == 32) { 
					imageData[colorsRead + 3] = color[3]; 
				} 
 
				pixels++; 
				colorCount--; 
				colorsRead += colorMode; 
			} 
		} 
		else 
		{ 
			/* The colroCount number of colors are the same */ 
 
			// Calculate the number of colors to be read 
			colorCount = rleID - 127; 
 
			// Read in the current color 
			for(j = 0; j < colorMode; j++) { 
				color[j] = buffer[counter++]; 
			} 
 
			// Write colorCount pixels of the smae color to the imageData 
			while(colorCount) 
			{ 
				// Swap to RGB form BGR 
				imageData[colorsRead + 0] = color[2]; 
				imageData[colorsRead + 1] = color[1]; 
				imageData[colorsRead + 2] = color[0]; 
 
				// Is this a RGBA file? 
				if(bitCount == 32) { 
					imageData[colorsRead + 3] = color[3]; 
				} 
 
 
				pixels++; 
				colorCount--; 
				colorsRead += colorMode; 
			}	 
		}		 
	} 
 
	// Free up the memory 
	delete [] color; 
	delete [] buffer; 
 
	return true; 
} 
 
///////////////////////////////////////////////////////////////////////////