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