zip: Better parsing of Info-ZIP type 1 extra field
[deark.git] / modules / misc.c
blob63353817373aeccd79e0fd377a145cc2f3ecb6d0
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 // **************************************************************************
56 // "copy" module
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)
68 mi->id = "copy";
69 mi->desc = "Copy the file unchanged";
70 mi->run_fn = de_run_copy;
73 // **************************************************************************
74 // "null" module
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)
86 mi->id = "null";
87 mi->desc = "Do nothing";
88 mi->run_fn = de_run_null;
89 mi->flags |= DE_MODFLAG_NOEXTRACT;
92 // **************************************************************************
93 // split
94 // Split the input file into equal-sized chunks.
95 // **************************************************************************
97 static void do_split_onechunk(deark *c, i64 chunknum, i64 offset, i64 size)
99 dbuf *outf = NULL;
100 char ext[32];
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);
105 dbuf_close(outf);
108 static void de_run_split(deark *c, de_module_params *mparams)
110 const char *s;
111 i64 pos;
112 i64 chunknum;
113 i64 chunksize, chunkstride;
114 i64 chunkcount;
116 s = de_get_ext_option(c, "split:size");
117 if(!s) {
118 de_err(c, "\"-opt split:size=<n>\" is required.");
119 goto done;
121 chunksize = de_atoi64(s);
122 if(chunksize<1) {
123 de_err(c, "Invalid chunk size");
124 goto done;
127 s = de_get_ext_option(c, "split:stride");
128 if(s) {
129 chunkstride = de_atoi64(s);
130 if(chunkstride<chunksize) {
131 de_err(c, "Stride must be "DE_CHAR_GEQ" size");
132 goto done;
135 else {
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);
144 goto done;
147 pos = 0;
148 for(chunknum = 0; chunknum<chunkcount; chunknum++) {
149 i64 this_chunk_size;
151 this_chunk_size = de_min_int(chunksize, c->infile->len-pos);
152 do_split_onechunk(c, chunknum, pos, this_chunk_size);
154 pos += chunkstride;
157 done:
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)
169 mi->id = "split";
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 // **************************************************************************
176 // plaintext
177 // Convert text files to UTF-8.
178 // **************************************************************************
180 struct plaintextctx_struct {
181 dbuf *outf;
182 de_ucstring *tmpstr;
183 struct de_encconv_state es;
186 static int plaintext_cbfn(struct de_bufferedreadctx *brctx, const u8 *buf,
187 i64 buf_len)
189 struct plaintextctx_struct *ptctx = (struct plaintextctx_struct*)brctx->userdata;
190 UI conv_flags;
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)
199 conv_flags = 0;
200 else
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,
205 &ptctx->es);
206 ucstring_write_as_utf8(brctx->c, ptctx->tmpstr, ptctx->outf, 0);
207 return 1;
210 static de_encoding get_bom_enc(deark *c, UI *blen)
212 u8 buf[3];
214 de_read(buf, 0, 3);
215 if(buf[0]==0xef && buf[1]==0xbb && buf[2]==0xbf) {
216 *blen = 3;
217 return DE_ENCODING_UTF8;
219 else if(buf[0]==0xfe && buf[1]==0xff) {
220 *blen = 2;
221 return DE_ENCODING_UTF16BE;
223 else if(buf[0]==0xff && buf[1]==0xfe) {
224 *blen = 2;
225 return DE_ENCODING_UTF16LE;
227 *blen = 0;
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;
237 i64 dpos, dlen;
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;
245 else {
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);
261 if(c->write_bom) {
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 // **************************************************************************
279 // CP437
280 // Convert CP437 text files to UTF-8.
281 // **************************************************************************
283 struct cp437ctx_struct {
284 dbuf *outf;
285 struct de_encconv_state es;
288 static int cp437_cbfn(struct de_bufferedreadctx *brctx, const u8 *buf,
289 i64 buf_len)
291 i32 u;
292 i64 i;
293 u8 ch;
294 struct cp437ctx_struct *cp437ctx = (struct cp437ctx_struct*)brctx->userdata;
296 for(i=0; i<buf_len; i++) {
297 ch = buf[i];
298 if(ch==0x09 || ch==0x0a || ch==0x0c || ch==0x0d) {
299 // Leave HT, NL, FF, CR as-is.
300 u = (i32)ch;
302 else if(ch==0x1a) {
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.
307 u = 0x2404;
309 else {
310 u = de_char_to_unicode_ex((i32)ch, &cp437ctx->es);
312 dbuf_write_uchar_as_utf8(cp437ctx->outf, u);
315 return 1;
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);
324 if(c->write_bom) {
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)
333 mi->id = "cp437";
334 mi->desc = "Code Page 437 text";
335 mi->run_fn = de_run_cp437;
338 // **************************************************************************
339 // crc
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;
347 u64 sum_of_bytes;
350 static int crc_cbfn(struct de_bufferedreadctx *brctx, const u8 *buf,
351 i64 buf_len)
353 struct crcctx_struct *crcctx = (struct crcctx_struct*)brctx->userdata;
354 i64 i;
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];
362 return 1;
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)
391 mi->id = "crc";
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 // **************************************************************************
399 // hexdump
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)
411 mi->id = "hexdump";
412 mi->desc = "Print a hex dump";
413 mi->run_fn = de_run_hexdump;
414 mi->flags |= DE_MODFLAG_NOEXTRACT;
417 // **************************************************************************
418 // bytefreq
419 // Prints a summary of how many times each byte value occurs.
420 // **************************************************************************
422 struct bytefreqentry {
423 i64 count;
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,
433 i64 buf_len)
435 i64 k;
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;
445 bf->count++;
447 return 1;
450 static void de_run_bytefreq(deark *c, de_module_params *mparams)
452 struct bytefreqctx_struct *bfctx = NULL;
453 de_ucstring *s = NULL;
454 unsigned int k;
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++) {
470 i32 ch;
471 int cflag;
472 unsigned int z;
473 struct bytefreqentry *bf = &bfctx->e[k];
475 if(bf->count==0) continue;
476 ucstring_empty(s);
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) {
482 cflag = 0;
484 else {
485 cflag = de_is_printable_uchar(ch);
488 if(cflag) {
489 ucstring_append_sz(s, "'", DE_ENCODING_LATIN1);
490 ucstring_append_char(s, ch);
491 ucstring_append_sz(s, "'", DE_ENCODING_LATIN1);
493 else {
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]);
501 if(z<bf->count-1) {
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);
512 ucstring_destroy(s);
513 de_free(c, bfctx);
516 void de_module_bytefreq(deark *c, struct deark_module_info *mi)
518 mi->id = "bytefreq";
519 mi->desc = "Print a byte frequence analysis";
520 mi->run_fn = de_run_bytefreq;
521 mi->flags |= DE_MODFLAG_NOEXTRACT;
524 // **************************************************************************
525 // zlib module
527 // This module is for decompressing zlib-compressed files.
528 // **************************************************************************
530 static void de_run_zlib(deark *c, de_module_params *mparams)
532 dbuf *f = NULL;
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);
536 dbuf_close(f);
539 static int de_identify_zlib(deark *c)
541 u8 b[2];
542 de_read(b, 0, 2);
544 if((b[0]&0x0f) != 8)
545 return 0;
547 if(b[0]<0x08 || b[0]>0x78)
548 return 0;
550 if(((((unsigned int)b[0])<<8)|b[1])%31 != 0)
551 return 0;
553 return 50;
556 void de_module_zlib(deark *c, struct deark_module_info *mi)
558 mi->id = "zlib";
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)
570 i64 width, height;
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)
580 u8 b[8];
581 de_read(b, 0, 8);
582 if(!de_memcmp(b, "\x01\x00\x01\x00\x2c\x00\x20\x00", 8))
583 return 100;
584 if(!de_memcmp(b, "\x01\x00\x01\x00", 4))
585 return 60;
586 return 0;
589 void de_module_hpicn(deark *c, struct deark_module_info *mi)
591 mi->id = "hpicn";
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 // **************************************************************************
603 struct xpuzzctx {
604 i64 w, h;
605 i64 palentries;
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;
615 return 1;
618 static void de_run_xpuzzle(deark *c, de_module_params *mparams)
620 struct xpuzzctx *d = NULL;
621 de_bitmap *img = NULL;
622 u32 pal[256];
623 i64 p;
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);
631 // Read the palette
632 de_zeromem(pal, sizeof(pal));
633 p = 9;
634 de_read_palette_rgb(c->infile, p, d->palentries, 3, pal, 256, 0);
635 p += 3*d->palentries;
637 // Read the bitmap
638 de_convert_image_paletted(c->infile, p, 8, d->w, pal, img, 0);
640 de_bitmap_write_to_file(img, NULL, 0);
642 done:
643 de_bitmap_destroy(img);
644 de_free(c, d);
647 static int de_identify_xpuzzle(deark *c)
649 struct xpuzzctx *d = NULL;
650 int retval = 0;
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) {
657 retval = 20;
660 done:
661 de_free(c, d);
662 return retval;
665 void de_module_xpuzzle(deark *c, struct deark_module_info *mi)
667 mi->id = "xpuzzle";
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)
679 u8 buf[256];
680 i64 xorsize;
681 i64 i;
682 dbuf *f = NULL;
684 xorsize = c->infile->len >= 256 ? 256 : c->infile->len;
685 de_read(buf, 0, xorsize);
686 for(i=0; i<xorsize; i++) {
687 buf[i] ^= 0x0d;
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);
695 dbuf_close(f);
698 static int de_identify_winzle(deark *c)
700 u8 b[18];
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) {
705 return 95;
707 return 40;
709 return 0;
712 void de_module_winzle(deark *c, struct deark_module_info *mi)
714 mi->id = "winzle";
715 mi->desc = "Winzle! puzzle image";
716 mi->run_fn = de_run_winzle;
717 mi->identify_fn = de_identify_winzle;
720 // **************************************************************************
721 // Minolta RAW (MRW)
722 // **************************************************************************
724 static void do_mrw_seg_list(deark *c, i64 pos1, i64 len)
726 i64 pos;
727 u8 seg_id[4];
728 i64 data_len;
730 pos = pos1;
731 while(pos < pos1+len) {
732 de_read(seg_id, pos, 4);
733 data_len = de_getu32be(pos+4);
734 pos+=8;
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);
739 pos+=data_len;
743 static void de_run_mrw(deark *c, de_module_params *mparams)
745 i64 mrw_seg_size;
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))
754 return 100;
755 return 0;
758 void de_module_mrw(deark *c, struct deark_module_info *mi)
760 mi->id = "mrw";
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;
775 i64 w, h;
776 u32 pal[256];
777 i64 p;
779 w = de_getu16le(0);
780 h = de_getu16le(2);
781 if(!de_good_image_dimensions(c, w, h)) goto done;
782 img = de_bitmap_create(c, w, h, 3);
784 // Read the palette
785 de_zeromem(pal, sizeof(pal));
786 p = 4;
787 de_read_palette_rgb(c->infile, p, 256, 3, pal, 256, 0);
788 p += 256*3;
790 // Read the bitmap
791 de_convert_image_paletted(c->infile, p, 8, w, pal, img, 0);
793 de_bitmap_write_to_file(img, NULL, 0);
795 done:
796 de_bitmap_destroy(img);
799 static int de_identify_bob(deark *c)
801 i64 w, h;
803 if(!de_input_file_has_ext(c, "bob")) return 0;
805 w = de_getu16le(0);
806 h = de_getu16le(2);
807 if(c->infile->len == 4 + 768 + w*h) {
808 return 100;
810 return 0;
813 void de_module_bob(deark *c, struct deark_module_info *mi)
815 mi->id = "bob";
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;
829 i64 w, h;
830 i64 i;
831 i64 pos;
832 i64 firstline;
833 i64 depth;
834 i64 xpos, ypos;
835 i64 runlen;
836 u32 clr;
838 w = de_getu16be(0);
839 h = de_getu16be(2);
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;
845 if(depth!=24) {
846 de_err(c, "Unsupported image type");
847 goto done;
850 img = de_bitmap_create(c, w, h, 3);
852 pos = 10;
853 xpos = 0;
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.
856 ypos = firstline;
857 while(1) {
858 if(pos+4 > c->infile->len) {
859 break; // EOF
861 runlen = (i64)de_getbyte(pos);
862 clr = dbuf_getRGB(c->infile, pos+1, DE_GETRGBFLAG_BGR);
863 pos+=4;
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
870 if(xpos >= w) {
871 xpos=0;
872 ypos++;
876 de_bitmap_write_to_file(img, NULL, 0);
877 done:
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"))
889 return 0;
892 w = de_getu16be(0);
893 h = de_getu16be(2);
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;
903 return 30;
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)
922 switch(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;
942 return 0xff;
945 static void de_run_applevol(deark *c, de_module_params *mparams)
947 de_bitmap *img = NULL;
948 i64 w, h;
949 i64 i, j;
950 i64 p;
951 u8 palent;
953 w = de_getu16be(1);
954 h = de_getu16be(3);
955 if(!de_good_image_dimensions(c, w, h)) goto done;
956 img = de_bitmap_create(c, w, h, 1);
958 p = 5;
959 for(j=0; j<h; j++) {
960 for(i=0; i<w; i++) {
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);
968 done:
969 de_bitmap_destroy(img);
972 static int de_identify_applevol(deark *c)
974 u8 buf[5];
976 de_read(buf, 0, sizeof(buf));
978 if(buf[0]==0x01 && buf[3]==0x00 && buf[4]==0x0c)
979 return 20;
980 return 0;
983 void de_module_applevol(deark *c, struct deark_module_info *mi)
985 mi->id = "applevol";
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;
998 de_finfo *fi = 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;
1017 return 0;
1020 void de_module_hr(deark *c, struct deark_module_info *mi)
1022 mi->id = "hr";
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)
1038 i64 width, height;
1039 de_bitmap *img = NULL;
1040 i64 chunk_span;
1041 i64 src_rowspan;
1042 i64 bitmap_len;
1043 i64 i, j, k;
1044 i64 pos = pos1;
1045 u8 x;
1046 u32 palent;
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
1072 palent = 0;
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);
1083 done:
1084 if(img) de_bitmap_destroy(img);
1085 de_dbg_indent_restore(c, saved_indent_level);
1086 return 1;
1089 static void de_run_ripicon(deark *c, de_module_params *mparams)
1091 i64 pos = 0;
1093 while(1) {
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)
1103 int has_ext = 0;
1104 i64 pos = 0;
1105 size_t i;
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])) {
1110 has_ext = 1;
1111 break;
1114 if(!has_ext) return 0;
1116 while(1) {
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;
1123 return 0;
1126 void de_module_ripicon(deark *c, struct deark_module_info *mi)
1128 mi->id = "ripicon";
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 // **************************************************************************
1138 struct lss16ctx {
1139 i64 pos;
1140 int nextnibble_valid;
1141 u8 nextnibble;
1144 static u8 lss16_get_nibble(deark *c, struct lss16ctx *d)
1146 u8 n;
1147 if(d->nextnibble_valid) {
1148 d->nextnibble_valid = 0;
1149 return d->nextnibble;
1151 n = de_getbyte(d->pos);
1152 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;
1157 return n&0x0f;
1160 static void de_run_lss16(deark *c, de_module_params *mparams)
1162 struct lss16ctx *d = NULL;
1163 de_bitmap *img = NULL;
1164 i64 width, height;
1165 i64 i;
1166 i64 xpos, ypos;
1167 u8 n;
1168 u8 prev;
1169 i64 run_len;
1170 u8 cr1, cg1, cb1;
1171 u8 cr2, cg2, cb2;
1172 u32 pal[16];
1173 char tmps[64];
1175 d = de_malloc(c, sizeof(struct lss16ctx));
1177 d->pos = 4;
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;
1183 d->pos += 4;
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);
1196 d->pos+=3;
1199 img = de_bitmap_create(c, width, height, 3);
1201 xpos=0; ypos=0;
1202 prev=0;
1203 while(d->pos<c->infile->len && ypos<height) {
1204 n = lss16_get_nibble(c, d);
1206 if(n == prev) {
1207 // A run of pixels
1208 run_len = (i64)lss16_get_nibble(c, d);
1209 if(run_len==0) {
1210 run_len = lss16_get_nibble(c, d);
1211 run_len |= ((i64)lss16_get_nibble(c, d)<<4);
1212 run_len += 16;
1214 for(i=0; i<run_len; i++) {
1215 de_bitmap_setpixel_rgb(img, xpos, ypos, pal[prev]);
1216 xpos++;
1219 else {
1220 // An uncompressed pixel
1221 de_bitmap_setpixel_rgb(img, xpos, ypos, pal[n]);
1222 xpos++;
1223 prev = n;
1226 // End of row reached?
1227 if(xpos>=width) {
1228 xpos=0;
1229 ypos++;
1230 d->nextnibble_valid = 0;
1231 prev = 0;
1235 de_bitmap_write_to_file(img, NULL, 0);
1236 done:
1237 de_bitmap_destroy(img);
1238 de_free(c, d);
1241 static int de_identify_lss16(deark *c)
1243 if(!dbuf_memcmp(c->infile, 0, "\x3d\xf3\x13\x14", 4))
1244 return 100;
1245 return 0;
1248 void de_module_lss16(deark *c, struct deark_module_info *mi)
1250 mi->id = "lss16";
1251 mi->desc = "SYSLINUX LSS16 image";
1252 mi->run_fn = de_run_lss16;
1253 mi->identify_fn = de_identify_lss16;
1256 // **************************************************************************
1257 // VBM (VDC BitMap)
1258 // **************************************************************************
1260 static void de_run_vbm(deark *c, de_module_params *mparams)
1262 i64 width, height;
1263 u8 ver;
1265 ver = de_getbyte(3);
1266 if(ver!=2) {
1267 // TODO: Support VBM v3.
1268 de_err(c, "Unsupported VBM version (%d)", (int)ver);
1269 return;
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)
1280 u8 b[4];
1281 de_read(b, 0, 4);
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;
1285 return 80;
1288 void de_module_vbm(deark *c, struct deark_module_info *mi)
1290 mi->id = "vbm";
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)
1302 i64 width, height;
1303 i64 rowspan;
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)
1313 i64 width, height;
1314 i64 rowspan;
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) {
1322 return 100;
1325 return 0;
1328 void de_module_fp_art(deark *c, struct deark_module_info *mi)
1330 mi->id = "fp_art";
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 // **************************************************************************
1337 // YBM
1338 // **************************************************************************
1340 static void de_run_ybm(deark *c, de_module_params *mparams)
1342 de_bitmap *img = NULL;
1343 i64 npwidth, pdwidth, height;
1344 i64 i, j;
1345 i64 words_per_row;
1346 i64 pos;
1348 pos = 2;
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++) {
1360 u8 x;
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);
1373 done:
1374 de_bitmap_destroy(img);
1377 static int de_identify_ybm(deark *c)
1379 i64 width, height;
1380 i64 rowspan;
1382 if(dbuf_memcmp(c->infile, 0, "!!", 2))
1383 return 0;
1384 width = de_getu16be(2);
1385 height = de_getu16be(4);
1386 rowspan = ((width+15)/16)*2;
1387 if(6+height*rowspan == c->infile->len)
1388 return 100;
1389 return 0;
1392 void de_module_ybm(deark *c, struct deark_module_info *mi)
1394 mi->id = "ybm";
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;
1407 i64 width, height;
1408 i64 i, j;
1409 i64 rowspan;
1410 u8 b0, b1;
1411 u32 clr;
1413 width = de_getu16le(4);
1414 height = de_getu16le(6);
1415 if(!de_good_image_dimensions(c, width, height)) goto done;
1416 rowspan = width*2;
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);
1431 done:
1432 de_bitmap_destroy(img);
1435 static int de_identify_olpc565(deark *c)
1437 if(!dbuf_memcmp(c->infile, 0, "C565", 4))
1438 return 100;
1439 return 0;
1442 void de_module_olpc565(deark *c, struct deark_module_info *mi)
1444 mi->id = "olpc565";
1445 mi->desc = "OLPC .565 firmware icon";
1446 mi->run_fn = de_run_olpc565;
1447 mi->identify_fn = de_identify_olpc565;
1450 // **************************************************************************
1451 // InShape .IIM
1452 // **************************************************************************
1454 static void de_run_iim(deark *c, de_module_params *mparams)
1456 de_bitmap *img = NULL;
1457 i64 width, height;
1458 i64 i, j;
1459 i64 n, bpp;
1460 i64 rowspan;
1461 u32 clr;
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");
1469 goto done;
1471 width = de_getu16be(12);
1472 height = de_getu16be(14);
1473 if(!de_good_image_dimensions(c, width, height)) goto done;
1474 rowspan = width*3;
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);
1486 done:
1487 de_bitmap_destroy(img);
1490 static int de_identify_iim(deark *c)
1492 if(!dbuf_memcmp(c->infile, 0, "IS_IMAGE", 8))
1493 return 100;
1494 return 0;
1497 void de_module_iim(deark *c, struct deark_module_info *mi)
1499 mi->id = "iim";
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;
1512 int is_le;
1513 i64 width, height;
1514 i64 nplanes;
1515 i64 nbands;
1516 i64 pixelformat;
1517 i64 commentsize;
1518 i64 i, j;
1519 i64 plane;
1520 i64 rowspan;
1521 i64 planespan;
1522 i64 pos;
1523 u8 b;
1525 if(!dbuf_memcmp(c->infile, 0, "WEIV", 4))
1526 is_le = 1;
1527 else
1528 is_le = 0;
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);
1547 pos = 28;
1549 if((pixelformat==0x8001 && nplanes==3 && nbands==1) ||
1550 (pixelformat==0x8001 && nplanes==1 && nbands==1))
1554 else {
1555 de_err(c, "Unsupported image type (pixel format=0x%04x, "
1556 "planes=%d, bands=%d)", (unsigned int)pixelformat,
1557 (int)nplanes, (int)nbands);
1558 goto done;
1561 rowspan = width;
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);
1570 if(nplanes==3) {
1571 de_bitmap_setsample(img, i, j, plane, b);
1573 else {
1574 de_bitmap_setpixel_gray(img, i, j, b);
1579 de_bitmap_write_to_file(img, NULL, 0);
1581 done:
1582 de_bitmap_destroy(img);
1585 static int de_identify_pm_xv(deark *c)
1587 if(!dbuf_memcmp(c->infile, 0, "VIEW", 4))
1588 return 15;
1589 if(!dbuf_memcmp(c->infile, 0, "WEIV", 4))
1590 return 15;
1591 return 0;
1594 void de_module_pm_xv(deark *c, struct deark_module_info *mi)
1596 mi->id = "pm_xv";
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)
1611 i64 width, height;
1612 i64 rowspan;
1613 i64 pos;
1614 u8 b1, b2;
1615 i64 count;
1616 i64 cmpr_img_start;
1617 i64 num_cmpr_bytes;
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);
1626 if(b1!=0x01) {
1627 de_err(c, "Unsupported CRG format");
1628 goto done;
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
1647 count = 1+(i64)b1;
1648 dbuf_copy(c->infile, pos, count, unc_pixels);
1649 pos += count;
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);
1662 done:
1663 dbuf_close(unc_pixels);
1666 static int de_identify_crg(deark *c)
1668 if(!dbuf_memcmp(c->infile, 0, "CALAMUSCRG", 10))
1669 return 100;
1670 return 0;
1673 void de_module_crg(deark *c, struct deark_module_info *mi)
1675 mi->id = "crg";
1676 mi->desc = "Calamus Raster Graphic";
1677 mi->run_fn = de_run_crg;
1678 mi->identify_fn = de_identify_crg;
1681 // **************************************************************************
1682 // farbfeld
1683 // **************************************************************************
1685 static void de_run_farbfeld(deark *c, de_module_params *mparams)
1687 de_bitmap *img = NULL;
1688 i64 width, height;
1689 i64 i, j, k;
1690 i64 ppos;
1691 u8 s[4];
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))
1717 return 100;
1718 return 0;
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;
1737 i64 i;
1738 i64 height;
1740 if(c->infile->len==16*256) {
1741 height = 16;
1743 else if(c->infile->len==14*256) {
1744 height = 14;
1746 else {
1747 de_err(c, "Bad file size");
1748 goto done;
1751 fontdata = de_malloc(c, height*256);
1752 de_read(fontdata, 0, height*256);
1754 if(de_get_ext_option(c, "vgafont:c")) {
1755 dbuf *ff;
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");
1763 dbuf_close(ff);
1764 goto done;
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);
1786 done:
1787 if(font) {
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)
1801 mi->id = "vgafont";
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)
1814 i64 w, h;
1815 i64 num_pal_colors;
1816 i64 pos;
1817 i64 ver;
1818 i64 hdpi, vdpi;
1819 i64 cmpr;
1820 i64 alpha_info;
1821 de_bitmap *img = NULL;
1822 u32 pal[256];
1823 int is_grayscale;
1825 ver = de_getu16be(6);
1826 de_dbg(c, "version: %d", (int)ver);
1827 if(ver!=4) {
1828 de_warn(c, "HSI Raw version %d might not be supported correctly", (int)ver);
1831 w = de_getu16be(8);
1832 if(w==0) {
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);
1845 // [18: Gamma]
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");
1853 goto done;
1855 if(!de_good_image_dimensions(c, w, h)) goto done;
1857 pos = 32;
1858 de_zeromem(pal, sizeof(pal));
1859 if(num_pal_colors==0) { // 24-bit RGB
1860 is_grayscale = 0;
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);
1873 else {
1874 de_convert_image_paletted(c->infile, pos, 8, w, pal, img, 0);
1877 de_bitmap_write_to_file(img, NULL, 0);
1879 done:
1880 de_bitmap_destroy(img);
1883 static int de_identify_hsiraw(deark *c)
1885 if(!dbuf_memcmp(c->infile, 0, "mhwanh", 6))
1886 return 100;
1887 return 0;
1890 void de_module_hsiraw(deark *c, struct deark_module_info *mi)
1892 mi->id = "hsiraw";
1893 mi->desc = "HSI Raw";
1894 mi->run_fn = de_run_hsiraw;
1895 mi->identify_fn = de_identify_hsiraw;
1898 // **************************************************************************
1899 // QDV (Giffer)
1900 // **************************************************************************
1902 static void de_run_qdv(deark *c, de_module_params *mparams)
1904 i64 w, h;
1905 i64 num_pal_colors;
1906 i64 pos;
1907 de_bitmap *img = NULL;
1908 u32 pal[256];
1910 // Warning: This decoder is based on reverse engineering, and may be
1911 // incorrect or incomplete.
1913 w = de_getu16be(0);
1914 h = de_getu16be(2);
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);
1921 pos = 5;
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);
1930 done:
1931 de_bitmap_destroy(img);
1934 static int de_identify_qdv(deark *c)
1936 i64 w, h;
1937 i64 num_pal_colors;
1939 w = de_getu16be(0);
1940 h = de_getu16be(2);
1941 num_pal_colors = 1 + (i64)de_getbyte(4);
1942 if(5+num_pal_colors*3+w*h != c->infile->len)
1943 return 0;
1944 if(de_input_file_has_ext(c, "qdv"))
1945 return 100;
1946 return 30;
1949 void de_module_qdv(deark *c, struct deark_module_info *mi)
1951 mi->id = "qdv";
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;
1964 i64 i, j, plane;
1965 de_bitmap *img = NULL;
1966 i64 samplesperpixel;
1967 i64 rowspan, planespan;
1968 i64 pos;
1969 u8 b;
1970 i64 h1size, h2size;
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.");
1978 pos = 4;
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.
1982 pos += h1size;
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);
2003 goto done;
2006 pos += h2size;
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);
2013 rowspan = pdwidth;
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);
2023 else {
2024 de_bitmap_setpixel_gray(img, i, j, b);
2030 de_bitmap_write_to_file(img, NULL, 0);
2032 done:
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))
2040 return 100;
2041 return 0;
2044 void de_module_vitec(deark *c, struct deark_module_info *mi)
2046 mi->id = "vitec";
2047 mi->desc = "VITec image format";
2048 mi->run_fn = de_run_vitec;
2049 mi->identify_fn = de_identify_vitec;
2052 // **************************************************************************
2053 // HS2 module
2055 // .HS2 format is associated with a program called POSTERING.
2056 // **************************************************************************
2058 static void de_run_hs2(deark *c, de_module_params *mparams)
2060 i64 width, height;
2061 i64 rowspan;
2063 rowspan = 105;
2064 width = rowspan*8;
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)) {
2073 return 15;
2075 return 0;
2078 void de_module_hs2(deark *c, struct deark_module_info *mi)
2080 mi->id = "hs2";
2081 mi->desc = "HS2 (POSTERING)";
2082 mi->run_fn = de_run_hs2;
2083 mi->identify_fn = de_identify_hs2;
2087 // **************************************************************************
2088 // Lumena CEL
2089 // **************************************************************************
2091 static void de_run_lumena_cel(deark *c, de_module_params *mparams)
2093 i64 width, height;
2094 i64 rowspan;
2095 i64 i, j;
2096 u32 clr;
2097 u8 a;
2098 int is_16bit = 0;
2099 int is_32bit = 0;
2100 de_bitmap *img = NULL;
2101 const i64 headersize = 4;
2102 i64 bypp;
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");
2113 is_32bit = 1;
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;
2125 if(is_32bit) {
2126 clr = dbuf_getRGB(c->infile, pos, 0);
2127 a = de_getbyte(pos + 3);
2128 clr = DE_SET_ALPHA(clr, a);
2130 else {
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);
2141 done:
2142 de_bitmap_destroy(img);
2145 static int de_identify_lumena_cel(deark *c)
2147 i64 width, height;
2148 int is_16bit = 0;
2149 int is_32bit = 0;
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)
2159 return 60;
2161 return 0;
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)
2178 i64 pos = 0;
2179 dbuf *outf = NULL;
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);
2195 dbuf_close(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;
2202 return 25;
2204 return 0;
2207 void de_module_zbr(deark *c, struct deark_module_info *mi)
2209 mi->id = "zbr";
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)
2222 u8 version;
2223 u8 b;
2224 i64 w, h;
2225 i64 rowspan;
2226 i64 pos = 0;
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.
2241 pos += 2;
2242 pos += 2;
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
2248 if(b!=1) goto done;
2249 b = de_getbyte_p(&pos); // bits/pixel
2250 if(b!=1) goto done;
2251 pos += 4; // bmBits
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);
2258 done:
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;
2267 return 6;
2269 return 0;
2272 void de_module_cdr_wl(deark *c, struct deark_module_info *mi)
2274 mi->id = "cdr_wl";
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 // **************************************************************************
2282 // compress (.Z)
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;
2291 dbuf *f = NULL;
2293 f = dbuf_create_output_file(c, "bin", NULL, 0);
2295 de_dfilter_init_objects(c, &dcmpri, &dcmpro, &dres);
2296 dcmpri.f = c->infile;
2297 dcmpri.pos = 0;
2298 dcmpri.len = c->infile->len;
2299 dcmpro.f = f;
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));
2310 dbuf_close(f);
2313 static int de_identify_compress(deark *c)
2315 if(!dbuf_memcmp(c->infile, 0, "\x1f\x9d", 2))
2316 return 100;
2317 return 0;
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;
2335 u8 v1, v2;
2336 i64 w, h;
2337 i64 pos;
2338 de_encoding encoding;
2339 de_ucstring *s = NULL;
2340 u32 pal[256];
2342 // This code is based on reverse engineering, and may be incorrect.
2343 encoding = de_get_input_encoding(c, NULL, DE_ENCODING_WINDOWS1252);
2344 pos = 4;
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));
2354 ucstring_empty(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));
2358 pos = 264;
2359 de_dbg(c, "image at %"I64_FMT, pos);
2360 w = 96;
2361 h = 96;
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,
2369 0xc3c3c3,0xffffff};
2370 unsigned int k;
2372 for(k=0; k<=250; k++) {
2373 pal[k] = DE_MAKE_RGB(
2374 rbvals[k%6],
2375 gvals[(k%42)/6],
2376 rbvals[k/42]);
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
2384 unsigned int k;
2386 for(k=0; k<256; k++) {
2387 u8 r, g, b;
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;
2406 return 0;
2409 void de_module_gws_thn(deark *c, struct deark_module_info *mi)
2411 mi->id = "gws_thn";
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)
2423 i64 w, h;
2424 i64 rowspan;
2425 i64 pos = 0;
2426 int k;
2427 int is_compressed;
2428 de_bitmap *img = NULL;
2429 dbuf *unc_pixels = NULL;
2430 i64 unc_pixels_size;
2431 u32 pal[16];
2433 pos += 22;
2434 de_dbg(c, "image at %"I64_FMT, pos);
2435 w = 312;
2436 h = 176;
2437 rowspan = w/2;
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);
2447 if(is_compressed) {
2448 unc_pixels = dbuf_create_membuf(c, unc_pixels_size, 0x1);
2449 while(1) {
2450 i64 count;
2451 u8 val;
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);
2460 else {
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;
2475 return 0;
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
2492 // be correct.
2494 static void de_run_corel_bmf(deark *c, de_module_params *mparams1)
2496 de_module_params *mparams2 = NULL;
2497 int saved_indent_level;
2498 i64 pos;
2499 i64 n;
2500 i64 seg_size;
2502 de_dbg_indent_save(c, &saved_indent_level);
2503 pos = 65;
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);
2513 if(n!=40) {
2514 de_err(c, "Unsupported Corel BMF version");
2515 goto done;
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);
2523 done:
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;
2531 return 0;
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)
2548 i64 jpgpos, pngpos;
2549 i64 jpglen, pnglen;
2550 i64 pos;
2552 pos = 12;
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) {
2561 const char *ext;
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;
2575 return 0;
2578 void de_module_hpi(deark *c, struct deark_module_info *mi)
2580 mi->id = "hpi";
2581 mi->desc = "Hemera Photo-Object image";
2582 mi->run_fn = de_run_hpi;
2583 mi->identify_fn = de_identify_hpi;
2586 // **************************************************************************
2587 // DWC archive
2588 // **************************************************************************
2590 struct dwc_member_data {
2591 de_ucstring *fn;
2592 i64 unclen, cmprlen;
2593 i64 cmprdatapos;
2594 u8 cmpr_meth;
2597 static void do_dwc_member(deark *c, i64 pos1)
2599 i64 pos = 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));
2609 pos += 13;
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);
2619 // pos += 2; // ?
2620 // pos += 2; // CRC
2621 de_dbg_indent(c, -1);
2622 if(md) {
2623 ucstring_destroy(md->fn);
2624 de_free(c, md);
2628 static void de_run_dwc(deark *c, de_module_params *mparams)
2630 i64 trailer_pos;
2631 i64 nmembers;
2632 i64 fhsize; // size of each file header
2633 i64 pos;
2634 i64 i;
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;
2638 pos = trailer_pos;
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);
2643 pos += 16;
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);
2652 pos += fhsize;
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)) {
2660 return 0;
2662 if(de_getu16le(c->infile->len-27) != 27) {
2663 return 0;
2665 return 70;
2668 void de_module_dwc(deark *c, struct deark_module_info *mi)
2670 mi->id = "dwc";
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"))
2704 return 90;
2706 return 20;
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 // **************************************************************************
2718 // TTComp
2719 // **************************************************************************
2721 static void de_run_ttcomp(deark *c, de_module_params *mparams)
2723 dbuf *outf = NULL;
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;
2731 dcmpri.pos = 0;
2732 dcmpri.len = c->infile->len;
2733 dcmpro.f = outf;
2735 fmtutil_dclimplode_codectype1(c, &dcmpri, &dcmpro, &dres, NULL);
2736 if(dres.errcode) {
2737 de_err(c, "Decompression failed: %s", de_dfilter_get_errmsg(c, &dres));
2740 dbuf_close(outf);
2743 static int de_identify_ttcomp(deark *c)
2745 u8 b0, b1;
2747 if(c->infile->len<5) return 0;
2748 b0 = de_getbyte(0);
2749 if(b0>1) return 0;
2750 b1 = de_getbyte(1);
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);
2757 int i;
2758 for(i=0; i<8; i++) {
2759 if((x & 0xfffffc00U)==0x01fe0000U) {
2760 if(b0==0 && b1==6) return 40;
2761 return 10;
2763 x >>= 1;
2765 return 0;
2768 void de_module_ttcomp(deark *c, struct deark_module_info *mi)
2770 mi->id = "ttcomp";
2771 mi->desc = "TTComp";
2772 mi->run_fn = de_run_ttcomp;
2773 mi->identify_fn = de_identify_ttcomp;