SWBF2-Classic-Msh-Viewer/MshViewer/Source/Texture.cpp

131 lines
3.7 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);
// extract all information from header
ui32IDLength = ui8x18Header[0];
bColorTabel = ui8x18Header[1] == 1;
ui32PicType = ui8x18Header[2];
ui32PaletteBegin = ui8x18Header[4] * 0x100 + ui8x18Header[3];
ui32PaletteLength = ui8x18Header[6] * 0x100 + ui8x18Header[5];
ui32PaletteBpP = ui8x18Header[7];
ui32Width = ui8x18Header[13] * 0x100 + ui8x18Header[12];
ui32Height = ui8x18Header[15] * 0x100 + ui8x18Header[14];
ui32BpP = ui8x18Header[16];
ui32Attribut = ui8x18Header[17];
// calculate some more information
ui32Size = ui32Width * ui32Height * ui32BpP/8;
bCompressed = ui32PicType == 9 || ui32PicType == 10;
vui8Pixels.resize(ui32Size);
/* consol output of the header
std::cout << "Header\n"
<< "ID länge: " << ui32IDLength << std::endl
<< "Farbtabelle: " << (int)bColorTabel << std::endl
<< "Bildtype: " << ui32PicType << std::endl
<< "Palletenbegin: " << ui32PaletteBegin << std::endl
<< "Palletenlängen: " << ui32PaletteLength << std::endl
<< "Bits pro Palleteneintrag: " << ui32PaletteBpP << std::endl
<< "Breite: " << ui32Width << std::endl
<< "Höhe: " << ui32Height << std::endl
<< "Bit pro Pixel: " << ui32BpP << std::endl
<< "Bild Attribute: " << ui32Attribut << std::endl;*/
// 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];
int tempByteIndex = 0;
std::size_t tempPixelIndex = 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[tempByteIndex++] = tempData[0];
vui8Pixels[tempByteIndex++] = tempData[1];
vui8Pixels[tempByteIndex++] = tempData[2];
if(ui32BpP == 32) vui8Pixels[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[tempByteIndex++] = tempData[0];
vui8Pixels[tempByteIndex++] = tempData[1];
vui8Pixels[tempByteIndex++] = tempData[2];
if (ui32BpP == 32) vui8Pixels[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()
{
vui8Pixels.clear();
}
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;
}