1 /**
2 * File: TGA Input
3 *
4 * Read TGA images.
5 */
6
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif /* HAVE_CONFIG_H */
10
11 #include <stdio.h>
12 #include <stddef.h>
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include "gd_tga.h"
17 #include "gd.h"
18 #include "gd_errors.h"
19 #include "gdhelpers.h"
20
21 /*
22 Function: gdImageCreateFromTga
23
24 Creates a gdImage from a TGA file
25
26 Parameters:
27
28 infile - Pointer to TGA binary file
29 */
gdImageCreateFromTga(FILE * fp)30 gdImagePtr gdImageCreateFromTga(FILE *fp)
31 {
32 gdImagePtr image;
33 gdIOCtx* in = gdNewFileCtx(fp);
34 if (in == NULL) return NULL;
35 image = gdImageCreateFromTgaCtx(in);
36 in->gd_free( in );
37 return image;
38 }
39
40 /*
41 Function: gdImageCreateFromTgaPtr
42 */
gdImageCreateFromTgaPtr(int size,void * data)43 gdImagePtr gdImageCreateFromTgaPtr(int size, void *data)
44 {
45 gdImagePtr im;
46 gdIOCtx *in = gdNewDynamicCtxEx (size, data, 0);
47 if (in == NULL) return NULL;
48 im = gdImageCreateFromTgaCtx(in);
49 in->gd_free(in);
50 return im;
51 }
52
53
54 /*
55 Function: gdImageCreateFromTgaCtx
56
57 Creates a gdImage from a gdIOCtx referencing a TGA binary file.
58
59 Parameters:
60 ctx - Pointer to a gdIOCtx structure
61 */
gdImageCreateFromTgaCtx(gdIOCtx * ctx)62 gdImagePtr gdImageCreateFromTgaCtx(gdIOCtx* ctx)
63 {
64 int bitmap_caret = 0;
65 oTga *tga = NULL;
66 /* int pixel_block_size = 0;
67 int image_block_size = 0; */
68 volatile gdImagePtr image = NULL;
69 int x = 0;
70 int y = 0;
71
72 tga = (oTga *) gdMalloc(sizeof(oTga));
73 if (!tga) {
74 return NULL;
75 }
76
77 tga->bitmap = NULL;
78 tga->ident = NULL;
79
80 if (read_header_tga(ctx, tga) < 0) {
81 free_tga(tga);
82 return NULL;
83 }
84
85 /*TODO: Will this be used?
86 pixel_block_size = tga->bits / 8;
87 image_block_size = (tga->width * tga->height) * pixel_block_size;
88 */
89
90 if (read_image_tga(ctx, tga) < 0) {
91 free_tga(tga);
92 return NULL;
93 }
94
95 image = gdImageCreateTrueColor((int)tga->width, (int)tga->height );
96
97 if (image == 0) {
98 free_tga( tga );
99 return NULL;
100 }
101
102 /*! \brief Populate GD image object
103 * Copy the pixel data from our tga bitmap buffer into the GD image
104 * Disable blending and save the alpha channel per default
105 */
106 if (tga->alphabits) {
107 gdImageAlphaBlending(image, 0);
108 gdImageSaveAlpha(image, 1);
109 }
110
111 /* TODO: use alphabits as soon as we support 24bit and other alpha bps (ie != 8bits) */
112 for (y = 0; y < tga->height; y++) {
113 register int *tpix = image->tpixels[y];
114 for ( x = 0; x < tga->width; x++, tpix++) {
115 if (tga->bits == TGA_BPP_24) {
116 *tpix = gdTrueColor(tga->bitmap[bitmap_caret + 2], tga->bitmap[bitmap_caret + 1], tga->bitmap[bitmap_caret]);
117 bitmap_caret += 3;
118 } else if (tga->bits == TGA_BPP_32 && tga->alphabits) {
119 register int a = tga->bitmap[bitmap_caret + 3];
120
121 *tpix = gdTrueColorAlpha(tga->bitmap[bitmap_caret + 2], tga->bitmap[bitmap_caret + 1], tga->bitmap[bitmap_caret], gdAlphaMax - (a >> 1));
122 bitmap_caret += 4;
123 }
124 }
125 }
126
127 if (tga->flipv && tga->fliph) {
128 gdImageFlipBoth(image);
129 } else if (tga->flipv) {
130 gdImageFlipVertical(image);
131 } else if (tga->fliph) {
132 gdImageFlipHorizontal(image);
133 }
134
135 free_tga(tga);
136
137 return image;
138 }
139
140 /*! \brief Reads a TGA header.
141 * Reads the header block from a binary TGA file populating the referenced TGA structure.
142 * \param ctx Pointer to TGA binary file
143 * \param tga Pointer to TGA structure
144 * \return int 1 on sucess, -1 on failure
145 */
read_header_tga(gdIOCtx * ctx,oTga * tga)146 int read_header_tga(gdIOCtx *ctx, oTga *tga)
147 {
148
149 unsigned char header[18];
150
151 if (gdGetBuf(header, sizeof(header), ctx) < 18) {
152 gd_error("fail to read header");
153 return -1;
154 }
155
156 tga->identsize = header[0];
157 tga->colormaptype = header[1];
158 tga->imagetype = header[2];
159 tga->colormapstart = header[3] + (header[4] << 8);
160 tga->colormaplength = header[5] + (header[6] << 8);
161 tga->colormapbits = header[7];
162 tga->xstart = header[8] + (header[9] << 8);
163 tga->ystart = header[10] + (header[11] << 8);
164 tga->width = header[12] + (header[13] << 8);
165 tga->height = header[14] + (header[15] << 8);
166 tga->bits = header[16];
167 tga->alphabits = header[17] & 0x0f;
168 tga->fliph = (header[17] & 0x10) ? 1 : 0;
169 tga->flipv = (header[17] & 0x20) ? 0 : 1;
170
171 #if DEBUG
172 printf("format bps: %i\n", tga->bits);
173 printf("flip h/v: %i / %i\n", tga->fliph, tga->flipv);
174 printf("alpha: %i\n", tga->alphabits);
175 printf("wxh: %i %i\n", tga->width, tga->height);
176 #endif
177
178 if (!((tga->bits == TGA_BPP_24 && tga->alphabits == 0)
179 || (tga->bits == TGA_BPP_32 && tga->alphabits == 8)))
180 {
181 gd_error_ex(GD_WARNING, "gd-tga: %u bits per pixel with %u alpha bits not supported\n",
182 tga->bits, tga->alphabits);
183 return -1;
184 }
185
186 tga->ident = NULL;
187
188 if (tga->identsize > 0) {
189 tga->ident = (char *) gdMalloc(tga->identsize * sizeof(char));
190 if(tga->ident == NULL) {
191 return -1;
192 }
193
194 gdGetBuf(tga->ident, tga->identsize, ctx);
195 }
196
197 return 1;
198 }
199
200 /*! \brief Reads a TGA image data into buffer.
201 * Reads the image data block from a binary TGA file populating the referenced TGA structure.
202 * \param ctx Pointer to TGA binary file
203 * \param tga Pointer to TGA structure
204 * \return int 0 on sucess, -1 on failure
205 */
read_image_tga(gdIOCtx * ctx,oTga * tga)206 int read_image_tga( gdIOCtx *ctx, oTga *tga )
207 {
208 int pixel_block_size = (tga->bits / 8);
209 int image_block_size;
210 int* decompression_buffer = NULL;
211 unsigned char* conversion_buffer = NULL;
212 int buffer_caret = 0;
213 int bitmap_caret = 0;
214 int i = 0;
215 int encoded_pixels;
216 int rle_size;
217
218 if(overflow2(tga->width, tga->height)) {
219 return -1;
220 }
221
222 if(overflow2(tga->width * tga->height, pixel_block_size)) {
223 return -1;
224 }
225
226 image_block_size = (tga->width * tga->height) * pixel_block_size;
227 if(overflow2(image_block_size, sizeof(int))) {
228 return -1;
229 }
230
231 /*! \todo Add more image type support.
232 */
233 if (tga->imagetype != TGA_TYPE_RGB && tga->imagetype != TGA_TYPE_RGB_RLE)
234 return -1;
235
236 /*! \brief Allocate memmory for image block
237 * Allocate a chunk of memory for the image block to be passed into.
238 */
239 tga->bitmap = (int *) gdMalloc(image_block_size * sizeof(int));
240 if (tga->bitmap == NULL)
241 return -1;
242
243 switch (tga->imagetype) {
244 case TGA_TYPE_RGB:
245 /*! \brief Read in uncompressed RGB TGA
246 * Chunk load the pixel data from an uncompressed RGB type TGA.
247 */
248 conversion_buffer = (unsigned char *) gdMalloc(image_block_size * sizeof(unsigned char));
249 if (conversion_buffer == NULL) {
250 return -1;
251 }
252
253 if (gdGetBuf(conversion_buffer, image_block_size, ctx) != image_block_size) {
254 gd_error("gd-tga: premature end of image data\n");
255 gdFree(conversion_buffer);
256 return -1;
257 }
258
259 while (buffer_caret < image_block_size) {
260 tga->bitmap[buffer_caret] = (int) conversion_buffer[buffer_caret];
261 buffer_caret++;
262 }
263
264 gdFree(conversion_buffer);
265 break;
266
267 case TGA_TYPE_RGB_RLE:
268 /*! \brief Read in RLE compressed RGB TGA
269 * Chunk load the pixel data from an RLE compressed RGB type TGA.
270 */
271 decompression_buffer = (int*) gdMalloc(image_block_size * sizeof(int));
272 if (decompression_buffer == NULL) {
273 return -1;
274 }
275 conversion_buffer = (unsigned char *) gdMalloc(image_block_size * sizeof(unsigned char));
276 if (conversion_buffer == NULL) {
277 gd_error("gd-tga: premature end of image data\n");
278 gdFree( decompression_buffer );
279 return -1;
280 }
281
282 rle_size = gdGetBuf(conversion_buffer, image_block_size, ctx);
283 if (rle_size <= 0) {
284 gdFree(conversion_buffer);
285 gdFree(decompression_buffer);
286 return -1;
287 }
288
289 buffer_caret = 0;
290
291 while( buffer_caret < rle_size) {
292 decompression_buffer[buffer_caret] = (int)conversion_buffer[buffer_caret];
293 buffer_caret++;
294 }
295
296 buffer_caret = 0;
297
298 while( bitmap_caret < image_block_size ) {
299
300 if (buffer_caret + pixel_block_size > rle_size) {
301 gdFree( decompression_buffer );
302 gdFree( conversion_buffer );
303 return -1;
304 }
305
306 if ((decompression_buffer[buffer_caret] & TGA_RLE_FLAG) == TGA_RLE_FLAG) {
307 encoded_pixels = ( ( decompression_buffer[ buffer_caret ] & ~TGA_RLE_FLAG ) + 1 );
308 buffer_caret++;
309
310 if ((bitmap_caret + (encoded_pixels * pixel_block_size)) > image_block_size
311 || buffer_caret + pixel_block_size > rle_size) {
312 gdFree( decompression_buffer );
313 gdFree( conversion_buffer );
314 return -1;
315 }
316
317 for (i = 0; i < encoded_pixels; i++) {
318 memcpy(tga->bitmap + bitmap_caret, decompression_buffer + buffer_caret, pixel_block_size * sizeof(int));
319 bitmap_caret += pixel_block_size;
320 }
321 buffer_caret += pixel_block_size;
322
323 } else {
324 encoded_pixels = decompression_buffer[ buffer_caret ] + 1;
325 buffer_caret++;
326
327 if ((bitmap_caret + (encoded_pixels * pixel_block_size)) > image_block_size
328 || buffer_caret + (encoded_pixels * pixel_block_size) > rle_size) {
329 gdFree( decompression_buffer );
330 gdFree( conversion_buffer );
331 return -1;
332 }
333
334 memcpy(tga->bitmap + bitmap_caret, decompression_buffer + buffer_caret, encoded_pixels * pixel_block_size * sizeof(int));
335 bitmap_caret += (encoded_pixels * pixel_block_size);
336 buffer_caret += (encoded_pixels * pixel_block_size);
337 }
338 }
339 gdFree( decompression_buffer );
340 gdFree( conversion_buffer );
341 break;
342 }
343
344 return 1;
345 }
346
347 /*! \brief Cleans up a TGA structure.
348 * Dereferences the bitmap referenced in a TGA structure, then the structure itself
349 * \param tga Pointer to TGA structure
350 */
free_tga(oTga * tga)351 void free_tga(oTga * tga)
352 {
353 if (tga) {
354 if (tga->ident)
355 gdFree(tga->ident);
356 if (tga->bitmap)
357 gdFree(tga->bitmap);
358 gdFree(tga);
359 }
360 }
361