1 /*         ______   ___    ___
2  *        /\  _  \ /\_ \  /\_ \
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *
11  *      TGA reader.
12  *
13  *      By Tim Gunn.
14  *
15  *      RLE support added by Michal Mertl and Salvador Eduardo Tropea.
16  *
17  *      Palette reading improved by Peter Wang.
18  *
19  *      Big-endian support added by Eric Botcazou.
20  *
21  *      See readme.txt for copyright information.
22  */
23 
24 
25 #include "allegro.h"
26 #include "allegro/internal/aintern.h"
27 
28 
29 
30 /* raw_tga_read8:
31  *  Helper for reading 256-color raw data from TGA files.
32  */
raw_tga_read8(unsigned char * b,int w,PACKFILE * f)33 static INLINE unsigned char *raw_tga_read8(unsigned char *b, int w, PACKFILE *f)
34 {
35    return b + pack_fread(b, w, f);
36 }
37 
38 
39 
40 /* rle_tga_read8:
41  *  Helper for reading 256-color RLE data from TGA files.
42  */
rle_tga_read8(unsigned char * b,int w,PACKFILE * f)43 static void rle_tga_read8(unsigned char *b, int w, PACKFILE *f)
44 {
45    int value, count, c = 0;
46 
47    do {
48       count = pack_getc(f);
49       if (count & 0x80) {
50 	 /* run-length packet */
51 	 count = (count & 0x7F) + 1;
52 	 c += count;
53 	 value = pack_getc(f);
54 	 while (count--)
55 	    *b++ = value;
56       }
57       else {
58 	 /* raw packet */
59 	 count++;
60 	 c += count;
61 	 b = raw_tga_read8(b, count, f);
62       }
63    } while (c < w);
64 }
65 
66 
67 
68 /* single_tga_read32:
69  *  Helper for reading a single 32-bit data from TGA files.
70  */
single_tga_read32(PACKFILE * f)71 static INLINE int single_tga_read32(PACKFILE *f)
72 {
73    RGB value;
74    int alpha;
75 
76    value.b = pack_getc(f);
77    value.g = pack_getc(f);
78    value.r = pack_getc(f);
79    alpha = pack_getc(f);
80 
81    return makeacol32(value.r, value.g, value.b, alpha);
82 }
83 
84 
85 
86 /* raw_tga_read32:
87  *  Helper for reading 32-bit raw data from TGA files.
88  */
raw_tga_read32(unsigned int * b,int w,PACKFILE * f)89 static unsigned int *raw_tga_read32(unsigned int *b, int w, PACKFILE *f)
90 {
91    while (w--)
92       *b++ = single_tga_read32(f);
93 
94    return b;
95 }
96 
97 
98 
99 /* rle_tga_read32:
100  *  Helper for reading 32-bit RLE data from TGA files.
101  */
rle_tga_read32(unsigned int * b,int w,PACKFILE * f)102 static void rle_tga_read32(unsigned int *b, int w, PACKFILE *f)
103 {
104    int color, count, c = 0;
105 
106    do {
107       count = pack_getc(f);
108       if (count & 0x80) {
109 	 /* run-length packet */
110 	 count = (count & 0x7F) + 1;
111 	 c += count;
112 	 color = single_tga_read32(f);
113 	 while (count--)
114 	    *b++ = color;
115       }
116       else {
117 	 /* raw packet */
118 	 count++;
119 	 c += count;
120 	 b = raw_tga_read32(b, count, f);
121       }
122    } while (c < w);
123 }
124 
125 
126 /* single_tga_read24:
127  *  Helper for reading a single 24-bit data from TGA files.
128  */
single_tga_read24(PACKFILE * f)129 static INLINE int single_tga_read24(PACKFILE *f)
130 {
131    RGB value;
132 
133    value.b = pack_getc(f);
134    value.g = pack_getc(f);
135    value.r = pack_getc(f);
136 
137    return makecol24(value.r, value.g, value.b);
138 }
139 
140 
141 
142 /* raw_tga_read24:
143  *  Helper for reading 24-bit raw data from TGA files.
144  */
raw_tga_read24(unsigned char * b,int w,PACKFILE * f)145 static unsigned char *raw_tga_read24(unsigned char *b, int w, PACKFILE *f)
146 {
147    int color;
148 
149    while (w--) {
150       color = single_tga_read24(f);
151       WRITE3BYTES(b, color);
152       b += 3;
153    }
154 
155    return b;
156 }
157 
158 
159 
160 /* rle_tga_read24:
161  *  Helper for reading 24-bit RLE data from TGA files.
162  */
rle_tga_read24(unsigned char * b,int w,PACKFILE * f)163 static void rle_tga_read24(unsigned char *b, int w, PACKFILE *f)
164 {
165    int color, count, c = 0;
166 
167    do {
168       count = pack_getc(f);
169       if (count & 0x80) {
170 	 /* run-length packet */
171 	 count = (count & 0x7F) + 1;
172 	 c += count;
173 	 color = single_tga_read24(f);
174 	 while (count--) {
175 	    WRITE3BYTES(b, color);
176 	    b += 3;
177 	 }
178       }
179       else {
180 	 /* raw packet */
181 	 count++;
182 	 c += count;
183 	 b = raw_tga_read24(b, count, f);
184       }
185    } while (c < w);
186 }
187 
188 
189 
190 /* single_tga_read16:
191  *  Helper for reading a single 16-bit data from TGA files.
192  */
single_tga_read16(PACKFILE * f)193 static INLINE int single_tga_read16(PACKFILE *f)
194 {
195    int value;
196 
197    value = pack_igetw(f);
198 
199    return (((value >> 10) & 0x1F) << _rgb_r_shift_15) |
200 	  (((value >> 5) & 0x1F) << _rgb_g_shift_15)  |
201 	  ((value & 0x1F) << _rgb_b_shift_15);
202 }
203 
204 
205 
206 /* raw_tga_read16:
207  *  Helper for reading 16-bit raw data from TGA files.
208  */
raw_tga_read16(unsigned short * b,int w,PACKFILE * f)209 static unsigned short *raw_tga_read16(unsigned short *b, int w, PACKFILE *f)
210 {
211    while (w--)
212       *b++ = single_tga_read16(f);
213 
214    return b;
215 }
216 
217 
218 
219 /* rle_tga_read16:
220  *  Helper for reading 16-bit RLE data from TGA files.
221  */
rle_tga_read16(unsigned short * b,int w,PACKFILE * f)222 static void rle_tga_read16(unsigned short *b, int w, PACKFILE *f)
223 {
224    int color, count, c = 0;
225 
226    do {
227       count = pack_getc(f);
228       if (count & 0x80) {
229 	 /* run-length packet */
230 	 count = (count & 0x7F) + 1;
231 	 c += count;
232 	 color = single_tga_read16(f);
233 	 while (count--)
234 	    *b++ = color;
235       }
236       else {
237 	 /* raw packet */
238 	 count++;
239 	 c += count;
240 	 b = raw_tga_read16(b, count, f);
241       }
242    } while (c < w);
243 }
244 
245 
246 
247 /* load_tga:
248  *  Loads a TGA file, returning a bitmap structure and storing the
249  *  palette data in the specified palette (this should be an array
250  *  of at least 256 RGB structures).
251  */
load_tga(AL_CONST char * filename,RGB * pal)252 BITMAP *load_tga(AL_CONST char *filename, RGB *pal)
253 {
254    PACKFILE *f;
255    BITMAP *bmp;
256    ASSERT(filename);
257 
258    f = pack_fopen(filename, F_READ);
259    if (!f)
260       return NULL;
261 
262    bmp = load_tga_pf(f, pal);
263 
264    pack_fclose(f);
265 
266    return bmp;
267 }
268 
269 
270 
271 /* load_tga_pf:
272  *  Like load_tga, but starts loading from the current place in the PACKFILE
273  *  specified. If successful the offset into the file will be left just after
274  *  the image data. If unsuccessful the offset into the file is unspecified,
275  *  i.e. you must either reset the offset to some known place or close the
276  *  packfile. The packfile is not closed by this function.
277  */
load_tga_pf(PACKFILE * f,RGB * pal)278 BITMAP *load_tga_pf(PACKFILE *f, RGB *pal)
279 {
280    unsigned char image_id[256], image_palette[256][3];
281    unsigned char id_length, palette_type, image_type, palette_entry_size;
282    unsigned char bpp, descriptor_bits;
283    short unsigned int palette_colors;
284    short unsigned int image_width, image_height;
285    unsigned int c, i, y, yc;
286    int dest_depth;
287    int compressed;
288    BITMAP *bmp;
289    PALETTE tmppal;
290    int want_palette = TRUE;
291    ASSERT(f);
292 
293    /* we really need a palette */
294    if (!pal) {
295       want_palette = FALSE;
296       pal = tmppal;
297    }
298 
299    id_length = pack_getc(f);
300    palette_type = pack_getc(f);
301    image_type = pack_getc(f);
302    /* first_color */ pack_igetw(f);
303    palette_colors  = pack_igetw(f);
304    palette_entry_size = pack_getc(f);
305    /* left */ pack_igetw(f);
306    /* top  */ pack_igetw(f);
307    image_width = pack_igetw(f);
308    image_height = pack_igetw(f);
309    bpp = pack_getc(f);
310    descriptor_bits = pack_getc(f);
311 
312    pack_fread(image_id, id_length, f);
313 
314    if (palette_type == 1) {
315 
316       for (i = 0; i < palette_colors; i++) {
317 
318 	 switch (palette_entry_size) {
319 
320 	    case 16:
321 	       c = pack_igetw(f);
322 	       image_palette[i][0] = (c & 0x1F) << 3;
323 	       image_palette[i][1] = ((c >> 5) & 0x1F) << 3;
324 	       image_palette[i][2] = ((c >> 10) & 0x1F) << 3;
325 	       break;
326 
327 	    case 24:
328 	    case 32:
329 	       image_palette[i][0] = pack_getc(f);
330 	       image_palette[i][1] = pack_getc(f);
331 	       image_palette[i][2] = pack_getc(f);
332 	       if (palette_entry_size == 32)
333 		  pack_getc(f);
334 	       break;
335 	 }
336       }
337    }
338    else if (palette_type != 0) {
339       return NULL;
340    }
341 
342    /* Image type:
343     *    0 = no image data
344     *    1 = uncompressed color mapped
345     *    2 = uncompressed true color
346     *    3 = grayscale
347     *    9 = RLE color mapped
348     *   10 = RLE true color
349     *   11 = RLE grayscale
350     */
351    compressed = (image_type & 8);
352    image_type &= 7;
353 
354    if ((image_type < 1) || (image_type > 3)) {
355       return NULL;
356    }
357 
358    switch (image_type) {
359 
360       case 1:
361 	 /* paletted image */
362 	 if ((palette_type != 1) || (bpp != 8)) {
363 	    return NULL;
364 	 }
365 
366 	 for(i=0; i<palette_colors; i++) {
367 	     pal[i].r = image_palette[i][2] >> 2;
368 	     pal[i].g = image_palette[i][1] >> 2;
369 	     pal[i].b = image_palette[i][0] >> 2;
370 	 }
371 
372 	 dest_depth = _color_load_depth(8, FALSE);
373 	 break;
374 
375       case 2:
376 	 /* truecolor image */
377 	 if ((palette_type == 0) && ((bpp == 15) || (bpp == 16))) {
378 	    bpp = 15;
379 	    dest_depth = _color_load_depth(15, FALSE);
380 	 }
381 	 else if ((palette_type == 0) && ((bpp == 24) || (bpp == 32))) {
382 	    dest_depth = _color_load_depth(bpp, (bpp == 32));
383 	 }
384 	 else {
385 	    return NULL;
386 	 }
387 	 break;
388 
389       case 3:
390 	 /* grayscale image */
391 	 if ((palette_type != 0) || (bpp != 8)) {
392 	    return NULL;
393 	 }
394 
395 	 for (i=0; i<256; i++) {
396 	     pal[i].r = i>>2;
397 	     pal[i].g = i>>2;
398 	     pal[i].b = i>>2;
399 	 }
400 
401 	 dest_depth = _color_load_depth(bpp, FALSE);
402 	 break;
403 
404       default:
405 	 return NULL;
406    }
407 
408    bmp = create_bitmap_ex(bpp, image_width, image_height);
409    if (!bmp) {
410       return NULL;
411    }
412 
413    *allegro_errno = 0;
414 
415    for (y=image_height; y; y--) {
416       yc = (descriptor_bits & 0x20) ? image_height-y : y-1;
417 
418       switch (image_type) {
419 
420 	 case 1:
421 	 case 3:
422 	    if (compressed)
423 	       rle_tga_read8(bmp->line[yc], image_width, f);
424 	    else
425 	       raw_tga_read8(bmp->line[yc], image_width, f);
426 	    break;
427 
428 	 case 2:
429 	    if (bpp == 32) {
430 	       if (compressed)
431 		  rle_tga_read32((unsigned int *)bmp->line[yc], image_width, f);
432 	       else
433 		  raw_tga_read32((unsigned int *)bmp->line[yc], image_width, f);
434 	    }
435 	    else if (bpp == 24) {
436 	       if (compressed)
437 		  rle_tga_read24(bmp->line[yc], image_width, f);
438 	       else
439 		  raw_tga_read24(bmp->line[yc], image_width, f);
440 	    }
441 	    else {
442 	       if (compressed)
443 		  rle_tga_read16((unsigned short *)bmp->line[yc], image_width, f);
444 	       else
445 		  raw_tga_read16((unsigned short *)bmp->line[yc], image_width, f);
446 	    }
447 	    break;
448       }
449    }
450 
451    if (*allegro_errno) {
452       destroy_bitmap(bmp);
453       return NULL;
454    }
455 
456    if (dest_depth != bpp) {
457       /* restore original palette except if it comes from the bitmap */
458       if ((bpp != 8) && (!want_palette))
459 	 pal = NULL;
460 
461       bmp = _fixup_loaded_bitmap(bmp, pal, dest_depth);
462    }
463 
464    /* construct a fake palette if 8-bit mode is not involved */
465    if ((bpp != 8) && (dest_depth != 8) && want_palette)
466       generate_332_palette(pal);
467 
468    return bmp;
469 }
470 
471 
472 
473 /* save_tga:
474  *  Writes a bitmap into a TGA file, using the specified palette (this
475  *  should be an array of at least 256 RGB structures).
476  */
save_tga(AL_CONST char * filename,BITMAP * bmp,AL_CONST RGB * pal)477 int save_tga(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *pal)
478 {
479    PACKFILE *f;
480    int ret;
481    ASSERT(filename);
482 
483    f = pack_fopen(filename, F_WRITE);
484    if (!f)
485       return -1;
486 
487    ret = save_tga_pf(f, bmp, pal);
488 
489    pack_fclose(f);
490 
491    return ret;
492 }
493 
494 
495 
496 /* save_tga_pf:
497  *  Like save_tga but writes into the PACKFILE given instead of a new file.
498  *  The packfile is not closed after writing is completed. On success the
499  *  offset into the file is left after the TGA file just written. On failure
500  *  the offset is left at the end of whatever incomplete data was written.
501  */
save_tga_pf(PACKFILE * f,BITMAP * bmp,AL_CONST RGB * pal)502 int save_tga_pf(PACKFILE *f, BITMAP *bmp, AL_CONST RGB *pal)
503 {
504    unsigned char image_palette[256][3];
505    int x, y, c, r, g, b;
506    int depth;
507    PALETTE tmppal;
508    ASSERT(f);
509    ASSERT(bmp);
510 
511    if (!pal) {
512       get_palette(tmppal);
513       pal = tmppal;
514    }
515 
516    depth = bitmap_color_depth(bmp);
517 
518    if (depth == 15)
519       depth = 16;
520 
521    *allegro_errno = 0;
522 
523    pack_putc(0, f);                          /* id length (no id saved) */
524    pack_putc((depth == 8) ? 1 : 0, f);       /* palette type */
525    pack_putc((depth == 8) ? 1 : 2, f);       /* image type */
526    pack_iputw(0, f);                         /* first colour */
527    pack_iputw((depth == 8) ? 256 : 0, f);    /* number of colours */
528    pack_putc((depth == 8) ? 24 : 0, f);      /* palette entry size */
529    pack_iputw(0, f);                         /* left */
530    pack_iputw(0, f);                         /* top */
531    pack_iputw(bmp->w, f);                    /* width */
532    pack_iputw(bmp->h, f);                    /* height */
533    pack_putc(depth, f);                      /* bits per pixel */
534    pack_putc(_bitmap_has_alpha (bmp) ? 8 : 0, f); /* descriptor (bottom to top, 8-bit alpha) */
535 
536    if (depth == 8) {
537       for (y=0; y<256; y++) {
538 	 image_palette[y][2] = _rgb_scale_6[pal[y].r];
539 	 image_palette[y][1] = _rgb_scale_6[pal[y].g];
540 	 image_palette[y][0] = _rgb_scale_6[pal[y].b];
541       }
542 
543       pack_fwrite(image_palette, 768, f);
544    }
545 
546    switch (bitmap_color_depth(bmp)) {
547 
548       #ifdef ALLEGRO_COLOR8
549 
550 	 case 8:
551 	    for (y=bmp->h; y; y--)
552 	       for (x=0; x<bmp->w; x++)
553 		  pack_putc(getpixel(bmp, x, y-1), f);
554 	    break;
555 
556       #endif
557 
558       #ifdef ALLEGRO_COLOR16
559 
560 	 case 15:
561 	    for (y=bmp->h; y; y--) {
562 	       for (x=0; x<bmp->w; x++) {
563 		  c = getpixel(bmp, x, y-1);
564 		  r = getr15(c);
565 		  g = getg15(c);
566 		  b = getb15(c);
567 		  c = ((r<<7)&0x7C00) | ((g<<2)&0x3E0) | ((b>>3)&0x1F);
568 		  pack_iputw(c, f);
569 	       }
570 	    }
571 	    break;
572 
573 	 case 16:
574 	    for (y=bmp->h; y; y--) {
575 	       for (x=0; x<bmp->w; x++) {
576 		  c = getpixel(bmp, x, y-1);
577 		  r = getr16(c);
578 		  g = getg16(c);
579 		  b = getb16(c);
580 		  c = ((r<<7)&0x7C00) | ((g<<2)&0x3E0) | ((b>>3)&0x1F);
581 		  pack_iputw(c, f);
582 	       }
583 	    }
584 	    break;
585 
586       #endif
587 
588       #ifdef ALLEGRO_COLOR24
589 
590 	 case 24:
591 	    for (y=bmp->h; y; y--) {
592 	       for (x=0; x<bmp->w; x++) {
593 		  c = getpixel(bmp, x, y-1);
594 		  pack_putc(getb24(c), f);
595 		  pack_putc(getg24(c), f);
596 		  pack_putc(getr24(c), f);
597 	       }
598 	    }
599 	    break;
600 
601       #endif
602 
603       #ifdef ALLEGRO_COLOR32
604 
605 	 case 32:
606 	    for (y=bmp->h; y; y--) {
607 	       for (x=0; x<bmp->w; x++) {
608 		  c = getpixel(bmp, x, y-1);
609 		  pack_putc(getb32(c), f);
610 		  pack_putc(getg32(c), f);
611 		  pack_putc(getr32(c), f);
612 		  pack_putc(geta32(c), f);
613 	       }
614 	    }
615 	    break;
616 
617       #endif
618    }
619 
620    if (*allegro_errno)
621       return -1;
622    else
623       return 0;
624 }
625 
626 
627