1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 // Playstation .TIM image format
6 // (Limited support. Probably works for 8-bits/pixel.)
8 #include <deark-config.h>
9 #include <deark-private.h>
10 DE_DECLARE_MODULE(de_module_tim
);
12 typedef struct localctx_struct
{
13 unsigned int bpp_code
;
14 unsigned int palette_flag
;
20 static void do_read_palette(deark
*c
, lctx
*d
, i64 pos
, i64 ncolors
)
26 de_dbg(c
, "CLUT block at %d", (int)pos
);
29 for(k
=0; k
<ncolors
&& k
<256; k
++) {
30 n1
= (u32
)de_getu16le(pos
+ 2*k
);
31 n2
= de_bgr555_to_888(n1
);
32 de_snprintf(tmps
, sizeof(tmps
), "0x%04x "DE_CHAR_RIGHTARROW
" ", (unsigned int)n1
);
33 de_dbg_pal_entry2(c
, k
, n2
, tmps
, NULL
, NULL
);
40 static void do_pal8(deark
*c
, lctx
*d
)
42 de_bitmap
*img
= NULL
;
46 i64 second_header_blk_pos
;
47 i64 img_data_size_field
;
51 int saved_indent_level
;
53 de_dbg_indent_save(c
, &saved_indent_level
);
54 de_dbg_indent(c
, 1); // still in the first header block
56 if(!d
->palette_flag
) {
57 de_err(c
, "8-bit images without a palette aren't supported");
61 clut_size
= de_getu32le(8);
63 ncolors_per_clut
= de_getu16le(16);
64 num_cluts
= de_getu16le(18);
66 de_dbg(c
, "clut 'size': %d", (int)clut_size
);
67 de_dbg(c
, "colors per clut: %d", (int)ncolors_per_clut
);
68 de_dbg(c
, "num cluts: %d", (int)num_cluts
);
69 de_dbg_indent(c
, -1); // end of first header block
71 do_read_palette(c
, d
, 20, ncolors_per_clut
);
73 second_header_blk_pos
= 20 + num_cluts
*ncolors_per_clut
*2;
74 de_dbg(c
, "second header block at %d", (int)second_header_blk_pos
);
76 img_data_size_field
= de_getu32le(second_header_blk_pos
);
77 de_dbg(c
, "image data size field: %d", (int)img_data_size_field
);
78 width_field
= de_getu16le(second_header_blk_pos
+8);
79 d
->width
= 2*width_field
;
80 d
->height
= de_getu16le(second_header_blk_pos
+10);
81 de_dbg(c
, "width field: %d (width=%d)", (int)width_field
, (int)d
->width
);
82 de_dbg(c
, "height: %d", (int)d
->height
);
83 if(!de_good_image_dimensions(c
, d
->width
, d
->height
)) goto done
;
86 img
= de_bitmap_create(c
, d
->width
, d
->height
, 3);
88 pos
= second_header_blk_pos
+ 12;
89 de_dbg(c
, "image data block at %d", (int)pos
);
92 de_convert_image_paletted(c
->infile
, pos
,
93 8, rowspan
, d
->pal
, img
, 0);
95 de_bitmap_write_to_file(img
, NULL
, 0);
97 de_dbg_indent_restore(c
, saved_indent_level
);
98 de_bitmap_destroy(img
);
101 static void de_run_tim(deark
*c
, de_module_params
*mparams
)
104 unsigned int tim_type
;
105 int saved_indent_level
;
107 de_dbg_indent_save(c
, &saved_indent_level
);
108 d
= de_malloc(c
, sizeof(lctx
));
110 de_dbg(c
, "first header block at %d", 0);
113 tim_type
= (unsigned int)de_getu32le(4);
114 d
->bpp_code
= tim_type
& 0x07;
115 d
->palette_flag
= (tim_type
>>3)&0x01;
117 de_dbg(c
, "TIM type: 0x%08x", tim_type
);
120 switch(d
->bpp_code
) {
121 case 0: d
->bpp
= 4; break;
122 case 1: d
->bpp
= 8; break;
123 case 2: d
->bpp
= 16; break;
124 case 3: d
->bpp
= 24; break;
126 de_err(c
, "Mixed Format not supported");
129 de_err(c
, "Unknown bits/pixel code (%u)", d
->bpp_code
);
133 de_dbg(c
, "bits/pixel: %d, has-palette: %u", (int)d
->bpp
, d
->palette_flag
);
135 de_dbg_indent(c
, -1); // end of TIM type field
137 // Hack: Unindent as if the first header block were complete.
138 // But it probably isn't. We'll re-indent if needed.
139 de_dbg_indent(c
, -1);
146 de_err(c
, "Unsupported bits/pixel (%d)", (int)d
->bpp
);
151 de_dbg_indent_restore(c
, saved_indent_level
);
155 static int de_identify_tim(deark
*c
)
159 if(dbuf_memcmp(c
->infile
, 0, "\x10\x00\x00\x00", 4))
163 if(x
<=3 || x
==8 || x
==9) {
164 if(de_input_file_has_ext(c
, "tim")) return 100;
170 void de_module_tim(deark
*c
, struct deark_module_info
*mi
)
173 mi
->desc
= "PlayStation graphics";
174 mi
->run_fn
= de_run_tim
;
175 mi
->identify_fn
= de_identify_tim
;