tga.h 3.69 KB
Newer Older
Anakin's avatar
Anakin committed
1
2
3
4
#pragma once
#include <fstream>
#include <QImage>
#include <QColor>
Anakin's avatar
Anakin committed
5
6
#include <QVector>
#include <QFile>
Anakin's avatar
Anakin committed
7

Anakin's avatar
Anakin committed
8
#include "Profiler.h"
Anakin's avatar
Anakin committed
9

Anakin's avatar
Anakin committed
10
QImage loadTga(QString filePath, bool &success)
Anakin's avatar
Anakin committed
11
{
Anakin's avatar
Anakin committed
12
	TIC("start");
Anakin's avatar
Anakin committed
13
	QImage img;
Anakin's avatar
Anakin committed
14
	success = true;
Anakin's avatar
Anakin committed
15

16
	// open the file
Anakin's avatar
Anakin committed
17
	QFile file(filePath);
Anakin's avatar
Anakin committed
18

Anakin's avatar
Anakin committed
19
	if (!file.open(QIODevice::ReadOnly))
20
21
22
	{
		success = false;
	}
Anakin's avatar
Anakin committed
23
	else
24
	{
Anakin's avatar
Anakin committed
25

Anakin's avatar
Anakin committed
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
		// read in the header
		quint8 ui8x18Header[19] = { 0 };
		file.read(reinterpret_cast<char*>(&ui8x18Header), sizeof(ui8x18Header) - 1);

		//get variables
		quint32 ui32BpP;
		quint32 ui32Width;
		quint32 ui32Height;
		quint32 ui32IDLength;
		quint32 ui32PicType;
		quint32 ui32PaletteLength;
		quint32 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
		file.seek(ui32IDLength + ui32PaletteLength + 18);

		img = QImage(ui32Width, ui32Height, QImage::Format_RGBA8888);

		// uncompressed
		if (ui32PicType == 2 && (ui32BpP == 24 || ui32BpP == 32))
57
		{
Anakin's avatar
Anakin committed
58
59
60
61
62
			QVector<quint8> vui8Pixels;
			vui8Pixels.resize(ui32Size);
			file.read(reinterpret_cast<char*>(vui8Pixels.data()), ui32Size);

			for (unsigned int y = 0; y < ui32Height; y++)
Anakin's avatar
Anakin committed
63
			{
Anakin's avatar
Anakin committed
64
				QRgb* imgLine = reinterpret_cast<QRgb*>(img.scanLine(ui32Height - y - 1));
Anakin's avatar
Anakin committed
65
66
				for (unsigned int x = 0; x < ui32Width; x++)
				{
Anakin's avatar
Anakin committed
67
					int valr = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8);
Anakin's avatar
Anakin committed
68
					int valg = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8 + 1);
Anakin's avatar
Anakin committed
69
					int valb = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8 + 2);
Anakin's avatar
Anakin committed
70
71
72
73
					int vala = 255;
					if (ui32BpP == 32)
						vala = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8 + 3);

Anakin's avatar
Anakin committed
74
					imgLine[x] = QColor(valr, valg, valb, vala).rgba();
Anakin's avatar
Anakin committed
75
				}
Anakin's avatar
Anakin committed
76
			}
Anakin's avatar
Anakin committed
77
		}
Anakin's avatar
Anakin committed
78
79
80
81
82
83
		// else if compressed 24 or 32 bit
		else if (ui32PicType == 10 && (ui32BpP == 24 || ui32BpP == 32))	// compressed
		{
			quint8 tempChunkHeader;
			quint8 tempData[5];
			unsigned int tmp_pixelIndex = 0;
Anakin's avatar
Anakin committed
84

Anakin's avatar
Anakin committed
85
86
			do {
				file.read(reinterpret_cast<char*>(&tempChunkHeader), sizeof(tempChunkHeader));
Anakin's avatar
Anakin committed
87

Anakin's avatar
Anakin committed
88
89
90
91
				if (tempChunkHeader >> 7)	// repeat count
				{
					// just use the first 7 bits
					tempChunkHeader = (quint8(tempChunkHeader << 1) >> 1);
Anakin's avatar
Anakin committed
92

Anakin's avatar
Anakin committed
93
					file.read(reinterpret_cast<char*>(&tempData), ui32BpP / 8);
Anakin's avatar
Anakin committed
94

Anakin's avatar
Anakin committed
95
96
97
					for (int i = 0; i <= tempChunkHeader; i++)
					{
						QColor color;
Anakin's avatar
Anakin committed
98

Anakin's avatar
Anakin committed
99
100
101
102
						if (ui32BpP == 32)
							color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], tempData[3]));
						else
							color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], 255));
Anakin's avatar
Anakin committed
103

Anakin's avatar
Anakin committed
104
105
106
						img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba());
						tmp_pixelIndex++;
					}
Anakin's avatar
Anakin committed
107
				}
Anakin's avatar
Anakin committed
108
				else						// data count
109
				{
Anakin's avatar
Anakin committed
110
111
					// just use the first 7 bits
					tempChunkHeader = (uint8_t(tempChunkHeader << 1) >> 1);
Anakin's avatar
Anakin committed
112

Anakin's avatar
Anakin committed
113
114
115
					for (int i = 0; i <= tempChunkHeader; i++)
					{
						file.read(reinterpret_cast<char*>(&tempData), ui32BpP / 8);
Anakin's avatar
Anakin committed
116

Anakin's avatar
Anakin committed
117
						QColor color;
Anakin's avatar
Anakin committed
118

Anakin's avatar
Anakin committed
119
120
121
122
123
124
125
126
						if (ui32BpP == 32)
							color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], tempData[3]));
						else
							color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], 255));

						img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba());
						tmp_pixelIndex++;
					}
Anakin's avatar
Anakin committed
127
				}
Anakin's avatar
Anakin committed
128
129
130
131
132
133
134
			} while (tmp_pixelIndex < (ui32Width * ui32Height));
		}
		// not useable format
		else
		{
			success = false;
		}
Anakin's avatar
Anakin committed
135
	}
136

Anakin's avatar
Anakin committed
137
138
139
140
	TOC("end");

	if (file.isOpen())
		file.close();
Anakin's avatar
Anakin committed
141
	return img;
142
	
Anakin's avatar
Anakin committed
143
}