1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 #include <deark-config.h>
6 #include <deark-private.h>
7 #include <deark-fmtutil.h>
8 DE_DECLARE_MODULE(de_module_tga
);
12 i64 img_size_in_bytes
;
14 int respect_alpha_channel
;
17 typedef struct localctx_struct
{
24 struct tgaimginfo main_image
;
25 struct tgaimginfo thumbnail_image
;
31 i64 num_attribute_bits
;
33 u8 top_down
, right_to_left
;
36 int has_extension_area
;
37 #define TGA_CMPR_UNKNOWN 0
38 #define TGA_CMPR_NONE 1
39 #define TGA_CMPR_RLE 2
41 #define TGA_CLRTYPE_UNKNOWN 0
42 #define TGA_CLRTYPE_PALETTE 1
43 #define TGA_CLRTYPE_TRUECOLOR 2
44 #define TGA_CLRTYPE_GRAYSCALE 3
46 const char *cmpr_name
;
47 const char *clrtype_name
;
48 i64 bytes_per_pixel
; // May be meaningless if pixel_depth is not a multiple of 8
49 i64 bytes_per_pal_entry
;
50 i64 pal_size_in_bytes
;
51 i64 aspect_ratio_num
, aspect_ratio_den
;
54 struct de_timestamp mod_time
;
57 // Figure out if the image has transparency, and emit a warning or other message if
59 // TGA transparency is kind of a mess. Multiple ways of labeling it, some of
60 // which are ambiguous... Files that have inconsistent labels... Files that
61 // claim to have transparency but don't, or that claim not to but do...
62 static int should_use_alpha_channel(deark
*c
, lctx
*d
, struct tgaimginfo
*imginfo
,
63 int has_alpha_0
, int has_alpha_partial
, int has_alpha_255
)
65 if(imginfo
->is_thumb
) {
66 // Do the same thing with the thumbnail as we did with the main image.
67 return d
->main_image
.respect_alpha_channel
;
70 if(d
->pixel_depth
!=32 || d
->color_type
!=TGA_CLRTYPE_TRUECOLOR
) {
74 if(d
->num_attribute_bits
!=0 && d
->num_attribute_bits
!=8) {
75 de_warn(c
, "%d-bit attribute channel not supported. Transparency disabled.",
76 (int)d
->num_attribute_bits
);
80 if(d
->has_extension_area
) {
81 if(d
->attributes_type
==0) {
82 // attributes_type==0 technically also means there is no transparency,
83 // but this cannot be trusted.
86 if(d
->attributes_type
==1 || d
->attributes_type
==2) {
87 // Indicates that attribute data can be ignored.
90 else if(d
->attributes_type
==3 && d
->num_attribute_bits
==8) {
91 // Alpha channel seems to be labeled correctly.
95 else if(d
->attributes_type
==4) {
96 // Sigh. The spec shows that Field 24 (Attributes Type) == 4 is for
97 // pre-multiplied alpha. Then the discussion section says that
98 // Field *23* ("Attributes Type") == *3* is for premultiplied alpha.
99 // I have to guess that the "23" and "3" are clerical errors, but that
100 // doesn't do me much good unless all TGA developers made the same guess.
101 de_warn(c
, "Pre-multiplied alpha is not supported. Disabling transparency.");
106 if(has_alpha_partial
|| (has_alpha_0
&& has_alpha_255
)) {
107 if(d
->num_attribute_bits
==0) {
108 de_warn(c
, "Detected likely alpha channel. Enabling transparency, even though "
109 "the image is labeled as non-transparent.");
113 else if(has_alpha_0
) { // All 0x00
114 if(d
->num_attribute_bits
!=0) {
115 de_warn(c
, "Non-visible image detected. Disabling transparency.");
118 de_dbg(c
, "potential alpha channel ignored: all 0 bits");
123 de_dbg(c
, "potential alpha channel is moot: all 1 bits");
128 static void do_decode_image(deark
*c
, lctx
*d
, struct tgaimginfo
*imginfo
, dbuf
*unc_pixels
,
129 const char *token
, unsigned int createflags
)
131 de_bitmap
*img
= NULL
;
140 unsigned int getrgbflags
;
141 i64 interleave_stride
;
143 i64 cur_rownum
; // 0-based, does not account for bottom-up orientation
145 int has_alpha_partial
= 0;
146 int has_alpha_255
= 0;
148 fi
= de_finfo_create(c
);
151 de_finfo_set_name_from_sz(c
, fi
, token
, 0, DE_ENCODING_LATIN1
);
153 if(d
->mod_time
.is_valid
) {
154 fi
->internal_mod_time
= d
->mod_time
;
157 pdwidth
= imginfo
->width
;
158 if(d
->pixel_depth
==1) {
159 de_warn(c
, "1-bit TGA images are not portable, and may not be decoded correctly");
160 pdwidth
= de_pad_to_n(imginfo
->width
, 8);
164 rowspan
= imginfo
->width
*d
->bytes_per_pixel
;
167 if(d
->color_type
==TGA_CLRTYPE_GRAYSCALE
|| d
->pixel_depth
==1)
169 else if(d
->pixel_depth
==32)
174 if(d
->file_format
==FMT_VST
)
177 getrgbflags
= DE_GETRGBFLAG_BGR
;
179 img
= de_bitmap_create2(c
, imginfo
->width
, pdwidth
, imginfo
->height
, output_bypp
);
181 switch(d
->interleave_mode
) {
182 case 1: interleave_stride
= 2; break;
183 case 2: interleave_stride
= 4; break;
184 default: interleave_stride
= 1;
190 for(j
=0; j
<imginfo
->height
; j
++) {
196 j_adj
= imginfo
->height
-1-cur_rownum
;
198 // Update the row number for next time
199 cur_rownum
+= interleave_stride
;
200 if(cur_rownum
>= imginfo
->height
) {
201 // Went past the end of the image; move back to near the start.
203 cur_rownum
= interleave_pass
;
206 if(d
->pixel_depth
==1) {
207 de_convert_row_bilevel(unc_pixels
, j
*rowspan
, img
, j_adj
, 0);
211 for(i
=0; i
<pdwidth
; i
++) {
215 i_adj
= imginfo
->width
-1-i
;
219 if(d
->color_type
==TGA_CLRTYPE_TRUECOLOR
&& (d
->pixel_depth
==15 || d
->pixel_depth
==16)) {
220 clr
= (u32
)dbuf_getu16le(unc_pixels
, j
*rowspan
+ i
*d
->bytes_per_pixel
);
221 clr
= de_rgb555_to_888(clr
);
222 de_bitmap_setpixel_rgb(img
, i_adj
, j_adj
, clr
);
224 else if(d
->color_type
==TGA_CLRTYPE_TRUECOLOR
) {
225 clr
= dbuf_getRGB(unc_pixels
, j
*rowspan
+ i
*d
->bytes_per_pixel
, getrgbflags
);
226 if(d
->pixel_depth
==32) {
227 a
= dbuf_getbyte(unc_pixels
, j
*rowspan
+ i
*d
->bytes_per_pixel
+3);
228 de_bitmap_setpixel_rgba(img
, i_adj
, j_adj
, DE_SET_ALPHA(clr
, a
));
230 // Collect metrics that we may need, to decide whether to keep the
231 // might-be-alpha channel.
239 has_alpha_partial
= 1;
243 de_bitmap_setpixel_rgb(img
, i_adj
, j_adj
, clr
);
246 else if(d
->color_type
==TGA_CLRTYPE_GRAYSCALE
) {
247 b
= dbuf_getbyte(unc_pixels
, j
*rowspan
+ i
*d
->bytes_per_pixel
);
248 de_bitmap_setpixel_gray(img
, i_adj
, j_adj
, b
);
250 else if(d
->color_type
==TGA_CLRTYPE_PALETTE
) {
251 b
= dbuf_getbyte(unc_pixels
, j
*rowspan
+ i
*d
->bytes_per_pixel
);
252 de_bitmap_setpixel_rgb(img
, i_adj
, j_adj
, d
->pal
[(unsigned int)b
]);
257 // TODO: 16-bit images could theoretically have a transparency bit, but I don't
258 // know how to detect that.
259 if(d
->pixel_depth
==32) {
260 imginfo
->respect_alpha_channel
= should_use_alpha_channel(c
, d
, imginfo
,
261 has_alpha_0
, has_alpha_partial
, has_alpha_255
);
263 if(!imginfo
->is_thumb
) {
264 de_dbg(c
, "using alpha channel: %s", imginfo
->respect_alpha_channel
?"yes":"no");
267 if(!imginfo
->respect_alpha_channel
) {
268 de_bitmap_remove_alpha(img
);
272 de_bitmap_write_to_file_finfo(img
, fi
, createflags
);
274 de_bitmap_destroy(img
);
275 de_finfo_destroy(c
, fi
);
278 static void do_decode_rle_internal(deark
*c1
, struct de_dfilter_in_params
*dcmpri
,
279 struct de_dfilter_out_params
*dcmpro
, struct de_dfilter_results
*dres
,
286 i64 pos
= dcmpri
->pos
;
288 if(bytes_per_pixel
<1 || bytes_per_pixel
>8) return;
291 if(pos
>= dcmpri
->pos
+ dcmpri
->len
) break;
292 if(dcmpro
->f
->len
>= dcmpro
->expected_len
) break;
294 b
= dbuf_getbyte(dcmpri
->f
, pos
);
297 if(b
& 0x80) { // RLE block
298 count
= (i64
)(b
- 0x80) + 1;
299 dbuf_read(dcmpri
->f
, buf
, pos
, bytes_per_pixel
);
300 pos
+= bytes_per_pixel
;
301 for(k
=0; k
<count
; k
++) {
302 dbuf_write(dcmpro
->f
, buf
, bytes_per_pixel
);
305 else { // uncompressed block
306 count
= (i64
)(b
) + 1;
307 dbuf_copy(dcmpri
->f
, pos
, count
* bytes_per_pixel
, dcmpro
->f
);
308 pos
+= count
* bytes_per_pixel
;
311 dres
->bytes_consumed
= pos
- dcmpri
->pos
;
312 dres
->bytes_consumed_valid
= 1;
315 static int do_decode_rle(deark
*c
, lctx
*d
, i64 pos1
, dbuf
*unc_pixels
)
317 struct de_dfilter_in_params dcmpri
;
318 struct de_dfilter_out_params dcmpro
;
319 struct de_dfilter_results dres
;
321 de_dfilter_init_objects(c
, &dcmpri
, &dcmpro
, &dres
);
322 dcmpri
.f
= c
->infile
;
324 dcmpri
.len
= c
->infile
->len
- pos1
;
325 dcmpro
.f
= unc_pixels
;
326 dcmpro
.len_known
= 1;
327 dcmpro
.expected_len
= d
->main_image
.img_size_in_bytes
;
329 do_decode_rle_internal(c
, &dcmpri
, &dcmpro
, &dres
, d
->bytes_per_pixel
);
332 de_err(c
, "%s", de_dfilter_get_errmsg(c
, &dres
));
335 de_dbg(c
, "decompressed %"I64_FMT
" bytes to %"I64_FMT
" bytes",
336 dres
.bytes_consumed
, unc_pixels
->len
);
340 static void do_decode_thumbnail(deark
*c
, lctx
*d
)
342 dbuf
*unc_pixels
= NULL
;
345 de_dbg(c
, "thumbnail image at %d", (int)d
->thumbnail_offset
);
348 // The thumbnail image is supposed to use the same format as the main image,
349 // except without compression. (And the dimensions are obviously different.)
350 // Presumably this means the origin, palette, etc. will be the same.
351 // But based on the few TGA thumbnails we've seen, nobody reads the spec, and
352 // it's anybody's guess what format the thumbnail will use.
354 // TGA 2.0 spec says the dimensions are one *byte* each.
355 d
->thumbnail_image
.width
= (i64
)de_getbyte(d
->thumbnail_offset
);
356 d
->thumbnail_image
.height
= (i64
)de_getbyte(d
->thumbnail_offset
+1);
357 de_dbg(c
, "thumbnail dimensions: %d"DE_CHAR_TIMES
"%d", (int)d
->thumbnail_image
.width
, (int)d
->thumbnail_image
.height
);
359 if(d
->thumbnail_image
.width
!=0 && d
->thumbnail_image
.height
==0) {
360 de_warn(c
, "Thumbnail image height is 0. Assuming the file incorrectly uses "
361 "16-bit thumbnail dimensions, instead of 8.");
362 d
->thumbnail_image
.width
= de_getu16le(d
->thumbnail_offset
);
363 d
->thumbnail_image
.height
= de_getu16le(d
->thumbnail_offset
+2);
364 de_dbg(c
, "revised thumbnail dimensions: %d"DE_CHAR_TIMES
"%d", (int)d
->thumbnail_image
.width
, (int)d
->thumbnail_image
.height
);
367 if(!de_good_image_dimensions(c
, d
->thumbnail_image
.width
, d
->thumbnail_image
.height
)) goto done
;
369 d
->thumbnail_image
.img_size_in_bytes
= d
->thumbnail_image
.height
* d
->thumbnail_image
.width
* d
->bytes_per_pixel
;
370 unc_pixels
= dbuf_open_input_subfile(c
->infile
, d
->thumbnail_offset
+hdrsize
, d
->thumbnail_image
.img_size_in_bytes
);
372 do_decode_image(c
, d
, &d
->thumbnail_image
, unc_pixels
, "thumb", DE_CREATEFLAG_IS_AUX
);
375 dbuf_close(unc_pixels
);
376 de_dbg_indent(c
, -1);
379 static int do_read_palette(deark
*c
, lctx
*d
, i64 pos
)
383 unsigned int getrgbflags
;
385 if(d
->color_type
!= TGA_CLRTYPE_PALETTE
) {
386 return 1; // don't care about the palette
389 if(d
->cmap_depth
!= 24) {
390 de_err(c
, "Palettes with depth=%d are not supported.", (int)d
->cmap_depth
);
393 if(d
->pixel_depth
!= 8) {
394 de_err(c
, "Paletted images with depth=%d are not supported.", (int)d
->pixel_depth
);
398 if(d
->file_format
==FMT_VST
)
401 getrgbflags
= DE_GETRGBFLAG_BGR
;
403 for(i
=0; i
<d
->cmap_length
; i
++) {
404 idx
= d
->cmap_start
+ i
;
405 if(idx
<0 || idx
>255) continue;
406 d
->pal
[idx
] = dbuf_getRGB(c
->infile
, pos
+ i
*d
->bytes_per_pal_entry
, getrgbflags
);
407 de_dbg_pal_entry(c
, idx
, d
->pal
[idx
]);
412 static void do_read_extension_area(deark
*c
, lctx
*d
, i64 pos
)
417 de_ucstring
*s
= NULL
;
420 de_dbg(c
, "extension area at %d", (int)pos
);
421 if(pos
> c
->infile
->len
- 2) {
422 de_warn(c
, "Bad extension area offset: %u", (unsigned int)pos
);
428 s
= ucstring_create(c
);
430 ext_area_size
= de_getu16le(pos
);
431 de_dbg(c
, "extension area size: %d", (int)ext_area_size
);
432 if(ext_area_size
<495) goto done
;
434 d
->has_extension_area
= 1;
437 dbuf_read_to_ucstring(c
->infile
, pos
+2, 41, s
, DE_CONVFLAG_STOP_AT_NUL
, DE_ENCODING_ASCII
);
438 ucstring_strip_trailing_spaces(s
);
439 de_dbg(c
, "author: \"%s\"", ucstring_getpsz_d(s
));
443 dbuf_read_to_ucstring(c
->infile
, pos
+43+81*k
, 81, s
, DE_CONVFLAG_STOP_AT_NUL
, DE_ENCODING_ASCII
);
444 ucstring_strip_trailing_spaces(s
);
445 de_dbg(c
, "comment line %d: \"%s\"", (int)k
, ucstring_getpsz_d(s
));
448 // date/time: pos=367, size=12
451 val
[k
] = de_getu16le(pos
+367+2*k
);
452 if(val
[k
]!=0) has_date
= 1;
455 char timestamp_buf
[64];
457 de_make_timestamp(&d
->mod_time
, val
[2], val
[0], val
[1], val
[3], val
[4], val
[5]);
458 d
->mod_time
.tzcode
= DE_TZCODE_LOCAL
;
459 de_timestamp_to_string(&d
->mod_time
, timestamp_buf
, sizeof(timestamp_buf
), 0);
460 de_dbg(c
, "timestamp: %s", timestamp_buf
);
463 // Job name: pos=379, size=41 (not implemented)
464 // Job time: pos=420, size=6 (not implemented)
467 dbuf_read_to_ucstring(c
->infile
, pos
+426, 41, s
, DE_CONVFLAG_STOP_AT_NUL
, DE_ENCODING_ASCII
);
468 ucstring_strip_trailing_spaces(s
);
469 de_dbg(c
, "software id: \"%s\"", ucstring_getpsz_d(s
));
471 val
[0] = de_getu16le(pos
+467);
472 val
[1] = (i64
)de_getbyte(pos
+469);
473 if(val
[0]!=0 || val
[1]!=32) {
474 de_dbg(c
, "software version: %u,%u,%u",
475 (unsigned int)(val
[0]/100), (unsigned int)(val
[0]%100),
476 (unsigned int)val
[1]);
479 val
[0] = de_getu32le(pos
+470);
481 de_dbg(c
, "background color: 0x%08x", (unsigned int)val
[0]);
484 // TODO: Retain the aspect ratio. (Need sample files. Nobody seems to use this field.)
485 d
->aspect_ratio_num
= de_getu16le(pos
+474);
486 d
->aspect_ratio_den
= de_getu16le(pos
+476);
487 if(d
->aspect_ratio_den
!=0) {
488 de_dbg(c
, "aspect ratio: %d/%d", (int)d
->aspect_ratio_num
, (int)d
->aspect_ratio_den
);
491 // Gamma: pos=478, size=4 (not implemented)
492 // Color correction table offset: pos=482, size=4 (not implemented)
494 d
->thumbnail_offset
= de_getu32le(pos
+486);
495 de_dbg(c
, "thumbnail image offset: %d", (int)d
->thumbnail_offset
);
497 val
[0] = de_getu32le(pos
+490);
498 de_dbg(c
, "scan line table offset: %"I64_FMT
, val
[0]);
500 d
->attributes_type
= de_getbyte(pos
+494);
501 de_dbg(c
, "attributes type: %d", (int)d
->attributes_type
);
502 if(d
->attributes_type
==0 && d
->num_attribute_bits
!=0) {
503 de_warn(c
, "Incompatible \"number of attribute bits\" (%d) and \"attributes type\" "
504 "(%d) fields. Transparency may not be handled correctly.",
505 (int)d
->num_attribute_bits
, (int)d
->attributes_type
);
509 de_dbg_indent(c
, -1);
513 static void do_read_developer_area(deark
*c
, lctx
*d
, i64 pos
)
517 i64 tag_id
, tag_data_pos
, tag_data_size
;
519 de_dbg(c
, "developer area at %d", (int)pos
);
520 if(pos
> c
->infile
->len
- 2) {
521 de_warn(c
, "Bad developer area offset: %u", (unsigned int)pos
);
526 num_tags
= de_getu16le(pos
);
527 de_dbg(c
, "number of tags: %d", (int)num_tags
);
528 for(i
=0; i
<num_tags
; i
++) {
530 tag_id
= de_getu16le(pos
+ 2 + 10*i
);
531 tag_data_pos
= de_getu32le(pos
+ 2 + 10*i
+ 2);
532 tag_data_size
= de_getu32le(pos
+ 2 + 10*i
+ 6);
533 de_dbg(c
, "tag #%d: id=%d, pos=%d, size=%d", (int)i
, (int)tag_id
,
534 (int)tag_data_pos
, (int)tag_data_size
);
537 // Tag 20 seems to contain Photoshop resources, though this is unconfirmed.
539 // TODO: We could retrieve the pixel density settings from the Photoshop data,
540 // but it's not clear whether they are ever useful.
541 fmtutil_handle_photoshop_rsrc(c
, c
->infile
, tag_data_pos
, tag_data_size
, 0x0);
542 de_dbg_indent(c
, -1);
545 de_dbg_indent(c
, -1);
548 static void do_read_footer(deark
*c
, lctx
*d
)
551 i64 ext_offset
, dev_offset
;
553 footerpos
= c
->infile
->len
- 26;
554 de_dbg(c
, "v2 footer at %d", (int)footerpos
);
556 ext_offset
= de_getu32le(footerpos
);
557 de_dbg(c
, "extension area offset: %d", (int)ext_offset
);
558 dev_offset
= de_getu32le(footerpos
+4);
559 de_dbg(c
, "developer area offset: %d", (int)dev_offset
);
560 de_dbg_indent(c
, -1);
563 do_read_extension_area(c
, d
, ext_offset
);
567 do_read_developer_area(c
, d
, dev_offset
);
571 static void do_read_image_descriptor(deark
*c
, lctx
*d
)
573 d
->image_descriptor
= de_getbyte(17);
574 de_dbg(c
, "descriptor: 0x%02x", (unsigned int)d
->image_descriptor
);
577 d
->num_attribute_bits
= (i64
)(d
->image_descriptor
& 0x0f);
578 de_dbg(c
, "number of %s bits: %d",
579 d
->file_format
==FMT_VST
?"alpha channel":"attribute",
580 (int)d
->num_attribute_bits
);
582 d
->right_to_left
= (d
->image_descriptor
>>4)&0x01;
583 d
->top_down
= (d
->image_descriptor
>>5)&0x01;
584 de_dbg(c
, "right-to-left flag: %d", (int)d
->right_to_left
);
585 de_dbg(c
, "top-down flag: %d", (int)d
->top_down
);
587 d
->interleave_mode
= d
->image_descriptor
>> 6;
588 if(d
->interleave_mode
!= 0) {
589 de_dbg(c
, "interleaving: %d", (int)d
->interleave_mode
);
591 de_dbg_indent(c
, -1);
594 static int do_read_tga_headers(deark
*c
, lctx
*d
)
598 de_dbg(c
, "header at %d", 0);
601 d
->id_field_len
= (i64
)de_getbyte(0);
602 d
->color_map_type
= de_getbyte(1);
603 de_dbg(c
, "color map type: %d", (int)d
->color_map_type
);
604 d
->img_type
= de_getbyte(2);
605 de_dbg(c
, "image type: %d", (int)d
->img_type
);
607 switch(d
->img_type
) {
610 d
->color_type
= TGA_CLRTYPE_PALETTE
;
611 d
->clrtype_name
= "palette";
614 d
->color_type
= TGA_CLRTYPE_TRUECOLOR
;
615 d
->clrtype_name
= "truecolor";
618 d
->color_type
= TGA_CLRTYPE_GRAYSCALE
;
619 d
->clrtype_name
= "grayscale";
622 d
->color_type
= TGA_CLRTYPE_UNKNOWN
;
623 d
->clrtype_name
= "unknown";
626 switch(d
->img_type
) {
627 case 1: case 2: case 3:
628 d
->cmpr_type
= TGA_CMPR_NONE
;
629 d
->cmpr_name
= "none";
631 case 9: case 10: case 11:
632 d
->cmpr_type
= TGA_CMPR_RLE
;
633 d
->cmpr_name
= "RLE";
636 d
->cmpr_type
= TGA_CMPR_UNKNOWN
;
637 d
->cmpr_name
= "unknown";
641 de_dbg(c
, "color type: %d (%s)", (int)d
->color_type
, d
->clrtype_name
);
642 de_dbg(c
, "compression: %d (%s)", (int)d
->cmpr_type
, d
->cmpr_name
);
643 de_dbg_indent(c
, -1);
645 if(d
->color_map_type
!= 0) {
646 d
->cmap_start
= de_getu16le(3);
647 d
->cmap_length
= de_getu16le(5);
648 d
->cmap_depth
= (i64
)de_getbyte(7);
649 de_dbg(c
, "color map start: %d, len: %d, depth: %d", (int)d
->cmap_start
,
650 (int)d
->cmap_length
, (int)d
->cmap_depth
);
653 d
->main_image
.width
= de_getu16le(12);
654 d
->main_image
.height
= de_getu16le(14);
655 de_dbg_dimensions(c
, d
->main_image
.width
, d
->main_image
.height
);
657 d
->pixel_depth
= (i64
)de_getbyte(16);
658 de_dbg(c
, "pixel depth: %d", (int)d
->pixel_depth
);
660 do_read_image_descriptor(c
, d
);
662 de_dbg_indent(c
, -1);
664 if(d
->has_signature
) {
665 do_read_footer(c
, d
);
668 if(!de_good_image_dimensions(c
, d
->main_image
.width
, d
->main_image
.height
)) goto done
;
675 // This .vst (TrueVista) decoder is based on guesswork, on the limited information
676 // in the TGA spec, and on the behavior of XnView. It may not be correct.
677 static int do_read_vst_headers(deark
*c
, lctx
*d
)
681 de_dbg(c
, "header at %d", 0);
684 d
->id_field_len
= (i64
)de_getbyte(0);
686 if(d
->id_field_len
==0) {
687 // ??? XnView seems to do something like this.
691 d
->cmpr_type
= TGA_CMPR_NONE
;
692 d
->cmpr_name
= "none";
694 d
->main_image
.width
= de_getu16le(12);
695 d
->main_image
.height
= de_getu16le(14);
696 de_dbg_dimensions(c
, d
->main_image
.width
, d
->main_image
.height
);
698 d
->pixel_depth
= (i64
)de_getbyte(16);
699 de_dbg(c
, "pixel depth: %d", (int)d
->pixel_depth
);
700 if(d
->pixel_depth
==8) {
701 d
->color_map_type
= 1;
702 d
->color_type
= TGA_CLRTYPE_PALETTE
;
703 d
->clrtype_name
= "palette";
706 d
->color_type
= TGA_CLRTYPE_TRUECOLOR
;
707 d
->clrtype_name
= "truecolor";
710 if(d
->color_type
==TGA_CLRTYPE_PALETTE
) {
712 d
->cmap_length
= 256;
716 do_read_image_descriptor(c
, d
);
718 de_dbg_indent(c
, -1);
720 if(!de_good_image_dimensions(c
, d
->main_image
.width
, d
->main_image
.height
)) goto done
;
727 static int has_signature(deark
*c
)
729 if(c
->infile
->len
<18+26) return 0;
730 if(!dbuf_memcmp(c
->infile
, c
->infile
->len
-18, "TRUEVISION-XFILE.\0", 18)) {
736 // Sets d->file_format and d->has_signature
737 static void detect_file_format(deark
*c
, lctx
*d
)
742 d
->has_signature
= has_signature(c
);
743 de_dbg(c
, "has v2 signature: %s", d
->has_signature
?"yes":"no");
744 if(d
->has_signature
) {
745 d
->file_format
= FMT_TGA
;
749 img_type
= de_getbyte(2);
751 has_igch
= !dbuf_memcmp(c
->infile
, 20, "IGCH", 4);
753 d
->file_format
= FMT_VST
;
758 d
->file_format
= FMT_TGA
;
761 static void de_run_tga(deark
*c
, de_module_params
*mparams
)
765 dbuf
*unc_pixels
= NULL
;
766 int saved_indent_level
;
769 de_dbg_indent_save(c
, &saved_indent_level
);
770 d
= de_malloc(c
, sizeof(lctx
));
772 detect_file_format(c
, d
);
774 if(d
->file_format
==FMT_VST
) {
775 de_declare_fmt(c
, "TrueVista");
778 de_declare_fmt(c
, "TGA");
781 d
->thumbnail_image
.is_thumb
= 1;
785 if(d
->file_format
==FMT_VST
) {
786 if(!do_read_vst_headers(c
, d
)) goto done
;
789 if(!do_read_tga_headers(c
, d
)) goto done
;
793 if(d
->id_field_len
>0) {
794 de_dbg(c
, "image ID at %d (len=%d)", (int)pos
, (int)d
->id_field_len
);
795 pos
+= d
->id_field_len
;
798 if(d
->color_map_type
!=0) {
799 d
->bytes_per_pal_entry
= (d
->cmap_depth
+7)/8;
800 d
->pal_size_in_bytes
= d
->cmap_length
* d
->bytes_per_pal_entry
;
801 de_dbg(c
, "color map at %d (%d colors, %d bytes)", (int)pos
,
802 (int)d
->cmap_length
, (int)d
->pal_size_in_bytes
);
805 if(!do_read_palette(c
, d
, pos
)) goto done
;
806 de_dbg_indent(c
, -1);
808 pos
+= d
->pal_size_in_bytes
;
811 de_dbg(c
, "bitmap at %d", (int)pos
);
814 d
->bytes_per_pixel
= ((d
->pixel_depth
+7)/8);
815 if(d
->pixel_depth
==1) {
816 rowspan_tmp
= (d
->main_image
.width
+7)/8;
819 rowspan_tmp
= d
->main_image
.width
* d
->bytes_per_pixel
;
821 d
->main_image
.img_size_in_bytes
= d
->main_image
.height
* rowspan_tmp
;
823 if(d
->color_type
!=TGA_CLRTYPE_PALETTE
&& d
->color_type
!=TGA_CLRTYPE_TRUECOLOR
&&
824 d
->color_type
!=TGA_CLRTYPE_GRAYSCALE
)
826 de_err(c
, "Unsupported color type (%d: %s)", (int)d
->color_type
, d
->clrtype_name
);
830 if( (d
->color_type
==TGA_CLRTYPE_PALETTE
&& d
->pixel_depth
==8) ||
831 (d
->color_type
==TGA_CLRTYPE_TRUECOLOR
&& d
->pixel_depth
==15) ||
832 (d
->color_type
==TGA_CLRTYPE_TRUECOLOR
&& d
->pixel_depth
==16) ||
833 (d
->color_type
==TGA_CLRTYPE_TRUECOLOR
&& d
->pixel_depth
==24) ||
834 (d
->color_type
==TGA_CLRTYPE_TRUECOLOR
&& d
->pixel_depth
==32) ||
835 (d
->color_type
==TGA_CLRTYPE_GRAYSCALE
&& d
->pixel_depth
==1) ||
836 (d
->color_type
==TGA_CLRTYPE_GRAYSCALE
&& d
->pixel_depth
==8) )
841 de_err(c
, "Unsupported TGA image type (%s, depth=%d)", d
->clrtype_name
,
842 (int)d
->pixel_depth
);
846 if(d
->cmpr_type
==TGA_CMPR_RLE
) {
847 if(d
->pixel_depth
<8) {
848 de_err(c
, "RLE compression not supported when depth (%d) is less than 8",
849 (int)d
->pixel_depth
);
852 unc_pixels
= dbuf_create_membuf(c
, d
->main_image
.img_size_in_bytes
, 1);
853 if(!do_decode_rle(c
, d
, pos
, unc_pixels
)) goto done
;
855 else if(d
->cmpr_type
==TGA_CMPR_NONE
) {
856 unc_pixels
= dbuf_open_input_subfile(c
->infile
, pos
, d
->main_image
.img_size_in_bytes
);
859 de_err(c
, "Unsupported compression type (%d, %s)", (int)d
->cmpr_type
, d
->cmpr_name
);
863 do_decode_image(c
, d
, &d
->main_image
, unc_pixels
, NULL
, 0);
865 de_dbg_indent(c
, -1);
867 if(d
->thumbnail_offset
!=0) {
868 do_decode_thumbnail(c
, d
);
872 dbuf_close(unc_pixels
);
873 de_dbg_indent_restore(c
, saved_indent_level
);
877 static int de_identify_tga(deark
*c
)
883 if(has_signature(c
)) {
887 // TGA v1 format has no signature, but there are only a few common types of
888 // it. We'll at least try to identify anything that we support.
891 if(b
[1]>1) return 0; // Color map type should be 0 or 1.
894 if(b
[16]!=1 && b
[16]!=8 && b
[16]!=15 && b
[16]!=16 && b
[16]!=24 && b
[16]!=32) return 0;
896 if(b
[2]!=0 && b
[2]!=1 && b
[2]!=2 && b
[2]!=3 &&
897 b
[2]!=9 && b
[2]!=10 && b
[2]!=11 && b
[2]!=32 && b
[2]!=33)
899 return 0; // Unknown image type
902 if(b
[12]==0 && b
[13]==0) return 0; // Width can't be 0.
903 if(b
[14]==0 && b
[15]==0) return 0; // Height can't be 0.
905 // Bits per palette entry. Supposed to be 0 if there is no palette, but
906 // in practice it may be 24 instead.
907 if((b
[1]==0 && b
[7]==0) || b
[7]==15 || b
[7]==16 || b
[7]==24 || b
[7]==32) {
914 has_tga_ext
= de_input_file_has_ext(c
, "tga");
916 x
= b
[17]&0x0f; // Number of attribute bits
917 if(x
!=0 && x
!=1 && x
!=8 && !has_tga_ext
) return 0;
922 if(de_input_file_has_ext(c
, "vst")) {
928 void de_module_tga(deark
*c
, struct deark_module_info
*mi
)
931 mi
->desc
= "Truevision TGA, a.k.a. TARGA";
932 mi
->run_fn
= de_run_tga
;
933 mi
->identify_fn
= de_identify_tga
;