summary refs log tree commit diff stats
path: root/libs/cocos2d/Support/TGAlib.m
diff options
context:
space:
mode:
Diffstat (limited to 'libs/cocos2d/Support/TGAlib.m')
-rwxr-xr-xlibs/cocos2d/Support/TGAlib.m274
1 files changed, 274 insertions, 0 deletions
diff --git a/libs/cocos2d/Support/TGAlib.m b/libs/cocos2d/Support/TGAlib.m new file mode 100755 index 0000000..11303b4 --- /dev/null +++ b/libs/cocos2d/Support/TGAlib.m
@@ -0,0 +1,274 @@
1//
2// TGA lib for cocos2d-iphone
3//
4// sources from: http://www.lighthouse3d.com/opengl/terrain/index.php3?tgasource
5//
6// TGA RLE compression support by Ernesto Corvi
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12#import "TGAlib.h"
13
14void tgaLoadRLEImageData(FILE *file, tImageTGA *info);
15void tgaFlipImage( tImageTGA *info );
16
17// load the image header fields. We only keep those that matter!
18void tgaLoadHeader(FILE *file, tImageTGA *info) {
19 unsigned char cGarbage;
20 short int iGarbage;
21
22 fread(&cGarbage, sizeof(unsigned char), 1, file);
23 fread(&cGarbage, sizeof(unsigned char), 1, file);
24
25 // type must be 2 or 3
26 fread(&info->type, sizeof(unsigned char), 1, file);
27
28 fread(&iGarbage, sizeof(short int), 1, file);
29 fread(&iGarbage, sizeof(short int), 1, file);
30 fread(&cGarbage, sizeof(unsigned char), 1, file);
31 fread(&iGarbage, sizeof(short int), 1, file);
32 fread(&iGarbage, sizeof(short int), 1, file);
33
34 fread(&info->width, sizeof(short int), 1, file);
35 fread(&info->height, sizeof(short int), 1, file);
36 fread(&info->pixelDepth, sizeof(unsigned char), 1, file);
37
38 fread(&cGarbage, sizeof(unsigned char), 1, file);
39
40 info->flipped = 0;
41 if ( cGarbage & 0x20 ) info->flipped = 1;
42}
43
44// loads the image pixels. You shouldn't call this function directly
45void tgaLoadImageData(FILE *file, tImageTGA *info) {
46
47 int mode,total,i;
48 unsigned char aux;
49
50 // mode equal the number of components for each pixel
51 mode = info->pixelDepth / 8;
52 // total is the number of unsigned chars we'll have to read
53 total = info->height * info->width * mode;
54
55 fread(info->imageData,sizeof(unsigned char),total,file);
56
57 // mode=3 or 4 implies that the image is RGB(A). However TGA
58 // stores it as BGR(A) so we'll have to swap R and B.
59 if (mode >= 3)
60 for (i=0; i < total; i+= mode) {
61 aux = info->imageData[i];
62 info->imageData[i] = info->imageData[i+2];
63 info->imageData[i+2] = aux;
64 }
65}
66
67// loads the RLE encoded image pixels. You shouldn't call this function directly
68void tgaLoadRLEImageData(FILE *file, tImageTGA *info)
69{
70 unsigned int mode,total,i, index = 0;
71 unsigned char aux[4], runlength = 0;
72 unsigned int skip = 0, flag = 0;
73
74 // mode equal the number of components for each pixel
75 mode = info->pixelDepth / 8;
76 // total is the number of unsigned chars we'll have to read
77 total = info->height * info->width;
78
79 for( i = 0; i < total; i++ )
80 {
81 // if we have a run length pending, run it
82 if ( runlength != 0 )
83 {
84 // we do, update the run length count
85 runlength--;
86 skip = (flag != 0);
87 }
88 else
89 {
90 // otherwise, read in the run length token
91 if ( fread(&runlength,sizeof(unsigned char),1,file) != 1 )
92 return;
93
94 // see if it's a RLE encoded sequence
95 flag = runlength & 0x80;
96 if ( flag ) runlength -= 128;
97 skip = 0;
98 }
99
100 // do we need to skip reading this pixel?
101 if ( !skip )
102 {
103 // no, read in the pixel data
104 if ( fread(aux,sizeof(unsigned char),mode,file) != mode )
105 return;
106
107 // mode=3 or 4 implies that the image is RGB(A). However TGA
108 // stores it as BGR(A) so we'll have to swap R and B.
109 if ( mode >= 3 )
110 {
111 unsigned char tmp;
112
113 tmp = aux[0];
114 aux[0] = aux[2];
115 aux[2] = tmp;
116 }
117 }
118
119 // add the pixel to our image
120 memcpy(&info->imageData[index], aux, mode);
121 index += mode;
122 }
123}
124
125void tgaFlipImage( tImageTGA *info )
126{
127 // mode equal the number of components for each pixel
128 int mode = info->pixelDepth / 8;
129 int rowbytes = info->width*mode;
130 unsigned char *row = (unsigned char *)malloc(rowbytes);
131 int y;
132
133 if (row == NULL) return;
134
135 for( y = 0; y < (info->height/2); y++ )
136 {
137 memcpy(row, &info->imageData[y*rowbytes],rowbytes);
138 memcpy(&info->imageData[y*rowbytes], &info->imageData[(info->height-(y+1))*rowbytes], rowbytes);
139 memcpy(&info->imageData[(info->height-(y+1))*rowbytes], row, rowbytes);
140 }
141
142 free(row);
143 info->flipped = 0;
144}
145
146// this is the function to call when we want to load an image
147tImageTGA * tgaLoad(const char *filename) {
148
149 FILE *file;
150 tImageTGA *info;
151 int mode,total;
152
153 // allocate memory for the info struct and check!
154 info = (tImageTGA *)malloc(sizeof(tImageTGA));
155 if (info == NULL)
156 return(NULL);
157
158
159 // open the file for reading (binary mode)
160 file = fopen(filename, "rb");
161 if (file == NULL) {
162 info->status = TGA_ERROR_FILE_OPEN;
163 return(info);
164 }
165
166 // load the header
167 tgaLoadHeader(file,info);
168
169 // check for errors when loading the header
170 if (ferror(file)) {
171 info->status = TGA_ERROR_READING_FILE;
172 fclose(file);
173 return(info);
174 }
175
176 // check if the image is color indexed
177 if (info->type == 1) {
178 info->status = TGA_ERROR_INDEXED_COLOR;
179 fclose(file);
180 return(info);
181 }
182 // check for other types (compressed images)
183 if ((info->type != 2) && (info->type !=3) && (info->type !=10) ) {
184 info->status = TGA_ERROR_COMPRESSED_FILE;
185 fclose(file);
186 return(info);
187 }
188
189 // mode equals the number of image components
190 mode = info->pixelDepth / 8;
191 // total is the number of unsigned chars to read
192 total = info->height * info->width * mode;
193 // allocate memory for image pixels
194 info->imageData = (unsigned char *)malloc(sizeof(unsigned char) *
195 total);
196
197 // check to make sure we have the memory required
198 if (info->imageData == NULL) {
199 info->status = TGA_ERROR_MEMORY;
200 fclose(file);
201 return(info);
202 }
203 // finally load the image pixels
204 if ( info->type == 10 )
205 tgaLoadRLEImageData(file, info);
206 else
207 tgaLoadImageData(file,info);
208
209 // check for errors when reading the pixels
210 if (ferror(file)) {
211 info->status = TGA_ERROR_READING_FILE;
212 fclose(file);
213 return(info);
214 }
215 fclose(file);
216 info->status = TGA_OK;
217
218 if ( info->flipped )
219 {
220 tgaFlipImage( info );
221 if ( info->flipped ) info->status = TGA_ERROR_MEMORY;
222 }
223
224 return(info);
225}
226
227// converts RGB to greyscale
228void tgaRGBtogreyscale(tImageTGA *info) {
229
230 int mode,i,j;
231
232 unsigned char *newImageData;
233
234 // if the image is already greyscale do nothing
235 if (info->pixelDepth == 8)
236 return;
237
238 // compute the number of actual components
239 mode = info->pixelDepth / 8;
240
241 // allocate an array for the new image data
242 newImageData = (unsigned char *)malloc(sizeof(unsigned char) *
243 info->height * info->width);
244 if (newImageData == NULL) {
245 return;
246 }
247
248 // convert pixels: greyscale = o.30 * R + 0.59 * G + 0.11 * B
249 for (i = 0,j = 0; j < info->width * info->height; i +=mode, j++)
250 newImageData[j] =
251 (unsigned char)(0.30 * info->imageData[i] +
252 0.59 * info->imageData[i+1] +
253 0.11 * info->imageData[i+2]);
254
255
256 //free old image data
257 free(info->imageData);
258
259 // reassign pixelDepth and type according to the new image type
260 info->pixelDepth = 8;
261 info->type = 3;
262 // reassing imageData to the new array.
263 info->imageData = newImageData;
264}
265
266// releases the memory used for the image
267void tgaDestroy(tImageTGA *info) {
268
269 if (info != NULL) {
270 if (info->imageData != NULL)
271 free(info->imageData);
272 free(info);
273 }
274}