1 /*
2 * TGALoader.cpp
3 * Copyright (C) 2007 by Bryan Duff <duff0097@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 */
20 #include "TGALoader.h"
21
LoadTGA(char * filename)22 TGAImageRec *LoadTGA(char *filename)
23 {
24 GLubyte TGAheader[12] = { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // Uncompressed TGA Header
25 GLubyte TGAcompare[12]; // Used To Compare TGA Header
26 GLubyte header[6]; // First 6 Useful Bytes From The Header
27 GLuint bytesPerPixel; // Holds Number Of Bytes Per Pixel Used In The TGA File
28 GLuint imageSize; // Used To Store The Image Size When Setting Aside Ram
29 GLuint temp; // Temporary Variable
30 TGAImageRec *texture;
31 FILE *file;
32
33 // Open The TGA File
34 file = cfh_fopen(filename, "rb");
35
36 if((file == NULL) || // Does File Even Exist?
37 (fread(TGAcompare, 1, sizeof (TGAcompare), file) != sizeof (TGAcompare)) || // Are There 12 Bytes To Read?
38 (memcmp(TGAheader, TGAcompare, sizeof (TGAheader)) != 0) || // Does The Header Match What We Want?
39 (fread(header, 1, sizeof (header), file) != sizeof (header))) // If So Read Next 6 Header Bytes
40 {
41 // If anything failed then close the file and return false
42 fclose(file);
43 return NULL;
44 }
45 // Create a new RGBAImageRec
46 texture = (TGAImageRec *) malloc(sizeof (TGAImageRec));
47
48 // Determine the TGA width (highbyte*256+lowbyte) and height (highbyte*256+lowbyte)
49 texture->sizeX = header[1] * 256 + header[0];
50 texture->sizeY = header[3] * 256 + header[2];
51
52 // Make sure the height, width, and bit depth are valid
53 if((texture->sizeX <= 0) || (texture->sizeY <= 0)
54 || ((header[4] != 24) && (header[4] != 32))) {
55 // If anything failed then close the file, free up memory for the image, and return NULL
56 fclose(file);
57 free(texture);
58 return NULL;
59 }
60 // Grab The TGA's Bits Per Pixel (24 or 32)
61 texture->bpp = header[4];
62 bytesPerPixel = texture->bpp / 8; // Divide By 8 To Get The Bytes Per Pixel
63
64 // Calculate The Memory Required For The TGA Data
65 imageSize = texture->sizeX * texture->sizeY * bytesPerPixel;
66
67 // Reserve Memory To Hold The TGA Data
68 texture->data = (GLubyte *) malloc(imageSize);
69
70 // Make sure the right amount of memory was allocated
71 if((texture->data == NULL)
72 || (fread(texture->data, 1, imageSize, file) != imageSize)) {
73 // Free up the image data if there was any
74 if(texture->data != NULL)
75 free(texture->data);
76
77 // If anything failed then close the file, free up memory for the image, and return NULL
78 fclose(file);
79 free(texture);
80 return NULL;
81 }
82 // Loop Through The Image Data
83 for(GLuint i = 0; i < (imageSize); i += bytesPerPixel) {
84 // Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)
85 temp = texture->data[i]; // Temporarily Store The Value At Image Data 'i'
86 texture->data[i] = texture->data[i + 2]; // Set The 1st Byte To The Value Of The 3rd Byte
87 texture->data[i + 2] = temp; // Set The 3rd Byte To The Value In 'temp' (1st Byte Value)
88 }
89
90 // Close The File
91 fclose(file);
92
93 return texture;
94 }
95
WriteTGA(const char * filename,TGAImageRec * image,unsigned int size)96 void WriteTGA(const char *filename, TGAImageRec *image, unsigned int size)
97 {
98 //TGA header is 18 bytes
99 // True color image with no color map, uncompressed = 2 (3rd byte)
100 GLubyte TGAheader[12] = { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
101 GLubyte header[6]; // First 6 Useful Bytes From The Header
102 int bytes_written = 0;
103 FILE* file;
104 unsigned char width[4];
105 unsigned char height[4];
106
107 file = fopen(filename, "w");
108 if(!file) {
109 perror("WriteTGA");
110 }
111
112 //defaults
113 memcpy(width, &image->sizeX, 4);
114 memcpy(height, &image->sizeY, 4);
115 //endian issues
116 header[0] = (GLubyte)width[0];
117 header[1] = (GLubyte)width[1];
118 header[2] = (GLubyte)height[0];
119 header[3] = (GLubyte)height[1];
120 header[4] = (GLubyte)24; //forced bpp
121 header[5] = 0; //no alpha
122
123 //write header
124 fwrite(TGAheader, sizeof(TGAheader), 1, file);
125 fwrite(header, sizeof(header), 1, file);
126
127 //write data
128 while(size != 0) {
129 bytes_written = fwrite(image->data, 1, size, file);
130 size -= bytes_written;
131 }
132 fclose(file);
133 }
134