141 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			141 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #pragma once
 | |
| #include <fstream>
 | |
| #include <QImage>
 | |
| #include <QColor>
 | |
| 
 | |
| #include <iostream>
 | |
| 
 | |
| QImage loadTga(QString filePath, bool &success)
 | |
| {
 | |
| 	QImage img;
 | |
| 	if (!img.load(filePath))
 | |
| 	{
 | |
| 
 | |
| 		// open the file
 | |
| 		std::fstream fsPicture(filePath.toStdString().c_str(), 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;
 | |
| 		}
 | |
| 
 | |
| 		// read in the header
 | |
| 		std::uint8_t ui8x18Header[19] = { 0 };
 | |
| 		fsPicture.read(reinterpret_cast<char*>(&ui8x18Header), sizeof(ui8x18Header) - 1);
 | |
| 
 | |
| 		//get variables
 | |
| 		std::uint32_t ui32BpP;
 | |
| 		std::uint32_t ui32Width;
 | |
| 		std::uint32_t ui32Height;
 | |
| 		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;
 | |
| 
 | |
| 		// jump to the data block
 | |
| 		fsPicture.seekg(ui32IDLength + ui32PaletteLength, std::ios_base::cur);
 | |
| 
 | |
| 		img = QImage(ui32Width, ui32Height, ui32BpP == 32? QImage::Format_RGBA8888 : QImage::Format_RGB888);
 | |
| 
 | |
| 		// uncompressed
 | |
| 		if (ui32PicType == 2 && (ui32BpP == 24 || ui32BpP == 32))
 | |
| 		{
 | |
| 			std::vector<std::uint8_t> vui8Pixels;
 | |
| 			vui8Pixels.resize(ui32Size);
 | |
| 			fsPicture.read(reinterpret_cast<char*>(vui8Pixels.data()), ui32Size);
 | |
| 
 | |
| 			for (unsigned int y = 0; y < ui32Height; y++)
 | |
| 			{
 | |
| 				for (unsigned int x = 0; x < ui32Width; x++)
 | |
| 				{
 | |
| 					int valr = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8 + 2);
 | |
| 					int valg = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8 + 1);
 | |
| 					int valb = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8);
 | |
| 
 | |
| 					QColor value(valr, valg, valb);
 | |
| 					img.setPixelColor(x, ui32Width - 1 - y, value);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		// 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 tmp_pixelIndex = 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++)
 | |
| 					{
 | |
| 						QColor color;
 | |
| 
 | |
| 						if (ui32BpP == 32)
 | |
| 							color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], tempData[3]));
 | |
| 						else
 | |
| 							color.setRgb(qRgb(tempData[2], tempData[1], tempData[0]));
 | |
| 
 | |
| 						img.setPixelColor(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color);
 | |
| 						tmp_pixelIndex++;
 | |
| 					}
 | |
| 				}
 | |
| 				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);
 | |
| 
 | |
| 						QColor color;
 | |
| 
 | |
| 						if (ui32BpP == 32)
 | |
| 							color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], tempData[3]));
 | |
| 						else
 | |
| 							color.setRgb(qRgb(tempData[2], tempData[1], tempData[0]));
 | |
| 
 | |
| 						img.setPixelColor(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color);
 | |
| 						tmp_pixelIndex++;
 | |
| 					}
 | |
| 				}
 | |
| 			} while (tmp_pixelIndex < (ui32Width * ui32Height));
 | |
| 		}
 | |
| 		// not useable format
 | |
| 		else
 | |
| 		{
 | |
| 			fsPicture.close();
 | |
| 			img = QImage(1, 1, QImage::Format_RGB32);
 | |
| 			img.fill(Qt::red);
 | |
| 			success = false;
 | |
| 			return img;
 | |
| 		}
 | |
| 
 | |
| 		fsPicture.close();
 | |
| 	}
 | |
| 	success = true;
 | |
| 	return img;
 | |
| }
 | 
