1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 // This file is for miscellaneous formats that are easy to support.
6 // Combining them in one file speeds up compilation and development time.
8 #include <deark-config.h>
9 #include <deark-private.h>
10 #include <deark-fmtutil.h>
11 DE_DECLARE_MODULE(de_module_copy
);
12 DE_DECLARE_MODULE(de_module_null
);
13 DE_DECLARE_MODULE(de_module_split
);
14 DE_DECLARE_MODULE(de_module_plaintext
);
15 DE_DECLARE_MODULE(de_module_cp437
);
16 DE_DECLARE_MODULE(de_module_crc
);
17 DE_DECLARE_MODULE(de_module_hexdump
);
18 DE_DECLARE_MODULE(de_module_bytefreq
);
19 DE_DECLARE_MODULE(de_module_zlib
);
20 DE_DECLARE_MODULE(de_module_hpicn
);
21 DE_DECLARE_MODULE(de_module_xpuzzle
);
22 DE_DECLARE_MODULE(de_module_winzle
);
23 DE_DECLARE_MODULE(de_module_mrw
);
24 DE_DECLARE_MODULE(de_module_bob
);
25 DE_DECLARE_MODULE(de_module_alias_pix
);
26 DE_DECLARE_MODULE(de_module_applevol
);
27 DE_DECLARE_MODULE(de_module_hr
);
28 DE_DECLARE_MODULE(de_module_ripicon
);
29 DE_DECLARE_MODULE(de_module_lss16
);
30 DE_DECLARE_MODULE(de_module_vbm
);
31 DE_DECLARE_MODULE(de_module_fp_art
);
32 DE_DECLARE_MODULE(de_module_ybm
);
33 DE_DECLARE_MODULE(de_module_olpc565
);
34 DE_DECLARE_MODULE(de_module_iim
);
35 DE_DECLARE_MODULE(de_module_pm_xv
);
36 DE_DECLARE_MODULE(de_module_crg
);
37 DE_DECLARE_MODULE(de_module_farbfeld
);
38 DE_DECLARE_MODULE(de_module_vgafont
);
39 DE_DECLARE_MODULE(de_module_hsiraw
);
40 DE_DECLARE_MODULE(de_module_qdv
);
41 DE_DECLARE_MODULE(de_module_vitec
);
42 DE_DECLARE_MODULE(de_module_hs2
);
43 DE_DECLARE_MODULE(de_module_lumena_cel
);
44 DE_DECLARE_MODULE(de_module_zbr
);
45 DE_DECLARE_MODULE(de_module_cdr_wl
);
46 DE_DECLARE_MODULE(de_module_compress
);
47 DE_DECLARE_MODULE(de_module_gws_thn
);
48 DE_DECLARE_MODULE(de_module_deskmate_pnt
);
49 DE_DECLARE_MODULE(de_module_corel_bmf
);
50 DE_DECLARE_MODULE(de_module_hpi
);
51 DE_DECLARE_MODULE(de_module_dwc
);
52 DE_DECLARE_MODULE(de_module_mdesk_icn
);
53 DE_DECLARE_MODULE(de_module_ttcomp
);
55 // **************************************************************************
58 // This is a trivial module that makes a copy of the input file.
59 // **************************************************************************
61 static void de_run_copy(deark
*c
, de_module_params
*mparams
)
63 dbuf_create_file_from_slice(c
->infile
, 0, c
->infile
->len
, "bin", NULL
, 0);
66 void de_module_copy(deark
*c
, struct deark_module_info
*mi
)
69 mi
->desc
= "Copy the file unchanged";
70 mi
->run_fn
= de_run_copy
;
73 // **************************************************************************
76 // This is a trivial module that does nothing.
77 // **************************************************************************
79 static void de_run_null(deark
*c
, de_module_params
*mparams
)
84 void de_module_null(deark
*c
, struct deark_module_info
*mi
)
87 mi
->desc
= "Do nothing";
88 mi
->run_fn
= de_run_null
;
89 mi
->flags
|= DE_MODFLAG_NOEXTRACT
;
92 // **************************************************************************
94 // Split the input file into equal-sized chunks.
95 // **************************************************************************
97 static void do_split_onechunk(deark
*c
, i64 chunknum
, i64 offset
, i64 size
)
102 de_snprintf(ext
, sizeof(ext
), "part%"I64_FMT
, chunknum
);
103 outf
= dbuf_create_output_file(c
, ext
, NULL
, 0);
104 dbuf_copy(c
->infile
, offset
, size
, outf
);
108 static void de_run_split(deark
*c
, de_module_params
*mparams
)
113 i64 chunksize
, chunkstride
;
116 s
= de_get_ext_option(c
, "split:size");
118 de_err(c
, "\"-opt split:size=<n>\" is required.");
121 chunksize
= de_atoi64(s
);
123 de_err(c
, "Invalid chunk size");
127 s
= de_get_ext_option(c
, "split:stride");
129 chunkstride
= de_atoi64(s
);
130 if(chunkstride
<chunksize
) {
131 de_err(c
, "Stride must be "DE_CHAR_GEQ
" size");
136 chunkstride
= chunksize
;
139 chunkcount
= (c
->infile
->len
+ (chunkstride
-1)) / chunkstride
;
141 if((chunkcount
>256) && (!c
->user_set_max_output_files
)) {
142 de_err(c
, "Large number of chunks; use \"-maxfiles %"I64_FMT
"\" if you "
143 "really want to do this.", chunkcount
);
148 for(chunknum
= 0; chunknum
<chunkcount
; chunknum
++) {
151 this_chunk_size
= de_min_int(chunksize
, c
->infile
->len
-pos
);
152 do_split_onechunk(c
, chunknum
, pos
, this_chunk_size
);
161 static void de_help_split(deark
*c
)
163 de_msg(c
, "-opt split:size=<n> : The size of each chunk, in bytes");
164 de_msg(c
, "-opt split:stride=<n> : Source distance between chunks");
167 void de_module_split(deark
*c
, struct deark_module_info
*mi
)
170 mi
->desc
= "Split the file into equal-sized chunks";
171 mi
->run_fn
= de_run_split
;
172 mi
->help_fn
= de_help_split
;
175 // **************************************************************************
177 // Convert text files to UTF-8.
178 // **************************************************************************
180 struct plaintextctx_struct
{
183 struct de_encconv_state es
;
186 static int plaintext_cbfn(struct de_bufferedreadctx
*brctx
, const u8
*buf
,
189 struct plaintextctx_struct
*ptctx
= (struct plaintextctx_struct
*)brctx
->userdata
;
192 // There's no limit to how much data dbuf_buffered_read() could send us
193 // at once, so we won't try to put it all in a ucstring at once.
194 brctx
->bytes_consumed
= de_min_int(buf_len
, 4096);
196 // For best results, ucstring_append_bytes_ex() needs to be told whether there will
197 // be any more bytes after this.
198 if(brctx
->eof_flag
&& brctx
->bytes_consumed
==buf_len
)
201 conv_flags
= DE_CONVFLAG_PARTIAL_DATA
;
203 ucstring_empty(ptctx
->tmpstr
);
204 ucstring_append_bytes_ex(ptctx
->tmpstr
, buf
, brctx
->bytes_consumed
, conv_flags
,
206 ucstring_write_as_utf8(brctx
->c
, ptctx
->tmpstr
, ptctx
->outf
, 0);
210 static de_encoding
get_bom_enc(deark
*c
, UI
*blen
)
215 if(buf
[0]==0xef && buf
[1]==0xbb && buf
[2]==0xbf) {
217 return DE_ENCODING_UTF8
;
219 else if(buf
[0]==0xfe && buf
[1]==0xff) {
221 return DE_ENCODING_UTF16BE
;
223 else if(buf
[0]==0xff && buf
[1]==0xfe) {
225 return DE_ENCODING_UTF16LE
;
228 return DE_ENCODING_UNKNOWN
;
231 static void de_run_plaintext(deark
*c
, de_module_params
*mparams
)
233 struct plaintextctx_struct ptctx
;
234 de_encoding input_encoding
;
235 de_encoding enc_from_bom
;
236 UI existing_bom_len
= 0;
239 enc_from_bom
= get_bom_enc(c
, &existing_bom_len
);
240 input_encoding
= de_get_input_encoding(c
, NULL
, DE_ENCODING_UNKNOWN
);
241 if(input_encoding
==DE_ENCODING_UNKNOWN
) {
242 if(enc_from_bom
!=DE_ENCODING_UNKNOWN
) {
243 input_encoding
= enc_from_bom
;
246 input_encoding
= DE_ENCODING_UTF8
;
249 if(input_encoding
!=enc_from_bom
) {
250 // Even if there was something that looked like a BOM, ignore it.
251 existing_bom_len
= 0;
254 dpos
= (i64
)existing_bom_len
;
255 dlen
= c
->infile
->len
- dpos
;
257 de_encconv_init(&ptctx
.es
, DE_EXTENC_MAKE(input_encoding
, DE_ENCSUBTYPE_HYBRID
));
258 ptctx
.tmpstr
= ucstring_create(c
);
259 ptctx
.outf
= dbuf_create_output_file(c
, "txt", NULL
, 0);
262 dbuf_write_uchar_as_utf8(ptctx
.outf
, 0xfeff);
265 dbuf_buffered_read(c
->infile
, dpos
, dlen
, plaintext_cbfn
, (void*)&ptctx
);
266 dbuf_close(ptctx
.outf
);
267 ucstring_destroy(ptctx
.tmpstr
);
270 void de_module_plaintext(deark
*c
, struct deark_module_info
*mi
)
272 mi
->id
= "plaintext";
273 mi
->desc
= "Plain text";
274 mi
->desc2
= "Convert to UTF-8";
275 mi
->run_fn
= de_run_plaintext
;
278 // **************************************************************************
280 // Convert CP437 text files to UTF-8.
281 // **************************************************************************
283 struct cp437ctx_struct
{
285 struct de_encconv_state es
;
288 static int cp437_cbfn(struct de_bufferedreadctx
*brctx
, const u8
*buf
,
294 struct cp437ctx_struct
*cp437ctx
= (struct cp437ctx_struct
*)brctx
->userdata
;
296 for(i
=0; i
<buf_len
; i
++) {
298 if(ch
==0x09 || ch
==0x0a || ch
==0x0c || ch
==0x0d) {
299 // Leave HT, NL, FF, CR as-is.
303 // Lots of CP437 files end with a Ctrl+Z character, but modern files
304 // don't use any in-band character to signify end-of-file.
305 // I don't just want to delete the character, though, so I guess I'll
306 // change it to U+2404 SYMBOL FOR END OF TRANSMISSION.
310 u
= de_char_to_unicode_ex((i32
)ch
, &cp437ctx
->es
);
312 dbuf_write_uchar_as_utf8(cp437ctx
->outf
, u
);
318 static void de_run_cp437(deark
*c
, de_module_params
*mparams
)
320 struct cp437ctx_struct cp437ctx
;
322 cp437ctx
.outf
= dbuf_create_output_file(c
, "txt", NULL
, 0);
323 de_encconv_init(&cp437ctx
.es
, DE_ENCODING_CP437_G
);
325 dbuf_write_uchar_as_utf8(cp437ctx
.outf
, 0xfeff);
327 dbuf_buffered_read(c
->infile
, 0, c
->infile
->len
, cp437_cbfn
, (void*)&cp437ctx
);
328 dbuf_close(cp437ctx
.outf
);
331 void de_module_cp437(deark
*c
, struct deark_module_info
*mi
)
334 mi
->desc
= "Code Page 437 text";
335 mi
->run_fn
= de_run_cp437
;
338 // **************************************************************************
340 // Prints various CRCs and checksums. Does not create any files.
341 // **************************************************************************
343 struct crcctx_struct
{
344 struct de_crcobj
*crco_32ieee
;
345 struct de_crcobj
*crco_16arc
;
346 struct de_crcobj
*crco_16ccitt
;
350 static int crc_cbfn(struct de_bufferedreadctx
*brctx
, const u8
*buf
,
353 struct crcctx_struct
*crcctx
= (struct crcctx_struct
*)brctx
->userdata
;
356 de_crcobj_addbuf(crcctx
->crco_32ieee
, buf
, buf_len
);
357 de_crcobj_addbuf(crcctx
->crco_16arc
, buf
, buf_len
);
358 de_crcobj_addbuf(crcctx
->crco_16ccitt
, buf
, buf_len
);
359 for(i
=0; i
<buf_len
; i
++) {
360 crcctx
->sum_of_bytes
+= buf
[i
];
365 static void de_run_crc(deark
*c
, de_module_params
*mparams
)
367 struct crcctx_struct crcctx
;
369 de_zeromem(&crcctx
, sizeof(struct crcctx_struct
));
370 crcctx
.crco_32ieee
= de_crcobj_create(c
, DE_CRCOBJ_CRC32_IEEE
);
371 crcctx
.crco_16arc
= de_crcobj_create(c
, DE_CRCOBJ_CRC16_ARC
);
372 crcctx
.crco_16ccitt
= de_crcobj_create(c
, DE_CRCOBJ_CRC16_CCITT
);
374 dbuf_buffered_read(c
->infile
, 0, c
->infile
->len
, crc_cbfn
, (void*)&crcctx
);
376 de_msg(c
, "CRC-32-IEEE: 0x%08x",
377 (unsigned int)de_crcobj_getval(crcctx
.crco_32ieee
));
378 de_msg(c
, "CRC-16-IBM/ARC: 0x%04x",
379 (unsigned int)de_crcobj_getval(crcctx
.crco_16arc
));
380 de_msg(c
, "CRC-16-CCITT: 0x%04x",
381 (unsigned int)de_crcobj_getval(crcctx
.crco_16ccitt
));
382 de_msg(c
, "Sum of bytes: 0x%"U64_FMTx
, crcctx
.sum_of_bytes
);
384 de_crcobj_destroy(crcctx
.crco_32ieee
);
385 de_crcobj_destroy(crcctx
.crco_16arc
);
386 de_crcobj_destroy(crcctx
.crco_16ccitt
);
389 void de_module_crc(deark
*c
, struct deark_module_info
*mi
)
392 mi
->id_alias
[0] = "crc32";
393 mi
->desc
= "Calculate various CRCs";
394 mi
->run_fn
= de_run_crc
;
395 mi
->flags
|= DE_MODFLAG_NOEXTRACT
;
398 // **************************************************************************
400 // Prints a hex dump. Does not create any files.
401 // **************************************************************************
403 static void de_run_hexdump(deark
*c
, de_module_params
*mparams
)
405 de_hexdump2(c
, c
->infile
, 0, c
->infile
->len
,
406 c
->infile
->len
, 0x3);
409 void de_module_hexdump(deark
*c
, struct deark_module_info
*mi
)
412 mi
->desc
= "Print a hex dump";
413 mi
->run_fn
= de_run_hexdump
;
414 mi
->flags
|= DE_MODFLAG_NOEXTRACT
;
417 // **************************************************************************
419 // Prints a summary of how many times each byte value occurs.
420 // **************************************************************************
422 struct bytefreqentry
{
424 #define DE_BYTEFREQ_NUMLOC 3
425 i64 locations
[DE_BYTEFREQ_NUMLOC
];
428 struct bytefreqctx_struct
{
429 struct bytefreqentry e
[256];
432 static int bytefreq_cbfn(struct de_bufferedreadctx
*brctx
, const u8
*buf
,
436 struct bytefreqctx_struct
*bfctx
= (struct bytefreqctx_struct
*)brctx
->userdata
;
438 for(k
=0; k
<buf_len
; k
++) {
439 struct bytefreqentry
*bf
= &bfctx
->e
[(unsigned int)buf
[k
]];
441 // Save the location of the first few occurrences of this byte value.
442 if(bf
->count
<DE_BYTEFREQ_NUMLOC
) {
443 bf
->locations
[bf
->count
] = brctx
->offset
+ k
;
450 static void de_run_bytefreq(deark
*c
, de_module_params
*mparams
)
452 struct bytefreqctx_struct
*bfctx
= NULL
;
453 de_ucstring
*s
= NULL
;
455 de_encoding input_encoding
;
456 struct de_encconv_state es
;
458 bfctx
= de_malloc(c
, sizeof(struct bytefreqctx_struct
));
459 input_encoding
= de_get_input_encoding(c
, NULL
, DE_ENCODING_WINDOWS1252
);
460 if(input_encoding
==DE_ENCODING_UTF8
) {
461 input_encoding
=DE_ENCODING_ASCII
;
463 de_encconv_init(&es
, input_encoding
);
465 dbuf_buffered_read(c
->infile
, 0, c
->infile
->len
, bytefreq_cbfn
, (void*)bfctx
);
467 de_msg(c
, "====Byte==== ===Count=== ==Locations==");
468 s
= ucstring_create(c
);
469 for(k
=0; k
<256; k
++) {
473 struct bytefreqentry
*bf
= &bfctx
->e
[k
];
475 if(bf
->count
==0) continue;
478 ucstring_printf(s
, DE_ENCODING_LATIN1
, "%3u 0x%02x ", k
, k
);
480 ch
= de_char_to_unicode_ex((i32
)k
, &es
);
481 if(ch
==DE_CODEPOINT_INVALID
) {
485 cflag
= de_is_printable_uchar(ch
);
489 ucstring_append_sz(s
, "'", DE_ENCODING_LATIN1
);
490 ucstring_append_char(s
, ch
);
491 ucstring_append_sz(s
, "'", DE_ENCODING_LATIN1
);
494 ucstring_append_sz(s
, " ", DE_ENCODING_LATIN1
);
497 ucstring_printf(s
, DE_ENCODING_LATIN1
, " %11"I64_FMT
" ", bf
->count
);
499 for(z
=0; z
<DE_BYTEFREQ_NUMLOC
&& z
<bf
->count
; z
++) {
500 ucstring_printf(s
, DE_ENCODING_LATIN1
, "%"I64_FMT
, bf
->locations
[z
]);
502 ucstring_append_sz(s
, ",", DE_ENCODING_LATIN1
);
505 if(bf
->count
>DE_BYTEFREQ_NUMLOC
) {
506 ucstring_append_sz(s
, "...", DE_ENCODING_LATIN1
);
509 de_msg(c
, "%s", ucstring_getpsz(s
));
511 de_msg(c
, " Total: %11"I64_FMT
, c
->infile
->len
);
516 void de_module_bytefreq(deark
*c
, struct deark_module_info
*mi
)
519 mi
->desc
= "Print a byte frequence analysis";
520 mi
->run_fn
= de_run_bytefreq
;
521 mi
->flags
|= DE_MODFLAG_NOEXTRACT
;
524 // **************************************************************************
527 // This module is for decompressing zlib-compressed files.
528 // **************************************************************************
530 static void de_run_zlib(deark
*c
, de_module_params
*mparams
)
534 f
= dbuf_create_output_file(c
, "unc", NULL
, 0);
535 fmtutil_decompress_deflate(c
->infile
, 0, c
->infile
->len
, f
, 0, NULL
, DE_DEFLATEFLAG_ISZLIB
);
539 static int de_identify_zlib(deark
*c
)
547 if(b
[0]<0x08 || b
[0]>0x78)
550 if(((((unsigned int)b
[0])<<8)|b
[1])%31 != 0)
556 void de_module_zlib(deark
*c
, struct deark_module_info
*mi
)
559 mi
->desc
= "Raw zlib compressed data";
560 mi
->run_fn
= de_run_zlib
;
561 mi
->identify_fn
= de_identify_zlib
;
564 // **************************************************************************
565 // HP 100LX / HP 200LX .ICN icon format
566 // **************************************************************************
568 static void de_run_hpicn(deark
*c
, de_module_params
*mparams
)
572 width
= de_getu16le(4);
573 height
= de_getu16le(6);
574 de_convert_and_write_image_bilevel2(c
->infile
, 8, width
, height
, (width
+7)/8,
575 DE_CVTF_WHITEISZERO
, NULL
, 0);
578 static int de_identify_hpicn(deark
*c
)
582 if(!de_memcmp(b
, "\x01\x00\x01\x00\x2c\x00\x20\x00", 8))
584 if(!de_memcmp(b
, "\x01\x00\x01\x00", 4))
589 void de_module_hpicn(deark
*c
, struct deark_module_info
*mi
)
592 mi
->desc
= "HP 100LX/200LX .ICN icon";
593 mi
->run_fn
= de_run_hpicn
;
594 mi
->identify_fn
= de_identify_hpicn
;
597 // **************************************************************************
598 // X11 "puzzle" format
599 // ftp://ftp.x.org/pub/unsupported/programs/puzzle/
600 // This is the format generated by Netpbm's ppmtopuzz utility.
601 // **************************************************************************
608 static int xpuzz_read_header(deark
*c
, struct xpuzzctx
*d
)
610 d
->w
= de_getu32be(0);
611 d
->h
= de_getu32be(4);
612 d
->palentries
= (i64
)de_getbyte(8);
613 if(!de_good_image_dimensions_noerr(c
, d
->w
, d
->h
)) return 0;
614 if(d
->palentries
==0) d
->palentries
= 256;
618 static void de_run_xpuzzle(deark
*c
, de_module_params
*mparams
)
620 struct xpuzzctx
*d
= NULL
;
621 de_bitmap
*img
= NULL
;
625 d
= de_malloc(c
, sizeof(struct xpuzzctx
));
626 if(!xpuzz_read_header(c
, d
)) goto done
;
627 if(!de_good_image_dimensions(c
, d
->w
, d
->h
)) goto done
;
629 img
= de_bitmap_create(c
, d
->w
, d
->h
, 3);
632 de_zeromem(pal
, sizeof(pal
));
634 de_read_palette_rgb(c
->infile
, p
, d
->palentries
, 3, pal
, 256, 0);
635 p
+= 3*d
->palentries
;
638 de_convert_image_paletted(c
->infile
, p
, 8, d
->w
, pal
, img
, 0);
640 de_bitmap_write_to_file(img
, NULL
, 0);
643 de_bitmap_destroy(img
);
647 static int de_identify_xpuzzle(deark
*c
)
649 struct xpuzzctx
*d
= NULL
;
652 d
= de_malloc(c
, sizeof(struct xpuzzctx
));
654 if(!xpuzz_read_header(c
, d
)) goto done
;
656 if(d
->w
* d
->h
+ 3*d
->palentries
+ 9 == c
->infile
->len
) {
665 void de_module_xpuzzle(deark
*c
, struct deark_module_info
*mi
)
668 mi
->desc
= "X11 \"puzzle\" image";
669 mi
->run_fn
= de_run_xpuzzle
;
670 mi
->identify_fn
= de_identify_xpuzzle
;
673 // **************************************************************************
674 // Winzle! puzzle image
675 // **************************************************************************
677 static void de_run_winzle(deark
*c
, de_module_params
*mparams
)
684 xorsize
= c
->infile
->len
>= 256 ? 256 : c
->infile
->len
;
685 de_read(buf
, 0, xorsize
);
686 for(i
=0; i
<xorsize
; i
++) {
690 f
= dbuf_create_output_file(c
, "bmp", NULL
, 0);
691 dbuf_write(f
, buf
, xorsize
);
692 if(c
->infile
->len
> 256) {
693 dbuf_copy(c
->infile
, 256, c
->infile
->len
- 256, f
);
698 static int de_identify_winzle(deark
*c
)
701 de_read(b
, 0, sizeof(b
));
703 if(b
[0]==0x4f && b
[1]==0x40) {
704 if(b
[14]==0x25 && b
[15]==0x0d && b
[16]==0x0d && b
[17]==0x0d) {
712 void de_module_winzle(deark
*c
, struct deark_module_info
*mi
)
715 mi
->desc
= "Winzle! puzzle image";
716 mi
->run_fn
= de_run_winzle
;
717 mi
->identify_fn
= de_identify_winzle
;
720 // **************************************************************************
722 // **************************************************************************
724 static void do_mrw_seg_list(deark
*c
, i64 pos1
, i64 len
)
731 while(pos
< pos1
+len
) {
732 de_read(seg_id
, pos
, 4);
733 data_len
= de_getu32be(pos
+4);
735 if(pos
+data_len
> pos1
+len
) break;
736 if(!de_memcmp(seg_id
, "\0TTW", 4)) { // Exif
737 fmtutil_handle_exif(c
, pos
, data_len
);
743 static void de_run_mrw(deark
*c
, de_module_params
*mparams
)
747 mrw_seg_size
= de_getu32be(4);
748 do_mrw_seg_list(c
, 8, mrw_seg_size
);
751 static int de_identify_mrw(deark
*c
)
753 if(!dbuf_memcmp(c
->infile
, 0, "\x00\x4d\x52\x4d", 4))
758 void de_module_mrw(deark
*c
, struct deark_module_info
*mi
)
761 mi
->desc
= "Minolta RAW";
762 mi
->desc2
= "resources only";
763 mi
->run_fn
= de_run_mrw
;
764 mi
->identify_fn
= de_identify_mrw
;
767 // **************************************************************************
768 // "Bob" bitmap image
769 // Used by the Bob ray tracer.
770 // **************************************************************************
772 static void de_run_bob(deark
*c
, de_module_params
*mparams
)
774 de_bitmap
*img
= NULL
;
781 if(!de_good_image_dimensions(c
, w
, h
)) goto done
;
782 img
= de_bitmap_create(c
, w
, h
, 3);
785 de_zeromem(pal
, sizeof(pal
));
787 de_read_palette_rgb(c
->infile
, p
, 256, 3, pal
, 256, 0);
791 de_convert_image_paletted(c
->infile
, p
, 8, w
, pal
, img
, 0);
793 de_bitmap_write_to_file(img
, NULL
, 0);
796 de_bitmap_destroy(img
);
799 static int de_identify_bob(deark
*c
)
803 if(!de_input_file_has_ext(c
, "bob")) return 0;
807 if(c
->infile
->len
== 4 + 768 + w
*h
) {
813 void de_module_bob(deark
*c
, struct deark_module_info
*mi
)
816 mi
->desc
= "Bob Ray Tracer bitmap image";
817 mi
->run_fn
= de_run_bob
;
818 mi
->identify_fn
= de_identify_bob
;
821 // **************************************************************************
822 // Alias PIX bitmap image.
823 // Also used by the Vivid ray tracer.
824 // **************************************************************************
826 static void de_run_alias_pix(deark
*c
, de_module_params
*mparams
)
828 de_bitmap
*img
= NULL
;
840 firstline
= de_getu16be(4);
841 depth
= de_getu16be(8);
843 if(!de_good_image_dimensions(c
, w
, h
)) goto done
;
844 if(firstline
>= h
) goto done
;
846 de_err(c
, "Unsupported image type");
850 img
= de_bitmap_create(c
, w
, h
, 3);
854 // I don't know for sure what to do with the "first scanline" field, in the
855 // unlikely event it is not 0. The documentation doesn't say.
858 if(pos
+4 > c
->infile
->len
) {
861 runlen
= (i64
)de_getbyte(pos
);
862 clr
= dbuf_getRGB(c
->infile
, pos
+1, DE_GETRGBFLAG_BGR
);
865 for(i
=0; i
<runlen
; i
++) {
866 de_bitmap_setpixel_rgb(img
, xpos
, ypos
, clr
);
867 xpos
++; // Runs are not allowed to span rows
876 de_bitmap_write_to_file(img
, NULL
, 0);
878 de_bitmap_destroy(img
);
881 static int de_identify_alias_pix(deark
*c
)
883 i64 w
, h
, firstline
, lastline
, depth
;
885 if(!de_input_file_has_ext(c
, "img") &&
886 !de_input_file_has_ext(c
, "als") &&
887 !de_input_file_has_ext(c
, "pix"))
894 firstline
= de_getu16be(4);
895 lastline
= de_getu16be(6);
896 depth
= de_getu16be(8);
898 if(depth
!=24) return 0;
899 if(firstline
>lastline
) return 0;
900 // 'lastline' should usually be h-1, but XnView apparently sets it to h.
901 if(firstline
>h
-1 || lastline
>h
) return 0;
902 if(!de_good_image_dimensions_noerr(c
, w
, h
)) return 0;
906 void de_module_alias_pix(deark
*c
, struct deark_module_info
*mi
)
908 mi
->id
= "alias_pix";
909 mi
->id_alias
[0] = "vivid";
910 mi
->desc
= "Alias PIX image, Vivid .IMG";
911 mi
->run_fn
= de_run_alias_pix
;
912 mi
->identify_fn
= de_identify_alias_pix
;
915 // **************************************************************************
916 // Apple volume label image
917 // Written by netpbm: ppmtoapplevol
918 // **************************************************************************
920 static u8
applevol_get_gray_shade(u8 clr
)
923 // TODO: These gray shades may not be quite right. I can't find good
924 // information about them.
925 case 0x00: return 0xff;
926 case 0xf6: return 0xee;
927 case 0xf7: return 0xdd;
928 case 0x2a: return 0xcc;
929 case 0xf8: return 0xbb;
930 case 0xf9: return 0xaa;
931 case 0x55: return 0x99;
932 case 0xfa: return 0x88;
933 case 0xfb: return 0x77;
934 case 0x80: return 0x66;
935 case 0xfc: return 0x55;
936 case 0xfd: return 0x44;
937 case 0xab: return 0x33;
938 case 0xfe: return 0x22;
939 case 0xff: return 0x11;
940 case 0xd6: return 0x00;
945 static void de_run_applevol(deark
*c
, de_module_params
*mparams
)
947 de_bitmap
*img
= NULL
;
955 if(!de_good_image_dimensions(c
, w
, h
)) goto done
;
956 img
= de_bitmap_create(c
, w
, h
, 1);
961 palent
= de_getbyte(p
+w
*j
+i
);
962 de_bitmap_setpixel_gray(img
, i
, j
, applevol_get_gray_shade(palent
));
966 de_bitmap_write_to_file(img
, NULL
, 0);
969 de_bitmap_destroy(img
);
972 static int de_identify_applevol(deark
*c
)
976 de_read(buf
, 0, sizeof(buf
));
978 if(buf
[0]==0x01 && buf
[3]==0x00 && buf
[4]==0x0c)
983 void de_module_applevol(deark
*c
, struct deark_module_info
*mi
)
986 mi
->desc
= "Apple volume label image";
987 mi
->run_fn
= de_run_applevol
;
988 mi
->identify_fn
= de_identify_applevol
;
991 // **************************************************************************
992 // TRS-80 "HR" ("High Resolution") image
993 // **************************************************************************
995 static void de_run_hr(deark
*c
, de_module_params
*mparams
)
997 de_bitmap
*img
= NULL
;
1000 fi
= de_finfo_create(c
);
1001 fi
->density
.code
= DE_DENSITY_UNK_UNITS
;
1002 fi
->density
.xdens
= 2;
1003 fi
->density
.ydens
= 1;
1004 img
= de_bitmap_create(c
, 640, 240, 1);
1005 de_convert_image_bilevel(c
->infile
, 0, 640/8, img
, 0);
1006 de_bitmap_write_to_file_finfo(img
, fi
, 0);
1007 de_bitmap_destroy(img
);
1008 de_finfo_destroy(c
, fi
);
1011 static int de_identify_hr(deark
*c
)
1013 if(de_input_file_has_ext(c
, "hr")) {
1014 if(c
->infile
->len
==19200) return 70;
1015 if(c
->infile
->len
>19200 && c
->infile
->len
<=19456) return 30;
1020 void de_module_hr(deark
*c
, struct deark_module_info
*mi
)
1023 mi
->desc
= "TRS-80 HR (High Resolution) image";
1024 mi
->run_fn
= de_run_hr
;
1025 mi
->identify_fn
= de_identify_hr
;
1028 // **************************************************************************
1029 // RIPterm icon (.ICN)
1030 // **************************************************************************
1032 // Don't know what this should be, but a limit will help us decide what is
1033 // and isn't an image.
1034 #define MAX_RIPICON_DIMENSION 2048
1036 static int do_one_ripicon(deark
*c
, i64 pos1
, i64
*pbytes_consumed
, int scan_mode
)
1039 de_bitmap
*img
= NULL
;
1047 int saved_indent_level
;
1049 if(pos1
+8 > c
->infile
->len
) return 0;
1050 width
= 1 + de_getu16le_p(&pos
);
1051 height
= 1 + de_getu16le_p(&pos
);
1052 if(width
>MAX_RIPICON_DIMENSION
|| height
>MAX_RIPICON_DIMENSION
) return 0;
1053 chunk_span
= (width
+7)/8;
1054 src_rowspan
= 4*chunk_span
;
1055 bitmap_len
= src_rowspan
* height
;
1056 if(pos
+bitmap_len
> c
->infile
->len
) return 0;
1058 *pbytes_consumed
= 4 + bitmap_len
+ 2;
1059 if(scan_mode
) return 1;
1061 de_dbg_indent_save(c
, &saved_indent_level
);
1062 de_dbg(c
, "image at %"I64_FMT
, pos1
);
1063 de_dbg_indent(c
, 1);
1064 de_dbg_dimensions(c
, width
, height
);
1066 de_dbg(c
, "bitmap at %"I64_FMT
", len=%"I64_FMT
, pos
, bitmap_len
);
1067 if(!de_good_image_dimensions(c
, width
, height
)) goto done
;
1068 img
= de_bitmap_create2(c
, width
, chunk_span
*8, height
, 3);
1070 for(j
=0; j
<height
; j
++) {
1071 for(i
=0; i
<img
->width
; i
++) { // Must use img->width, for -padpix
1073 for(k
=0; k
<4; k
++) {
1074 x
= de_get_bits_symbol(c
->infile
, 1, pos
+ j
*src_rowspan
+ k
*chunk_span
, i
);
1075 palent
= (palent
<<1)|x
;
1077 de_bitmap_setpixel_rgb(img
, i
, j
, de_palette_pc16(palent
));
1081 de_bitmap_write_to_file(img
, NULL
, 0);
1084 if(img
) de_bitmap_destroy(img
);
1085 de_dbg_indent_restore(c
, saved_indent_level
);
1089 static void de_run_ripicon(deark
*c
, de_module_params
*mparams
)
1094 i64 bytes_consumed
= 0;
1096 if(!do_one_ripicon(c
, pos
, &bytes_consumed
, 0)) break;
1097 pos
+= bytes_consumed
;
1101 static int de_identify_ripicon(deark
*c
)
1106 static const char *exts
[] = { "icn", "hot", "msk", "bgi" };
1108 for(i
=0; i
<DE_ARRAYCOUNT(exts
); i
++) {
1109 if(de_input_file_has_ext(c
, exts
[i
])) {
1114 if(!has_ext
) return 0;
1117 i64 bytes_consumed
= 0;
1119 if(!do_one_ripicon(c
, pos
, &bytes_consumed
, 1)) break;
1120 pos
+= bytes_consumed
;
1121 if(pos
== c
->infile
->len
) return 50;
1126 void de_module_ripicon(deark
*c
, struct deark_module_info
*mi
)
1129 mi
->desc
= "RIP/RIPscrip/RIPterm Icon / BGI image";
1130 mi
->run_fn
= de_run_ripicon
;
1131 mi
->identify_fn
= de_identify_ripicon
;
1134 // **************************************************************************
1135 // LSS16 image (Used by SYSLINUX)
1136 // **************************************************************************
1140 int nextnibble_valid
;
1144 static u8
lss16_get_nibble(deark
*c
, struct lss16ctx
*d
)
1147 if(d
->nextnibble_valid
) {
1148 d
->nextnibble_valid
= 0;
1149 return d
->nextnibble
;
1151 n
= de_getbyte(d
->pos
);
1153 // The low nibble of each byte is interpreted first.
1154 // Record the high nibble, and return the low nibble.
1155 d
->nextnibble
= (n
&0xf0)>>4;
1156 d
->nextnibble_valid
= 1;
1160 static void de_run_lss16(deark
*c
, de_module_params
*mparams
)
1162 struct lss16ctx
*d
= NULL
;
1163 de_bitmap
*img
= NULL
;
1175 d
= de_malloc(c
, sizeof(struct lss16ctx
));
1178 width
= de_getu16le(d
->pos
);
1179 height
= de_getu16le(d
->pos
+2);
1180 de_dbg_dimensions(c
, width
, height
);
1181 if(!de_good_image_dimensions(c
, width
, height
)) goto done
;
1184 for(i
=0; i
<16; i
++) {
1185 cr1
= de_getbyte(d
->pos
);
1186 cg1
= de_getbyte(d
->pos
+1);
1187 cb1
= de_getbyte(d
->pos
+2);
1188 // Palette samples are from [0 to 63]. Convert to [0 to 255].
1189 cr2
= de_scale_63_to_255(cr1
);
1190 cg2
= de_scale_63_to_255(cg1
);
1191 cb2
= de_scale_63_to_255(cb1
);
1192 pal
[i
] = DE_MAKE_RGB(cr2
, cg2
, cb2
);
1193 de_snprintf(tmps
, sizeof(tmps
), "(%2d,%2d,%2d) "DE_CHAR_RIGHTARROW
" ",
1194 (int)cr1
, (int)cg1
, (int)cb1
);
1195 de_dbg_pal_entry2(c
, i
, pal
[i
], tmps
, NULL
, NULL
);
1199 img
= de_bitmap_create(c
, width
, height
, 3);
1203 while(d
->pos
<c
->infile
->len
&& ypos
<height
) {
1204 n
= lss16_get_nibble(c
, d
);
1208 run_len
= (i64
)lss16_get_nibble(c
, d
);
1210 run_len
= lss16_get_nibble(c
, d
);
1211 run_len
|= ((i64
)lss16_get_nibble(c
, d
)<<4);
1214 for(i
=0; i
<run_len
; i
++) {
1215 de_bitmap_setpixel_rgb(img
, xpos
, ypos
, pal
[prev
]);
1220 // An uncompressed pixel
1221 de_bitmap_setpixel_rgb(img
, xpos
, ypos
, pal
[n
]);
1226 // End of row reached?
1230 d
->nextnibble_valid
= 0;
1235 de_bitmap_write_to_file(img
, NULL
, 0);
1237 de_bitmap_destroy(img
);
1241 static int de_identify_lss16(deark
*c
)
1243 if(!dbuf_memcmp(c
->infile
, 0, "\x3d\xf3\x13\x14", 4))
1248 void de_module_lss16(deark
*c
, struct deark_module_info
*mi
)
1251 mi
->desc
= "SYSLINUX LSS16 image";
1252 mi
->run_fn
= de_run_lss16
;
1253 mi
->identify_fn
= de_identify_lss16
;
1256 // **************************************************************************
1258 // **************************************************************************
1260 static void de_run_vbm(deark
*c
, de_module_params
*mparams
)
1265 ver
= de_getbyte(3);
1267 // TODO: Support VBM v3.
1268 de_err(c
, "Unsupported VBM version (%d)", (int)ver
);
1271 width
= de_getu16be(4);
1272 height
= de_getu16be(6);
1273 de_convert_and_write_image_bilevel2(c
->infile
, 8, width
, height
, (width
+7)/8,
1274 DE_CVTF_WHITEISZERO
, NULL
, 0);
1277 // Note that this function must work together with de_identify_bmp().
1278 static int de_identify_vbm(deark
*c
)
1282 if(de_memcmp(b
, "BM\xcb", 3)) return 0;
1283 if(b
[3]!=2 && b
[3]!=3) return 0;
1284 if(de_input_file_has_ext(c
, "vbm")) return 100;
1288 void de_module_vbm(deark
*c
, struct deark_module_info
*mi
)
1291 mi
->desc
= "C64/128 VBM (VDC BitMap)";
1292 mi
->run_fn
= de_run_vbm
;
1293 mi
->identify_fn
= de_identify_vbm
;
1296 // **************************************************************************
1297 // PFS: 1st Publisher clip art (.ART)
1298 // **************************************************************************
1300 static void de_run_fp_art(deark
*c
, de_module_params
*mparams
)
1305 width
= de_getu16le(2);
1306 height
= de_getu16le(6);
1307 rowspan
= ((width
+15)/16)*2;
1308 de_convert_and_write_image_bilevel2(c
->infile
, 8, width
, height
, rowspan
, 0, NULL
, 0);
1311 static int de_identify_fp_art(deark
*c
)
1316 if(!de_input_file_has_ext(c
, "art")) return 0;
1318 width
= de_getu16le(2);
1319 height
= de_getu16le(6);
1320 rowspan
= ((width
+15)/16)*2;
1321 if(8 + rowspan
*height
== c
->infile
->len
) {
1328 void de_module_fp_art(deark
*c
, struct deark_module_info
*mi
)
1331 mi
->desc
= "PFS: 1st Publisher clip art (.ART)";
1332 mi
->run_fn
= de_run_fp_art
;
1333 mi
->identify_fn
= de_identify_fp_art
;
1336 // **************************************************************************
1338 // **************************************************************************
1340 static void de_run_ybm(deark
*c
, de_module_params
*mparams
)
1342 de_bitmap
*img
= NULL
;
1343 i64 npwidth
, pdwidth
, height
;
1349 npwidth
= de_getu16be_p(&pos
);
1350 height
= de_getu16be_p(&pos
);
1351 de_dbg_dimensions(c
, npwidth
, height
);
1352 if(!de_good_image_dimensions(c
, npwidth
, height
)) goto done
;
1353 pdwidth
= de_pad_to_n(npwidth
, 16);
1354 words_per_row
= pdwidth
/16;
1356 img
= de_bitmap_create2(c
, npwidth
, pdwidth
, height
, 1);
1358 for(j
=0; j
<height
; j
++) {
1359 for(i
=0; i
<words_per_row
; i
++) {
1362 // This encoding is unusual: LSB-first 16-bit integers.
1363 x
= de_getbyte_p(&pos
);
1364 de_unpack_pixels_bilevel_from_byte(img
, i
*16+8, j
, x
, 8,
1365 DE_CVTF_WHITEISZERO
|DE_CVTF_LSBFIRST
|DE_CVTF_ONLYWHITE
);
1366 x
= de_getbyte_p(&pos
);
1367 de_unpack_pixels_bilevel_from_byte(img
, i
*16, j
, x
, 8,
1368 DE_CVTF_WHITEISZERO
|DE_CVTF_LSBFIRST
|DE_CVTF_ONLYWHITE
);
1371 de_bitmap_write_to_file(img
, NULL
, 0);
1374 de_bitmap_destroy(img
);
1377 static int de_identify_ybm(deark
*c
)
1382 if(dbuf_memcmp(c
->infile
, 0, "!!", 2))
1384 width
= de_getu16be(2);
1385 height
= de_getu16be(4);
1386 rowspan
= ((width
+15)/16)*2;
1387 if(6+height
*rowspan
== c
->infile
->len
)
1392 void de_module_ybm(deark
*c
, struct deark_module_info
*mi
)
1395 mi
->desc
= "Bennet Yee's face format, a.k.a. YBM";
1396 mi
->run_fn
= de_run_ybm
;
1397 mi
->identify_fn
= de_identify_ybm
;
1400 // **************************************************************************
1401 // OLPC .565 firmware icon
1402 // **************************************************************************
1404 static void de_run_olpc565(deark
*c
, de_module_params
*mparams
)
1406 de_bitmap
*img
= NULL
;
1413 width
= de_getu16le(4);
1414 height
= de_getu16le(6);
1415 if(!de_good_image_dimensions(c
, width
, height
)) goto done
;
1418 img
= de_bitmap_create(c
, width
, height
, 3);
1420 for(j
=0; j
<height
; j
++) {
1421 for(i
=0; i
<width
; i
++) {
1422 b0
= de_getbyte(8 + j
*rowspan
+ i
*2);
1423 b1
= de_getbyte(8 + j
*rowspan
+ i
*2 + 1);
1424 clr
= (((u32
)b1
)<<8) | b0
;
1425 clr
= de_rgb565_to_888(clr
);
1426 de_bitmap_setpixel_rgb(img
, i
, j
, clr
);
1429 de_bitmap_write_to_file(img
, NULL
, 0);
1432 de_bitmap_destroy(img
);
1435 static int de_identify_olpc565(deark
*c
)
1437 if(!dbuf_memcmp(c
->infile
, 0, "C565", 4))
1442 void de_module_olpc565(deark
*c
, struct deark_module_info
*mi
)
1445 mi
->desc
= "OLPC .565 firmware icon";
1446 mi
->run_fn
= de_run_olpc565
;
1447 mi
->identify_fn
= de_identify_olpc565
;
1450 // **************************************************************************
1452 // **************************************************************************
1454 static void de_run_iim(deark
*c
, de_module_params
*mparams
)
1456 de_bitmap
*img
= NULL
;
1463 // This code is based on reverse engineering, and may be incorrect.
1465 n
= de_getu16be(8); // Unknown field
1466 bpp
= de_getu16be(10);
1467 if(n
!=4 || bpp
!=24) {
1468 de_dbg(c
, "This type of IIM image is not supported");
1471 width
= de_getu16be(12);
1472 height
= de_getu16be(14);
1473 if(!de_good_image_dimensions(c
, width
, height
)) goto done
;
1476 img
= de_bitmap_create(c
, width
, height
, 3);
1478 for(j
=0; j
<height
; j
++) {
1479 for(i
=0; i
<width
; i
++) {
1480 clr
= dbuf_getRGB(c
->infile
, 16+j
*rowspan
+i
*3, 0);
1481 de_bitmap_setpixel_rgb(img
, i
, j
, clr
);
1484 de_bitmap_write_to_file(img
, NULL
, 0);
1487 de_bitmap_destroy(img
);
1490 static int de_identify_iim(deark
*c
)
1492 if(!dbuf_memcmp(c
->infile
, 0, "IS_IMAGE", 8))
1497 void de_module_iim(deark
*c
, struct deark_module_info
*mi
)
1500 mi
->desc
= "InShape IIM";
1501 mi
->run_fn
= de_run_iim
;
1502 mi
->identify_fn
= de_identify_iim
;
1505 // **************************************************************************
1506 // PM (format supported by the XV image viewer)
1507 // **************************************************************************
1509 static void de_run_pm_xv(deark
*c
, de_module_params
*mparams
)
1511 de_bitmap
*img
= NULL
;
1525 if(!dbuf_memcmp(c
->infile
, 0, "WEIV", 4))
1530 nplanes
= dbuf_geti32x(c
->infile
, 4, is_le
);
1531 de_dbg(c
, "planes: %d", (int)nplanes
);
1533 height
= dbuf_geti32x(c
->infile
, 8, is_le
);
1534 width
= dbuf_geti32x(c
->infile
, 12, is_le
);
1535 de_dbg_dimensions(c
, width
, height
);
1536 if(!de_good_image_dimensions(c
, width
, height
)) goto done
;
1538 nbands
= dbuf_geti32x(c
->infile
, 16, is_le
);
1539 de_dbg(c
, "bands: %d", (int)nbands
);
1541 pixelformat
= dbuf_geti32x(c
->infile
, 20, is_le
);
1542 de_dbg(c
, "pixel format: 0x%04x", (unsigned int)pixelformat
);
1544 commentsize
= dbuf_geti32x(c
->infile
, 24, is_le
);
1545 de_dbg(c
, "comment size: %d", (int)commentsize
);
1549 if((pixelformat
==0x8001 && nplanes
==3 && nbands
==1) ||
1550 (pixelformat
==0x8001 && nplanes
==1 && nbands
==1))
1555 de_err(c
, "Unsupported image type (pixel format=0x%04x, "
1556 "planes=%d, bands=%d)", (unsigned int)pixelformat
,
1557 (int)nplanes
, (int)nbands
);
1562 planespan
= rowspan
*height
;
1564 img
= de_bitmap_create(c
, width
, height
, (int)nplanes
);
1566 for(plane
=0; plane
<nplanes
; plane
++) {
1567 for(j
=0; j
<height
; j
++) {
1568 for(i
=0; i
<width
; i
++) {
1569 b
= de_getbyte(pos
+ plane
*planespan
+ j
*rowspan
+ i
);
1571 de_bitmap_setsample(img
, i
, j
, plane
, b
);
1574 de_bitmap_setpixel_gray(img
, i
, j
, b
);
1579 de_bitmap_write_to_file(img
, NULL
, 0);
1582 de_bitmap_destroy(img
);
1585 static int de_identify_pm_xv(deark
*c
)
1587 if(!dbuf_memcmp(c
->infile
, 0, "VIEW", 4))
1589 if(!dbuf_memcmp(c
->infile
, 0, "WEIV", 4))
1594 void de_module_pm_xv(deark
*c
, struct deark_module_info
*mi
)
1597 mi
->desc
= "PM (XV)";
1598 mi
->run_fn
= de_run_pm_xv
;
1599 mi
->identify_fn
= de_identify_pm_xv
;
1602 // **************************************************************************
1603 // Calamus Raster Graphic - CRG
1604 // **************************************************************************
1606 // Warning: The CRG decoder is based on reverse engineering, may not be
1607 // correct, and is definitely incomplete.
1609 static void de_run_crg(deark
*c
, de_module_params
*mparams
)
1618 dbuf
*unc_pixels
= NULL
;
1620 width
= de_getu32be(20);
1621 height
= de_getu32be(24);
1622 de_dbg_dimensions(c
, width
, height
);
1623 if(!de_good_image_dimensions(c
, width
, height
)) goto done
;
1625 b1
= de_getbyte(32);
1627 de_err(c
, "Unsupported CRG format");
1631 num_cmpr_bytes
= de_getu32be(38);
1632 de_dbg(c
, "compressed data size: %d", (int)num_cmpr_bytes
);
1633 cmpr_img_start
= 42;
1635 if(cmpr_img_start
+ num_cmpr_bytes
> c
->infile
->len
) {
1636 num_cmpr_bytes
= c
->infile
->len
- cmpr_img_start
;
1639 // Uncompress the image
1640 rowspan
= (width
+7)/8;
1641 unc_pixels
= dbuf_create_membuf(c
, height
*rowspan
, 1);
1643 pos
= cmpr_img_start
;
1644 while(pos
< cmpr_img_start
+ num_cmpr_bytes
) {
1645 b1
= de_getbyte(pos
++);
1646 if(b1
<=0x7f) { // Uncompressed bytes
1648 dbuf_copy(c
->infile
, pos
, count
, unc_pixels
);
1651 else { // A compressed run
1652 b2
= de_getbyte(pos
++);
1653 count
= (i64
)(b1
-127);
1654 dbuf_write_run(unc_pixels
, b2
, count
);
1657 de_dbg(c
, "decompressed to %d bytes", (int)unc_pixels
->len
);
1659 de_convert_and_write_image_bilevel2(unc_pixels
, 0, width
, height
, rowspan
,
1660 DE_CVTF_WHITEISZERO
, NULL
, 0);
1663 dbuf_close(unc_pixels
);
1666 static int de_identify_crg(deark
*c
)
1668 if(!dbuf_memcmp(c
->infile
, 0, "CALAMUSCRG", 10))
1673 void de_module_crg(deark
*c
, struct deark_module_info
*mi
)
1676 mi
->desc
= "Calamus Raster Graphic";
1677 mi
->run_fn
= de_run_crg
;
1678 mi
->identify_fn
= de_identify_crg
;
1681 // **************************************************************************
1683 // **************************************************************************
1685 static void de_run_farbfeld(deark
*c
, de_module_params
*mparams
)
1687 de_bitmap
*img
= NULL
;
1693 width
= de_getu32be(8);
1694 height
= de_getu32be(12);
1695 de_dbg_dimensions(c
, width
, height
);
1696 if(!de_good_image_dimensions(c
, width
, height
)) return;
1698 img
= de_bitmap_create(c
, width
, height
, 4);
1700 for(j
=0; j
<height
; j
++) {
1701 for(i
=0; i
<width
; i
++) {
1702 ppos
= 16 + 8*(width
*j
+ i
);
1703 for(k
=0; k
<4; k
++) {
1704 s
[k
] = de_getbyte(ppos
+2*k
);
1706 de_bitmap_setpixel_rgba(img
, i
, j
,
1707 DE_MAKE_RGBA(s
[0],s
[1],s
[2],s
[3]));
1710 de_bitmap_write_to_file(img
, NULL
, 0);
1711 de_bitmap_destroy(img
);
1714 static int de_identify_farbfeld(deark
*c
)
1716 if(!dbuf_memcmp(c
->infile
, 0, "farbfeld", 8))
1721 void de_module_farbfeld(deark
*c
, struct deark_module_info
*mi
)
1723 mi
->id
= "farbfeld";
1724 mi
->desc
= "farbfeld image";
1725 mi
->run_fn
= de_run_farbfeld
;
1726 mi
->identify_fn
= de_identify_farbfeld
;
1729 // **************************************************************************
1730 // VGA font (intended for development/debugging use)
1731 // **************************************************************************
1733 static void de_run_vgafont(deark
*c
, de_module_params
*mparams
)
1735 u8
*fontdata
= NULL
;
1736 struct de_bitmap_font
*font
= NULL
;
1740 if(c
->infile
->len
==16*256) {
1743 else if(c
->infile
->len
==14*256) {
1747 de_err(c
, "Bad file size");
1751 fontdata
= de_malloc(c
, height
*256);
1752 de_read(fontdata
, 0, height
*256);
1754 if(de_get_ext_option(c
, "vgafont:c")) {
1756 ff
= dbuf_create_output_file(c
, "h", NULL
, 0);
1757 for(i
=0; i
<(height
*256); i
++) {
1758 if(i
%height
==0) dbuf_puts(ff
, "\t");
1759 dbuf_printf(ff
, "%d", (int)fontdata
[i
]);
1760 if(i
!=(height
*256-1)) dbuf_puts(ff
, ",");
1761 if(i
%height
==(height
-1)) dbuf_puts(ff
, "\n");
1767 font
= de_create_bitmap_font(c
);
1768 font
->num_chars
= 256;
1769 font
->has_nonunicode_codepoints
= 1;
1770 font
->has_unicode_codepoints
= 0;
1771 font
->prefer_unicode
= 0;
1772 font
->nominal_width
= 8;
1773 font
->nominal_height
= (int)height
;
1774 font
->char_array
= de_mallocarray(c
, font
->num_chars
, sizeof(struct de_bitmap_font_char
));
1776 for(i
=0; i
<font
->num_chars
; i
++) {
1777 font
->char_array
[i
].codepoint_nonunicode
= (i32
)i
;
1778 font
->char_array
[i
].width
= font
->nominal_width
;
1779 font
->char_array
[i
].height
= font
->nominal_height
;
1780 font
->char_array
[i
].rowspan
= 1;
1781 font
->char_array
[i
].bitmap
= &fontdata
[i
*font
->nominal_height
];
1784 de_font_bitmap_font_to_image(c
, font
, NULL
, 0);
1788 de_free(c
, font
->char_array
);
1789 de_destroy_bitmap_font(c
, font
);
1791 de_free(c
, fontdata
);
1794 static void de_help_vgafont(deark
*c
)
1796 de_msg(c
, "-opt vgafont:c : Emit C code");
1799 void de_module_vgafont(deark
*c
, struct deark_module_info
*mi
)
1802 mi
->desc
= "Raw 8x16 or 8x14 VGA font";
1803 mi
->run_fn
= de_run_vgafont
;
1804 mi
->help_fn
= de_help_vgafont
;
1805 mi
->flags
|= DE_MODFLAG_HIDDEN
;
1808 // **************************************************************************
1809 // HSI Raw image format (from Image Alchemy / Handmade Software)
1810 // **************************************************************************
1812 static void de_run_hsiraw(deark
*c
, de_module_params
*mparams
)
1821 de_bitmap
*img
= NULL
;
1825 ver
= de_getu16be(6);
1826 de_dbg(c
, "version: %d", (int)ver
);
1828 de_warn(c
, "HSI Raw version %d might not be supported correctly", (int)ver
);
1833 // MPlayer extension?
1834 de_dbg2(c
, "reading 32-bit width");
1835 w
= de_getu32be(28);
1837 h
= de_getu16be(10);
1838 de_dbg_dimensions(c
, w
, h
);
1839 num_pal_colors
= de_getu16be(12);
1840 de_dbg(c
, "number of palette colors: %d", (int)num_pal_colors
);
1842 hdpi
= de_geti16be(14);
1843 vdpi
= de_geti16be(16);
1844 de_dbg(c
, "density: %d"DE_CHAR_TIMES
"%d", (int)hdpi
, (int)vdpi
);
1846 cmpr
= de_getu16be(20);
1847 de_dbg(c
, "compression: %d", (int)cmpr
);
1848 alpha_info
= de_getu16be(22);
1849 de_dbg(c
, "alpha: %d", (int)alpha_info
);
1851 if(num_pal_colors
>256 || cmpr
!=0 || alpha_info
!=0) {
1852 de_err(c
, "This type of HSI Raw image is not supported");
1855 if(!de_good_image_dimensions(c
, w
, h
)) goto done
;
1858 de_zeromem(pal
, sizeof(pal
));
1859 if(num_pal_colors
==0) { // 24-bit RGB
1862 else { // 8-bit paletted
1863 de_read_palette_rgb(c
->infile
, pos
, num_pal_colors
, 3, pal
, 256, 0);
1864 pos
+= 3*num_pal_colors
;
1865 is_grayscale
= de_is_grayscale_palette(pal
, num_pal_colors
);
1868 img
= de_bitmap_create(c
, w
, h
, is_grayscale
?1:3);
1870 if(num_pal_colors
==0) {
1871 de_convert_image_rgb(c
->infile
, pos
, 3*w
, 3, img
, 0);
1874 de_convert_image_paletted(c
->infile
, pos
, 8, w
, pal
, img
, 0);
1877 de_bitmap_write_to_file(img
, NULL
, 0);
1880 de_bitmap_destroy(img
);
1883 static int de_identify_hsiraw(deark
*c
)
1885 if(!dbuf_memcmp(c
->infile
, 0, "mhwanh", 6))
1890 void de_module_hsiraw(deark
*c
, struct deark_module_info
*mi
)
1893 mi
->desc
= "HSI Raw";
1894 mi
->run_fn
= de_run_hsiraw
;
1895 mi
->identify_fn
= de_identify_hsiraw
;
1898 // **************************************************************************
1900 // **************************************************************************
1902 static void de_run_qdv(deark
*c
, de_module_params
*mparams
)
1907 de_bitmap
*img
= NULL
;
1910 // Warning: This decoder is based on reverse engineering, and may be
1911 // incorrect or incomplete.
1915 de_dbg_dimensions(c
, w
, h
);
1916 if(!de_good_image_dimensions(c
, w
, h
)) goto done
;
1918 num_pal_colors
= 1 + (i64
)de_getbyte(4);
1919 de_dbg(c
, "number of palette colors: %d", (int)num_pal_colors
);
1922 de_zeromem(pal
, sizeof(pal
));
1923 de_read_palette_rgb(c
->infile
, pos
, num_pal_colors
, 3, pal
, 256, 0);
1924 pos
+= 3*num_pal_colors
;
1926 img
= de_bitmap_create(c
, w
, h
, 3);
1927 de_convert_image_paletted(c
->infile
, pos
, 8, w
, pal
, img
, 0);
1928 de_bitmap_write_to_file(img
, NULL
, 0);
1931 de_bitmap_destroy(img
);
1934 static int de_identify_qdv(deark
*c
)
1941 num_pal_colors
= 1 + (i64
)de_getbyte(4);
1942 if(5+num_pal_colors
*3+w
*h
!= c
->infile
->len
)
1944 if(de_input_file_has_ext(c
, "qdv"))
1949 void de_module_qdv(deark
*c
, struct deark_module_info
*mi
)
1952 mi
->desc
= "QDV (Giffer)";
1953 mi
->run_fn
= de_run_qdv
;
1954 mi
->identify_fn
= de_identify_qdv
;
1957 // **************************************************************************
1958 // VITec image format
1959 // **************************************************************************
1961 static void de_run_vitec(deark
*c
, de_module_params
*mparams
)
1963 i64 npwidth
, pdwidth
, h
;
1965 de_bitmap
*img
= NULL
;
1966 i64 samplesperpixel
;
1967 i64 rowspan
, planespan
;
1971 int saved_indent_level
;
1973 // This code is based on reverse engineering, and may be incorrect.
1975 de_dbg_indent_save(c
, &saved_indent_level
);
1976 de_warn(c
, "VITec image support is experimental, and may not work correctly.");
1979 h1size
= de_getu32be(pos
);
1980 de_dbg(c
, "header 1 at %d, len=%d", (int)pos
, (int)h1size
);
1981 // Don't know what's in this part of the header. Just ignore it.
1983 if(pos
>=c
->infile
->len
) goto done
;
1985 h2size
= de_getu32be(pos
);
1986 de_dbg(c
, "header 2 at %d, len=%d", (int)pos
, (int)h2size
);
1987 de_dbg_indent(c
, 1);
1989 // pos+4: Bits size?
1990 // pos+24: Unknown field, usually 7
1992 npwidth
= de_getu32be(pos
+36);
1993 h
= de_getu32be(pos
+40);
1994 de_dbg_dimensions(c
, npwidth
, h
);
1995 if(!de_good_image_dimensions(c
, npwidth
, h
)) goto done
;
1997 // pos+52: Unknown field, 1 in grayscale images
1999 samplesperpixel
= de_getu32be(pos
+56);
2000 de_dbg(c
, "samples/pixel: %d", (int)samplesperpixel
);
2001 if(samplesperpixel
!=1 && samplesperpixel
!=3) {
2002 de_err(c
, "Unsupported samples/pixel: %d", (int)samplesperpixel
);
2007 if(pos
>=c
->infile
->len
) goto done
;
2008 de_dbg_indent(c
, -1);
2010 de_dbg(c
, "bitmap at %d", (int)pos
);
2011 pdwidth
= de_pad_to_n(npwidth
, 8);
2012 img
= de_bitmap_create2(c
, npwidth
, pdwidth
, h
, (int)samplesperpixel
);
2014 planespan
= rowspan
*h
;
2016 for(plane
=0; plane
<samplesperpixel
; plane
++) {
2017 for(j
=0; j
<h
; j
++) {
2018 for(i
=0; i
<pdwidth
; i
++) {
2019 b
= de_getbyte(pos
+ plane
*planespan
+ j
*rowspan
+ i
);
2020 if(samplesperpixel
==3) {
2021 de_bitmap_setsample(img
, i
, j
, plane
, b
);
2024 de_bitmap_setpixel_gray(img
, i
, j
, b
);
2030 de_bitmap_write_to_file(img
, NULL
, 0);
2033 de_bitmap_destroy(img
);
2034 de_dbg_indent_restore(c
, saved_indent_level
);
2037 static int de_identify_vitec(deark
*c
)
2039 if(!dbuf_memcmp(c
->infile
, 0, "\x00\x5b\x07\x20", 4))
2044 void de_module_vitec(deark
*c
, struct deark_module_info
*mi
)
2047 mi
->desc
= "VITec image format";
2048 mi
->run_fn
= de_run_vitec
;
2049 mi
->identify_fn
= de_identify_vitec
;
2052 // **************************************************************************
2055 // .HS2 format is associated with a program called POSTERING.
2056 // **************************************************************************
2058 static void de_run_hs2(deark
*c
, de_module_params
*mparams
)
2065 height
= (c
->infile
->len
+(rowspan
-1))/rowspan
;
2066 de_convert_and_write_image_bilevel(c
->infile
, 0, width
, height
, rowspan
, 0, NULL
, 0);
2069 static int de_identify_hs2(deark
*c
)
2071 if(!de_input_file_has_ext(c
, "hs2")) return 0;
2072 if(c
->infile
->len
>0 && (c
->infile
->len
%105 == 0)) {
2078 void de_module_hs2(deark
*c
, struct deark_module_info
*mi
)
2081 mi
->desc
= "HS2 (POSTERING)";
2082 mi
->run_fn
= de_run_hs2
;
2083 mi
->identify_fn
= de_identify_hs2
;
2087 // **************************************************************************
2089 // **************************************************************************
2091 static void de_run_lumena_cel(deark
*c
, de_module_params
*mparams
)
2100 de_bitmap
*img
= NULL
;
2101 const i64 headersize
= 4;
2104 width
= de_getu16le(0);
2105 height
= de_getu16le(2);
2106 if(!de_good_image_dimensions_noerr(c
, width
, height
)) goto done
;
2108 // TODO: Support multi-image files
2109 is_16bit
= (c
->infile
->len
== headersize
+ width
*height
*2);
2110 is_32bit
= (c
->infile
->len
== headersize
+ width
*height
*4);
2111 if(!is_16bit
&& !is_32bit
) {
2112 de_warn(c
, "Cannot detect bits/pixel, assuming 32");
2116 bypp
= (is_32bit
) ? 4 : 2;
2117 de_dbg(c
, "bytes/pixel: %d", (int)bypp
);
2118 rowspan
= width
* bypp
;
2120 img
= de_bitmap_create(c
, width
, height
, is_32bit
?4:3);
2122 for(j
=0; j
<height
; j
++) {
2123 for(i
=0; i
<width
; i
++) {
2124 i64 pos
= headersize
+ j
*rowspan
+ i
*bypp
;
2126 clr
= dbuf_getRGB(c
->infile
, pos
, 0);
2127 a
= de_getbyte(pos
+ 3);
2128 clr
= DE_SET_ALPHA(clr
, a
);
2131 clr
= (u32
)de_getu16le(pos
);
2132 clr
= de_rgb555_to_888(clr
);
2134 de_bitmap_setpixel_rgba(img
, i
, j
, clr
);
2138 de_bitmap_optimize_alpha(img
, 0x3);
2139 de_bitmap_write_to_file(img
, NULL
, DE_CREATEFLAG_FLIP_IMAGE
);
2142 de_bitmap_destroy(img
);
2145 static int de_identify_lumena_cel(deark
*c
)
2151 if(!de_input_file_has_ext(c
, "cel")) return 0;
2152 width
= de_getu16le(0);
2153 height
= de_getu16le(2);
2155 is_16bit
= (c
->infile
->len
== 4 + width
*height
*2);
2156 is_32bit
= (c
->infile
->len
== 4 + width
*height
*4);
2158 if(is_16bit
|| is_32bit
)
2164 void de_module_lumena_cel(deark
*c
, struct deark_module_info
*mi
)
2166 mi
->id
= "lumena_cel";
2167 mi
->desc
= "Lumena CEL";
2168 mi
->run_fn
= de_run_lumena_cel
;
2169 mi
->identify_fn
= de_identify_lumena_cel
;
2172 // **************************************************************************
2173 // ZBR (Zoner Zebra Metafile)
2174 // **************************************************************************
2176 static void de_run_zbr(deark
*c
, de_module_params
*mparams
)
2180 static const u8 hdrs
[54] = {
2181 0x42,0x4d,0xc6,0x14,0,0,0,0,0,0,0x76,0,0,0, // FILEHEADER
2182 0x28,0,0,0,0x64,0,0,0,0x64,0,0,0,0x01,0,0x04,0, // INFOHEADER...
2183 0,0,0,0,0x50,0x14,0,0,0,0,0,0,0,0,0,0,
2184 0x10,0,0,0,0,0,0,0 };
2186 pos
+= 4; // signature, version
2187 pos
+= 100; // comment
2189 de_dbg(c
, "preview image at %d", (int)pos
);
2190 // By design, this image is formatted as a headerless BMP/DIB. We'll just
2191 // add the 54 bytes of headers needed to make it a BMP, and call it done.
2192 outf
= dbuf_create_output_file(c
, "preview.bmp", NULL
, DE_CREATEFLAG_IS_AUX
);
2193 dbuf_write(outf
, hdrs
, 54);
2194 dbuf_copy(c
->infile
, pos
, 16*4 + 100*52, outf
);
2198 static int de_identify_zbr(deark
*c
)
2200 if(!dbuf_memcmp(c
->infile
, 0, "\x9a\x02", 2)) {
2201 if(de_input_file_has_ext(c
, "zbr")) return 100;
2207 void de_module_zbr(deark
*c
, struct deark_module_info
*mi
)
2210 mi
->desc
= "ZBR (Zebra Metafile)";
2211 mi
->desc2
= "extract preview image";
2212 mi
->run_fn
= de_run_zbr
;
2213 mi
->identify_fn
= de_identify_zbr
;
2216 // **************************************************************************
2217 // CorelDRAW CDR - old "WL" format
2218 // **************************************************************************
2220 static void de_run_cdr_wl(deark
*c
, de_module_params
*mparams
)
2227 de_bitmap
*img
= NULL
;
2228 int saved_indent_level
;
2230 de_dbg_indent_save(c
, &saved_indent_level
);
2231 de_declare_fmt(c
, "CorelDRAW (WL format)");
2232 version
= de_getbyte(2);
2233 de_dbg(c
, "version code: 0x%02x", (unsigned int)version
);
2234 if(version
<= (u8
)'e') goto done
;
2236 pos
= de_getu32le(28);
2237 de_dbg(c
, "preview image at %d", (int)pos
);
2238 de_dbg_indent(c
, 1);
2240 // Seems to be Windows DDB format, or something like it.
2243 w
= de_getu16le_p(&pos
);
2244 h
= de_getu16le_p(&pos
);
2245 de_dbg_dimensions(c
, w
, h
);
2246 rowspan
= de_getu16le_p(&pos
);
2247 b
= de_getbyte_p(&pos
); // planes
2249 b
= de_getbyte_p(&pos
); // bits/pixel
2253 if(!de_good_image_dimensions(c
, w
, h
)) goto done
;
2254 img
= de_bitmap_create2(c
, w
, rowspan
*8, h
, 1);
2255 de_convert_image_bilevel(c
->infile
, pos
, rowspan
, img
, 0);
2256 de_bitmap_write_to_file(img
, "preview", DE_CREATEFLAG_IS_AUX
);
2259 de_bitmap_destroy(img
);
2260 de_dbg_indent_restore(c
, saved_indent_level
);
2263 static int de_identify_cdr_wl(deark
*c
)
2265 if(!dbuf_memcmp(c
->infile
, 0, "WL", 2)) {
2266 if(de_input_file_has_ext(c
, "cdr")) return 100;
2272 void de_module_cdr_wl(deark
*c
, struct deark_module_info
*mi
)
2275 mi
->desc
= "CorelDRAW (old WL format)";
2276 mi
->desc2
= "extract preview image";
2277 mi
->run_fn
= de_run_cdr_wl
;
2278 mi
->identify_fn
= de_identify_cdr_wl
;
2281 // **************************************************************************
2283 // **************************************************************************
2285 static void de_run_compress(deark
*c
, de_module_params
*mparams
)
2287 struct de_dfilter_results dres
;
2288 struct de_dfilter_in_params dcmpri
;
2289 struct de_dfilter_out_params dcmpro
;
2290 struct de_lzw_params delzwp
;
2293 f
= dbuf_create_output_file(c
, "bin", NULL
, 0);
2295 de_dfilter_init_objects(c
, &dcmpri
, &dcmpro
, &dres
);
2296 dcmpri
.f
= c
->infile
;
2298 dcmpri
.len
= c
->infile
->len
;
2300 dcmpro
.len_known
= 0;
2302 de_zeromem(&delzwp
, sizeof(struct de_lzw_params
));
2303 delzwp
.fmt
= DE_LZWFMT_UNIXCOMPRESS
;
2304 delzwp
.flags
|= DE_LZWFLAG_HAS3BYTEHEADER
;
2306 fmtutil_decompress_lzw(c
, &dcmpri
, &dcmpro
, &dres
, &delzwp
);
2307 if(dres
.errcode
!=0) {
2308 de_err(c
, "%s", de_dfilter_get_errmsg(c
, &dres
));
2313 static int de_identify_compress(deark
*c
)
2315 if(!dbuf_memcmp(c
->infile
, 0, "\x1f\x9d", 2))
2320 void de_module_compress(deark
*c
, struct deark_module_info
*mi
)
2322 mi
->id
= "compress";
2323 mi
->desc
= "Compress (.Z)";
2324 mi
->run_fn
= de_run_compress
;
2325 mi
->identify_fn
= de_identify_compress
;
2328 // **************************************************************************
2329 // Graphic Workshop .THN
2330 // **************************************************************************
2332 static void de_run_gws_thn(deark
*c
, de_module_params
*mparams
)
2334 de_bitmap
*img
= NULL
;
2338 de_encoding encoding
;
2339 de_ucstring
*s
= NULL
;
2342 // This code is based on reverse engineering, and may be incorrect.
2343 encoding
= de_get_input_encoding(c
, NULL
, DE_ENCODING_WINDOWS1252
);
2345 v1
= de_getbyte_p(&pos
);
2346 v2
= de_getbyte_p(&pos
);
2347 de_dbg(c
, "version?: 0x%02x 0x%02x", (unsigned int)v1
, (unsigned int)v2
);
2349 s
= ucstring_create(c
);
2350 // For the text fields, the field size appears to be 129, but the software
2351 // only properly supports up to 127 non-NUL bytes.
2352 dbuf_read_to_ucstring(c
->infile
, 6, 127, s
, DE_CONVFLAG_STOP_AT_NUL
, encoding
);
2353 if(s
->len
>0) de_dbg(c
, "comments: \"%s\"", ucstring_getpsz_d(s
));
2355 dbuf_read_to_ucstring(c
->infile
, 135, 127, s
, DE_CONVFLAG_STOP_AT_NUL
, encoding
);
2356 if(s
->len
>0) de_dbg(c
, "key words: \"%s\"", ucstring_getpsz_d(s
));
2359 de_dbg(c
, "image at %"I64_FMT
, pos
);
2363 // Set up the palette. There are two possible fixed palettes.
2364 if(v1
==0) { // Original palette
2365 // Based on Graphic Workshop v1.1a for Windows
2366 static const u8 rbvals
[6] = {0x00,0x57,0x83,0xab,0xd7,0xff};
2367 static const u8 gvals
[7] = {0x00,0x2b,0x57,0x83,0xab,0xd7,0xff};
2368 static const u32 gwspal_last5
[5] = {0x3f3f3f,0x6b6b6b,0x979797,
2372 for(k
=0; k
<=250; k
++) {
2373 pal
[k
] = DE_MAKE_RGB(
2378 for(k
=251; k
<=255; k
++) {
2379 pal
[k
] = gwspal_last5
[k
-251];
2382 else { // New palette (really RGB332), introduced by v1.1c
2383 // Based on Graphic Workshop v1.1u for Windows
2386 for(k
=0; k
<256; k
++) {
2388 r
= de_sample_nbit_to_8bit(3, k
>>5);
2389 g
= de_sample_nbit_to_8bit(3, (k
>>2)&0x07);
2390 b
= de_sample_nbit_to_8bit(2, k
&0x03);
2391 pal
[k
] = DE_MAKE_RGB(r
, g
, b
);
2395 img
= de_bitmap_create(c
, w
, h
, 3);
2396 de_convert_image_paletted(c
->infile
, pos
, 8, w
, pal
, img
, 0);
2397 de_bitmap_write_to_file(img
, NULL
, DE_CREATEFLAG_FLIP_IMAGE
);
2398 de_bitmap_destroy(img
);
2399 ucstring_destroy(s
);
2402 static int de_identify_gws_thn(deark
*c
)
2404 if(c
->infile
->len
!=9480) return 0;
2405 if(!dbuf_memcmp(c
->infile
, 0, "THNL", 4)) return 100;
2409 void de_module_gws_thn(deark
*c
, struct deark_module_info
*mi
)
2412 mi
->desc
= "Graphic Workshop thumbnail .THN";
2413 mi
->run_fn
= de_run_gws_thn
;
2414 mi
->identify_fn
= de_identify_gws_thn
;
2417 // **************************************************************************
2418 // Tandy DeskMate Paint .PNT
2419 // **************************************************************************
2421 static void de_run_deskmate_pnt(deark
*c
, de_module_params
*mparams
)
2428 de_bitmap
*img
= NULL
;
2429 dbuf
*unc_pixels
= NULL
;
2430 i64 unc_pixels_size
;
2434 de_dbg(c
, "image at %"I64_FMT
, pos
);
2438 unc_pixels_size
= rowspan
* h
;
2440 for(k
=0; k
<16; k
++) {
2441 pal
[k
] = de_palette_pc16(k
);
2444 is_compressed
= (pos
+unc_pixels_size
!= c
->infile
->len
);
2445 de_dbg(c
, "compressed: %d", is_compressed
);
2448 unc_pixels
= dbuf_create_membuf(c
, unc_pixels_size
, 0x1);
2453 if(pos
>= c
->infile
->len
) break; // out of source data
2454 if(unc_pixels
->len
>= unc_pixels_size
) break; // enough dst data
2455 val
= de_getbyte_p(&pos
);
2456 count
= (i64
)de_getbyte_p(&pos
);
2457 dbuf_write_run(unc_pixels
, val
, count
);
2461 unc_pixels
= dbuf_open_input_subfile(c
->infile
, pos
, unc_pixels_size
);
2464 img
= de_bitmap_create(c
, w
, h
, 3);
2465 de_convert_image_paletted(unc_pixels
, 0, 4, rowspan
, pal
, img
, 0);
2466 de_bitmap_write_to_file(img
, NULL
, 0);
2468 dbuf_close(unc_pixels
);
2469 de_bitmap_destroy(img
);
2472 static int de_identify_deskmate_pnt(deark
*c
)
2474 if(!dbuf_memcmp(c
->infile
, 0, "\x13" "PNT", 4)) return 100;
2478 void de_module_deskmate_pnt(deark
*c
, struct deark_module_info
*mi
)
2480 mi
->id
= "deskmate_pnt";
2481 mi
->desc
= "Tandy DeskMate Paint";
2482 mi
->run_fn
= de_run_deskmate_pnt
;
2483 mi
->identify_fn
= de_identify_deskmate_pnt
;
2487 // **************************************************************************
2488 // Corel Gallery .BMF
2489 // **************************************************************************
2491 // Warning: The BMF preview image decoder is based on reverse engineering, may not
2494 static void de_run_corel_bmf(deark
*c
, de_module_params
*mparams1
)
2496 de_module_params
*mparams2
= NULL
;
2497 int saved_indent_level
;
2502 de_dbg_indent_save(c
, &saved_indent_level
);
2504 seg_size
= de_getu32le_p(&pos
);
2505 de_dbg(c
, "preview image segment at %"I64_FMT
", len=%"I64_FMT
, pos
, seg_size
);
2506 de_dbg_indent(c
, 1);
2508 if(pos
+ seg_size
> c
->infile
->len
) {
2509 seg_size
= c
->infile
->len
- pos
;
2512 n
= de_getu32le(pos
);
2514 de_err(c
, "Unsupported Corel BMF version");
2518 mparams2
= de_malloc(c
, sizeof(de_module_params
));
2519 mparams2
->in_params
.codes
= "X";
2520 mparams2
->in_params
.flags
= 0x81;
2521 de_run_module_by_id_on_slice(c
, "dib", mparams2
, c
->infile
, pos
, seg_size
);
2524 de_free(c
, mparams2
);
2525 de_dbg_indent_restore(c
, saved_indent_level
);
2528 static int de_identify_corel_bmf(deark
*c
)
2530 if(!dbuf_memcmp(c
->infile
, 0, "@CorelBMF\x0a\x0d", 11)) return 100;
2534 void de_module_corel_bmf(deark
*c
, struct deark_module_info
*mi
)
2536 mi
->id
= "corel_bmf";
2537 mi
->desc
= "Corel Gallery BMF";
2538 mi
->run_fn
= de_run_corel_bmf
;
2539 mi
->identify_fn
= de_identify_corel_bmf
;
2542 // **************************************************************************
2543 // Hemera Photo-Object image (.hpi)
2544 // **************************************************************************
2546 static void de_run_hpi(deark
*c
, de_module_params
*mparams
)
2553 jpgpos
= de_getu32le_p(&pos
);
2554 jpglen
= de_getu32le_p(&pos
);
2555 de_dbg(c
, "jpeg: pos=%"I64_FMT
", len=%"I64_FMT
, jpgpos
, jpglen
);
2556 pngpos
= de_getu32le_p(&pos
);
2557 pnglen
= de_getu32le_p(&pos
);
2558 de_dbg(c
, "png: pos=%"I64_FMT
", len=%"I64_FMT
, pngpos
, pnglen
);
2560 if(jpglen
>0 && jpgpos
+jpglen
<=c
->infile
->len
&& de_getbyte(jpgpos
)==0xff) {
2563 if(pnglen
==0) ext
="jpg";
2564 else ext
="foreground.jpg";
2565 dbuf_create_file_from_slice(c
->infile
, jpgpos
, jpglen
, ext
, NULL
, 0);
2567 if(pnglen
>0 && pngpos
+pnglen
<=c
->infile
->len
&& de_getbyte(pngpos
)==0x89) {
2568 dbuf_create_file_from_slice(c
->infile
, pngpos
, pnglen
, "mask.png", NULL
, 0);
2572 static int de_identify_hpi(deark
*c
)
2574 if(!dbuf_memcmp(c
->infile
, 0, "\x89\x48\x50\x49\x0d\x0a\x1a\x0a", 8)) return 100;
2578 void de_module_hpi(deark
*c
, struct deark_module_info
*mi
)
2581 mi
->desc
= "Hemera Photo-Object image";
2582 mi
->run_fn
= de_run_hpi
;
2583 mi
->identify_fn
= de_identify_hpi
;
2586 // **************************************************************************
2588 // **************************************************************************
2590 struct dwc_member_data
{
2592 i64 unclen
, cmprlen
;
2597 static void do_dwc_member(deark
*c
, i64 pos1
)
2600 struct dwc_member_data
*md
= NULL
;
2602 md
= de_malloc(c
, sizeof(struct dwc_member_data
));
2603 de_dbg(c
, "member header at %"I64_FMT
, pos1
);
2604 de_dbg_indent(c
, 1);
2605 md
->fn
= ucstring_create(c
);
2606 dbuf_read_to_ucstring(c
->infile
, pos
, 12, md
->fn
, DE_CONVFLAG_STOP_AT_NUL
,
2607 DE_ENCODING_CP437_G
);
2608 de_dbg(c
, "filename: \"%s\"", ucstring_getpsz_d(md
->fn
));
2610 md
->unclen
= de_getu32le_p(&pos
);
2611 de_dbg(c
, "unc. size: %"I64_FMT
, md
->unclen
);
2612 pos
+= 4; // time/date
2613 md
->cmprlen
= de_getu32le_p(&pos
);
2614 de_dbg(c
, "cmpr. size: %"I64_FMT
, md
->cmprlen
);
2615 md
->cmprdatapos
= de_getu32le_p(&pos
);
2616 de_dbg(c
, "cmpr. data pos: %"I64_FMT
, md
->cmprdatapos
);
2617 md
->cmpr_meth
= de_getbyte_p(&pos
);
2618 de_dbg(c
, "cmpr. method: %d", (int)md
->cmpr_meth
);
2621 de_dbg_indent(c
, -1);
2623 ucstring_destroy(md
->fn
);
2628 static void de_run_dwc(deark
*c
, de_module_params
*mparams
)
2632 i64 fhsize
; // size of each file header
2636 de_info(c
, "Note: DWC files can be parsed, but no files can be extracted from them.");
2637 trailer_pos
= c
->infile
->len
- 27;
2639 de_dbg(c
, "trailer at %"I64_FMT
, trailer_pos
);
2640 de_dbg_indent(c
, 1);
2641 pos
+= 2; // trailer length (27)
2642 fhsize
= de_getu16le_p(&pos
);
2644 nmembers
= de_getu16le_p(&pos
);
2645 de_dbg(c
, "number of member files: %d", (int)nmembers
);
2646 de_dbg_indent(c
, -1);
2648 pos
= trailer_pos
- fhsize
*nmembers
;
2649 for(i
=0; i
<nmembers
; i
++) {
2650 if(pos
<0 || pos
>(trailer_pos
-fhsize
)) break;
2651 do_dwc_member(c
, pos
);
2656 static int de_identify_dwc(deark
*c
)
2658 if(!de_input_file_has_ext(c
, "dwc")) return 0;
2659 if(dbuf_memcmp(c
->infile
, c
->infile
->len
-3, (const u8
*)"DWC", 3)) {
2662 if(de_getu16le(c
->infile
->len
-27) != 27) {
2668 void de_module_dwc(deark
*c
, struct deark_module_info
*mi
)
2671 mi
->desc
= "DWC compressed archive";
2672 mi
->run_fn
= de_run_dwc
;
2673 mi
->identify_fn
= de_identify_dwc
;
2676 // **************************************************************************
2677 // Magic Desk icon (.ICN)
2678 // **************************************************************************
2680 static void de_run_mdesk_icn(deark
*c
, de_module_params
*mparams
)
2682 de_bitmap
*img
= NULL
;
2683 static const de_color pal
[16] = {
2684 0xff000000U
, 0xffaa0000U
, 0xff00aa00U
, 0xffaaaa00U
,
2685 0xff0000aaU
, 0xffaa00aaU
, 0xff00aaaaU
, 0xff7d7d7dU
,
2686 0xffbababaU
, 0xffff5555U
, 0xff55ff55U
, 0xffffff55U
,
2687 0xff5555ffU
, 0xffff55ffU
, 0xff55ffffU
, 0xffffffffU
2690 img
= de_bitmap_create(c
, 32, 32, 3);
2691 de_convert_image_paletted(c
->infile
, 3, 4, 16, pal
, img
, 0);
2692 de_bitmap_transpose(img
);
2693 de_bitmap_write_to_file(img
, NULL
, 0);
2694 de_bitmap_destroy(img
);
2697 static int de_identify_mdesk_icn(deark
*c
)
2699 if(c
->infile
->len
!=515) return 0;
2700 if(de_getu16be(0)!=0x1f1f) return 0;
2701 if(de_input_file_has_ext(c
, "icn") ||
2702 de_input_file_has_ext(c
, "tbi"))
2709 void de_module_mdesk_icn(deark
*c
, struct deark_module_info
*mi
)
2711 mi
->id
= "mdesk_icn";
2712 mi
->desc
= "Magic Desk icon";
2713 mi
->run_fn
= de_run_mdesk_icn
;
2714 mi
->identify_fn
= de_identify_mdesk_icn
;
2717 // **************************************************************************
2719 // **************************************************************************
2721 static void de_run_ttcomp(deark
*c
, de_module_params
*mparams
)
2724 struct de_dfilter_in_params dcmpri
;
2725 struct de_dfilter_out_params dcmpro
;
2726 struct de_dfilter_results dres
;
2728 outf
= dbuf_create_output_file(c
, "unc", NULL
, 0);
2729 de_dfilter_init_objects(c
, &dcmpri
, &dcmpro
, &dres
);
2730 dcmpri
.f
= c
->infile
;
2732 dcmpri
.len
= c
->infile
->len
;
2735 fmtutil_dclimplode_codectype1(c
, &dcmpri
, &dcmpro
, &dres
, NULL
);
2737 de_err(c
, "Decompression failed: %s", de_dfilter_get_errmsg(c
, &dres
));
2743 static int de_identify_ttcomp(deark
*c
)
2747 if(c
->infile
->len
<5) return 0;
2751 if(b1
<4 || b1
>6) return 0;
2753 // Look for the end-of-data code in the last 2 or 3 bytes.
2754 // Assumes the last byte is padded with '0' bits, and there are
2755 // no extraneous bytes after that.
2756 u32 x
= (u32
)de_getu32le(c
->infile
->len
-4);
2758 for(i
=0; i
<8; i
++) {
2759 if((x
& 0xfffffc00U
)==0x01fe0000U
) {
2760 if(b0
==0 && b1
==6) return 40;
2768 void de_module_ttcomp(deark
*c
, struct deark_module_info
*mi
)
2771 mi
->desc
= "TTComp";
2772 mi
->run_fn
= de_run_ttcomp
;
2773 mi
->identify_fn
= de_identify_ttcomp
;