120 lines
3.1 KiB
C++
120 lines
3.1 KiB
C++
|
#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
|
||
|
std::uint8_t ui8x18Header[19] = { 0 };
|
||
|
fsPicture.read(reinterpret_cast<char*>(&ui8x18Header), sizeof(ui8x18Header)-1);
|
||
|
|
||
|
//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;
|
||
|
|
||
|
// 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;
|
||
|
vui8Pixels->resize(ui32Size);
|
||
|
|
||
|
// 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))
|
||
|
{
|
||
|
fsPicture.read(reinterpret_cast<char*>(vui8Pixels->data()), ui32Size);
|
||
|
}
|
||
|
// else if compressed 24 or 32 bit
|
||
|
else if (ui32PicType == 10 && (ui32BpP == 24 || ui32BpP == 32)) // compressed
|
||
|
{
|
||
|
std::uint8_t tempChunkHeader;
|
||
|
std::uint8_t tempData[5];
|
||
|
unsigned int tempByteIndex = 0;
|
||
|
|
||
|
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++)
|
||
|
{
|
||
|
vui8Pixels->at(tempByteIndex++) = tempData[0];
|
||
|
vui8Pixels->at(tempByteIndex++) = tempData[1];
|
||
|
vui8Pixels->at(tempByteIndex++) = tempData[2];
|
||
|
if(ui32BpP == 32) vui8Pixels->at(tempByteIndex++) = tempData[3];
|
||
|
}
|
||
|
}
|
||
|
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);
|
||
|
|
||
|
vui8Pixels->at(tempByteIndex++) = tempData[0];
|
||
|
vui8Pixels->at(tempByteIndex++) = tempData[1];
|
||
|
vui8Pixels->at(tempByteIndex++) = tempData[2];
|
||
|
if (ui32BpP == 32) vui8Pixels->at(tempByteIndex++) = tempData[3];
|
||
|
}
|
||
|
}
|
||
|
} while (tempByteIndex < ui32Size);
|
||
|
}
|
||
|
// not useable format
|
||
|
else
|
||
|
{
|
||
|
fsPicture.close();
|
||
|
throw std::invalid_argument("Invaild File Format! Required 24 or 31 Bit Image.");
|
||
|
}
|
||
|
|
||
|
fsPicture.close();
|
||
|
}
|
||
|
|
||
|
TextureTGA::~TextureTGA()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
std::vector<std::uint8_t>* TextureTGA::getData() const
|
||
|
{
|
||
|
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;
|
||
|
}
|