diff --git a/QtMeshViewer/Header/tga.h b/QtMeshViewer/Header/tga.h new file mode 100644 index 0000000..957f110 --- /dev/null +++ b/QtMeshViewer/Header/tga.h @@ -0,0 +1,139 @@ +#pragma once +#include +#include +#include + +#include + +QImage loadTga(const char* filePath, bool &success) +{ + QImage img; + if (!img.load(filePath)) + { + + // open the file + std::fstream fsPicture(filePath, std::ios::in | std::ios::binary); + + if (!fsPicture.is_open()) + { + img = QImage(1, 1, QImage::Format_RGB32); + img.fill(Qt::red); + success = false; + return img; + } + + // some variables + std::vector* vui8Pixels; + std::uint32_t ui32BpP; + std::uint32_t ui32Width; + std::uint32_t ui32Height; + + // read in the header + std::uint8_t ui8x18Header[19] = { 0 }; + fsPicture.read(reinterpret_cast(&ui8x18Header), sizeof(ui8x18Header) - 1); + + //get variables + vui8Pixels = new std::vector; + 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 (ui32PicType == 2 && (ui32BpP == 24 || ui32BpP == 32)) + { + fsPicture.read(reinterpret_cast(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(&tempChunkHeader), sizeof(tempChunkHeader)); + + if (tempChunkHeader >> 7) // repeat count + { + // just use the first 7 bits + tempChunkHeader = (uint8_t(tempChunkHeader << 1) >> 1); + + fsPicture.read(reinterpret_cast(&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(&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(); + img = QImage(1, 1, QImage::Format_RGB32); + img.fill(Qt::red); + success = false; + return img; + } + + fsPicture.close(); + + img = QImage(ui32Width, ui32Height, QImage::Format_RGB888); + + int pixelSize = ui32BpP == 32 ? 4 : 3; + //TODO: write direct into img + for (unsigned int x = 0; x < ui32Width; x++) + { + for (unsigned int y = 0; y < ui32Height; y++) + { + int valr = vui8Pixels->at(y * ui32Width * pixelSize + x * pixelSize + 2); + int valg = vui8Pixels->at(y * ui32Width * pixelSize + x * pixelSize + 1); + int valb = vui8Pixels->at(y * ui32Width * pixelSize + x * pixelSize); + + QColor value(valr, valg, valb); + img.setPixelColor(x, y, value); + } + } + + img = img.mirrored(); + + } + success = true; + return img; +} diff --git a/QtMeshViewer/Source/GeometryEngine.cpp b/QtMeshViewer/Source/GeometryEngine.cpp index 6420288..49ccbbd 100644 --- a/QtMeshViewer/Source/GeometryEngine.cpp +++ b/QtMeshViewer/Source/GeometryEngine.cpp @@ -2,6 +2,7 @@ #include "..\Header\MshFile.h" #include "..\Header\OglViewerWidget.h" #include "..\Header\MainWindow.h" +#include "..\Header\tga.h" #include @@ -110,13 +111,8 @@ void GeometryEngine::loadFile(const char* filePath) void GeometryEngine::loadTexture(const char* filePath) { - - QImage img; - if (!img.load(filePath)) - { - img = QImage(1, 1, QImage::Format_RGB32); - img.fill(Qt::red); - } + bool loadSuccess; + QImage img = loadTga(filePath, loadSuccess); // Load image to OglTexture QOpenGLTexture* new_texture = new QOpenGLTexture(img.mirrored()); diff --git a/QtMeshViewer/Source/MainWindow.cpp b/QtMeshViewer/Source/MainWindow.cpp index d908ed3..cd5afa6 100644 --- a/QtMeshViewer/Source/MainWindow.cpp +++ b/QtMeshViewer/Source/MainWindow.cpp @@ -5,6 +5,7 @@ #include #include #include +#include "..\Header\FileInterface.h" #define WINDOW_NAME "Mesh Viewer" diff --git a/Release/Msh/texture32R.tga b/Release/Msh/texture32R.tga index b54937f..6b996ed 100644 Binary files a/Release/Msh/texture32R.tga and b/Release/Msh/texture32R.tga differ