⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 targa.cpp

📁 小型的3D游戏引擎
💻 CPP
字号:
#include <windows.h>
#include <fstream>
#include <gl/gl.h>
#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;
}

///////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -