-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtga.cpp
More file actions
executable file
·284 lines (241 loc) · 9.26 KB
/
Copy pathtga.cpp
File metadata and controls
executable file
·284 lines (241 loc) · 9.26 KB
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
#include "tga.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
// Uncompressed TGA Header
const unsigned char uTGAcompare[12] = {0,0, 2,0,0,0,0,0,0,0,0,0};
// Compressed TGA Header
const unsigned char cTGAcompare[12] = {0,0,10,0,0,0,0,0,0,0,0,0};
bool tga::saveTGA(const TGAImage& image, const char * filename)
{
const unsigned int bytesPerPixel = image.bpp / 8;
std::ofstream myfile;
myfile.open (filename, std::ios::out | std::ios::trunc | std::ios::binary);
//create the tga header
unsigned char header[6];
// 1x1 image
header[0] = image.width % 256;
header[1] = image.width / 256;
header[2] = image.height % 256;
header[3] = image.height / 256;
header[4] = image.bpp;
header[5] = image.bpp == 32 ? 8 : 0; //flag alpha depth and other flags
//add the headers
for (int i = 0; i < 12; ++i)
{
myfile << uTGAcompare[i];
}
for (int i = 0; i < 6; ++i)
{
myfile << header[i];
}
//myfile << header;
//add the image data
std::vector<unsigned char> imageData(image.imageData);
//swap from RGB to BGR
// Start The Loop
for(unsigned int cswap = 0; cswap < imageData.size(); cswap += bytesPerPixel)
{
// 1st Byte XOR 3rd Byte XOR 1st Byte XOR 3rd Byte
imageData[cswap] ^= imageData[cswap+2] ^=
imageData[cswap] ^= imageData[cswap+2];
}
for (size_t i = 0; i < imageData.size(); ++i)
{
unsigned char x = imageData[i];
myfile << imageData[i];
}
myfile.close();
return true;
}
// Load A TGA File!
bool tga::LoadTGA(TGAImage * image, const char * filename)
{
tga::TGAHeader tgaheader; // Used To Store Our File Header
tga::TGA tga_; // Used To Store File Information
FILE * fTGA; // Declare File Pointer
fTGA = fopen(filename, "rb"); // Open File For Reading
if(fTGA == NULL) // If Here Was An Error
{
std::cout << "loadTGA: error reading file " << filename << std::endl;
return false; // Return False
}
// Attempt To Read The File Header
if(fread(&tgaheader, sizeof(tga::TGAHeader), 1, fTGA) == 0)
{
printf("error trying to read the tga file header\n");
fclose(fTGA);
return false; // Return False If It Fails
}
// If The File Header Matches The Uncompressed Header
if(memcmp(uTGAcompare, &tgaheader, sizeof(tgaheader)) == 0)
{
// Load An Uncompressed TGA
LoadUncompressedTGA(image, filename, fTGA, tgaheader, tga_);
}
// If The File Header Matches The Compressed Header
else if(memcmp(cTGAcompare, &tgaheader, sizeof(tgaheader)) == 0)
{
// Load A Compressed TGA
LoadCompressedTGA(image, filename, fTGA, tgaheader, tga_);
}
else // If It Doesn't Match Either One
{
std::cout << "loadTGA: error: tga file header does not match\n";
return false; // Return False
}
return true;
}
// Load An Uncompressed TGA
bool tga::LoadUncompressedTGA(tga::TGAImage * image, const char * filename, FILE * fTGA, tga::TGAHeader& tgaheader, tga::TGA& tga_){
// Attempt To Read Next 6 Bytes
if(fread(tga_.header, sizeof(tga_.header), 1, fTGA) == 0)
{
std::cout << "loadTGA: error reading the next 6 bytes of the TGA\n" ;
return false; // Return False
}
image->width = tga_.header[1] * 256 + tga_.header[0]; // Calculate Height
image->height = tga_.header[3] * 256 + tga_.header[2]; // Calculate The Width
image->bpp = tga_.header[4]; // Calculate Bits Per Pixel
tga_.Width = image->width; // Copy Width Into Local Structure
tga_.Height = image->height; // Copy Height Into Local Structure
tga_.Bpp = image->bpp; // Copy Bpp Into Local Structure
// Make Sure All Information Is Valid
if((image->width <= 0) || (image->height <= 0) || ((image->bpp != 24) && (image->bpp !=32)))
{
std::cout << "loadTGA: error: width/height or bbp invalid\n" ;
return false; // Return False
}
if(image->bpp == 24) // Is It A 24bpp Image?
image->type = 0; // If So, Set Type To GL_RGB
else // If It's Not 24, It Must Be 32
image->type = 1; // So Set The Type To GL_RGBA
tga_.bytesPerPixel = (tga_.Bpp / 8); // Calculate The BYTES Per Pixel
// Calculate Memory Needed To Store Image
tga_.imageSize = (tga_.bytesPerPixel * tga_.Width * tga_.Height);
// Allocate Memory
image->imageData = std::vector<unsigned char>(tga_.imageSize);//(char *)malloc(tga_.imageSize);
//if(image->imageData == NULL) // Make Sure It Was Allocated Ok
//{
// std::cout << "loadTGA: error: image data was not allocated properly\n";
// return false; // If Not, Return False
//}
// Attempt To Read All The Image Data
if(fread(&image->imageData[0], 1, tga_.imageSize, fTGA) != tga_.imageSize)
{
std::cout << "loadTGA: error reading image data\n";
return false; // If We Cant, Return False
}
//swap from BGR to RGB
// Start The Loop
for(unsigned int cswap = 0; cswap < tga_.imageSize; cswap += tga_.bytesPerPixel)
{
// 1st Byte XOR 3rd Byte XOR 1st Byte XOR 3rd Byte
image->imageData[cswap] ^= image->imageData[cswap+2] ^=
image->imageData[cswap] ^= image->imageData[cswap+2];
}
fclose(fTGA); // Close The File
return true; // Return Success
}
bool tga::LoadCompressedTGA(tga::TGAImage * image, const char * filename, FILE * fTGA, tga::TGAHeader& tgaheader, tga::TGA& tga) {
// Attempt To Read Next 6 Bytes
if(fread(tga.header, sizeof(tga.header), 1, fTGA) == 0)
{
std::cout << "loadTGA: error reading the next 6 bytes of the TGA\n" ;
return false; // Return False
}
image->width = tga.header[1] * 256 + tga.header[0]; // Calculate Height
image->height = tga.header[3] * 256 + tga.header[2]; // Calculate The Width
image->bpp = tga.header[4]; // Calculate Bits Per Pixel
tga.Width = image->width; // Copy Width Into Local Structure
tga.Height = image->height; // Copy Height Into Local Structure
tga.Bpp = image->bpp; // Copy Bpp Into Local Structure
// Make Sure All Information Is Valid
if((image->width <= 0) || (image->height <= 0) || ((image->bpp != 24) && (image->bpp !=32)))
{
std::cout << "loadTGA: error: width/height or bbp invalid\n" ;
return false; // Return False
}
if(image->bpp == 24) // Is It A 24bpp Image?
image->type = 0; // If So, Set Type To GL_RGB
else // If It's Not 24, It Must Be 32
image->type = 1; // So Set The Type To GL_RGBA
tga.bytesPerPixel = (tga.Bpp / 8); // Calculate The BYTES Per Pixel
// Calculate Memory Needed To Store Image
tga.imageSize = (tga.bytesPerPixel * tga.Width * tga.Height);
// Allocate Memory To Store Image Data
image->imageData = std::vector<unsigned char>(tga.imageSize);
unsigned int pixelcount = tga.Height * tga.Width; // Number Of Pixels In The Image
unsigned int currentpixel = 0; // Current Pixel We Are Reading From Data
unsigned int currentbyte = 0; // Current Byte We Are Writing Into Imagedata
// Storage For 1 Pixel
unsigned char * colorbuffer = (unsigned char *)malloc(tga.bytesPerPixel);
do // Start Loop
{
unsigned char chunkheader = 0; // Variable To Store The Value Of The Id Chunk
if(fread(&chunkheader, sizeof(unsigned char), 1, fTGA) == 0) // Attempt To Read The Chunk's Header
{
std::cout << "loadTGA: error reading chunk header \n";
free(colorbuffer);
return false; // If It Fails, Return False
}
if(chunkheader < 128) // If The Chunk Is A 'RAW' Chunk
{
chunkheader++; // Add 1 To The Value To Get Total Number Of Raw Pixels
// Start Pixel Reading Loop
for(short counter = 0; counter < chunkheader; counter++)
{
// Try To Read 1 Pixel
if(fread(colorbuffer, 1, tga.bytesPerPixel, fTGA) != tga.bytesPerPixel)
{
std::cout << "loadTGA: error reading a single pixel\n";
free(colorbuffer);
return false; // If It Fails, Return False
}
image->imageData[currentbyte] = colorbuffer[2]; // Write The 'R' Byte
image->imageData[currentbyte + 1 ] = colorbuffer[1]; // Write The 'G' Byte
image->imageData[currentbyte + 2 ] = colorbuffer[0]; // Write The 'B' Byte
if(tga.bytesPerPixel == 4) // If It's A 32bpp Image...
{
image->imageData[currentbyte + 3] = colorbuffer[3]; // Write The 'A' Byte
}
// Increment The Byte Counter By The Number Of Bytes In A Pixel
currentbyte += tga.bytesPerPixel;
currentpixel++; // Increment The Number Of Pixels By 1
}
}
else // If It's An RLE Header
{
chunkheader -= 127; // Subtract 127 To Get Rid Of The ID Bit
// Read The Next Pixel
if(fread(colorbuffer, 1, tga.bytesPerPixel, fTGA) != tga.bytesPerPixel)
{
std::cout << "loadTGA: error reading a single pixel\n";
free(colorbuffer);
return false; // If It Fails, Return False
}
// Start The Loop
for(short counter = 0; counter < chunkheader; counter++)
{
// Copy The 'R' Byte
image->imageData[currentbyte] = colorbuffer[2];
// Copy The 'G' Byte
image->imageData[currentbyte + 1 ] = colorbuffer[1];
// Copy The 'B' Byte
image->imageData[currentbyte + 2 ] = colorbuffer[0];
if(tga.bytesPerPixel == 4) // If It's A 32bpp Image
{
// Copy The 'A' Byte
image->imageData[currentbyte + 3] = colorbuffer[3];
}
currentbyte += tga.bytesPerPixel; // Increment The Byte Counter
currentpixel++; // Increment The Pixel Counter
}
}
}while(currentpixel < pixelcount);
fclose(fTGA);
free(colorbuffer);
return true;
}