arc.c: Rearranged some functions
[deark.git] / modules / misc.c
blob3e8afe29ef03b626be83bba07e504c701d633340
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 rowspan;
1346 u8 x;
1348 npwidth = de_getu16be(2);
1349 height = de_getu16be(4);
1350 de_dbg_dimensions(c, npwidth, height);
1351 if(!de_good_image_dimensions(c, npwidth, height)) goto done;
1352 pdwidth = de_pad_to_n(npwidth, 16);
1353 rowspan = pdwidth/8;
1355 img = de_bitmap_create2(c, npwidth, pdwidth, height, 1);
1357 for(j=0; j<height; j++) {
1358 for(i=0; i<pdwidth; i++) {
1359 // This encoding is unusual: LSB-first 16-bit integers.
1360 x = de_get_bits_symbol(c->infile, 1, 6 + j*rowspan,
1361 (i-i%16) + (15-i%16));
1362 de_bitmap_setpixel_gray(img, i, j, x ? 0 : 255);
1365 de_bitmap_write_to_file(img, NULL, 0);
1367 done:
1368 de_bitmap_destroy(img);
1371 static int de_identify_ybm(deark *c)
1373 i64 width, height;
1374 i64 rowspan;
1376 if(dbuf_memcmp(c->infile, 0, "!!", 2))
1377 return 0;
1378 width = de_getu16be(2);
1379 height = de_getu16be(4);
1380 rowspan = ((width+15)/16)*2;
1381 if(6+height*rowspan == c->infile->len)
1382 return 100;
1383 return 0;
1386 void de_module_ybm(deark *c, struct deark_module_info *mi)
1388 mi->id = "ybm";
1389 mi->desc = "Bennet Yee's face format, a.k.a. YBM";
1390 mi->run_fn = de_run_ybm;
1391 mi->identify_fn = de_identify_ybm;
1394 // **************************************************************************
1395 // OLPC .565 firmware icon
1396 // **************************************************************************
1398 static void de_run_olpc565(deark *c, de_module_params *mparams)
1400 de_bitmap *img = NULL;
1401 i64 width, height;
1402 i64 i, j;
1403 i64 rowspan;
1404 u8 b0, b1;
1405 u32 clr;
1407 width = de_getu16le(4);
1408 height = de_getu16le(6);
1409 if(!de_good_image_dimensions(c, width, height)) goto done;
1410 rowspan = width*2;
1412 img = de_bitmap_create(c, width, height, 3);
1414 for(j=0; j<height; j++) {
1415 for(i=0; i<width; i++) {
1416 b0 = de_getbyte(8 + j*rowspan + i*2);
1417 b1 = de_getbyte(8 + j*rowspan + i*2 + 1);
1418 clr = (((u32)b1)<<8) | b0;
1419 clr = de_rgb565_to_888(clr);
1420 de_bitmap_setpixel_rgb(img, i, j, clr);
1423 de_bitmap_write_to_file(img, NULL, 0);
1425 done:
1426 de_bitmap_destroy(img);
1429 static int de_identify_olpc565(deark *c)
1431 if(!dbuf_memcmp(c->infile, 0, "C565", 4))
1432 return 100;
1433 return 0;
1436 void de_module_olpc565(deark *c, struct deark_module_info *mi)
1438 mi->id = "olpc565";
1439 mi->desc = "OLPC .565 firmware icon";
1440 mi->run_fn = de_run_olpc565;
1441 mi->identify_fn = de_identify_olpc565;
1444 // **************************************************************************
1445 // InShape .IIM
1446 // **************************************************************************
1448 static void de_run_iim(deark *c, de_module_params *mparams)
1450 de_bitmap *img = NULL;
1451 i64 width, height;
1452 i64 i, j;
1453 i64 n, bpp;
1454 i64 rowspan;
1455 u32 clr;
1457 // This code is based on reverse engineering, and may be incorrect.
1459 n = de_getu16be(8); // Unknown field
1460 bpp = de_getu16be(10);
1461 if(n!=4 || bpp!=24) {
1462 de_dbg(c, "This type of IIM image is not supported");
1463 goto done;
1465 width = de_getu16be(12);
1466 height = de_getu16be(14);
1467 if(!de_good_image_dimensions(c, width, height)) goto done;
1468 rowspan = width*3;
1470 img = de_bitmap_create(c, width, height, 3);
1472 for(j=0; j<height; j++) {
1473 for(i=0; i<width; i++) {
1474 clr = dbuf_getRGB(c->infile, 16+j*rowspan+i*3, 0);
1475 de_bitmap_setpixel_rgb(img, i, j, clr);
1478 de_bitmap_write_to_file(img, NULL, 0);
1480 done:
1481 de_bitmap_destroy(img);
1484 static int de_identify_iim(deark *c)
1486 if(!dbuf_memcmp(c->infile, 0, "IS_IMAGE", 8))
1487 return 100;
1488 return 0;
1491 void de_module_iim(deark *c, struct deark_module_info *mi)
1493 mi->id = "iim";
1494 mi->desc = "InShape IIM";
1495 mi->run_fn = de_run_iim;
1496 mi->identify_fn = de_identify_iim;
1499 // **************************************************************************
1500 // PM (format supported by the XV image viewer)
1501 // **************************************************************************
1503 static void de_run_pm_xv(deark *c, de_module_params *mparams)
1505 de_bitmap *img = NULL;
1506 int is_le;
1507 i64 width, height;
1508 i64 nplanes;
1509 i64 nbands;
1510 i64 pixelformat;
1511 i64 commentsize;
1512 i64 i, j;
1513 i64 plane;
1514 i64 rowspan;
1515 i64 planespan;
1516 i64 pos;
1517 u8 b;
1519 if(!dbuf_memcmp(c->infile, 0, "WEIV", 4))
1520 is_le = 1;
1521 else
1522 is_le = 0;
1524 nplanes = dbuf_geti32x(c->infile, 4, is_le);
1525 de_dbg(c, "planes: %d", (int)nplanes);
1527 height = dbuf_geti32x(c->infile, 8, is_le);
1528 width = dbuf_geti32x(c->infile, 12, is_le);
1529 de_dbg_dimensions(c, width, height);
1530 if(!de_good_image_dimensions(c, width, height)) goto done;
1532 nbands = dbuf_geti32x(c->infile, 16, is_le);
1533 de_dbg(c, "bands: %d", (int)nbands);
1535 pixelformat = dbuf_geti32x(c->infile, 20, is_le);
1536 de_dbg(c, "pixel format: 0x%04x", (unsigned int)pixelformat);
1538 commentsize = dbuf_geti32x(c->infile, 24, is_le);
1539 de_dbg(c, "comment size: %d", (int)commentsize);
1541 pos = 28;
1543 if((pixelformat==0x8001 && nplanes==3 && nbands==1) ||
1544 (pixelformat==0x8001 && nplanes==1 && nbands==1))
1548 else {
1549 de_err(c, "Unsupported image type (pixel format=0x%04x, "
1550 "planes=%d, bands=%d)", (unsigned int)pixelformat,
1551 (int)nplanes, (int)nbands);
1552 goto done;
1555 rowspan = width;
1556 planespan = rowspan*height;
1558 img = de_bitmap_create(c, width, height, (int)nplanes);
1560 for(plane=0; plane<nplanes; plane++) {
1561 for(j=0; j<height; j++) {
1562 for(i=0; i<width; i++) {
1563 b = de_getbyte(pos + plane*planespan + j*rowspan + i);
1564 if(nplanes==3) {
1565 de_bitmap_setsample(img, i, j, plane, b);
1567 else {
1568 de_bitmap_setpixel_gray(img, i, j, b);
1573 de_bitmap_write_to_file(img, NULL, 0);
1575 done:
1576 de_bitmap_destroy(img);
1579 static int de_identify_pm_xv(deark *c)
1581 if(!dbuf_memcmp(c->infile, 0, "VIEW", 4))
1582 return 15;
1583 if(!dbuf_memcmp(c->infile, 0, "WEIV", 4))
1584 return 15;
1585 return 0;
1588 void de_module_pm_xv(deark *c, struct deark_module_info *mi)
1590 mi->id = "pm_xv";
1591 mi->desc = "PM (XV)";
1592 mi->run_fn = de_run_pm_xv;
1593 mi->identify_fn = de_identify_pm_xv;
1596 // **************************************************************************
1597 // Calamus Raster Graphic - CRG
1598 // **************************************************************************
1600 // Warning: The CRG decoder is based on reverse engineering, may not be
1601 // correct, and is definitely incomplete.
1603 static void de_run_crg(deark *c, de_module_params *mparams)
1605 i64 width, height;
1606 i64 rowspan;
1607 i64 pos;
1608 u8 b1, b2;
1609 i64 count;
1610 i64 cmpr_img_start;
1611 i64 num_cmpr_bytes;
1612 dbuf *unc_pixels = NULL;
1614 width = de_getu32be(20);
1615 height = de_getu32be(24);
1616 de_dbg_dimensions(c, width, height);
1617 if(!de_good_image_dimensions(c, width, height)) goto done;
1619 b1 = de_getbyte(32);
1620 if(b1!=0x01) {
1621 de_err(c, "Unsupported CRG format");
1622 goto done;
1625 num_cmpr_bytes = de_getu32be(38);
1626 de_dbg(c, "compressed data size: %d", (int)num_cmpr_bytes);
1627 cmpr_img_start = 42;
1629 if(cmpr_img_start + num_cmpr_bytes > c->infile->len) {
1630 num_cmpr_bytes = c->infile->len - cmpr_img_start;
1633 // Uncompress the image
1634 rowspan = (width+7)/8;
1635 unc_pixels = dbuf_create_membuf(c, height*rowspan, 1);
1637 pos = cmpr_img_start;
1638 while(pos < cmpr_img_start + num_cmpr_bytes) {
1639 b1 = de_getbyte(pos++);
1640 if(b1<=0x7f) { // Uncompressed bytes
1641 count = 1+(i64)b1;
1642 dbuf_copy(c->infile, pos, count, unc_pixels);
1643 pos += count;
1645 else { // A compressed run
1646 b2 = de_getbyte(pos++);
1647 count = (i64)(b1-127);
1648 dbuf_write_run(unc_pixels, b2, count);
1651 de_dbg(c, "decompressed to %d bytes", (int)unc_pixels->len);
1653 de_convert_and_write_image_bilevel2(unc_pixels, 0, width, height, rowspan,
1654 DE_CVTF_WHITEISZERO, NULL, 0);
1656 done:
1657 dbuf_close(unc_pixels);
1660 static int de_identify_crg(deark *c)
1662 if(!dbuf_memcmp(c->infile, 0, "CALAMUSCRG", 10))
1663 return 100;
1664 return 0;
1667 void de_module_crg(deark *c, struct deark_module_info *mi)
1669 mi->id = "crg";
1670 mi->desc = "Calamus Raster Graphic";
1671 mi->run_fn = de_run_crg;
1672 mi->identify_fn = de_identify_crg;
1675 // **************************************************************************
1676 // farbfeld
1677 // **************************************************************************
1679 static void de_run_farbfeld(deark *c, de_module_params *mparams)
1681 de_bitmap *img = NULL;
1682 i64 width, height;
1683 i64 i, j, k;
1684 i64 ppos;
1685 u8 s[4];
1687 width = de_getu32be(8);
1688 height = de_getu32be(12);
1689 de_dbg_dimensions(c, width, height);
1690 if(!de_good_image_dimensions(c, width, height)) return;
1692 img = de_bitmap_create(c, width, height, 4);
1694 for(j=0; j<height; j++) {
1695 for(i=0; i<width; i++) {
1696 ppos = 16 + 8*(width*j + i);
1697 for(k=0; k<4; k++) {
1698 s[k] = de_getbyte(ppos+2*k);
1700 de_bitmap_setpixel_rgba(img, i, j,
1701 DE_MAKE_RGBA(s[0],s[1],s[2],s[3]));
1704 de_bitmap_write_to_file(img, NULL, 0);
1705 de_bitmap_destroy(img);
1708 static int de_identify_farbfeld(deark *c)
1710 if(!dbuf_memcmp(c->infile, 0, "farbfeld", 8))
1711 return 100;
1712 return 0;
1715 void de_module_farbfeld(deark *c, struct deark_module_info *mi)
1717 mi->id = "farbfeld";
1718 mi->desc = "farbfeld image";
1719 mi->run_fn = de_run_farbfeld;
1720 mi->identify_fn = de_identify_farbfeld;
1723 // **************************************************************************
1724 // VGA font (intended for development/debugging use)
1725 // **************************************************************************
1727 static void de_run_vgafont(deark *c, de_module_params *mparams)
1729 u8 *fontdata = NULL;
1730 struct de_bitmap_font *font = NULL;
1731 i64 i;
1732 i64 height;
1734 if(c->infile->len==16*256) {
1735 height = 16;
1737 else if(c->infile->len==14*256) {
1738 height = 14;
1740 else {
1741 de_err(c, "Bad file size");
1742 goto done;
1745 fontdata = de_malloc(c, height*256);
1746 de_read(fontdata, 0, height*256);
1748 if(de_get_ext_option(c, "vgafont:c")) {
1749 dbuf *ff;
1750 ff = dbuf_create_output_file(c, "h", NULL, 0);
1751 for(i=0; i<(height*256); i++) {
1752 if(i%height==0) dbuf_puts(ff, "\t");
1753 dbuf_printf(ff, "%d", (int)fontdata[i]);
1754 if(i!=(height*256-1)) dbuf_puts(ff, ",");
1755 if(i%height==(height-1)) dbuf_puts(ff, "\n");
1757 dbuf_close(ff);
1758 goto done;
1761 font = de_create_bitmap_font(c);
1762 font->num_chars = 256;
1763 font->has_nonunicode_codepoints = 1;
1764 font->has_unicode_codepoints = 0;
1765 font->prefer_unicode = 0;
1766 font->nominal_width = 8;
1767 font->nominal_height = (int)height;
1768 font->char_array = de_mallocarray(c, font->num_chars, sizeof(struct de_bitmap_font_char));
1770 for(i=0; i<font->num_chars; i++) {
1771 font->char_array[i].codepoint_nonunicode = (i32)i;
1772 font->char_array[i].width = font->nominal_width;
1773 font->char_array[i].height = font->nominal_height;
1774 font->char_array[i].rowspan = 1;
1775 font->char_array[i].bitmap = &fontdata[i*font->nominal_height];
1778 de_font_bitmap_font_to_image(c, font, NULL, 0);
1780 done:
1781 if(font) {
1782 de_free(c, font->char_array);
1783 de_destroy_bitmap_font(c, font);
1785 de_free(c, fontdata);
1788 static void de_help_vgafont(deark *c)
1790 de_msg(c, "-opt vgafont:c : Emit C code");
1793 void de_module_vgafont(deark *c, struct deark_module_info *mi)
1795 mi->id = "vgafont";
1796 mi->desc = "Raw 8x16 or 8x14 VGA font";
1797 mi->run_fn = de_run_vgafont;
1798 mi->help_fn = de_help_vgafont;
1799 mi->flags |= DE_MODFLAG_HIDDEN;
1802 // **************************************************************************
1803 // HSI Raw image format (from Image Alchemy / Handmade Software)
1804 // **************************************************************************
1806 static void de_run_hsiraw(deark *c, de_module_params *mparams)
1808 i64 w, h;
1809 i64 num_pal_colors;
1810 i64 pos;
1811 i64 ver;
1812 i64 hdpi, vdpi;
1813 i64 cmpr;
1814 i64 alpha_info;
1815 de_bitmap *img = NULL;
1816 u32 pal[256];
1817 int is_grayscale;
1819 ver = de_getu16be(6);
1820 de_dbg(c, "version: %d", (int)ver);
1821 if(ver!=4) {
1822 de_warn(c, "HSI Raw version %d might not be supported correctly", (int)ver);
1825 w = de_getu16be(8);
1826 if(w==0) {
1827 // MPlayer extension?
1828 de_dbg2(c, "reading 32-bit width");
1829 w = de_getu32be(28);
1831 h = de_getu16be(10);
1832 de_dbg_dimensions(c, w, h);
1833 num_pal_colors = de_getu16be(12);
1834 de_dbg(c, "number of palette colors: %d", (int)num_pal_colors);
1836 hdpi = de_geti16be(14);
1837 vdpi = de_geti16be(16);
1838 de_dbg(c, "density: %d"DE_CHAR_TIMES"%d", (int)hdpi, (int)vdpi);
1839 // [18: Gamma]
1840 cmpr = de_getu16be(20);
1841 de_dbg(c, "compression: %d", (int)cmpr);
1842 alpha_info = de_getu16be(22);
1843 de_dbg(c, "alpha: %d", (int)alpha_info);
1845 if(num_pal_colors>256 || cmpr!=0 || alpha_info!=0) {
1846 de_err(c, "This type of HSI Raw image is not supported");
1847 goto done;
1849 if(!de_good_image_dimensions(c, w, h)) goto done;
1851 pos = 32;
1852 de_zeromem(pal, sizeof(pal));
1853 if(num_pal_colors==0) { // 24-bit RGB
1854 is_grayscale = 0;
1856 else { // 8-bit paletted
1857 de_read_palette_rgb(c->infile, pos, num_pal_colors, 3, pal, 256, 0);
1858 pos += 3*num_pal_colors;
1859 is_grayscale = de_is_grayscale_palette(pal, num_pal_colors);
1862 img = de_bitmap_create(c, w, h, is_grayscale?1:3);
1864 if(num_pal_colors==0) {
1865 de_convert_image_rgb(c->infile, pos, 3*w, 3, img, 0);
1867 else {
1868 de_convert_image_paletted(c->infile, pos, 8, w, pal, img, 0);
1871 de_bitmap_write_to_file(img, NULL, 0);
1873 done:
1874 de_bitmap_destroy(img);
1877 static int de_identify_hsiraw(deark *c)
1879 if(!dbuf_memcmp(c->infile, 0, "mhwanh", 6))
1880 return 100;
1881 return 0;
1884 void de_module_hsiraw(deark *c, struct deark_module_info *mi)
1886 mi->id = "hsiraw";
1887 mi->desc = "HSI Raw";
1888 mi->run_fn = de_run_hsiraw;
1889 mi->identify_fn = de_identify_hsiraw;
1892 // **************************************************************************
1893 // QDV (Giffer)
1894 // **************************************************************************
1896 static void de_run_qdv(deark *c, de_module_params *mparams)
1898 i64 w, h;
1899 i64 num_pal_colors;
1900 i64 pos;
1901 de_bitmap *img = NULL;
1902 u32 pal[256];
1904 // Warning: This decoder is based on reverse engineering, and may be
1905 // incorrect or incomplete.
1907 w = de_getu16be(0);
1908 h = de_getu16be(2);
1909 de_dbg_dimensions(c, w, h);
1910 if(!de_good_image_dimensions(c, w, h)) goto done;
1912 num_pal_colors = 1 + (i64)de_getbyte(4);
1913 de_dbg(c, "number of palette colors: %d", (int)num_pal_colors);
1915 pos = 5;
1916 de_zeromem(pal, sizeof(pal));
1917 de_read_palette_rgb(c->infile, pos, num_pal_colors, 3, pal, 256, 0);
1918 pos += 3*num_pal_colors;
1920 img = de_bitmap_create(c, w, h, 3);
1921 de_convert_image_paletted(c->infile, pos, 8, w, pal, img, 0);
1922 de_bitmap_write_to_file(img, NULL, 0);
1924 done:
1925 de_bitmap_destroy(img);
1928 static int de_identify_qdv(deark *c)
1930 i64 w, h;
1931 i64 num_pal_colors;
1933 w = de_getu16be(0);
1934 h = de_getu16be(2);
1935 num_pal_colors = 1 + (i64)de_getbyte(4);
1936 if(5+num_pal_colors*3+w*h != c->infile->len)
1937 return 0;
1938 if(de_input_file_has_ext(c, "qdv"))
1939 return 100;
1940 return 30;
1943 void de_module_qdv(deark *c, struct deark_module_info *mi)
1945 mi->id = "qdv";
1946 mi->desc = "QDV (Giffer)";
1947 mi->run_fn = de_run_qdv;
1948 mi->identify_fn = de_identify_qdv;
1951 // **************************************************************************
1952 // VITec image format
1953 // **************************************************************************
1955 static void de_run_vitec(deark *c, de_module_params *mparams)
1957 i64 npwidth, pdwidth, h;
1958 i64 i, j, plane;
1959 de_bitmap *img = NULL;
1960 i64 samplesperpixel;
1961 i64 rowspan, planespan;
1962 i64 pos;
1963 u8 b;
1964 i64 h1size, h2size;
1965 int saved_indent_level;
1967 // This code is based on reverse engineering, and may be incorrect.
1969 de_dbg_indent_save(c, &saved_indent_level);
1970 de_warn(c, "VITec image support is experimental, and may not work correctly.");
1972 pos = 4;
1973 h1size = de_getu32be(pos);
1974 de_dbg(c, "header 1 at %d, len=%d", (int)pos, (int)h1size);
1975 // Don't know what's in this part of the header. Just ignore it.
1976 pos += h1size;
1977 if(pos>=c->infile->len) goto done;
1979 h2size = de_getu32be(pos);
1980 de_dbg(c, "header 2 at %d, len=%d", (int)pos, (int)h2size);
1981 de_dbg_indent(c, 1);
1983 // pos+4: Bits size?
1984 // pos+24: Unknown field, usually 7
1986 npwidth = de_getu32be(pos+36);
1987 h = de_getu32be(pos+40);
1988 de_dbg_dimensions(c, npwidth, h);
1989 if(!de_good_image_dimensions(c, npwidth, h)) goto done;
1991 // pos+52: Unknown field, 1 in grayscale images
1993 samplesperpixel = de_getu32be(pos+56);
1994 de_dbg(c, "samples/pixel: %d", (int)samplesperpixel);
1995 if(samplesperpixel!=1 && samplesperpixel!=3) {
1996 de_err(c, "Unsupported samples/pixel: %d", (int)samplesperpixel);
1997 goto done;
2000 pos += h2size;
2001 if(pos>=c->infile->len) goto done;
2002 de_dbg_indent(c, -1);
2004 de_dbg(c, "bitmap at %d", (int)pos);
2005 pdwidth = de_pad_to_n(npwidth, 8);
2006 img = de_bitmap_create2(c, npwidth, pdwidth, h, (int)samplesperpixel);
2007 rowspan = pdwidth;
2008 planespan = rowspan*h;
2010 for(plane=0; plane<samplesperpixel; plane++) {
2011 for(j=0; j<h; j++) {
2012 for(i=0; i<pdwidth; i++) {
2013 b = de_getbyte(pos + plane*planespan + j*rowspan + i);
2014 if(samplesperpixel==3) {
2015 de_bitmap_setsample(img, i, j, plane, b);
2017 else {
2018 de_bitmap_setpixel_gray(img, i, j, b);
2024 de_bitmap_write_to_file(img, NULL, 0);
2026 done:
2027 de_bitmap_destroy(img);
2028 de_dbg_indent_restore(c, saved_indent_level);
2031 static int de_identify_vitec(deark *c)
2033 if(!dbuf_memcmp(c->infile, 0, "\x00\x5b\x07\x20", 4))
2034 return 100;
2035 return 0;
2038 void de_module_vitec(deark *c, struct deark_module_info *mi)
2040 mi->id = "vitec";
2041 mi->desc = "VITec image format";
2042 mi->run_fn = de_run_vitec;
2043 mi->identify_fn = de_identify_vitec;
2046 // **************************************************************************
2047 // HS2 module
2049 // .HS2 format is associated with a program called POSTERING.
2050 // **************************************************************************
2052 static void de_run_hs2(deark *c, de_module_params *mparams)
2054 i64 width, height;
2055 i64 rowspan;
2057 rowspan = 105;
2058 width = rowspan*8;
2059 height = (c->infile->len+(rowspan-1))/rowspan;
2060 de_convert_and_write_image_bilevel(c->infile, 0, width, height, rowspan, 0, NULL, 0);
2063 static int de_identify_hs2(deark *c)
2065 if(!de_input_file_has_ext(c, "hs2")) return 0;
2066 if(c->infile->len>0 && (c->infile->len%105 == 0)) {
2067 return 15;
2069 return 0;
2072 void de_module_hs2(deark *c, struct deark_module_info *mi)
2074 mi->id = "hs2";
2075 mi->desc = "HS2 (POSTERING)";
2076 mi->run_fn = de_run_hs2;
2077 mi->identify_fn = de_identify_hs2;
2081 // **************************************************************************
2082 // Lumena CEL
2083 // **************************************************************************
2085 static void de_run_lumena_cel(deark *c, de_module_params *mparams)
2087 i64 width, height;
2088 i64 rowspan;
2089 i64 i, j;
2090 u32 clr;
2091 u8 a;
2092 int is_16bit = 0;
2093 int is_32bit = 0;
2094 de_bitmap *img = NULL;
2095 const i64 headersize = 4;
2096 i64 bypp;
2098 width = de_getu16le(0);
2099 height = de_getu16le(2);
2100 if(!de_good_image_dimensions_noerr(c, width, height)) goto done;
2102 // TODO: Support multi-image files
2103 is_16bit = (c->infile->len == headersize + width*height*2);
2104 is_32bit = (c->infile->len == headersize + width*height*4);
2105 if(!is_16bit && !is_32bit) {
2106 de_warn(c, "Cannot detect bits/pixel, assuming 32");
2107 is_32bit = 1;
2110 bypp = (is_32bit) ? 4 : 2;
2111 de_dbg(c, "bytes/pixel: %d", (int)bypp);
2112 rowspan = width * bypp;
2114 img = de_bitmap_create(c, width, height, is_32bit?4:3);
2116 for(j=0; j<height; j++) {
2117 for(i=0; i<width; i++) {
2118 i64 pos = headersize + j*rowspan + i*bypp;
2119 if(is_32bit) {
2120 clr = dbuf_getRGB(c->infile, pos, 0);
2121 a = de_getbyte(pos + 3);
2122 clr = DE_SET_ALPHA(clr, a);
2124 else {
2125 clr = (u32)de_getu16le(pos);
2126 clr = de_rgb555_to_888(clr);
2128 de_bitmap_setpixel_rgba(img, i, j, clr);
2132 de_bitmap_optimize_alpha(img, 0x3);
2133 de_bitmap_write_to_file(img, NULL, DE_CREATEFLAG_FLIP_IMAGE);
2135 done:
2136 de_bitmap_destroy(img);
2139 static int de_identify_lumena_cel(deark *c)
2141 i64 width, height;
2142 int is_16bit = 0;
2143 int is_32bit = 0;
2145 if(!de_input_file_has_ext(c, "cel")) return 0;
2146 width = de_getu16le(0);
2147 height = de_getu16le(2);
2149 is_16bit = (c->infile->len == 4 + width*height*2);
2150 is_32bit = (c->infile->len == 4 + width*height*4);
2152 if(is_16bit || is_32bit)
2153 return 60;
2155 return 0;
2158 void de_module_lumena_cel(deark *c, struct deark_module_info *mi)
2160 mi->id = "lumena_cel";
2161 mi->desc = "Lumena CEL";
2162 mi->run_fn = de_run_lumena_cel;
2163 mi->identify_fn = de_identify_lumena_cel;
2166 // **************************************************************************
2167 // ZBR (Zoner Zebra Metafile)
2168 // **************************************************************************
2170 static void de_run_zbr(deark *c, de_module_params *mparams)
2172 i64 pos = 0;
2173 dbuf *outf = NULL;
2174 static const u8 hdrs[54] = {
2175 0x42,0x4d,0xc6,0x14,0,0,0,0,0,0,0x76,0,0,0, // FILEHEADER
2176 0x28,0,0,0,0x64,0,0,0,0x64,0,0,0,0x01,0,0x04,0, // INFOHEADER...
2177 0,0,0,0,0x50,0x14,0,0,0,0,0,0,0,0,0,0,
2178 0x10,0,0,0,0,0,0,0 };
2180 pos += 4; // signature, version
2181 pos += 100; // comment
2183 de_dbg(c, "preview image at %d", (int)pos);
2184 // By design, this image is formatted as a headerless BMP/DIB. We'll just
2185 // add the 54 bytes of headers needed to make it a BMP, and call it done.
2186 outf = dbuf_create_output_file(c, "preview.bmp", NULL, DE_CREATEFLAG_IS_AUX);
2187 dbuf_write(outf, hdrs, 54);
2188 dbuf_copy(c->infile, pos, 16*4 + 100*52, outf);
2189 dbuf_close(outf);
2192 static int de_identify_zbr(deark *c)
2194 if(!dbuf_memcmp(c->infile, 0, "\x9a\x02", 2)) {
2195 if(de_input_file_has_ext(c, "zbr")) return 100;
2196 return 25;
2198 return 0;
2201 void de_module_zbr(deark *c, struct deark_module_info *mi)
2203 mi->id = "zbr";
2204 mi->desc = "ZBR (Zebra Metafile)";
2205 mi->desc2 = "extract preview image";
2206 mi->run_fn = de_run_zbr;
2207 mi->identify_fn = de_identify_zbr;
2210 // **************************************************************************
2211 // CorelDRAW CDR - old "WL" format
2212 // **************************************************************************
2214 static void de_run_cdr_wl(deark *c, de_module_params *mparams)
2216 u8 version;
2217 u8 b;
2218 i64 w, h;
2219 i64 rowspan;
2220 i64 pos = 0;
2221 de_bitmap *img = NULL;
2222 int saved_indent_level;
2224 de_dbg_indent_save(c, &saved_indent_level);
2225 de_declare_fmt(c, "CorelDRAW (WL format)");
2226 version = de_getbyte(2);
2227 de_dbg(c, "version code: 0x%02x", (unsigned int)version);
2228 if(version <= (u8)'e') goto done;
2230 pos = de_getu32le(28);
2231 de_dbg(c, "preview image at %d", (int)pos);
2232 de_dbg_indent(c, 1);
2234 // Seems to be Windows DDB format, or something like it.
2235 pos += 2;
2236 pos += 2;
2237 w = de_getu16le_p(&pos);
2238 h = de_getu16le_p(&pos);
2239 de_dbg_dimensions(c, w, h);
2240 rowspan = de_getu16le_p(&pos);
2241 b = de_getbyte_p(&pos); // planes
2242 if(b!=1) goto done;
2243 b = de_getbyte_p(&pos); // bits/pixel
2244 if(b!=1) goto done;
2245 pos += 4; // bmBits
2247 if(!de_good_image_dimensions(c, w, h)) goto done;
2248 img = de_bitmap_create2(c, w, rowspan*8, h, 1);
2249 de_convert_image_bilevel(c->infile, pos, rowspan, img, 0);
2250 de_bitmap_write_to_file(img, "preview", DE_CREATEFLAG_IS_AUX);
2252 done:
2253 de_bitmap_destroy(img);
2254 de_dbg_indent_restore(c, saved_indent_level);
2257 static int de_identify_cdr_wl(deark *c)
2259 if(!dbuf_memcmp(c->infile, 0, "WL", 2)) {
2260 if(de_input_file_has_ext(c, "cdr")) return 100;
2261 return 6;
2263 return 0;
2266 void de_module_cdr_wl(deark *c, struct deark_module_info *mi)
2268 mi->id = "cdr_wl";
2269 mi->desc = "CorelDRAW (old WL format)";
2270 mi->desc2 = "extract preview image";
2271 mi->run_fn = de_run_cdr_wl;
2272 mi->identify_fn = de_identify_cdr_wl;
2275 // **************************************************************************
2276 // compress (.Z)
2277 // **************************************************************************
2279 static void de_run_compress(deark *c, de_module_params *mparams)
2281 struct de_dfilter_results dres;
2282 struct de_dfilter_in_params dcmpri;
2283 struct de_dfilter_out_params dcmpro;
2284 struct de_lzw_params delzwp;
2285 dbuf *f = NULL;
2287 f = dbuf_create_output_file(c, "bin", NULL, 0);
2289 de_dfilter_init_objects(c, &dcmpri, &dcmpro, &dres);
2290 dcmpri.f = c->infile;
2291 dcmpri.pos = 0;
2292 dcmpri.len = c->infile->len;
2293 dcmpro.f = f;
2294 dcmpro.len_known = 0;
2296 de_zeromem(&delzwp, sizeof(struct de_lzw_params));
2297 delzwp.fmt = DE_LZWFMT_UNIXCOMPRESS;
2298 delzwp.flags |= DE_LZWFLAG_HAS3BYTEHEADER;
2300 fmtutil_decompress_lzw(c, &dcmpri, &dcmpro, &dres, &delzwp);
2301 if(dres.errcode!=0) {
2302 de_err(c, "%s", de_dfilter_get_errmsg(c, &dres));
2304 dbuf_close(f);
2307 static int de_identify_compress(deark *c)
2309 if(!dbuf_memcmp(c->infile, 0, "\x1f\x9d", 2))
2310 return 100;
2311 return 0;
2314 void de_module_compress(deark *c, struct deark_module_info *mi)
2316 mi->id = "compress";
2317 mi->desc = "Compress (.Z)";
2318 mi->run_fn = de_run_compress;
2319 mi->identify_fn = de_identify_compress;
2322 // **************************************************************************
2323 // Graphic Workshop .THN
2324 // **************************************************************************
2326 static void de_run_gws_thn(deark *c, de_module_params *mparams)
2328 de_bitmap *img = NULL;
2329 u8 v1, v2;
2330 i64 w, h;
2331 i64 pos;
2332 de_encoding encoding;
2333 de_ucstring *s = NULL;
2334 u32 pal[256];
2336 // This code is based on reverse engineering, and may be incorrect.
2337 encoding = de_get_input_encoding(c, NULL, DE_ENCODING_WINDOWS1252);
2338 pos = 4;
2339 v1 = de_getbyte_p(&pos);
2340 v2 = de_getbyte_p(&pos);
2341 de_dbg(c, "version?: 0x%02x 0x%02x", (unsigned int)v1, (unsigned int)v2);
2343 s = ucstring_create(c);
2344 // For the text fields, the field size appears to be 129, but the software
2345 // only properly supports up to 127 non-NUL bytes.
2346 dbuf_read_to_ucstring(c->infile, 6, 127, s, DE_CONVFLAG_STOP_AT_NUL, encoding);
2347 if(s->len>0) de_dbg(c, "comments: \"%s\"", ucstring_getpsz_d(s));
2348 ucstring_empty(s);
2349 dbuf_read_to_ucstring(c->infile, 135, 127, s, DE_CONVFLAG_STOP_AT_NUL, encoding);
2350 if(s->len>0) de_dbg(c, "key words: \"%s\"", ucstring_getpsz_d(s));
2352 pos = 264;
2353 de_dbg(c, "image at %"I64_FMT, pos);
2354 w = 96;
2355 h = 96;
2357 // Set up the palette. There are two possible fixed palettes.
2358 if(v1==0) { // Original palette
2359 // Based on Graphic Workshop v1.1a for Windows
2360 static const u8 rbvals[6] = {0x00,0x57,0x83,0xab,0xd7,0xff};
2361 static const u8 gvals[7] = {0x00,0x2b,0x57,0x83,0xab,0xd7,0xff};
2362 static const u32 gwspal_last5[5] = {0x3f3f3f,0x6b6b6b,0x979797,
2363 0xc3c3c3,0xffffff};
2364 unsigned int k;
2366 for(k=0; k<=250; k++) {
2367 pal[k] = DE_MAKE_RGB(
2368 rbvals[k%6],
2369 gvals[(k%42)/6],
2370 rbvals[k/42]);
2372 for(k=251; k<=255; k++) {
2373 pal[k] = gwspal_last5[k-251];
2376 else { // New palette (really RGB332), introduced by v1.1c
2377 // Based on Graphic Workshop v1.1u for Windows
2378 unsigned int k;
2380 for(k=0; k<256; k++) {
2381 u8 r, g, b;
2382 r = de_sample_nbit_to_8bit(3, k>>5);
2383 g = de_sample_nbit_to_8bit(3, (k>>2)&0x07);
2384 b = de_sample_nbit_to_8bit(2, k&0x03);
2385 pal[k] = DE_MAKE_RGB(r, g, b);
2389 img = de_bitmap_create(c, w, h, 3);
2390 de_convert_image_paletted(c->infile, pos, 8, w, pal, img, 0);
2391 de_bitmap_write_to_file(img, NULL, DE_CREATEFLAG_FLIP_IMAGE);
2392 de_bitmap_destroy(img);
2393 ucstring_destroy(s);
2396 static int de_identify_gws_thn(deark *c)
2398 if(c->infile->len!=9480) return 0;
2399 if(!dbuf_memcmp(c->infile, 0, "THNL", 4)) return 100;
2400 return 0;
2403 void de_module_gws_thn(deark *c, struct deark_module_info *mi)
2405 mi->id = "gws_thn";
2406 mi->desc = "Graphic Workshop thumbnail .THN";
2407 mi->run_fn = de_run_gws_thn;
2408 mi->identify_fn = de_identify_gws_thn;
2411 // **************************************************************************
2412 // Tandy DeskMate Paint .PNT
2413 // **************************************************************************
2415 static void de_run_deskmate_pnt(deark *c, de_module_params *mparams)
2417 i64 w, h;
2418 i64 rowspan;
2419 i64 pos = 0;
2420 int k;
2421 int is_compressed;
2422 de_bitmap *img = NULL;
2423 dbuf *unc_pixels = NULL;
2424 i64 unc_pixels_size;
2425 u32 pal[16];
2427 pos += 22;
2428 de_dbg(c, "image at %"I64_FMT, pos);
2429 w = 312;
2430 h = 176;
2431 rowspan = w/2;
2432 unc_pixels_size = rowspan * h;
2434 for(k=0; k<16; k++) {
2435 pal[k] = de_palette_pc16(k);
2438 is_compressed = (pos+unc_pixels_size != c->infile->len);
2439 de_dbg(c, "compressed: %d", is_compressed);
2441 if(is_compressed) {
2442 unc_pixels = dbuf_create_membuf(c, unc_pixels_size, 0x1);
2443 while(1) {
2444 i64 count;
2445 u8 val;
2447 if(pos >= c->infile->len) break; // out of source data
2448 if(unc_pixels->len >= unc_pixels_size) break; // enough dst data
2449 val = de_getbyte_p(&pos);
2450 count = (i64)de_getbyte_p(&pos);
2451 dbuf_write_run(unc_pixels, val, count);
2454 else {
2455 unc_pixels = dbuf_open_input_subfile(c->infile, pos, unc_pixels_size);
2458 img = de_bitmap_create(c, w, h, 3);
2459 de_convert_image_paletted(unc_pixels, 0, 4, rowspan, pal, img, 0);
2460 de_bitmap_write_to_file(img, NULL, 0);
2462 dbuf_close(unc_pixels);
2463 de_bitmap_destroy(img);
2466 static int de_identify_deskmate_pnt(deark *c)
2468 if(!dbuf_memcmp(c->infile, 0, "\x13" "PNT", 4)) return 100;
2469 return 0;
2472 void de_module_deskmate_pnt(deark *c, struct deark_module_info *mi)
2474 mi->id = "deskmate_pnt";
2475 mi->desc = "Tandy DeskMate Paint";
2476 mi->run_fn = de_run_deskmate_pnt;
2477 mi->identify_fn = de_identify_deskmate_pnt;
2481 // **************************************************************************
2482 // Corel Gallery .BMF
2483 // **************************************************************************
2485 // Warning: The BMF preview image decoder is based on reverse engineering, may not
2486 // be correct.
2488 static void de_run_corel_bmf(deark *c, de_module_params *mparams1)
2490 de_module_params *mparams2 = NULL;
2491 int saved_indent_level;
2492 i64 pos;
2493 i64 n;
2494 i64 seg_size;
2496 de_dbg_indent_save(c, &saved_indent_level);
2497 pos = 65;
2498 seg_size = de_getu32le_p(&pos);
2499 de_dbg(c, "preview image segment at %"I64_FMT", len=%"I64_FMT, pos, seg_size);
2500 de_dbg_indent(c, 1);
2502 if(pos + seg_size > c->infile->len) {
2503 seg_size = c->infile->len - pos;
2506 n = de_getu32le(pos);
2507 if(n!=40) {
2508 de_err(c, "Unsupported Corel BMF version");
2509 goto done;
2512 mparams2 = de_malloc(c, sizeof(de_module_params));
2513 mparams2->in_params.codes = "X";
2514 mparams2->in_params.flags = 0x81;
2515 de_run_module_by_id_on_slice(c, "dib", mparams2, c->infile, pos, seg_size);
2517 done:
2518 de_free(c, mparams2);
2519 de_dbg_indent_restore(c, saved_indent_level);
2522 static int de_identify_corel_bmf(deark *c)
2524 if(!dbuf_memcmp(c->infile, 0, "@CorelBMF\x0a\x0d", 11)) return 100;
2525 return 0;
2528 void de_module_corel_bmf(deark *c, struct deark_module_info *mi)
2530 mi->id = "corel_bmf";
2531 mi->desc = "Corel Gallery BMF";
2532 mi->run_fn = de_run_corel_bmf;
2533 mi->identify_fn = de_identify_corel_bmf;
2536 // **************************************************************************
2537 // Hemera Photo-Object image (.hpi)
2538 // **************************************************************************
2540 static void de_run_hpi(deark *c, de_module_params *mparams)
2542 i64 jpgpos, pngpos;
2543 i64 jpglen, pnglen;
2544 i64 pos;
2546 pos = 12;
2547 jpgpos = de_getu32le_p(&pos);
2548 jpglen = de_getu32le_p(&pos);
2549 de_dbg(c, "jpeg: pos=%"I64_FMT", len=%"I64_FMT, jpgpos, jpglen);
2550 pngpos = de_getu32le_p(&pos);
2551 pnglen = de_getu32le_p(&pos);
2552 de_dbg(c, "png: pos=%"I64_FMT", len=%"I64_FMT, pngpos, pnglen);
2554 if(jpglen>0 && jpgpos+jpglen<=c->infile->len && de_getbyte(jpgpos)==0xff) {
2555 const char *ext;
2557 if(pnglen==0) ext="jpg";
2558 else ext="foreground.jpg";
2559 dbuf_create_file_from_slice(c->infile, jpgpos, jpglen, ext, NULL, 0);
2561 if(pnglen>0 && pngpos+pnglen<=c->infile->len && de_getbyte(pngpos)==0x89) {
2562 dbuf_create_file_from_slice(c->infile, pngpos, pnglen, "mask.png", NULL, 0);
2566 static int de_identify_hpi(deark *c)
2568 if(!dbuf_memcmp(c->infile, 0, "\x89\x48\x50\x49\x0d\x0a\x1a\x0a", 8)) return 100;
2569 return 0;
2572 void de_module_hpi(deark *c, struct deark_module_info *mi)
2574 mi->id = "hpi";
2575 mi->desc = "Hemera Photo-Object image";
2576 mi->run_fn = de_run_hpi;
2577 mi->identify_fn = de_identify_hpi;
2580 // **************************************************************************
2581 // DWC archive
2582 // **************************************************************************
2584 struct dwc_member_data {
2585 de_ucstring *fn;
2586 i64 unclen, cmprlen;
2587 i64 cmprdatapos;
2588 u8 cmpr_meth;
2591 static void do_dwc_member(deark *c, i64 pos1)
2593 i64 pos = pos1;
2594 struct dwc_member_data *md = NULL;
2596 md = de_malloc(c, sizeof(struct dwc_member_data));
2597 de_dbg(c, "member header at %"I64_FMT, pos1);
2598 de_dbg_indent(c, 1);
2599 md->fn = ucstring_create(c);
2600 dbuf_read_to_ucstring(c->infile, pos, 12, md->fn, DE_CONVFLAG_STOP_AT_NUL,
2601 DE_ENCODING_CP437_G);
2602 de_dbg(c, "filename: \"%s\"", ucstring_getpsz_d(md->fn));
2603 pos += 13;
2604 md->unclen = de_getu32le_p(&pos);
2605 de_dbg(c, "unc. size: %"I64_FMT, md->unclen);
2606 pos += 4; // time/date
2607 md->cmprlen = de_getu32le_p(&pos);
2608 de_dbg(c, "cmpr. size: %"I64_FMT, md->cmprlen);
2609 md->cmprdatapos = de_getu32le_p(&pos);
2610 de_dbg(c, "cmpr. data pos: %"I64_FMT, md->cmprdatapos);
2611 md->cmpr_meth = de_getbyte_p(&pos);
2612 de_dbg(c, "cmpr. method: %d", (int)md->cmpr_meth);
2613 // pos += 2; // ?
2614 // pos += 2; // CRC
2615 de_dbg_indent(c, -1);
2616 if(md) {
2617 ucstring_destroy(md->fn);
2618 de_free(c, md);
2622 static void de_run_dwc(deark *c, de_module_params *mparams)
2624 i64 trailer_pos;
2625 i64 nmembers;
2626 i64 fhsize; // size of each file header
2627 i64 pos;
2628 i64 i;
2630 de_info(c, "Note: DWC files can be parsed, but no files can be extracted from them.");
2631 trailer_pos = c->infile->len - 27;
2632 pos = trailer_pos;
2633 de_dbg(c, "trailer at %"I64_FMT, trailer_pos);
2634 de_dbg_indent(c, 1);
2635 pos += 2; // trailer length (27)
2636 fhsize = de_getu16le_p(&pos);
2637 pos += 16;
2638 nmembers = de_getu16le_p(&pos);
2639 de_dbg(c, "number of member files: %d", (int)nmembers);
2640 de_dbg_indent(c, -1);
2642 pos = trailer_pos - fhsize*nmembers;
2643 for(i=0; i<nmembers; i++) {
2644 if(pos<0 || pos>(trailer_pos-fhsize)) break;
2645 do_dwc_member(c, pos);
2646 pos += fhsize;
2650 static int de_identify_dwc(deark *c)
2652 if(!de_input_file_has_ext(c, "dwc")) return 0;
2653 if(dbuf_memcmp(c->infile, c->infile->len-3, (const u8*)"DWC", 3)) {
2654 return 0;
2656 if(de_getu16le(c->infile->len-27) != 27) {
2657 return 0;
2659 return 70;
2662 void de_module_dwc(deark *c, struct deark_module_info *mi)
2664 mi->id = "dwc";
2665 mi->desc = "DWC compressed archive";
2666 mi->run_fn = de_run_dwc;
2667 mi->identify_fn = de_identify_dwc;
2670 // **************************************************************************
2671 // Magic Desk icon (.ICN)
2672 // **************************************************************************
2674 static void de_run_mdesk_icn(deark *c, de_module_params *mparams)
2676 de_bitmap *img = NULL;
2677 static const de_color pal[16] = {
2678 0xff000000U, 0xffaa0000U, 0xff00aa00U, 0xffaaaa00U,
2679 0xff0000aaU, 0xffaa00aaU, 0xff00aaaaU, 0xff7d7d7dU,
2680 0xffbababaU, 0xffff5555U, 0xff55ff55U, 0xffffff55U,
2681 0xff5555ffU, 0xffff55ffU, 0xff55ffffU, 0xffffffffU
2684 img = de_bitmap_create(c, 32, 32, 3);
2685 de_convert_image_paletted(c->infile, 3, 4, 16, pal, img, 0);
2686 de_bitmap_transpose(img);
2687 de_bitmap_write_to_file(img, NULL, 0);
2688 de_bitmap_destroy(img);
2691 static int de_identify_mdesk_icn(deark *c)
2693 if(c->infile->len!=515) return 0;
2694 if(de_getu16be(0)!=0x1f1f) return 0;
2695 if(de_input_file_has_ext(c, "icn") ||
2696 de_input_file_has_ext(c, "tbi"))
2698 return 90;
2700 return 20;
2703 void de_module_mdesk_icn(deark *c, struct deark_module_info *mi)
2705 mi->id = "mdesk_icn";
2706 mi->desc = "Magic Desk icon";
2707 mi->run_fn = de_run_mdesk_icn;
2708 mi->identify_fn = de_identify_mdesk_icn;
2711 // **************************************************************************
2712 // TTComp
2713 // **************************************************************************
2715 static void de_run_ttcomp(deark *c, de_module_params *mparams)
2717 dbuf *outf = NULL;
2718 struct de_dfilter_in_params dcmpri;
2719 struct de_dfilter_out_params dcmpro;
2720 struct de_dfilter_results dres;
2722 outf = dbuf_create_output_file(c, "unc", NULL, 0);
2723 de_dfilter_init_objects(c, &dcmpri, &dcmpro, &dres);
2724 dcmpri.f = c->infile;
2725 dcmpri.pos = 0;
2726 dcmpri.len = c->infile->len;
2727 dcmpro.f = outf;
2729 fmtutil_dclimplode_codectype1(c, &dcmpri, &dcmpro, &dres, NULL);
2730 if(dres.errcode) {
2731 de_err(c, "Decompression failed: %s", de_dfilter_get_errmsg(c, &dres));
2734 dbuf_close(outf);
2737 static int de_identify_ttcomp(deark *c)
2739 u8 b0, b1;
2741 if(c->infile->len<5) return 0;
2742 b0 = de_getbyte(0);
2743 if(b0>1) return 0;
2744 b1 = de_getbyte(1);
2745 if(b1<4 || b1>6) return 0;
2747 // Look for the end-of-data code in the last 2 or 3 bytes.
2748 // Assumes the last byte is padded with '0' bits, and there are
2749 // no extraneous bytes after that.
2750 u32 x = (u32)de_getu32le(c->infile->len-4);
2751 int i;
2752 for(i=0; i<8; i++) {
2753 if((x & 0xfffffc00U)==0x01fe0000U) {
2754 if(b0==0 && b1==6) return 40;
2755 return 10;
2757 x >>= 1;
2759 return 0;
2762 void de_module_ttcomp(deark *c, struct deark_module_info *mi)
2764 mi->id = "ttcomp";
2765 mi->desc = "TTComp";
2766 mi->run_fn = de_run_ttcomp;
2767 mi->identify_fn = de_identify_ttcomp;