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 success, -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 #ifdef 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 if (gdGetBuf(tga->ident, tga->identsize, ctx) != tga->identsize) {
195 gd_error("fail to read header ident");
196 return -1;
197 }
198 }
199
200 return 1;
201 }
202
203 /*! \brief Reads a TGA image data into buffer.
204 * Reads the image data block from a binary TGA file populating the referenced TGA structure.
205 * \param ctx Pointer to TGA binary file
206 * \param tga Pointer to TGA structure
207 * \return int 0 on success, -1 on failure
208 */
read_image_tga(gdIOCtx * ctx,oTga * tga)209 int read_image_tga( gdIOCtx *ctx, oTga *tga )
210 {
211 int pixel_block_size = (tga->bits / 8);
212 int image_block_size;
213 int* decompression_buffer = NULL;
214 unsigned char* conversion_buffer = NULL;
215 int buffer_caret = 0;
216 int bitmap_caret = 0;
217 int i = 0;
218 int encoded_pixels;
219 int rle_size;
220
221 if(overflow2(tga->width, tga->height)) {
222 return -1;
223 }
224
225 if(overflow2(tga->width * tga->height, pixel_block_size)) {
226 return -1;
227 }
228
229 image_block_size = (tga->width * tga->height) * pixel_block_size;
230 if(overflow2(image_block_size, sizeof(int))) {
231 return -1;
232 }
233
234 /*! \todo Add more image type support.
235 */
236 if (tga->imagetype != TGA_TYPE_RGB && tga->imagetype != TGA_TYPE_RGB_RLE)
237 return -1;
238
239 /*! \brief Allocate memmory for image block
240 * Allocate a chunk of memory for the image block to be passed into.
241 */
242 tga->bitmap = (int *) gdMalloc(image_block_size * sizeof(int));
243 if (tga->bitmap == NULL)
244 return -1;
245
246 switch (tga->imagetype) {
247 case TGA_TYPE_RGB:
248 /*! \brief Read in uncompressed RGB TGA
249 * Chunk load the pixel data from an uncompressed RGB type TGA.
250 */
251 conversion_buffer = (unsigned char *) gdMalloc(image_block_size * sizeof(unsigned char));
252 if (conversion_buffer == NULL) {
253 return -1;
254 }
255
256 if (gdGetBuf(conversion_buffer, image_block_size, ctx) != image_block_size) {
257 gd_error("gd-tga: premature end of image data\n");
258 gdFree(conversion_buffer);
259 return -1;
260 }
261
262 while (buffer_caret < image_block_size) {
263 tga->bitmap[buffer_caret] = (int) conversion_buffer[buffer_caret];
264 buffer_caret++;
265 }
266
267 gdFree(conversion_buffer);
268 break;
269
270 case TGA_TYPE_RGB_RLE:
271 /*! \brief Read in RLE compressed RGB TGA
272 * Chunk load the pixel data from an RLE compressed RGB type TGA.
273 */
274 decompression_buffer = (int*) gdMalloc(image_block_size * sizeof(int));
275 if (decompression_buffer == NULL) {
276 return -1;
277 }
278 conversion_buffer = (unsigned char *) gdMalloc(image_block_size * sizeof(unsigned char));
279 if (conversion_buffer == NULL) {
280 gd_error("gd-tga: premature end of image data\n");
281 gdFree( decompression_buffer );
282 return -1;
283 }
284
285 rle_size = gdGetBuf(conversion_buffer, image_block_size, ctx);
286 if (rle_size <= 0) {
287 gdFree(conversion_buffer);
288 gdFree(decompression_buffer);
289 return -1;
290 }
291
292 buffer_caret = 0;
293
294 while( buffer_caret < rle_size) {
295 decompression_buffer[buffer_caret] = (int)conversion_buffer[buffer_caret];
296 buffer_caret++;
297 }
298
299 buffer_caret = 0;
300
301 while( bitmap_caret < image_block_size ) {
302
303 if (buffer_caret + pixel_block_size > rle_size) {
304 gdFree( decompression_buffer );
305 gdFree( conversion_buffer );
306 return -1;
307 }
308
309 if ((decompression_buffer[buffer_caret] & TGA_RLE_FLAG) == TGA_RLE_FLAG) {
310 encoded_pixels = ( ( decompression_buffer[ buffer_caret ] & ~TGA_RLE_FLAG ) + 1 );
311 buffer_caret++;
312
313 if ((bitmap_caret + (encoded_pixels * pixel_block_size)) > image_block_size
314 || buffer_caret + pixel_block_size > rle_size) {
315 gdFree( decompression_buffer );
316 gdFree( conversion_buffer );
317 return -1;
318 }
319
320 for (i = 0; i < encoded_pixels; i++) {
321 memcpy(tga->bitmap + bitmap_caret, decompression_buffer + buffer_caret, pixel_block_size * sizeof(int));
322 bitmap_caret += pixel_block_size;
323 }
324 buffer_caret += pixel_block_size;
325
326 } else {
327 encoded_pixels = decompression_buffer[ buffer_caret ] + 1;
328 buffer_caret++;
329
330 if ((bitmap_caret + (encoded_pixels * pixel_block_size)) > image_block_size
331 || buffer_caret + (encoded_pixels * pixel_block_size) > rle_size) {
332 gdFree( decompression_buffer );
333 gdFree( conversion_buffer );
334 return -1;
335 }
336
337 memcpy(tga->bitmap + bitmap_caret, decompression_buffer + buffer_caret, encoded_pixels * pixel_block_size * sizeof(int));
338 bitmap_caret += (encoded_pixels * pixel_block_size);
339 buffer_caret += (encoded_pixels * pixel_block_size);
340 }
341 }
342 gdFree( decompression_buffer );
343 gdFree( conversion_buffer );
344 break;
345 }
346
347 return 1;
348 }
349
350 /*! \brief Cleans up a TGA structure.
351 * Dereferences the bitmap referenced in a TGA structure, then the structure itself
352 * \param tga Pointer to TGA structure
353 */
free_tga(oTga * tga)354 void free_tga(oTga * tga)
355 {
356 if (tga) {
357 if (tga->ident)
358 gdFree(tga->ident);
359 if (tga->bitmap)
360 gdFree(tga->bitmap);
361 gdFree(tga);
362 }
363 }
364