-
Notifications
You must be signed in to change notification settings - Fork 0
/
tga_load.cpp
131 lines (114 loc) · 3.21 KB
/
tga_load.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* TARGA file must be 32 bpp, correct resolution, with 0|0 left-bottom origin,
no Color Map, no Image Identification */
template <>
bool SciResourceNan<SciPixel>::LoadTGA(cstr fname)
{
std::fstream img(fname, std::fstream::in | std::fstream::binary | std::fstream::ate);
if(!img.is_open() || !img.tellg())
{
return false; // Error, file could not be opened or it's empty
}
char b;
TgaHeader head;
img.seekg(0); // Return to the beginning of a file
while(img.get(b))
{
switch((int)img.tellg()-1)
{
case 2:
head.image_type = b;
break;
case 12:
{
byte low_byte = b; // Save low order byte of width (little-endian)
img.get(b); // Move 1 byte forward, to high order byte
int high_byte = (byte)b;
head.width = (high_byte << 8) + low_byte; // Combine 2 bytes to form width
img.get(b); // Move on to height bytes
low_byte = b;
img.get(b);
high_byte = (byte)b;
head.height = (high_byte << 8) + low_byte; // Combine 2 bytes to form height
img.get(b); // Move on to "bits per pixel" byte
head.bpp = b;
break;
}
case 18:
if(head.width != width_ || head.height != height_ || head.bpp != 32)
{
return false; // Exit function, incorrect image dimentions or bpp
}
switch(head.image_type)
{
case 2: // Unmapped (raw) RGB image
for(int i = 0; i < size_; ++i)
{
data[i].b = charToFloat(b);
img.get(b); // Move to green
data[i].g = charToFloat(b);
img.get(b); // Move to red
data[i].r = charToFloat(b);
img.get(b); // Move to alpha
data[i].a = charToFloat(b);
img.get(b); // Move to next pixel
}
break;
case 10: // Run Length Encoded (RLE) RGB image
for(int i = 0; i < size_; ++i)
{
const byte mask_id = 128;
const byte mask_length = 127;
const byte packet = b; // Packet header
const byte pl = (packet & mask_length) + 1; // Packet length
const int pix_to_fill = i + pl; // bound on how much pixels to fill
if(packet & mask_id) // Run-length packet
{
SciPixel run_color;
img.get(b); // Move to color bytes
run_color.b = charToFloat(b);
img.get(b); // Move to green
run_color.g = charToFloat(b);
img.get(b); // Move to red
run_color.r = charToFloat(b);
img.get(b); // Move to alpha
run_color.a = charToFloat(b);
for(int j = i; j < pix_to_fill; ++j)
{
// Set run-color to all pixels of packet length
data[j] = run_color;
++i;
}
--i;
img.get(b); // Move to next packet's header byte
}
else // Raw packet
{
for(int j = i; j < pix_to_fill; ++j)
{
img.get(b); // Move to pixel data (or next color)
data[j].b = charToFloat(b);
img.get(b); // Move to green
data[j].g = charToFloat(b);
img.get(b); // Move to red
data[j].r = charToFloat(b);
img.get(b); // Move to alpha
data[j].a = charToFloat(b);
++i;
}
--i;
img.get(b); // Move to next packet's header byte
}
}
break;
default:
return false; // Exit function, unsupported TARGA file type
break;
}
break;
default:
break;
}
}
return true; // Image successfully loaded
}
// End of Private functions