Texture.cpp 3.12 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
#include "Texture.h"
#include <fstream>

TextureTGA::TextureTGA(const char * filePath)
{
	// open the file
	std::fstream fsPicture(filePath, std::ios::in | std::ios::binary);

	if (!fsPicture.is_open())
		throw std::invalid_argument(std::string("file not found: ") += filePath);

	// read in the header
Anakin's avatar
Anakin committed
13 14
	std::uint8_t ui8x18Header[19] = { 0 };
	fsPicture.read(reinterpret_cast<char*>(&ui8x18Header), sizeof(ui8x18Header)-1);
15
	
16 17 18 19 20 21 22 23
	//get variables
	vui8Pixels = new std::vector<std::uint8_t>;
	bool bCompressed;
	std::uint32_t ui32IDLength;
	std::uint32_t ui32PicType;
	std::uint32_t ui32PaletteLength;
	std::uint32_t ui32Size;

24 25 26 27 28 29 30 31 32 33 34
	// extract all information from header
	ui32IDLength = ui8x18Header[0];
	ui32PicType = ui8x18Header[2];
	ui32PaletteLength = ui8x18Header[6] * 0x100 + ui8x18Header[5];
	ui32Width = ui8x18Header[13] * 0x100 + ui8x18Header[12];
	ui32Height = ui8x18Header[15] * 0x100 + ui8x18Header[14];
	ui32BpP = ui8x18Header[16];

	// calculate some more information
	ui32Size = ui32Width * ui32Height * ui32BpP/8;
	bCompressed = ui32PicType == 9 || ui32PicType == 10;
35
	vui8Pixels->resize(ui32Size);
36 37 38 39 40 41 42

	// jump to the data block
	fsPicture.seekg(ui32IDLength + ui32PaletteLength, std::ios_base::cur);

	// If not compressed 24 or 32 bit
	if (ui32PicType == 2 && (ui32BpP == 24 || ui32BpP == 32))
	{
43
		fsPicture.read(reinterpret_cast<char*>(vui8Pixels->data()), ui32Size);
44 45 46 47
	}
	// else if compressed 24 or 32 bit
	else if (ui32PicType == 10 && (ui32BpP == 24 || ui32BpP == 32))	// compressed
	{
Anakin's avatar
Anakin committed
48 49
		std::uint8_t tempChunkHeader;
		std::uint8_t tempData[5];
Anakin's avatar
Anakin committed
50
		unsigned int tempByteIndex = 0;
Anakin's avatar
Anakin committed
51 52 53 54 55 56 57 58 59 60 61 62 63

		do {
			fsPicture.read(reinterpret_cast<char*>(&tempChunkHeader), sizeof(tempChunkHeader));

			if (tempChunkHeader >> 7)	// repeat count
			{
				// just use the first 7 bits
				tempChunkHeader = (uint8_t(tempChunkHeader << 1) >> 1);

				fsPicture.read(reinterpret_cast<char*>(&tempData), ui32BpP/8);

				for (int i = 0; i <= tempChunkHeader; i++)
				{
64 65 66 67
					vui8Pixels->at(tempByteIndex++) = tempData[0];
					vui8Pixels->at(tempByteIndex++) = tempData[1];
					vui8Pixels->at(tempByteIndex++) = tempData[2];
					if(ui32BpP == 32) vui8Pixels->at(tempByteIndex++) = tempData[3];
Anakin's avatar
Anakin committed
68 69 70 71 72 73 74 75 76 77 78
				}
			}
			else						// data count
			{
				// just use the first 7 bits
				tempChunkHeader = (uint8_t(tempChunkHeader << 1) >> 1);

				for (int i = 0; i <= tempChunkHeader; i++)
				{
					fsPicture.read(reinterpret_cast<char*>(&tempData), ui32BpP/8);

79 80 81 82
					vui8Pixels->at(tempByteIndex++) = tempData[0];
					vui8Pixels->at(tempByteIndex++) = tempData[1];
					vui8Pixels->at(tempByteIndex++) = tempData[2];
					if (ui32BpP == 32) vui8Pixels->at(tempByteIndex++) = tempData[3];
Anakin's avatar
Anakin committed
83 84 85
				}
			}
		} while (tempByteIndex < ui32Size);
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
	}
	// not useable format
	else
	{
		fsPicture.close();
		throw std::invalid_argument("Invaild File Format! Required 24 or 31 Bit Image.");
	}

	fsPicture.close();
}

TextureTGA::~TextureTGA()
{
}

101
std::vector<std::uint8_t>* TextureTGA::getData() const
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
{
	return vui8Pixels;
}

bool TextureTGA::hasAlpha() const
{
	return ui32BpP == 32;
}

std::uint32_t TextureTGA::getWidth() const
{
	return ui32Width;
}

std::uint32_t TextureTGA::getHeight() const
{
	return ui32Height;
}