1 // This file is part of Deark.
2 // Copyright (C) 2016-2021 Jason Summers
3 // See the file COPYING for terms of use.
5 // This file is for miscellaneous small modules that primarily do image decoding.
7 #include <deark-private.h>
8 #include <deark-fmtutil.h>
9 DE_DECLARE_MODULE(de_module_hpicn
);
10 DE_DECLARE_MODULE(de_module_xpuzzle
);
11 DE_DECLARE_MODULE(de_module_bob
);
12 DE_DECLARE_MODULE(de_module_alias_pix
);
13 DE_DECLARE_MODULE(de_module_applevol
);
14 DE_DECLARE_MODULE(de_module_hr
);
15 DE_DECLARE_MODULE(de_module_ripicon
);
16 DE_DECLARE_MODULE(de_module_lss16
);
17 DE_DECLARE_MODULE(de_module_vbm
);
18 DE_DECLARE_MODULE(de_module_fp_art
);
19 DE_DECLARE_MODULE(de_module_ybm
);
20 DE_DECLARE_MODULE(de_module_olpc565
);
21 DE_DECLARE_MODULE(de_module_iim
);
22 DE_DECLARE_MODULE(de_module_pm_xv
);
23 DE_DECLARE_MODULE(de_module_crg
);
24 DE_DECLARE_MODULE(de_module_farbfeld
);
25 DE_DECLARE_MODULE(de_module_hsiraw
);
26 DE_DECLARE_MODULE(de_module_qdv
);
27 DE_DECLARE_MODULE(de_module_vitec
);
28 DE_DECLARE_MODULE(de_module_hs2
);
29 DE_DECLARE_MODULE(de_module_lumena_cel
);
30 DE_DECLARE_MODULE(de_module_deskmate_pnt
);
31 DE_DECLARE_MODULE(de_module_mdesk_icn
);
32 DE_DECLARE_MODULE(de_module_animator_pic
);
33 DE_DECLARE_MODULE(de_module_dgi
);
34 DE_DECLARE_MODULE(de_module_cserve_rle
);
35 DE_DECLARE_MODULE(de_module_lotus_mscr
);
36 DE_DECLARE_MODULE(de_module_fastgraph_spr
);
37 DE_DECLARE_MODULE(de_module_fastgraph_ppr
);
38 DE_DECLARE_MODULE(de_module_young_picasso
);
39 DE_DECLARE_MODULE(de_module_iconmgr_ica
);
40 DE_DECLARE_MODULE(de_module_thumbsplus
);
41 DE_DECLARE_MODULE(de_module_fmtowns_icn
);
42 DE_DECLARE_MODULE(de_module_pixfolio
);
43 DE_DECLARE_MODULE(de_module_apple2icons
);
45 static void datetime_dbgmsg(deark
*c
, struct de_timestamp
*ts
, const char *name
)
47 char timestamp_buf
[64];
49 de_timestamp_to_string(ts
, timestamp_buf
, sizeof(timestamp_buf
), 0);
50 de_dbg(c
, "%s: %s", name
, timestamp_buf
);
53 // Assumes path separators are '/' or '\'.
54 static void get_base_filename(de_ucstring
*s1
, de_ucstring
*s2
)
61 for(i
=0; i
<len
; i
++) {
65 if(ch
=='\\' || ch
=='/') {
69 ucstring_append_char(s2
, ch
);
74 // **************************************************************************
75 // HP 100LX / HP 200LX .ICN icon format
76 // **************************************************************************
83 static void read_hpicn_params(deark
*c
, struct hpicn_params
*icnp
)
85 icnp
->w
= de_getu16le(4);
86 icnp
->h
= de_getu16le(6);
87 icnp
->rowspan
= (icnp
->w
+7)/8;
90 static void de_run_hpicn(deark
*c
, de_module_params
*mparams
)
92 struct hpicn_params icnp
;
94 read_hpicn_params(c
, &icnp
);
95 de_dbg_dimensions(c
, icnp
.w
, icnp
.h
);
96 de_convert_and_write_image_bilevel2(c
->infile
, 8, icnp
.w
, icnp
.h
, icnp
.rowspan
,
97 DE_CVTF_WHITEISZERO
, NULL
, 0);
100 static int de_identify_hpicn(deark
*c
)
102 struct hpicn_params icnp
;
104 if(dbuf_memcmp(c
->infile
, 0, "\x01\x00\x01\x00", 4))
106 read_hpicn_params(c
, &icnp
);
107 if(8 + icnp
.rowspan
*icnp
.h
!= c
->infile
->len
) return 0;
108 if(icnp
.w
<1 || icnp
.w
>2048 || icnp
.h
<1 || icnp
.h
>2048) return 0;
109 if(icnp
.w
==44 && icnp
.h
==32) return 100;
113 void de_module_hpicn(deark
*c
, struct deark_module_info
*mi
)
116 mi
->desc
= "HP 100LX/200LX .ICN icon";
117 mi
->run_fn
= de_run_hpicn
;
118 mi
->identify_fn
= de_identify_hpicn
;
121 // **************************************************************************
122 // X11 "puzzle" format
123 // ftp://ftp.x.org/pub/unsupported/programs/puzzle/
124 // This is the format generated by Netpbm's ppmtopuzz utility.
125 // **************************************************************************
132 static void xpuzz_read_header(deark
*c
, struct xpuzzhdr
*hdr
)
134 hdr
->w
= de_getu32be(0);
135 hdr
->h
= de_getu32be(4);
136 hdr
->palentries
= (i64
)de_getbyte(8);
137 if(hdr
->palentries
==0) hdr
->palentries
= 256;
140 static void de_run_xpuzzle(deark
*c
, de_module_params
*mparams
)
142 de_bitmap
*img
= NULL
;
147 xpuzz_read_header(c
, &hdr
);
148 de_dbg_dimensions(c
, hdr
.w
, hdr
.h
);
149 if(!de_good_image_dimensions(c
, hdr
.w
, hdr
.h
)) goto done
;
151 img
= de_bitmap_create(c
, hdr
.w
, hdr
.h
, 3);
155 de_read_simple_palette(c
, c
->infile
, p
, hdr
.palentries
, 3, pal
, 256,
156 DE_RDPALTYPE_24BIT
, DE_RDPALFLAG_INITPAL
);
157 p
+= 3*hdr
.palentries
;
160 de_convert_image_paletted(c
->infile
, p
, 8, hdr
.w
, pal
, img
, 0);
162 de_bitmap_write_to_file(img
, NULL
, 0);
165 de_bitmap_destroy(img
);
168 static int de_identify_xpuzzle(deark
*c
)
173 xpuzz_read_header(c
, &hdr
);
174 // 4096 is an arbitrary limit.
175 if(hdr
.w
<1 || hdr
.w
>4096 || hdr
.h
<1 || hdr
.h
>4096) goto done
;
176 if(hdr
.w
* hdr
.h
+ 3*hdr
.palentries
+ 9 == c
->infile
->len
) {
184 void de_module_xpuzzle(deark
*c
, struct deark_module_info
*mi
)
187 mi
->desc
= "X11 \"puzzle\" image";
188 mi
->run_fn
= de_run_xpuzzle
;
189 mi
->identify_fn
= de_identify_xpuzzle
;
192 // **************************************************************************
193 // "Bob" bitmap image
194 // Used by the Bob ray tracer.
195 // **************************************************************************
197 static void de_run_bob(deark
*c
, de_module_params
*mparams
)
199 de_bitmap
*img
= NULL
;
206 if(!de_good_image_dimensions(c
, w
, h
)) goto done
;
207 img
= de_bitmap_create(c
, w
, h
, 3);
211 de_read_simple_palette(c
, c
->infile
, p
, 256, 3, pal
, 256, DE_RDPALTYPE_24BIT
, 0);
215 de_convert_image_paletted(c
->infile
, p
, 8, w
, pal
, img
, 0);
217 de_bitmap_write_to_file(img
, NULL
, 0);
220 de_bitmap_destroy(img
);
223 static int de_identify_bob(deark
*c
)
227 if(!de_input_file_has_ext(c
, "bob")) return 0;
231 if(c
->infile
->len
== 4 + 768 + w
*h
) {
237 void de_module_bob(deark
*c
, struct deark_module_info
*mi
)
240 mi
->desc
= "Bob Ray Tracer bitmap image";
241 mi
->run_fn
= de_run_bob
;
242 mi
->identify_fn
= de_identify_bob
;
245 // **************************************************************************
246 // Alias PIX bitmap image.
247 // Also used by the Vivid ray tracer.
248 // **************************************************************************
250 static void de_run_alias_pix(deark
*c
, de_module_params
*mparams
)
252 de_bitmap
*img
= NULL
;
264 firstline
= de_getu16be(4);
265 depth
= de_getu16be(8);
267 if(!de_good_image_dimensions(c
, w
, h
)) goto done
;
268 if(firstline
>= h
) goto done
;
270 de_err(c
, "Unsupported image type");
274 img
= de_bitmap_create(c
, w
, h
, 3);
278 // I don't know for sure what to do with the "first scanline" field, in the
279 // unlikely event it is not 0. The documentation doesn't say.
282 if(pos
+4 > c
->infile
->len
) {
285 runlen
= (i64
)de_getbyte(pos
);
286 clr
= dbuf_getRGB(c
->infile
, pos
+1, DE_GETRGBFLAG_BGR
);
289 for(i
=0; i
<runlen
; i
++) {
290 de_bitmap_setpixel_rgb(img
, xpos
, ypos
, clr
);
291 xpos
++; // Runs are not allowed to span rows
300 de_bitmap_write_to_file(img
, NULL
, 0);
302 de_bitmap_destroy(img
);
305 static int de_identify_alias_pix(deark
*c
)
307 i64 w
, h
, firstline
, lastline
, depth
;
309 if(!de_input_file_has_ext(c
, "img") &&
310 !de_input_file_has_ext(c
, "als") &&
311 !de_input_file_has_ext(c
, "pix"))
318 firstline
= de_getu16be(4);
319 lastline
= de_getu16be(6);
320 depth
= de_getu16be(8);
322 if(depth
!=24) return 0;
323 if(firstline
>lastline
) return 0;
324 // 'lastline' should usually be h-1, but XnView apparently sets it to h.
325 if(firstline
>h
-1 || lastline
>h
) return 0;
326 if(!de_good_image_dimensions_noerr(c
, w
, h
)) return 0;
330 void de_module_alias_pix(deark
*c
, struct deark_module_info
*mi
)
332 mi
->id
= "alias_pix";
333 mi
->id_alias
[0] = "vivid";
334 mi
->desc
= "Alias PIX image, Vivid .IMG";
335 mi
->run_fn
= de_run_alias_pix
;
336 mi
->identify_fn
= de_identify_alias_pix
;
339 // **************************************************************************
340 // Apple volume label image
341 // Written by netpbm: ppmtoapplevol
342 // **************************************************************************
344 static u8
applevol_get_gray_shade(u8 clr
)
347 // TODO: These gray shades may not be quite right. I can't find good
348 // information about them.
349 case 0x00: return 0xff;
350 case 0xf6: return 0xee;
351 case 0xf7: return 0xdd;
352 case 0x2a: return 0xcc;
353 case 0xf8: return 0xbb;
354 case 0xf9: return 0xaa;
355 case 0x55: return 0x99;
356 case 0xfa: return 0x88;
357 case 0xfb: return 0x77;
358 case 0x80: return 0x66;
359 case 0xfc: return 0x55;
360 case 0xfd: return 0x44;
361 case 0xab: return 0x33;
362 case 0xfe: return 0x22;
363 case 0xff: return 0x11;
364 case 0xd6: return 0x00;
369 static void de_run_applevol(deark
*c
, de_module_params
*mparams
)
371 de_bitmap
*img
= NULL
;
379 if(!de_good_image_dimensions(c
, w
, h
)) goto done
;
380 img
= de_bitmap_create(c
, w
, h
, 1);
385 palent
= de_getbyte(p
+w
*j
+i
);
386 de_bitmap_setpixel_gray(img
, i
, j
, applevol_get_gray_shade(palent
));
390 de_bitmap_write_to_file(img
, NULL
, 0);
393 de_bitmap_destroy(img
);
396 static int de_identify_applevol(deark
*c
)
400 de_read(buf
, 0, sizeof(buf
));
402 if(buf
[0]==0x01 && buf
[3]==0x00 && buf
[4]==0x0c)
407 void de_module_applevol(deark
*c
, struct deark_module_info
*mi
)
410 mi
->desc
= "Apple volume label image";
411 mi
->run_fn
= de_run_applevol
;
412 mi
->identify_fn
= de_identify_applevol
;
415 // **************************************************************************
416 // TRS-80 "HR" ("High Resolution") image
417 // **************************************************************************
419 static void de_run_hr(deark
*c
, de_module_params
*mparams
)
421 de_bitmap
*img
= NULL
;
424 fi
= de_finfo_create(c
);
425 fi
->density
.code
= DE_DENSITY_UNK_UNITS
;
426 fi
->density
.xdens
= 2;
427 fi
->density
.ydens
= 1;
428 img
= de_bitmap_create(c
, 640, 240, 1);
429 de_convert_image_bilevel(c
->infile
, 0, 640/8, img
, 0);
430 de_bitmap_write_to_file_finfo(img
, fi
, DE_CREATEFLAG_IS_BWIMG
);
431 de_bitmap_destroy(img
);
432 de_finfo_destroy(c
, fi
);
435 static int de_identify_hr(deark
*c
)
437 if(de_input_file_has_ext(c
, "hr")) {
438 if(c
->infile
->len
==19200) return 70;
439 if(c
->infile
->len
>19200 && c
->infile
->len
<=19456) return 30;
444 void de_module_hr(deark
*c
, struct deark_module_info
*mi
)
447 mi
->desc
= "TRS-80 HR (High Resolution) image";
448 mi
->run_fn
= de_run_hr
;
449 mi
->identify_fn
= de_identify_hr
;
452 // **************************************************************************
453 // RIPterm icon (.ICN)
454 // **************************************************************************
456 // Don't know what this should be, but a limit will help us decide what is
457 // and isn't an image.
458 #define MAX_RIPICON_DIMENSION 2048
460 static int do_one_ripicon(deark
*c
, i64 pos1
, i64
*pbytes_consumed
, int scan_mode
)
463 de_bitmap
*img
= NULL
;
468 int saved_indent_level
;
471 if(pos1
+8 > c
->infile
->len
) return 0;
472 width
= 1 + de_getu16le_p(&pos
);
473 height
= 1 + de_getu16le_p(&pos
);
474 if(width
>MAX_RIPICON_DIMENSION
|| height
>MAX_RIPICON_DIMENSION
) return 0;
475 chunk_span
= (width
+7)/8;
476 src_rowspan
= 4*chunk_span
;
477 bitmap_len
= src_rowspan
* height
;
478 if(pos
+bitmap_len
> c
->infile
->len
) return 0;
480 *pbytes_consumed
= 4 + bitmap_len
+ 2;
481 if(scan_mode
) return 1;
483 de_dbg_indent_save(c
, &saved_indent_level
);
484 de_dbg(c
, "image at %"I64_FMT
, pos1
);
486 de_dbg_dimensions(c
, width
, height
);
488 de_dbg(c
, "bitmap at %"I64_FMT
", len=%"I64_FMT
, pos
, bitmap_len
);
489 if(!de_good_image_dimensions(c
, width
, height
)) goto done
;
490 img
= de_bitmap_create2(c
, width
, chunk_span
*8, height
, 3);
491 de_copy_std_palette(DE_PALID_PC16
, 0, 0, pal
, 16, 0);
492 de_convert_image_paletted_planar(c
->infile
, pos
, 4, src_rowspan
, chunk_span
,
494 de_bitmap_write_to_file(img
, NULL
, DE_CREATEFLAG_OPT_IMAGE
);
497 if(img
) de_bitmap_destroy(img
);
498 de_dbg_indent_restore(c
, saved_indent_level
);
502 static void de_run_ripicon(deark
*c
, de_module_params
*mparams
)
507 i64 bytes_consumed
= 0;
509 if(!do_one_ripicon(c
, pos
, &bytes_consumed
, 0)) break;
510 pos
+= bytes_consumed
;
514 static int de_identify_ripicon(deark
*c
)
519 static const char *exts
[] = { "icn", "hot", "msk", "bgi" };
521 for(i
=0; i
<DE_ARRAYCOUNT(exts
); i
++) {
522 if(de_input_file_has_ext(c
, exts
[i
])) {
527 if(!has_ext
) return 0;
530 i64 bytes_consumed
= 0;
532 if(!do_one_ripicon(c
, pos
, &bytes_consumed
, 1)) break;
533 pos
+= bytes_consumed
;
534 if(pos
== c
->infile
->len
) return 50;
539 void de_module_ripicon(deark
*c
, struct deark_module_info
*mi
)
542 mi
->desc
= "RIP/RIPscrip/RIPterm Icon / BGI image";
543 mi
->run_fn
= de_run_ripicon
;
544 mi
->identify_fn
= de_identify_ripicon
;
547 // **************************************************************************
548 // LSS16 image (Used by SYSLINUX)
549 // **************************************************************************
553 int nextnibble_valid
;
557 static u8
lss16_get_nibble(deark
*c
, struct lss16ctx
*d
)
560 if(d
->nextnibble_valid
) {
561 d
->nextnibble_valid
= 0;
562 return d
->nextnibble
;
564 n
= de_getbyte(d
->pos
);
566 // The low nibble of each byte is interpreted first.
567 // Record the high nibble, and return the low nibble.
568 d
->nextnibble
= (n
&0xf0)>>4;
569 d
->nextnibble_valid
= 1;
573 static void de_run_lss16(deark
*c
, de_module_params
*mparams
)
575 struct lss16ctx
*d
= NULL
;
576 de_bitmap
*img
= NULL
;
585 d
= de_malloc(c
, sizeof(struct lss16ctx
));
588 width
= de_getu16le(d
->pos
);
589 height
= de_getu16le(d
->pos
+2);
590 de_dbg_dimensions(c
, width
, height
);
591 if(!de_good_image_dimensions(c
, width
, height
)) goto done
;
594 de_read_simple_palette(c
, c
->infile
, d
->pos
, 16, 3, pal
, 16, DE_RDPALTYPE_VGA18BIT
, 0);
597 img
= de_bitmap_create(c
, width
, height
, 3);
601 while(d
->pos
<c
->infile
->len
&& ypos
<height
) {
602 n
= lss16_get_nibble(c
, d
);
606 run_len
= (i64
)lss16_get_nibble(c
, d
);
608 run_len
= lss16_get_nibble(c
, d
);
609 run_len
|= ((i64
)lss16_get_nibble(c
, d
)<<4);
612 for(i
=0; i
<run_len
; i
++) {
613 de_bitmap_setpixel_rgb(img
, xpos
, ypos
, pal
[prev
]);
618 // An uncompressed pixel
619 de_bitmap_setpixel_rgb(img
, xpos
, ypos
, pal
[n
]);
624 // End of row reached?
628 d
->nextnibble_valid
= 0;
633 de_bitmap_write_to_file(img
, NULL
, 0);
635 de_bitmap_destroy(img
);
639 static int de_identify_lss16(deark
*c
)
641 if(!dbuf_memcmp(c
->infile
, 0, "\x3d\xf3\x13\x14", 4))
646 void de_module_lss16(deark
*c
, struct deark_module_info
*mi
)
649 mi
->desc
= "SYSLINUX LSS16 image";
650 mi
->run_fn
= de_run_lss16
;
651 mi
->identify_fn
= de_identify_lss16
;
654 // **************************************************************************
656 // **************************************************************************
658 static void de_run_vbm(deark
*c
, de_module_params
*mparams
)
665 // TODO: Support VBM v3.
666 de_err(c
, "Unsupported VBM version (%d)", (int)ver
);
669 width
= de_getu16be(4);
670 height
= de_getu16be(6);
671 de_convert_and_write_image_bilevel2(c
->infile
, 8, width
, height
, (width
+7)/8,
672 DE_CVTF_WHITEISZERO
, NULL
, 0);
675 // Note that this function must work together with de_identify_bmp().
676 static int de_identify_vbm(deark
*c
)
680 if(de_memcmp(b
, "BM\xcb", 3)) return 0;
681 if(b
[3]!=2 && b
[3]!=3) return 0;
682 if(de_input_file_has_ext(c
, "vbm")) return 100;
686 void de_module_vbm(deark
*c
, struct deark_module_info
*mi
)
689 mi
->desc
= "C64/128 VBM (VDC BitMap)";
690 mi
->run_fn
= de_run_vbm
;
691 mi
->identify_fn
= de_identify_vbm
;
694 // **************************************************************************
695 // PFS: 1st Publisher clip art (.ART)
696 // **************************************************************************
698 static void de_run_fp_art(deark
*c
, de_module_params
*mparams
)
703 width
= de_getu16le(2);
704 height
= de_getu16le(6);
705 rowspan
= ((width
+15)/16)*2;
706 de_convert_and_write_image_bilevel2(c
->infile
, 8, width
, height
, rowspan
, 0, NULL
, 0);
709 static int de_identify_fp_art(deark
*c
)
714 if(!de_input_file_has_ext(c
, "art")) return 0;
716 width
= de_getu16le(2);
717 height
= de_getu16le(6);
718 rowspan
= ((width
+15)/16)*2;
719 if(8 + rowspan
*height
== c
->infile
->len
) {
726 void de_module_fp_art(deark
*c
, struct deark_module_info
*mi
)
729 mi
->desc
= "PFS: 1st Publisher clip art (.ART)";
730 mi
->run_fn
= de_run_fp_art
;
731 mi
->identify_fn
= de_identify_fp_art
;
734 // **************************************************************************
736 // **************************************************************************
738 static void de_run_ybm(deark
*c
, de_module_params
*mparams
)
740 de_bitmap
*img
= NULL
;
741 i64 npwidth
, pdwidth
, height
;
747 npwidth
= de_getu16be_p(&pos
);
748 height
= de_getu16be_p(&pos
);
749 de_dbg_dimensions(c
, npwidth
, height
);
750 if(!de_good_image_dimensions(c
, npwidth
, height
)) goto done
;
751 pdwidth
= de_pad_to_n(npwidth
, 16);
752 words_per_row
= pdwidth
/16;
754 img
= de_bitmap_create2(c
, npwidth
, pdwidth
, height
, 1);
756 for(j
=0; j
<height
; j
++) {
757 for(i
=0; i
<words_per_row
; i
++) {
760 // This encoding is unusual: LSB-first 16-bit integers.
761 x
= de_getbyte_p(&pos
);
762 de_unpack_pixels_bilevel_from_byte(img
, i
*16+8, j
, x
, 8,
763 DE_CVTF_WHITEISZERO
|DE_CVTF_LSBFIRST
|DE_CVTF_ONLYWHITE
);
764 x
= de_getbyte_p(&pos
);
765 de_unpack_pixels_bilevel_from_byte(img
, i
*16, j
, x
, 8,
766 DE_CVTF_WHITEISZERO
|DE_CVTF_LSBFIRST
|DE_CVTF_ONLYWHITE
);
769 de_bitmap_write_to_file(img
, NULL
, 0);
772 de_bitmap_destroy(img
);
775 static int de_identify_ybm(deark
*c
)
780 if(dbuf_memcmp(c
->infile
, 0, "!!", 2))
782 width
= de_getu16be(2);
783 height
= de_getu16be(4);
784 rowspan
= ((width
+15)/16)*2;
785 if(6+height
*rowspan
== c
->infile
->len
)
790 void de_module_ybm(deark
*c
, struct deark_module_info
*mi
)
793 mi
->desc
= "Bennet Yee's face format, a.k.a. YBM";
794 mi
->run_fn
= de_run_ybm
;
795 mi
->identify_fn
= de_identify_ybm
;
798 // **************************************************************************
799 // OLPC .565 firmware icon
800 // **************************************************************************
802 static void de_run_olpc565(deark
*c
, de_module_params
*mparams
)
804 de_bitmap
*img
= NULL
;
811 width
= de_getu16le(4);
812 height
= de_getu16le(6);
813 if(!de_good_image_dimensions(c
, width
, height
)) goto done
;
816 img
= de_bitmap_create(c
, width
, height
, 3);
818 for(j
=0; j
<height
; j
++) {
819 for(i
=0; i
<width
; i
++) {
820 b0
= de_getbyte(8 + j
*rowspan
+ i
*2);
821 b1
= de_getbyte(8 + j
*rowspan
+ i
*2 + 1);
822 clr
= (((u32
)b1
)<<8) | b0
;
823 clr
= de_rgb565_to_888(clr
);
824 de_bitmap_setpixel_rgb(img
, i
, j
, clr
);
827 de_bitmap_write_to_file(img
, NULL
, 0);
830 de_bitmap_destroy(img
);
833 static int de_identify_olpc565(deark
*c
)
835 if(!dbuf_memcmp(c
->infile
, 0, "C565", 4))
840 void de_module_olpc565(deark
*c
, struct deark_module_info
*mi
)
843 mi
->desc
= "OLPC .565 firmware icon";
844 mi
->run_fn
= de_run_olpc565
;
845 mi
->identify_fn
= de_identify_olpc565
;
848 // **************************************************************************
850 // **************************************************************************
852 static void de_run_iim(deark
*c
, de_module_params
*mparams
)
854 de_bitmap
*img
= NULL
;
861 // This code is based on reverse engineering, and may be incorrect.
863 n
= de_getu16be(8); // Unknown field
864 bpp
= de_getu16be(10);
865 if(n
!=4 || bpp
!=24) {
866 de_dbg(c
, "This type of IIM image is not supported");
869 width
= de_getu16be(12);
870 height
= de_getu16be(14);
871 if(!de_good_image_dimensions(c
, width
, height
)) goto done
;
874 img
= de_bitmap_create(c
, width
, height
, 3);
876 for(j
=0; j
<height
; j
++) {
877 for(i
=0; i
<width
; i
++) {
878 clr
= dbuf_getRGB(c
->infile
, 16+j
*rowspan
+i
*3, 0);
879 de_bitmap_setpixel_rgb(img
, i
, j
, clr
);
882 de_bitmap_write_to_file(img
, NULL
, 0);
885 de_bitmap_destroy(img
);
888 static int de_identify_iim(deark
*c
)
890 if(!dbuf_memcmp(c
->infile
, 0, "IS_IMAGE", 8))
895 void de_module_iim(deark
*c
, struct deark_module_info
*mi
)
898 mi
->desc
= "InShape IIM";
899 mi
->run_fn
= de_run_iim
;
900 mi
->identify_fn
= de_identify_iim
;
903 // **************************************************************************
904 // PM (format supported by the XV image viewer)
905 // **************************************************************************
907 static void de_run_pm_xv(deark
*c
, de_module_params
*mparams
)
909 de_bitmap
*img
= NULL
;
923 if(!dbuf_memcmp(c
->infile
, 0, "WEIV", 4))
928 nplanes
= dbuf_geti32x(c
->infile
, 4, is_le
);
929 de_dbg(c
, "planes: %d", (int)nplanes
);
931 height
= dbuf_geti32x(c
->infile
, 8, is_le
);
932 width
= dbuf_geti32x(c
->infile
, 12, is_le
);
933 de_dbg_dimensions(c
, width
, height
);
934 if(!de_good_image_dimensions(c
, width
, height
)) goto done
;
936 nbands
= dbuf_geti32x(c
->infile
, 16, is_le
);
937 de_dbg(c
, "bands: %d", (int)nbands
);
939 pixelformat
= dbuf_geti32x(c
->infile
, 20, is_le
);
940 de_dbg(c
, "pixel format: 0x%04x", (unsigned int)pixelformat
);
942 commentsize
= dbuf_geti32x(c
->infile
, 24, is_le
);
943 de_dbg(c
, "comment size: %d", (int)commentsize
);
947 if((pixelformat
==0x8001 && nplanes
==3 && nbands
==1) ||
948 (pixelformat
==0x8001 && nplanes
==1 && nbands
==1))
953 de_err(c
, "Unsupported image type (pixel format=0x%04x, "
954 "planes=%d, bands=%d)", (unsigned int)pixelformat
,
955 (int)nplanes
, (int)nbands
);
960 planespan
= rowspan
*height
;
962 img
= de_bitmap_create(c
, width
, height
, (int)nplanes
);
964 for(plane
=0; plane
<nplanes
; plane
++) {
965 for(j
=0; j
<height
; j
++) {
966 for(i
=0; i
<width
; i
++) {
967 b
= de_getbyte(pos
+ plane
*planespan
+ j
*rowspan
+ i
);
969 de_bitmap_setsample(img
, i
, j
, plane
, b
);
972 de_bitmap_setpixel_gray(img
, i
, j
, b
);
977 de_bitmap_write_to_file(img
, NULL
, 0);
980 de_bitmap_destroy(img
);
983 static int de_identify_pm_xv(deark
*c
)
985 if(!dbuf_memcmp(c
->infile
, 0, "VIEW", 4))
987 if(!dbuf_memcmp(c
->infile
, 0, "WEIV", 4))
992 void de_module_pm_xv(deark
*c
, struct deark_module_info
*mi
)
995 mi
->desc
= "PM (XV)";
996 mi
->run_fn
= de_run_pm_xv
;
997 mi
->identify_fn
= de_identify_pm_xv
;
1000 // **************************************************************************
1001 // Calamus Raster Graphic - CRG
1002 // **************************************************************************
1004 // Warning: The CRG decoder is based on reverse engineering, may not be
1005 // correct, and is definitely incomplete.
1007 static void de_run_crg(deark
*c
, de_module_params
*mparams
)
1016 dbuf
*unc_pixels
= NULL
;
1018 width
= de_getu32be(20);
1019 height
= de_getu32be(24);
1020 de_dbg_dimensions(c
, width
, height
);
1021 if(!de_good_image_dimensions(c
, width
, height
)) goto done
;
1023 b1
= de_getbyte(32);
1025 de_err(c
, "Unsupported CRG format");
1029 num_cmpr_bytes
= de_getu32be(38);
1030 de_dbg(c
, "compressed data size: %d", (int)num_cmpr_bytes
);
1031 cmpr_img_start
= 42;
1033 if(cmpr_img_start
+ num_cmpr_bytes
> c
->infile
->len
) {
1034 num_cmpr_bytes
= c
->infile
->len
- cmpr_img_start
;
1037 // Uncompress the image
1038 rowspan
= (width
+7)/8;
1039 unc_pixels
= dbuf_create_membuf(c
, height
*rowspan
, 1);
1041 pos
= cmpr_img_start
;
1042 while(pos
< cmpr_img_start
+ num_cmpr_bytes
) {
1043 b1
= de_getbyte(pos
++);
1044 if(b1
<=0x7f) { // Uncompressed bytes
1046 dbuf_copy(c
->infile
, pos
, count
, unc_pixels
);
1049 else { // A compressed run
1050 b2
= de_getbyte(pos
++);
1051 count
= (i64
)(b1
-127);
1052 dbuf_write_run(unc_pixels
, b2
, count
);
1055 de_dbg(c
, "decompressed to %d bytes", (int)unc_pixels
->len
);
1057 de_convert_and_write_image_bilevel2(unc_pixels
, 0, width
, height
, rowspan
,
1058 DE_CVTF_WHITEISZERO
, NULL
, 0);
1061 dbuf_close(unc_pixels
);
1064 static int de_identify_crg(deark
*c
)
1066 if(!dbuf_memcmp(c
->infile
, 0, "CALAMUSCRG", 10))
1071 void de_module_crg(deark
*c
, struct deark_module_info
*mi
)
1074 mi
->desc
= "Calamus Raster Graphic";
1075 mi
->run_fn
= de_run_crg
;
1076 mi
->identify_fn
= de_identify_crg
;
1079 // **************************************************************************
1081 // **************************************************************************
1083 static void de_run_farbfeld(deark
*c
, de_module_params
*mparams
)
1085 de_bitmap
*imghi
= NULL
; // high 8 bits of each sample
1086 de_bitmap
*imglo
= NULL
; // low 8 bits of each sample
1093 width
= de_getu32be(8);
1094 height
= de_getu32be(12);
1095 de_dbg_dimensions(c
, width
, height
);
1096 if(!de_good_image_dimensions(c
, width
, height
)) return;
1098 imghi
= de_bitmap_create(c
, width
, height
, 4);
1099 imglo
= de_bitmap_create(c
, width
, height
, 4);
1101 for(j
=0; j
<height
; j
++) {
1102 for(i
=0; i
<width
; i
++) {
1103 ppos
= 16 + 8*(width
*j
+ i
);
1104 for(k
=0; k
<4; k
++) {
1105 sh
[k
] = de_getbyte(ppos
+2*k
);
1106 sl
[k
] = de_getbyte(ppos
+2*k
+1);
1108 de_bitmap_setpixel_rgba(imghi
, i
, j
,
1109 DE_MAKE_RGBA(sh
[0],sh
[1],sh
[2],sh
[3]));
1110 de_bitmap_setpixel_rgba(imglo
, i
, j
,
1111 DE_MAKE_RGBA(sl
[0],sl
[1],sl
[2],sl
[3]));
1114 de_bitmap16_write_to_file_finfo(imghi
, imglo
, NULL
, DE_CREATEFLAG_OPT_IMAGE
);
1115 de_bitmap_destroy(imghi
);
1116 de_bitmap_destroy(imglo
);
1119 static int de_identify_farbfeld(deark
*c
)
1121 if(!dbuf_memcmp(c
->infile
, 0, "farbfeld", 8))
1126 void de_module_farbfeld(deark
*c
, struct deark_module_info
*mi
)
1128 mi
->id
= "farbfeld";
1129 mi
->desc
= "farbfeld image";
1130 mi
->run_fn
= de_run_farbfeld
;
1131 mi
->identify_fn
= de_identify_farbfeld
;
1134 // **************************************************************************
1135 // HSI Raw image format (from Image Alchemy / Handmade Software)
1136 // **************************************************************************
1138 static void de_run_hsiraw(deark
*c
, de_module_params
*mparams
)
1147 de_bitmap
*img
= NULL
;
1151 ver
= de_getu16be(6);
1152 de_dbg(c
, "version: %d", (int)ver
);
1154 de_warn(c
, "HSI Raw version %d might not be supported correctly", (int)ver
);
1159 // MPlayer extension?
1160 de_dbg2(c
, "reading 32-bit width");
1161 w
= de_getu32be(28);
1163 h
= de_getu16be(10);
1164 de_dbg_dimensions(c
, w
, h
);
1165 num_pal_colors
= de_getu16be(12);
1166 de_dbg(c
, "number of palette colors: %d", (int)num_pal_colors
);
1168 hdpi
= de_geti16be(14);
1169 vdpi
= de_geti16be(16);
1170 de_dbg(c
, "density: %d"DE_CHAR_TIMES
"%d", (int)hdpi
, (int)vdpi
);
1172 cmpr
= de_getu16be(20);
1173 de_dbg(c
, "compression: %d", (int)cmpr
);
1174 alpha_info
= de_getu16be(22);
1175 de_dbg(c
, "alpha: %d", (int)alpha_info
);
1177 if(num_pal_colors
>256 || cmpr
!=0 || alpha_info
!=0) {
1178 de_err(c
, "This type of HSI Raw image is not supported");
1181 if(!de_good_image_dimensions(c
, w
, h
)) goto done
;
1184 de_zeromem(pal
, sizeof(pal
));
1185 if(num_pal_colors
==0) { // 24-bit RGB
1188 else { // 8-bit paletted
1189 de_read_simple_palette(c
, c
->infile
, pos
, num_pal_colors
, 3, pal
, 256,
1190 DE_RDPALTYPE_24BIT
, 0);
1191 pos
+= 3*num_pal_colors
;
1192 is_grayscale
= de_is_grayscale_palette(pal
, num_pal_colors
);
1195 img
= de_bitmap_create(c
, w
, h
, is_grayscale
?1:3);
1197 if(num_pal_colors
==0) {
1198 de_convert_image_rgb(c
->infile
, pos
, 3*w
, 3, img
, 0);
1201 de_convert_image_paletted(c
->infile
, pos
, 8, w
, pal
, img
, 0);
1204 de_bitmap_write_to_file(img
, NULL
, 0);
1207 de_bitmap_destroy(img
);
1210 static int de_identify_hsiraw(deark
*c
)
1212 if(!dbuf_memcmp(c
->infile
, 0, "mhwanh", 6))
1217 void de_module_hsiraw(deark
*c
, struct deark_module_info
*mi
)
1220 mi
->desc
= "HSI Raw";
1221 mi
->run_fn
= de_run_hsiraw
;
1222 mi
->identify_fn
= de_identify_hsiraw
;
1225 // **************************************************************************
1227 // **************************************************************************
1229 static void de_run_qdv(deark
*c
, de_module_params
*mparams
)
1234 de_bitmap
*img
= NULL
;
1237 // Warning: This decoder is based on reverse engineering, and may be
1238 // incorrect or incomplete.
1242 de_dbg_dimensions(c
, w
, h
);
1243 if(!de_good_image_dimensions(c
, w
, h
)) goto done
;
1245 num_pal_colors
= 1 + (i64
)de_getbyte(4);
1246 de_dbg(c
, "number of palette colors: %d", (int)num_pal_colors
);
1249 de_read_simple_palette(c
, c
->infile
, pos
, num_pal_colors
, 3, pal
, 256,
1250 DE_RDPALTYPE_24BIT
, DE_RDPALFLAG_INITPAL
);
1251 pos
+= 3*num_pal_colors
;
1253 img
= de_bitmap_create(c
, w
, h
, 3);
1254 de_convert_image_paletted(c
->infile
, pos
, 8, w
, pal
, img
, 0);
1255 de_bitmap_write_to_file(img
, NULL
, 0);
1258 de_bitmap_destroy(img
);
1261 static int de_identify_qdv(deark
*c
)
1268 num_pal_colors
= 1 + (i64
)de_getbyte(4);
1269 if(5+num_pal_colors
*3+w
*h
!= c
->infile
->len
)
1271 if(de_input_file_has_ext(c
, "qdv"))
1276 void de_module_qdv(deark
*c
, struct deark_module_info
*mi
)
1279 mi
->desc
= "QDV (Giffer)";
1280 mi
->run_fn
= de_run_qdv
;
1281 mi
->identify_fn
= de_identify_qdv
;
1284 // **************************************************************************
1285 // VITec image format
1286 // **************************************************************************
1288 static void de_run_vitec(deark
*c
, de_module_params
*mparams
)
1290 i64 npwidth
, pdwidth
, h
;
1292 de_bitmap
*img
= NULL
;
1293 i64 samplesperpixel
;
1294 i64 rowspan
, planespan
;
1298 int saved_indent_level
;
1300 // This code is based on reverse engineering, and may be incorrect.
1302 de_dbg_indent_save(c
, &saved_indent_level
);
1303 de_warn(c
, "VITec image support is experimental, and may not work correctly.");
1306 h1size
= de_getu32be(pos
);
1307 de_dbg(c
, "header 1 at %d, len=%d", (int)pos
, (int)h1size
);
1308 // Don't know what's in this part of the header. Just ignore it.
1310 if(pos
>=c
->infile
->len
) goto done
;
1312 h2size
= de_getu32be(pos
);
1313 de_dbg(c
, "header 2 at %d, len=%d", (int)pos
, (int)h2size
);
1314 de_dbg_indent(c
, 1);
1316 // pos+4: Bits size?
1317 // pos+24: Unknown field, usually 7
1319 npwidth
= de_getu32be(pos
+36);
1320 h
= de_getu32be(pos
+40);
1321 de_dbg_dimensions(c
, npwidth
, h
);
1322 if(!de_good_image_dimensions(c
, npwidth
, h
)) goto done
;
1324 // pos+52: Unknown field, 1 in grayscale images
1326 samplesperpixel
= de_getu32be(pos
+56);
1327 de_dbg(c
, "samples/pixel: %d", (int)samplesperpixel
);
1328 if(samplesperpixel
!=1 && samplesperpixel
!=3) {
1329 de_err(c
, "Unsupported samples/pixel: %d", (int)samplesperpixel
);
1334 if(pos
>=c
->infile
->len
) goto done
;
1335 de_dbg_indent(c
, -1);
1337 de_dbg(c
, "bitmap at %d", (int)pos
);
1338 pdwidth
= de_pad_to_n(npwidth
, 8);
1339 img
= de_bitmap_create2(c
, npwidth
, pdwidth
, h
, (int)samplesperpixel
);
1341 planespan
= rowspan
*h
;
1343 for(plane
=0; plane
<samplesperpixel
; plane
++) {
1344 for(j
=0; j
<h
; j
++) {
1345 for(i
=0; i
<pdwidth
; i
++) {
1346 b
= de_getbyte(pos
+ plane
*planespan
+ j
*rowspan
+ i
);
1347 if(samplesperpixel
==3) {
1348 de_bitmap_setsample(img
, i
, j
, plane
, b
);
1351 de_bitmap_setpixel_gray(img
, i
, j
, b
);
1357 de_bitmap_write_to_file(img
, NULL
, 0);
1360 de_bitmap_destroy(img
);
1361 de_dbg_indent_restore(c
, saved_indent_level
);
1364 static int de_identify_vitec(deark
*c
)
1366 if(!dbuf_memcmp(c
->infile
, 0, "\x00\x5b\x07\x20", 4))
1371 void de_module_vitec(deark
*c
, struct deark_module_info
*mi
)
1374 mi
->desc
= "VITec image format";
1375 mi
->run_fn
= de_run_vitec
;
1376 mi
->identify_fn
= de_identify_vitec
;
1379 // **************************************************************************
1382 // .HS2 format is associated with a program called POSTERING.
1383 // **************************************************************************
1385 static void de_run_hs2(deark
*c
, de_module_params
*mparams
)
1392 height
= (c
->infile
->len
+(rowspan
-1))/rowspan
;
1393 de_convert_and_write_image_bilevel(c
->infile
, 0, width
, height
, rowspan
, 0, NULL
, 0);
1396 static int de_identify_hs2(deark
*c
)
1398 if(!de_input_file_has_ext(c
, "hs2")) return 0;
1399 if(c
->infile
->len
>0 && (c
->infile
->len
%105 == 0)) {
1405 void de_module_hs2(deark
*c
, struct deark_module_info
*mi
)
1408 mi
->desc
= "HS2 (POSTERING)";
1409 mi
->run_fn
= de_run_hs2
;
1410 mi
->identify_fn
= de_identify_hs2
;
1414 // **************************************************************************
1416 // **************************************************************************
1418 static void de_run_lumena_cel(deark
*c
, de_module_params
*mparams
)
1427 de_bitmap
*img
= NULL
;
1428 const i64 headersize
= 4;
1431 width
= de_getu16le(0);
1432 height
= de_getu16le(2);
1433 if(!de_good_image_dimensions_noerr(c
, width
, height
)) goto done
;
1435 // TODO: Support multi-image files
1436 is_16bit
= (c
->infile
->len
== headersize
+ width
*height
*2);
1437 is_32bit
= (c
->infile
->len
== headersize
+ width
*height
*4);
1438 if(!is_16bit
&& !is_32bit
) {
1439 de_warn(c
, "Cannot detect bits/pixel, assuming 32");
1443 bypp
= (is_32bit
) ? 4 : 2;
1444 de_dbg(c
, "bytes/pixel: %d", (int)bypp
);
1445 rowspan
= width
* bypp
;
1447 img
= de_bitmap_create(c
, width
, height
, is_32bit
?4:3);
1449 for(j
=0; j
<height
; j
++) {
1450 for(i
=0; i
<width
; i
++) {
1451 i64 pos
= headersize
+ j
*rowspan
+ i
*bypp
;
1453 clr
= dbuf_getRGB(c
->infile
, pos
, 0);
1454 a
= de_getbyte(pos
+ 3);
1455 clr
= DE_SET_ALPHA(clr
, a
);
1458 clr
= (u32
)de_getu16le(pos
);
1459 clr
= de_rgb555_to_888(clr
);
1461 de_bitmap_setpixel_rgba(img
, i
, j
, clr
);
1465 de_bitmap_optimize_alpha(img
, 0x3);
1466 de_bitmap_write_to_file(img
, NULL
, DE_CREATEFLAG_FLIP_IMAGE
);
1469 de_bitmap_destroy(img
);
1472 static int de_identify_lumena_cel(deark
*c
)
1478 if(!de_input_file_has_ext(c
, "cel")) return 0;
1479 width
= de_getu16le(0);
1480 height
= de_getu16le(2);
1482 is_16bit
= (c
->infile
->len
== 4 + width
*height
*2);
1483 is_32bit
= (c
->infile
->len
== 4 + width
*height
*4);
1485 if(is_16bit
|| is_32bit
)
1491 void de_module_lumena_cel(deark
*c
, struct deark_module_info
*mi
)
1493 mi
->id
= "lumena_cel";
1494 mi
->desc
= "Lumena CEL";
1495 mi
->run_fn
= de_run_lumena_cel
;
1496 mi
->identify_fn
= de_identify_lumena_cel
;
1499 // **************************************************************************
1500 // Tandy DeskMate Paint .PNT
1501 // **************************************************************************
1503 static void de_run_deskmate_pnt(deark
*c
, de_module_params
*mparams
)
1509 de_bitmap
*img
= NULL
;
1510 dbuf
*unc_pixels
= NULL
;
1511 i64 unc_pixels_size
;
1515 de_dbg(c
, "image at %"I64_FMT
, pos
);
1519 unc_pixels_size
= rowspan
* h
;
1521 de_copy_std_palette(DE_PALID_PC16
, 0, 0, pal
, 16, 0);
1523 is_compressed
= (pos
+unc_pixels_size
!= c
->infile
->len
);
1524 de_dbg(c
, "compressed: %d", is_compressed
);
1527 unc_pixels
= dbuf_create_membuf(c
, unc_pixels_size
, 0x1);
1532 if(pos
>= c
->infile
->len
) break; // out of source data
1533 if(unc_pixels
->len
>= unc_pixels_size
) break; // enough dst data
1534 val
= de_getbyte_p(&pos
);
1535 count
= (i64
)de_getbyte_p(&pos
);
1536 dbuf_write_run(unc_pixels
, val
, count
);
1540 unc_pixels
= dbuf_open_input_subfile(c
->infile
, pos
, unc_pixels_size
);
1543 img
= de_bitmap_create(c
, w
, h
, 3);
1544 de_convert_image_paletted(unc_pixels
, 0, 4, rowspan
, pal
, img
, 0);
1545 de_bitmap_write_to_file(img
, NULL
, 0);
1547 dbuf_close(unc_pixels
);
1548 de_bitmap_destroy(img
);
1551 static int de_identify_deskmate_pnt(deark
*c
)
1553 if(!dbuf_memcmp(c
->infile
, 0, "\x13" "PNT", 4)) return 100;
1557 void de_module_deskmate_pnt(deark
*c
, struct deark_module_info
*mi
)
1559 mi
->id
= "deskmate_pnt";
1560 mi
->desc
= "Tandy DeskMate Paint";
1561 mi
->run_fn
= de_run_deskmate_pnt
;
1562 mi
->identify_fn
= de_identify_deskmate_pnt
;
1565 // **************************************************************************
1566 // Magic Desk icon (.ICN)
1567 // **************************************************************************
1569 static void de_run_mdesk_icn(deark
*c
, de_module_params
*mparams
)
1575 de_bitmap
*img
= NULL
;
1577 static const de_color pal_mdesk
[16] = {
1578 0xff000000U
, 0xffaa0000U
, 0xff00aa00U
, 0xffaaaa00U
,
1579 0xff0000aaU
, 0xffaa00aaU
, 0xff00aaaaU
, 0xff7d7d7dU
,
1580 0xffbababaU
, 0xffff5555U
, 0xff55ff55U
, 0xffffff55U
,
1581 0xff5555ffU
, 0xffff55ffU
, 0xff55ffffU
, 0xffffffffU
1584 s
= de_get_ext_option(c
, "mdesk_icn:pal");
1586 pal_req
= de_atoi(s
);
1589 if(pal_req
<1 || pal_req
>4) pal_req
= 4; // default = prefer Magic Desk
1592 de_dbg2(c
, "byte[2]: 0x%02x", (UI
)b2
);
1594 if(pal_req
==1) { // ToyBox only
1597 else if(pal_req
==2) { // Magic Desk only
1600 else if(pal_req
==3) { // prefer ToyBox
1601 toybox_mode
= (b2
!= 0x03);
1604 toybox_mode
= (b2
== 0x00);
1607 de_declare_fmtf(c
, "%s icon", (toybox_mode
?"ToyBox":"Magic Desk"));
1610 de_copy_std_palette(DE_PALID_PC16
, 0, 0, pal
, 16, 0);
1613 de_memcpy(pal
, pal_mdesk
, sizeof(pal
));
1616 img
= de_bitmap_create(c
, 32, 32, 3);
1617 de_convert_image_paletted(c
->infile
, 3, 4, 16, pal
, img
, 0);
1618 de_bitmap_transpose(img
);
1619 de_bitmap_write_to_file(img
, NULL
, 0);
1620 de_bitmap_destroy(img
);
1623 static int de_identify_mdesk_icn(deark
*c
)
1629 if(c
->infile
->len
!=515) return 0;
1630 if(de_getu16be(0)!=0x1f1f) return 0;
1633 has_ext
= (de_input_file_has_ext(c
, "icn") ||
1634 de_input_file_has_ext(c
, "tbi"));
1635 b2_ok
= (b2
==0x00 || b2
==0x03 || b2
==0xff);
1637 if(has_ext
&& b2_ok
) {
1643 static void de_help_mdesk_icn(deark
*c
)
1645 de_msg(c
, "-opt mdesk_icn:pal=<n> : Refer to documentation");
1648 void de_module_mdesk_icn(deark
*c
, struct deark_module_info
*mi
)
1650 mi
->id
= "mdesk_icn";
1651 mi
->desc
= "Magic Desk icon";
1652 mi
->run_fn
= de_run_mdesk_icn
;
1653 mi
->identify_fn
= de_identify_mdesk_icn
;
1654 mi
->help_fn
= de_help_mdesk_icn
;
1657 // **************************************************************************
1658 // Autodesk Animator PIC/CEL
1659 // **************************************************************************
1661 static void de_run_animator_pic(deark
*c
, de_module_params
*mparams
)
1663 de_bitmap
*img
= NULL
;
1664 de_finfo
*fi
= NULL
;
1670 w
= de_getu16le_p(&pos
);
1671 h
= de_getu16le_p(&pos
);
1672 de_dbg_dimensions(c
, w
, h
);
1673 if(!de_good_image_dimensions(c
, w
, h
)) goto done
;
1674 pos
+= 4; // xcoord/ycoord
1676 pos
+= 1; // compression type
1677 imgsize
= de_getu32le_p(&pos
);
1678 de_dbg(c
, "image size: %"I64_FMT
, imgsize
);
1680 de_read_simple_palette(c
, c
->infile
, pos
, 256, 3, pal
, 256, DE_RDPALTYPE_VGA18BIT
, 0);
1683 fi
= de_finfo_create(c
);
1684 fi
->density
.code
= DE_DENSITY_UNK_UNITS
;
1685 fi
->density
.xdens
= 240.0;
1686 fi
->density
.ydens
= 200.0;
1687 img
= de_bitmap_create(c
, w
, h
, 3);
1688 de_convert_image_paletted(c
->infile
, pos
, 8, w
, pal
, img
, 0);;
1689 de_bitmap_write_to_file_finfo(img
, fi
, 0);
1692 de_bitmap_destroy(img
);
1693 de_finfo_destroy(c
, fi
);
1696 static int de_identify_animator_pic(deark
*c
)
1698 if(de_getu16le(0)!=0x9119) return 0;
1699 if(de_getbyte(10)!=0x08) return 0;
1700 if(de_getbyte(11)!=0x00) return 0;
1701 if(de_input_file_has_ext(c
, "pic") ||
1702 de_input_file_has_ext(c
, "cel"))
1709 void de_module_animator_pic(deark
*c
, struct deark_module_info
*mi
)
1711 mi
->id
= "animator_pic";
1712 mi
->desc
= "Autodesk Animator PIC/CEL";
1713 mi
->run_fn
= de_run_animator_pic
;
1714 mi
->identify_fn
= de_identify_animator_pic
;
1717 // **************************************************************************
1719 // **************************************************************************
1721 static void do_dgi_convert_quadrant(deark
*c
, dbuf
*imgbuf
, i64 srcoffs
, i64 dstoffs
)
1725 for(j
=0; j
<50; j
++) {
1726 dbuf_copy_at(c
->infile
, srcoffs
+j
*160, 80, imgbuf
, dstoffs
+j
*640);
1727 dbuf_copy_at(c
->infile
, srcoffs
+j
*160+80, 80, imgbuf
, dstoffs
+j
*640+320);
1728 dbuf_copy_at(c
->infile
, srcoffs
+8000+j
*160, 80, imgbuf
, dstoffs
+j
*640+160);
1729 dbuf_copy_at(c
->infile
, srcoffs
+8000+j
*160+80, 80, imgbuf
, dstoffs
+j
*640+480);
1733 static void de_run_dgi(deark
*c
, de_module_params
*mparams
)
1735 dbuf
*imgbuf
= NULL
;
1736 de_bitmap
*img
= NULL
;
1737 de_finfo
*fi
= NULL
;
1740 imgbuf
= dbuf_create_membuf(c
, 64000, 0x1);
1742 // Full 640x400 image is stored as four 320x200-pixel quadrants.
1743 // Each quadrant is interlaced.
1744 do_dgi_convert_quadrant(c
, imgbuf
, 0, 0);
1745 do_dgi_convert_quadrant(c
, imgbuf
, 16000, 80);
1746 do_dgi_convert_quadrant(c
, imgbuf
, 32008, 32000);
1747 do_dgi_convert_quadrant(c
, imgbuf
, 48008, 32080);
1749 de_copy_std_palette(DE_PALID_CGA
, 1, 0, pal
, 4, 0);
1751 fi
= de_finfo_create(c
);
1752 img
= de_bitmap_create(c
, 640, 400, 3);
1753 de_convert_image_paletted(imgbuf
, 0, 2, 160, pal
, img
, 0);
1755 // DGI targets CGA 320x200.
1756 fi
->density
.code
= DE_DENSITY_UNK_UNITS
;
1757 fi
->density
.xdens
= 240;
1758 fi
->density
.ydens
= 200;
1760 de_bitmap_write_to_file_finfo(img
, fi
, 0);
1763 de_bitmap_destroy(img
);
1764 de_finfo_destroy(c
, fi
);
1767 static int de_identify_dgi(deark
*c
)
1771 if(c
->infile
->len
< 64008) return 0;
1772 has_ext
= de_input_file_has_ext(c
, "dgi");
1773 if(!has_ext
&& c
->infile
->len
!=64008) return 0;
1774 if(dbuf_memcmp(c
->infile
, 32000, (const void*)"\x01\x04\0\0\0\0\0\0", 8)) return 0;
1775 if(has_ext
&& c
->infile
->len
==64008) return 100;
1776 return 20; // either no .dgi extension, or file unexpectedly large (but not both)
1779 void de_module_dgi(deark
*c
, struct deark_module_info
*mi
)
1782 mi
->desc
= "DGI (Digi-Pic)";
1783 mi
->run_fn
= de_run_dgi
;
1784 mi
->identify_fn
= de_identify_dgi
;
1787 // **************************************************************************
1789 // **************************************************************************
1791 static int get_cserve_rle_fmt(deark
*c
)
1796 if(buf
[0]!=0x1b || buf
[1]!=0x47) return 0;
1797 if(buf
[2]==0x4d) return 1;
1798 if(buf
[2]==0x48) return 2;
1802 static void de_run_cserve_rle(deark
*c
, de_module_params
*mparams
)
1805 i64 w
, expected_h
, actual_h
;
1807 i64 npixels_expected
;
1811 dbuf
*unc_pixels
= NULL
;
1812 de_bitmap
*img
= NULL
;
1815 fmt
= get_cserve_rle_fmt(c
);
1825 de_err(c
, "Not a CompuServe RLE file");
1829 de_dbg(c
, "width: %"I64_FMT
, w
);
1830 npixels_expected
= w
*expected_h
;
1831 #define CSRLE_MAX_H 1920 // arbitrary
1832 max_npixels
= w
*CSRLE_MAX_H
;
1833 unc_pixels
= dbuf_create_membuf(c
, max_npixels
, 0x1);
1834 dbuf_enable_wbuffer(unc_pixels
);
1837 next_color
= 1; // 1=black, 2=white, 0=unset
1841 if(npixels_found
>= max_npixels
) {
1844 if(pos
>= c
->infile
->len
) break;
1846 x
= de_getbyte_p(&pos
);
1850 count
= (i64
)x
- 0x20;
1851 dbuf_write_run(unc_pixels
, next_color
, count
);
1852 npixels_found
+= count
;
1853 next_color
= (next_color
==1)?2:1;
1858 // TODO: Could do more error checking
1861 dbuf_flush(unc_pixels
);
1862 actual_h
= expected_h
;
1863 if(npixels_found
!= npixels_expected
) {
1864 de_warn(c
, "Expected %"I64_FMT
" pixels, found %"I64_FMT
"%s", npixels_expected
,
1866 ((npixels_found
>npixels_expected
&& !c
->padpix
)?" (try -padpix)":""));
1867 if(npixels_found
>npixels_expected
&& c
->padpix
) {
1868 actual_h
= de_pad_to_n(npixels_found
, w
)/w
;
1872 img
= de_bitmap_create(c
, w
, actual_h
, 3);
1873 de_zeromem(pal
, sizeof(pal
));
1874 // Images that don't end cleanly are common enough that we go to
1875 // the trouble of making missing pixels a special color.
1876 pal
[0] = DE_MAKE_RGB(255,0,255);
1877 pal
[1] = DE_STOCKCOLOR_BLACK
;
1878 pal
[2] = DE_STOCKCOLOR_WHITE
;
1879 de_convert_image_paletted(unc_pixels
, 0, 8, w
, pal
, img
, 0);
1880 de_bitmap_write_to_file(img
, NULL
, DE_CREATEFLAG_OPT_IMAGE
);
1883 dbuf_close(unc_pixels
);
1884 de_bitmap_destroy(img
);
1887 static int de_identify_cserve_rle(deark
*c
)
1891 x
= get_cserve_rle_fmt(c
);
1896 void de_module_cserve_rle(deark
*c
, struct deark_module_info
*mi
)
1898 mi
->id
= "cserve_rle";
1899 mi
->desc
= "CompuServe RLE";
1900 mi
->run_fn
= de_run_cserve_rle
;
1901 mi
->identify_fn
= de_identify_cserve_rle
;
1904 // **************************************************************************
1905 // Lotus Manuscript graphics (.bit, .rle)
1906 // **************************************************************************
1908 struct lotus_mscr_ctx
{
1914 // Warning: This algorithm is based on reverse engineering, and might not
1916 static void do_lotus_mscr_rle(deark
*c
, struct lotus_mscr_ctx
*d
)
1918 i64 npixels_expected
;
1921 dbuf
*unc_pixels
= NULL
;
1922 de_bitmap
*img
= NULL
;
1925 npixels_expected
= d
->w
*d
->h
;
1926 unc_pixels
= dbuf_create_membuf(c
, npixels_expected
, 0x1);
1927 dbuf_enable_wbuffer(unc_pixels
);
1936 if(npixels_found
>= npixels_expected
) break;
1937 if(pos
>= c
->infile
->len
) break;
1939 x
= de_getbyte_p(&pos
);
1941 count
= (i64
)(x
& 0x7f);
1942 if(count
==0) count
= 128;
1944 dbuf_write_run(unc_pixels
, color
, count
);
1945 npixels_found
+= count
;
1948 dbuf_flush(unc_pixels
);
1949 if(npixels_found
!= npixels_expected
) {
1950 de_warn(c
, "Expected %"I64_FMT
" pixels, found %"I64_FMT
, npixels_expected
,
1954 img
= de_bitmap_create(c
, d
->w
, d
->h
, 1);
1955 de_zeromem(pal
, sizeof(pal
));
1956 pal
[0] = DE_STOCKCOLOR_WHITE
;
1957 pal
[1] = DE_STOCKCOLOR_BLACK
;
1958 de_convert_image_paletted(unc_pixels
, 0, 8, d
->w
, pal
, img
, 0);
1959 de_bitmap_write_to_file_finfo(img
, d
->fi
, 0);
1961 dbuf_close(unc_pixels
);
1962 de_bitmap_destroy(img
);
1965 static void de_run_lotus_mscr(deark
*c
, de_module_params
*mparams
)
1971 struct lotus_mscr_ctx
*d
= NULL
;
1973 d
= de_malloc(c
, sizeof(struct lotus_mscr_ctx
));
1974 d
->fi
= de_finfo_create(c
);
1975 x
= de_getbyte_p(&pos
);
1983 de_err(c
, "Not a Lotus Manuscript file");
1986 de_dbg(c
, "compressed: %u", (UI
)is_rle
);
1987 dens1
= de_getu16le_p(&pos
);
1988 dens2
= de_getu16le_p(&pos
);
1989 de_dbg(c
, "dpi: %d, %d", (int)dens1
, (int)dens2
);
1990 // TODO: Figure out which dpi is which.
1991 // ART2WP thinks x is first, but that's a little surprising when the y
1992 // *dimension* is first, so I'm not trusting it.
1993 if(dens1
==dens2
&& dens1
>=50 && dens1
<=1200) {
1994 d
->fi
->density
.code
= DE_DENSITY_DPI
;
1995 d
->fi
->density
.xdens
= (double)dens1
;
1996 d
->fi
->density
.ydens
= d
->fi
->density
.xdens
;
1998 d
->h
= de_getu16le_p(&pos
);
1999 d
->rowspan
= de_getu16le_p(&pos
);
2000 d
->w
= d
->rowspan
* 8;
2001 de_dbg_dimensions(c
, d
->w
, d
->h
);
2002 if(!de_good_image_dimensions(c
, d
->w
, d
->h
)) goto done
;
2004 do_lotus_mscr_rle(c
, d
);
2007 de_convert_and_write_image_bilevel(c
->infile
, pos
, d
->w
, d
->h
, d
->rowspan
,
2008 DE_CVTF_WHITEISZERO
, d
->fi
, 0);
2013 de_finfo_destroy(c
, d
->fi
);
2018 static int de_identify_lotus_mscr(deark
*c
)
2024 if(x
=='B' && de_input_file_has_ext(c
, "bit")) {
2027 else if(x
=='R' && de_input_file_has_ext(c
, "rle")) {
2034 d1
= de_getu16le(1);
2035 d2
= de_getu16le(3);
2037 // RLE is particularly hard to detect, because we can't use the file size.
2038 if(d1
!=d2
) return 0;
2039 if(d1
!=72 && d1
!=300) return 0;
2042 if(d1
>=600 || d2
>600) return 0;
2046 rb
= de_getu16le(7);
2047 if(h
==0 || rb
==0 || h
>3300 || rb
>320) return 0;
2052 if(9+h
*rb
== c
->infile
->len
) return 75;
2058 void de_module_lotus_mscr(deark
*c
, struct deark_module_info
*mi
)
2060 mi
->id
= "lotus_mscr";
2061 mi
->desc
= "Lotus Manuscript graphics";
2062 mi
->run_fn
= de_run_lotus_mscr
;
2063 mi
->identify_fn
= de_identify_lotus_mscr
;
2066 // **************************************************************************
2069 // **************************************************************************
2071 struct fastgraph_ctx
{
2074 i64 w
, h
; // 0 if unknown
2081 static void decompress_fastgraph_spr(deark
*c
, struct fastgraph_ctx
*d
,
2082 dbuf
*unc_pixels
, i64 pos1
)
2087 d
->max_color_used
= 1;
2093 if(pos
>= c
->infile
->len
) break;
2094 if(unc_total
>= d
->max_unc_bytes
) break;
2096 clr
= de_getbyte_p(&pos
);
2097 count
= (i64
)de_getbyte_p(&pos
);
2099 if(clr
> d
->max_color_used
) {
2100 d
->max_color_used
= clr
;
2102 dbuf_write_run(unc_pixels
, clr
, count
);
2107 dbuf_flush(unc_pixels
);
2110 // This is a pixel-oriented 4bpp format. We expand it to 8 bits per pixel.
2111 static void decompress_fastgraph_ppr(deark
*c
, struct fastgraph_ctx
*d
,
2112 dbuf
*unc_pixels
, i64 pos1
)
2117 d
->max_color_used
= 1;
2125 if(pos
>= c
->infile
->len
) break;
2126 if(unc_total
>= d
->max_unc_bytes
) break;
2128 b
= de_getbyte_p(&pos
);
2132 for(k
=0; k
<2; k
++) {
2133 count
= (i64
)de_getbyte_p(&pos
);
2135 if(clr
[k
] > d
->max_color_used
) {
2136 d
->max_color_used
= clr
[k
];
2138 dbuf_write_run(unc_pixels
, clr
[k
], count
);
2144 dbuf_flush(unc_pixels
);
2147 static int has_fastgraph_spr_sig(deark
*c
)
2149 return !dbuf_memcmp(c
->infile
, 0, (const u8
*)"F\0A\0S\0T\0G\0", 10);
2154 // optional: ->w, or both ->w and ->h
2155 // optional: ->pal_is_set and ->pal
2156 // optional: ->img_startpos
2157 static void do_fastgraph_internal(deark
*c
, struct fastgraph_ctx
*d
)
2159 dbuf
*unc_pixels
= NULL
;
2160 de_bitmap
*img
= NULL
;
2164 s
= de_get_ext_option(c
, "width");
2166 d
->w
= de_atoi64(s
);
2170 s
= de_get_ext_option(c
, "height");
2172 d
->h
= de_atoi64(s
);
2177 de_err(c
, "Image width unknown. Try \"-opt width=...\".");
2182 de_dbg_dimensions(c
, d
->w
, d
->h
);
2185 de_dbg(c
, "width: %"I64_FMT
, d
->w
);
2188 if(d
->w
<1 || d
->w
>c
->max_image_dimension
||
2189 d
->h
<0 || d
->h
>c
->max_image_dimension
)
2191 de_err(c
, "Bad image dimensions");
2196 d
->max_unc_bytes
= DE_MAX_SANE_OBJECT_SIZE
;
2197 unc_pixels
= dbuf_create_membuf(c
, 0, 0);
2200 d
->max_unc_bytes
= d
->w
* d
->h
;
2201 unc_pixels
= dbuf_create_membuf(c
, d
->max_unc_bytes
, 0x1);
2205 decompress_fastgraph_ppr(c
, d
, unc_pixels
, d
->img_startpos
);
2208 decompress_fastgraph_spr(c
, d
, unc_pixels
, d
->img_startpos
);
2211 de_dbg(c
, "decompressed %"I64_FMT
" pixels", unc_pixels
->len
);
2213 d
->h
= de_pad_to_n(unc_pixels
->len
, d
->w
) / d
->w
;
2214 de_dbg(c
, "height: %"I64_FMT
, d
->h
);
2217 if(!de_good_image_dimensions(c
, d
->w
, d
->h
)) goto done
;
2219 img
= de_bitmap_create(c
, d
->w
, d
->h
, d
->pal_is_set
?3:1);
2220 if(!d
->pal_is_set
) {
2221 de_info(c
, "Note: Color map unknown. Rendering as grayscale.");
2222 de_make_grayscale_palette(d
->pal
, 1+(i64
)d
->max_color_used
, 0);
2225 de_convert_image_paletted(unc_pixels
, 0, 8, d
->w
, d
->pal
, img
, 0);
2226 de_bitmap_write_to_file(img
, NULL
, DE_CREATEFLAG_FLIP_IMAGE
|
2227 DE_CREATEFLAG_OPT_IMAGE
);
2230 dbuf_close(unc_pixels
);
2231 de_bitmap_destroy(img
);
2234 static void de_run_fastgraph_spr(deark
*c
, de_module_params
*mparams
)
2236 struct fastgraph_ctx
*d
= NULL
;
2238 d
= de_malloc(c
, sizeof(struct fastgraph_ctx
));
2241 if(has_fastgraph_spr_sig(c
)) {
2242 d
->w
= 1 + 256*(i64
)de_getbyte(18) + (i64
)de_getbyte(16);
2243 d
->h
= 1 + 256*(i64
)de_getbyte(22) + (i64
)de_getbyte(20);
2244 d
->img_startpos
= 26;
2247 do_fastgraph_internal(c
, d
);
2252 static int de_identify_fastgraph_spr(deark
*c
)
2254 if(has_fastgraph_spr_sig(c
)) {
2260 static void help_fastgraph_common(deark
*c
)
2262 de_msg(c
, "-opt width=<n> : Hint: image width");
2263 de_msg(c
, "-opt height=<n> : Hint: image height");
2266 static void de_help_fastgraph_spr(deark
*c
)
2268 help_fastgraph_common(c
);
2271 void de_module_fastgraph_spr(deark
*c
, struct deark_module_info
*mi
)
2273 mi
->id
= "fastgraph_spr";
2274 mi
->desc
= "Fastgraph SPR";
2275 mi
->run_fn
= de_run_fastgraph_spr
;
2276 mi
->identify_fn
= de_identify_fastgraph_spr
;
2277 mi
->help_fn
= de_help_fastgraph_spr
;
2278 mi
->flags
|= DE_MODFLAG_HIDDEN
;
2281 // **************************************************************************
2284 // **************************************************************************
2286 static void de_run_fastgraph_ppr(deark
*c
, de_module_params
*mparams
)
2288 struct fastgraph_ctx
*d
= NULL
;
2290 d
= de_malloc(c
, sizeof(struct fastgraph_ctx
));
2293 do_fastgraph_internal(c
, d
);
2298 static void de_help_fastgraph_ppr(deark
*c
)
2300 help_fastgraph_common(c
);
2303 void de_module_fastgraph_ppr(deark
*c
, struct deark_module_info
*mi
)
2305 mi
->id
= "fastgraph_ppr";
2306 mi
->desc
= "Fastgraph PPR";
2307 mi
->run_fn
= de_run_fastgraph_ppr
;
2308 mi
->identify_fn
= NULL
;
2309 mi
->help_fn
= de_help_fastgraph_ppr
;
2310 mi
->flags
|= DE_MODFLAG_HIDDEN
;
2313 // **************************************************************************
2314 // Young Picasso .YP
2315 // **************************************************************************
2317 static int has_yp_sig(deark
*c
)
2319 return !dbuf_memcmp(c
->infile
, 0, (const u8
*)"P\0\0P\0\0R\0\0", 9);
2322 static void de_run_yp(deark
*c
, de_module_params
*mparams
)
2324 struct fastgraph_ctx
*d
= NULL
;
2325 de_bitmap
*img
= NULL
;
2326 de_finfo
*fi
= NULL
;
2327 dbuf
*unc_pixels
= NULL
;
2329 d
= de_malloc(c
, sizeof(struct fastgraph_ctx
));
2330 // TODO?: Maybe we should call do_fastgraph_internal() instead of
2331 // just decompress_fastgraph_ppr(), but it would be a bit messy.
2335 d
->w
= (i64
)de_getbyte(9) * 256;
2336 d
->w
+= (i64
)de_getbyte(12);
2337 d
->h
= (i64
)de_getbyte(15) * 256;
2338 d
->h
+= (i64
)de_getbyte(18);
2339 d
->img_startpos
= 24; // (Not actually necessary)
2346 de_dbg_dimensions(c
, d
->w
, d
->h
);
2347 if(!de_good_image_dimensions(c
, d
->w
, d
->h
)) goto done
;
2349 d
->max_unc_bytes
= d
->w
* d
->h
;
2350 unc_pixels
= dbuf_create_membuf(c
, d
->max_unc_bytes
, 0x1);
2351 dbuf_enable_wbuffer(unc_pixels
);
2352 decompress_fastgraph_ppr(c
, d
, unc_pixels
, d
->img_startpos
);
2354 fi
= de_finfo_create(c
);
2355 fi
->density
.code
= DE_DENSITY_UNK_UNITS
;
2356 fi
->density
.xdens
= 6.0;
2357 fi
->density
.ydens
= 5.0;
2359 de_copy_std_palette(DE_PALID_PC16
, 0, 0, d
->pal
, 16, 0);
2360 img
= de_bitmap_create(c
, d
->w
, d
->h
, 3);
2361 de_convert_image_paletted(unc_pixels
, 0, 8, d
->w
, d
->pal
, img
, 0);
2362 de_bitmap_write_to_file_finfo(img
, fi
, DE_CREATEFLAG_FLIP_IMAGE
|
2363 DE_CREATEFLAG_OPT_IMAGE
);
2366 dbuf_close(unc_pixels
);
2367 de_bitmap_destroy(img
);
2368 de_finfo_destroy(c
, fi
);
2372 static int de_identify_yp(deark
*c
)
2375 if(de_input_file_has_ext(c
, "yp")) return 100;
2381 void de_module_young_picasso(deark
*c
, struct deark_module_info
*mi
)
2383 mi
->id
= "young_picasso";
2384 mi
->desc
= "Young Picasso .YP";
2385 mi
->run_fn
= de_run_yp
;
2386 mi
->identify_fn
= de_identify_yp
;
2389 // **************************************************************************
2390 // Icon Manager .ICA (Impact Software, Leonard A. Gray)
2391 // **************************************************************************
2393 struct iconmgr_icon_ctx
{
2399 struct iconmgr_ica_ctx
{
2402 de_encoding input_encoding
;
2404 i64 reported_file_size
;
2408 static void iconmgr_icon_destroy(deark
*c
, struct iconmgr_icon_ctx
*md
)
2411 ucstring_destroy(md
->name
);
2415 // On fatal error, leaves md->total_len set to 0.
2416 static void do_iconmgr_icon(deark
*c
, struct iconmgr_ica_ctx
*d
,
2417 struct iconmgr_icon_ctx
*md
)
2419 de_bitmap
*img
= NULL
;
2420 de_bitmap
*mask
= NULL
;
2421 de_finfo
*fi
= NULL
;
2423 i64 bpp
, xpos
, ypos
;
2424 int saved_indent_level
;
2426 de_dbg_indent_save(c
, &saved_indent_level
);
2427 de_dbg(c
, "icon at %"I64_FMT
, md
->icon_pos
);
2428 de_dbg_indent(c
, 1);
2431 // Try to detect if we've gone off the rails.
2432 // TODO: Are bit depths other than 4 possible?
2433 bpp
= de_getbyte_p(&pos
);
2434 xpos
= de_getu16le_p(&pos
);
2435 ypos
= de_getu16le_p(&pos
);
2436 if(bpp
!=4 || xpos
>=4096 || ypos
>=4096) {
2442 md
->name
= ucstring_create(c
);
2443 dbuf_read_to_ucstring(c
->infile
, pos
, 26, md
->name
, DE_CONVFLAG_STOP_AT_NUL
,
2445 de_dbg(c
, "name: \"%s\"", ucstring_getpsz_d(md
->name
));
2449 de_dbg(c
, "bitmap at %"I64_FMT
, pos
);
2450 img
= de_bitmap_create(c
, 32, 32, 4);
2451 de_convert_image_paletted(c
->infile
, pos
, 4, 16, d
->pal
, img
, 0);
2454 de_dbg(c
, "mask at %"I64_FMT
, pos
);
2455 mask
= de_bitmap_create(c
, 32, 32, 1);
2456 de_convert_image_bilevel(c
->infile
, pos
, 4, mask
, 0);
2459 de_bitmap_apply_mask(img
, mask
, DE_BITMAPFLAG_WHITEISTRNS
);
2461 fi
= de_finfo_create(c
);
2462 if(c
->filenames_from_file
&& ucstring_isnonempty(md
->name
)) {
2463 de_finfo_set_name_from_ucstring(c
, fi
, md
->name
, 0);
2466 de_bitmap_write_to_file_finfo(img
, fi
, DE_CREATEFLAG_FLIP_IMAGE
|DE_CREATEFLAG_OPT_IMAGE
);
2467 md
->total_len
= pos
- md
->icon_pos
;
2470 de_bitmap_destroy(img
);
2471 de_bitmap_destroy(mask
);
2472 de_finfo_destroy(c
, fi
);
2473 de_dbg_indent_restore(c
, saved_indent_level
);
2476 static void de_run_iconmgr_ica(deark
*c
, de_module_params
*mparams
)
2478 struct iconmgr_ica_ctx
*d
= NULL
;
2479 struct iconmgr_icon_ctx
*md
= NULL
;
2483 d
= de_malloc(c
, sizeof(struct iconmgr_ica_ctx
));
2484 d
->input_encoding
= de_get_input_encoding(c
, NULL
, DE_ENCODING_WINDOWS1252
);
2498 d
->icon_count
= de_getu16le(4);
2499 de_dbg(c
, "count: %d", (int)d
->icon_count
);
2500 d
->reported_file_size
= de_getu32le(4);
2502 de_copy_std_palette(DE_PALID_WIN16
, 0, 0, d
->pal
, 16, 0);
2505 if(pos
>=c
->infile
->len
|| pos
>=d
->reported_file_size
) goto done
;
2507 iconmgr_icon_destroy(c
, md
);
2510 md
= de_malloc(c
, sizeof(struct iconmgr_icon_ctx
));
2512 do_iconmgr_icon(c
, d
, md
);
2513 if(md
->total_len
<=0) goto done
;
2514 pos
+= md
->total_len
;
2518 iconmgr_icon_destroy(c
, md
);
2520 if(d
->need_errmsg
) {
2521 de_err(c
, "Bad or unsupported file");
2527 static int de_identify_iconmgr_ica(deark
*c
)
2531 if(dbuf_memcmp(c
->infile
, 0, "IC", 2)) return 0;
2533 if(de_getbyte(3) != 0) return 0;
2534 if(b
=='M' || b
=='2') {
2540 void de_module_iconmgr_ica(deark
*c
, struct deark_module_info
*mi
)
2542 mi
->id
= "iconmgr_ica";
2543 mi
->desc
= "Icon Manager Archive (.ica)";
2544 mi
->run_fn
= de_run_iconmgr_ica
;
2545 mi
->identify_fn
= de_identify_iconmgr_ica
;
2548 // **************************************************************************
2549 // ThumbsPlus (v1.x-2.x) thumbnail database (.tud)
2550 // **************************************************************************
2552 #define THUMBSPLUS_W 96
2553 #define THUMBSPLUS_H 72
2554 #define THUMBSPLUS_IMGSIZE (THUMBSPLUS_W*THUMBSPLUS_H)
2556 struct thumbsplus_icon_ctx
{
2560 struct de_stringreaderdata
*orig_name_srd
;
2561 de_ucstring
*name_token
;
2562 struct de_timestamp mod_dt
;
2565 struct thumbsplus_ctx
{
2568 de_encoding input_encoding
;
2570 i64 reported_file_size
;
2574 static void thumbsplus_icon_destroy(deark
*c
, struct thumbsplus_icon_ctx
*md
)
2577 de_destroy_stringreaderdata(c
, md
->orig_name_srd
);
2578 ucstring_destroy(md
->name_token
);
2582 static void thumbsplus_decompress(deark
*c
, struct thumbsplus_ctx
*d
,
2583 struct thumbsplus_icon_ctx
*md
, i64 pos1
, i64 len
, dbuf
*unc_pixels
)
2585 i64 endpos
= pos1
+ len
;
2593 if(pos
>= endpos
) break;
2594 b
= de_getbyte_p(&pos
);
2597 count
= (i64
)de_getbyte_p(&pos
);
2600 count
= (i64
)b
- 233;
2602 val
= de_getbyte_p(&pos
);
2603 dbuf_write_run(unc_pixels
, val
, count
);
2606 dbuf_writebyte(unc_pixels
, b
);
2611 // On success, sets md->total_len.
2612 static void do_thumbsplus_icon(deark
*c
, struct thumbsplus_ctx
*d
,
2613 struct thumbsplus_icon_ctx
*md
)
2615 de_bitmap
*img
= NULL
;
2616 de_finfo
*fi
= NULL
;
2617 dbuf
*unc_pixels
= NULL
;
2619 i64 mod_time_raw
, mod_date_raw
;
2620 int saved_indent_level
;
2622 de_dbg_indent_save(c
, &saved_indent_level
);
2623 de_dbg(c
, "icon at %"I64_FMT
, md
->icon_pos
);
2624 de_dbg_indent(c
, 1);
2628 mod_date_raw
= de_getu16le_p(&pos
);
2629 mod_time_raw
= de_getu16le_p(&pos
);
2630 de_dos_datetime_to_timestamp(&md
->mod_dt
, mod_date_raw
, mod_time_raw
);
2631 md
->mod_dt
.tzcode
= DE_TZCODE_LOCAL
;
2632 datetime_dbgmsg(c
, &md
->mod_dt
, "mod time");
2634 md
->data_len
= de_getu16le_p(&pos
);
2635 de_dbg(c
, "cmpr len: %"I64_FMT
, md
->data_len
);
2638 md
->orig_name_srd
= dbuf_read_string(c
->infile
, pos
, 260, 260,
2639 DE_CONVFLAG_STOP_AT_NUL
, d
->input_encoding
);
2640 if(!md
->orig_name_srd
->found_nul
) {
2644 de_dbg(c
, "name: \"%s\"", ucstring_getpsz_d(md
->orig_name_srd
->str
));
2645 pos
+= md
->orig_name_srd
->bytes_consumed
;
2647 md
->name_token
= ucstring_create(c
);
2648 get_base_filename(md
->orig_name_srd
->str
, md
->name_token
);
2650 de_dbg(c
, "bitmap at %"I64_FMT
, pos
);
2651 unc_pixels
= dbuf_create_membuf(c
, THUMBSPLUS_IMGSIZE
+2, 0x1);
2652 dbuf_enable_wbuffer(unc_pixels
);
2653 thumbsplus_decompress(c
, d
, md
, pos
, md
->data_len
, unc_pixels
);
2654 dbuf_flush(unc_pixels
);
2655 if(unc_pixels
->len
!= THUMBSPLUS_IMGSIZE
) {
2656 // We're strict about this, because it's how we detect if we've gone off
2658 de_err(c
, "Decompression failed");
2662 img
= de_bitmap_create(c
, THUMBSPLUS_W
, THUMBSPLUS_H
, 3);
2663 de_convert_image_paletted(unc_pixels
, 0, 8, THUMBSPLUS_W
, d
->pal
, img
, 0);
2665 fi
= de_finfo_create(c
);
2666 if(c
->filenames_from_file
&& ucstring_isnonempty(md
->name_token
)) {
2667 de_finfo_set_name_from_ucstring(c
, fi
, md
->name_token
, 0);
2669 fi
->timestamp
[DE_TIMESTAMPIDX_MODIFY
] = md
->mod_dt
;
2670 de_bitmap_write_to_file_finfo(img
, fi
, DE_CREATEFLAG_FLIP_IMAGE
|DE_CREATEFLAG_OPT_IMAGE
);
2672 pos
+= md
->data_len
;
2673 md
->total_len
= pos
- md
->icon_pos
;
2676 dbuf_close(unc_pixels
);
2677 de_bitmap_destroy(img
);
2678 de_finfo_destroy(c
, fi
);
2679 de_dbg_indent_restore(c
, saved_indent_level
);
2682 static void make_thumbsplus_pal(deark
*c
, struct thumbsplus_ctx
*d
)
2684 static const u8 tppal
[236*3] = {
2685 0x00,0x00,0x00,0xff,0xff,0xff,0x09,0x09,0x09,0x13,0x13,0x13,0x1d,0x1d,0x1d,0x27,0x27,0x27,
2686 0x31,0x31,0x31,0x3b,0x3b,0x3b,0x44,0x44,0x44,0x4e,0x4e,0x4e,0x58,0x58,0x58,0x62,0x62,0x62,
2687 0x6c,0x6c,0x6c,0x76,0x76,0x76,0x89,0x89,0x89,0x93,0x93,0x93,0x9d,0x9d,0x9d,0xa7,0xa7,0xa7,
2688 0xb0,0xb0,0xb0,0xba,0xba,0xba,0xc4,0xc4,0xc4,0xce,0xce,0xce,0xd7,0xd7,0xd7,0xe1,0xe1,0xe1,
2689 0xeb,0xeb,0xeb,0xf5,0xf5,0xf5,0x03,0x13,0x03,0x06,0x27,0x06,0x09,0x3a,0x09,0x0c,0x4e,0x0c,
2690 0x0f,0x62,0x0f,0x12,0x75,0x12,0x15,0x89,0x15,0x18,0x9c,0x18,0x1b,0xb0,0x1b,0x1e,0xc4,0x1e,
2691 0x21,0xd7,0x21,0x24,0xeb,0x24,0x38,0xff,0x38,0x49,0xff,0x49,0x59,0xff,0x59,0x6a,0xff,0x6a,
2692 0x7a,0xff,0x7a,0x8b,0xff,0x8b,0x9b,0xff,0x9b,0xac,0xff,0xac,0xbc,0xff,0xbc,0xcd,0xff,0xcd,
2693 0xdd,0xff,0xdd,0xee,0xff,0xee,0x03,0x03,0x13,0x06,0x06,0x27,0x09,0x09,0x3a,0x0c,0x0c,0x4e,
2694 0x0f,0x0f,0x62,0x12,0x12,0x75,0x15,0x15,0x89,0x18,0x18,0x9c,0x1b,0x1b,0xb0,0x1e,0x1e,0xc4,
2695 0x21,0x21,0xd7,0x24,0x24,0xeb,0x38,0x38,0xff,0x49,0x49,0xff,0x59,0x59,0xff,0x6a,0x6a,0xff,
2696 0x7a,0x7a,0xff,0x8b,0x8b,0xff,0x9b,0x9b,0xff,0xac,0xac,0xff,0xbc,0xbc,0xff,0xcd,0xcd,0xff,
2697 0xdd,0xdd,0xff,0xee,0xee,0xff,0x13,0x13,0x03,0x27,0x27,0x06,0x3a,0x3a,0x09,0x4e,0x4e,0x0c,
2698 0x62,0x62,0x0f,0x75,0x75,0x12,0x89,0x89,0x15,0x9c,0x9c,0x18,0xb0,0xb0,0x1b,0xc4,0xc4,0x1e,
2699 0xd7,0xd7,0x21,0xeb,0xeb,0x24,0xff,0xff,0x38,0xff,0xff,0x49,0xff,0xff,0x59,0xff,0xff,0x6a,
2700 0xff,0xff,0x7a,0xff,0xff,0x8b,0xff,0xff,0x9b,0xff,0xff,0xac,0xff,0xff,0xbc,0xff,0xff,0xcd,
2701 0xff,0xff,0xdd,0xff,0xff,0xee,0x0d,0x03,0x13,0x1b,0x06,0x27,0x29,0x09,0x3a,0x37,0x0c,0x4e,
2702 0x45,0x0f,0x62,0x53,0x12,0x75,0x60,0x15,0x89,0x6e,0x18,0x9c,0x7c,0x1b,0xb0,0x8a,0x1e,0xc4,
2703 0x98,0x21,0xd7,0xa6,0x24,0xeb,0xb9,0x38,0xff,0xbf,0x49,0xff,0xc5,0x59,0xff,0xcb,0x6a,0xff,
2704 0xd0,0x7a,0xff,0xd6,0x8b,0xff,0xdc,0x9b,0xff,0xe2,0xac,0xff,0xe7,0xbc,0xff,0xed,0xcd,0xff,
2705 0xf3,0xdd,0xff,0xf9,0xee,0xff,0x03,0x13,0x13,0x06,0x27,0x27,0x09,0x3a,0x3a,0x0c,0x4e,0x4e,
2706 0x0f,0x62,0x62,0x12,0x75,0x75,0x15,0x89,0x89,0x18,0x9c,0x9c,0x1b,0xb0,0xb0,0x1e,0xc4,0xc4,
2707 0x21,0xd7,0xd7,0x24,0xeb,0xeb,0x38,0xff,0xff,0x49,0xff,0xff,0x59,0xff,0xff,0x6a,0xff,0xff,
2708 0x7a,0xff,0xff,0x8b,0xff,0xff,0x9b,0xff,0xff,0xac,0xff,0xff,0xbc,0xff,0xff,0xcd,0xff,0xff,
2709 0xdd,0xff,0xff,0xee,0xff,0xff,0x12,0x0a,0x03,0x24,0x15,0x06,0x37,0x20,0x09,0x49,0x2b,0x0c,
2710 0x5c,0x35,0x0f,0x6e,0x40,0x12,0x81,0x4b,0x15,0x93,0x56,0x18,0xa6,0x60,0x1b,0xb8,0x6b,0x1e,
2711 0xcb,0x76,0x21,0xdd,0x81,0x24,0xf1,0x94,0x38,0xf2,0x9d,0x49,0xf3,0xa6,0x59,0xf4,0xaf,0x6a,
2712 0xf5,0xb8,0x7a,0xf6,0xc1,0x8b,0xf8,0xc9,0x9b,0xf9,0xd2,0xac,0xfa,0xdb,0xbc,0xfb,0xe4,0xcd,
2713 0xfc,0xed,0xdd,0xfd,0xf6,0xee,0x13,0x03,0x03,0x27,0x06,0x06,0x3a,0x09,0x09,0x4e,0x0c,0x0c,
2714 0x62,0x0f,0x0f,0x75,0x12,0x12,0x89,0x15,0x15,0x9c,0x18,0x18,0xb0,0x1b,0x1b,0xc4,0x1e,0x1e,
2715 0xd7,0x21,0x21,0xeb,0x24,0x24,0xff,0x38,0x38,0xff,0x49,0x49,0xff,0x59,0x59,0xff,0x6a,0x6a,
2716 0xff,0x7a,0x7a,0xff,0x8b,0x8b,0xff,0x9b,0x9b,0xff,0xac,0xac,0xff,0xbc,0xbc,0xff,0xcd,0xcd,
2717 0xff,0xdd,0xdd,0xff,0xee,0xee,0x12,0x0c,0x08,0x25,0x18,0x10,0x38,0x24,0x19,0x4a,0x30,0x21,
2718 0x5d,0x3c,0x29,0x70,0x48,0x32,0x82,0x54,0x3a,0x95,0x60,0x42,0xa8,0x6c,0x4b,0xba,0x78,0x53,
2719 0xcd,0x84,0x5b,0xe2,0x98,0x6f,0xe4,0xa1,0x7b,0xe7,0xa9,0x87,0xe9,0xb2,0x93,0xeb,0xba,0x9f,
2720 0xee,0xc3,0xab,0xf0,0xcb,0xb7,0xf3,0xd4,0xc3,0xf5,0xdc,0xcf,0xf7,0xe5,0xdb,0xfa,0xed,0xe7,
2721 0xfc,0xf6,0xf3,0x12,0x14,0x18,0x24,0x28,0x30,0x36,0x3c,0x48,0x48,0x50,0x60,0x75,0x7d,0x8e,
2722 0x91,0x97,0xa5,0xac,0xb1,0xbb,0xc8,0xcb,0xd2,0xe3,0xe5,0xe8,0x10,0x14,0x0f,0x21,0x28,0x1e,
2723 0x32,0x3c,0x2d,0x42,0x50,0x3c,0x53,0x64,0x4b,0x7d,0x8e,0x75,0x97,0xa5,0x91,0xb1,0xbb,0xac,
2724 0xcb,0xd2,0xc8,0xe5,0xe8,0xe3 };
2726 de_copy_palette_from_rgb24(tppal
, d
->pal
, 236);
2729 static void de_run_thumbsplus(deark
*c
, de_module_params
*mparams
)
2731 struct thumbsplus_ctx
*d
= NULL
;
2732 struct thumbsplus_icon_ctx
*md
= NULL
;
2735 d
= de_malloc(c
, sizeof(struct thumbsplus_ctx
));
2736 d
->input_encoding
= de_get_input_encoding(c
, NULL
, DE_ENCODING_WINDOWS1252
);
2739 d
->icon_count
= de_getu32le_p(&pos
);
2740 de_dbg(c
, "count: %"I64_FMT
, d
->icon_count
);
2741 d
->reported_file_size
= de_getu32le_p(&pos
);
2743 make_thumbsplus_pal(c
, d
);
2747 if(pos
>=c
->infile
->len
|| pos
>=d
->reported_file_size
) goto done
;
2749 thumbsplus_icon_destroy(c
, md
);
2752 md
= de_malloc(c
, sizeof(struct thumbsplus_icon_ctx
));
2754 do_thumbsplus_icon(c
, d
, md
);
2755 if(md
->total_len
<=0) goto done
;
2756 pos
+= md
->total_len
;
2760 thumbsplus_icon_destroy(c
, md
);
2762 if(d
->need_errmsg
) {
2763 de_err(c
, "Bad or unsupported file");
2769 static int de_identify_thumbsplus(deark
*c
)
2771 if((UI
)de_getu32be(0) == 0xbebadabeU
) {
2777 void de_module_thumbsplus(deark
*c
, struct deark_module_info
*mi
)
2779 mi
->id
= "thumbsplus";
2780 mi
->desc
= "ThumbsPlus v1-2 database (.tud)";
2781 mi
->run_fn
= de_run_thumbsplus
;
2782 mi
->identify_fn
= de_identify_thumbsplus
;
2785 // **************************************************************************
2787 // **************************************************************************
2789 struct fmtownsicn_table_ctx
{
2795 struct fmtownsicn_ctx
{
2804 static void do_fmtownsicn_icon(deark
*c
, struct fmtownsicn_ctx
*d
,
2805 struct fmtownsicn_table_ctx
*tbl
, i64 idx
, i64 pos1
)
2807 int saved_indent_level
;
2809 de_bitmap
*img
= NULL
;
2818 de_dbg_indent_save(c
, &saved_indent_level
);
2819 if(pos1
>=c
->infile
->len
) {
2820 d
->fatalerrflag
= 1;
2824 de_dbg(c
, "icon header (table #%u icon #%u) at %"I64_FMT
, (UI
)tbl
->idx
,
2826 de_dbg_indent(c
, 1);
2829 w
= de_getu16le_p(&pos
);
2830 h
= de_getu16le_p(&pos
);
2831 de_dbg_dimensions(c
, w
, h
);
2832 ncolors
= (UI
)de_getu32le_p(&pos
);
2833 de_dbg(c
, "num colors: %u", ncolors
);
2834 isize
= de_getu16le_p(&pos
);
2835 de_dbg(c
, "size: %"I64_FMT
, isize
);
2837 fg_pos
= de_getu32le_p(&pos
);
2838 de_dbg(c
, "fg pos: %"I64_FMT
, fg_pos
);
2840 if(fg_pos
<= pos1
|| fg_pos
+ isize
> c
->infile
->len
) {
2841 d
->fatalerrflag
= 1;
2849 else if(ncolors
==16) {
2853 de_err(c
, "Unsupported image type");
2857 if(!de_good_image_dimensions(c
, w
, h
)) goto done
;
2858 img
= de_bitmap_create(c
, w
, h
, 3);
2861 if(bits_per_pixel
==1) {
2862 rowspan
= de_pad_to_n(w
*bits_per_pixel
, 8) / 8;
2863 de_convert_image_paletted(c
->infile
, fg_pos
, 1, rowspan
,
2865 createflags
|= DE_CREATEFLAG_IS_BWIMG
;
2868 rowspan
= de_pad_to_n(w
*bits_per_pixel
, 32) / 8;
2869 de_convert_image_paletted(c
->infile
, fg_pos
, 4, rowspan
,
2870 d
->pal16
, img
, 0x01);
2871 createflags
|= DE_CREATEFLAG_OPT_IMAGE
;
2874 de_bitmap_write_to_file(img
, NULL
, createflags
);
2877 de_bitmap_destroy(img
);
2878 de_dbg_indent_restore(c
, saved_indent_level
);
2881 static void do_fmtownsicn_table(deark
*c
, struct fmtownsicn_ctx
*d
, i64 idx
,
2884 int saved_indent_level
;
2886 struct fmtownsicn_table_ctx
*tbl
= NULL
;
2889 de_dbg_indent_save(c
, &saved_indent_level
);
2891 if(pos1
+32>c
->infile
->len
) {
2892 d
->fatalerrflag
= 1;
2897 tbl
= de_malloc(c
, sizeof(struct fmtownsicn_table_ctx
));
2900 de_dbg(c
, "table #%"I64_FMT
" at %"I64_FMT
, idx
, pos1
);
2901 de_dbg_indent(c
, 1);
2903 tbl
->num_icons
= de_getu16le_p(&pos
);
2904 de_dbg(c
, "num icons: %u", (UI
)tbl
->num_icons
);
2908 tbl
->icon_arr_offs
= de_getu32le_p(&pos
);
2909 de_dbg(c
, "offset of icon array: %"I64_FMT
, tbl
->icon_arr_offs
);
2910 if(tbl
->icon_arr_offs
<= pos1
) {
2911 d
->fatalerrflag
= 1;
2916 for(i
=0; i
<tbl
->num_icons
; i
++) {
2917 if(d
->fatalerrflag
) goto done
;
2918 do_fmtownsicn_icon(c
, d
, tbl
, i
, tbl
->icon_arr_offs
+48*i
);
2923 de_dbg_indent_restore(c
, saved_indent_level
);
2926 static void fmtownsicn_make_palettes(deark
*c
, struct fmtownsicn_ctx
*d
)
2928 static const u8 pal16_std
[16*3] = {
2929 0x22,0x22,0x22, 0x22,0x77,0xbb, 0xcc,0x66,0x44, 0xff,0xcc,0xaa,
2930 0x99,0x99,0x99, 0x00,0xcc,0x77, 0xcc,0xcc,0xcc, 0x77,0x77,0x77,
2931 0x00,0x00,0x00, 0x88,0xbb,0xee, 0xdd,0x00,0x00, 0x00,0x00,0xaa,
2932 0x55,0x55,0x55, 0x00,0xff,0xff, 0xff,0xdd,0x00, 0xff,0xff,0xff
2935 de_make_grayscale_palette(d
->pal2
, 2, 0x1);
2936 de_copy_palette_from_rgb24(pal16_std
, d
->pal16
, 16);
2939 static void do_fmtownsicn_ICNFILE(deark
*c
, struct fmtownsicn_ctx
*d
)
2945 de_dbg(c
, "header at %"I64_FMT
, pos1
);
2946 de_dbg_indent(c
, 1);
2948 pos
+= 2; // version
2949 d
->num_tables
= de_getu16le_p(&pos
);
2950 de_dbg(c
, "num tables: %u", (UI
)d
->num_tables
);
2951 de_dbg_indent(c
, -1);
2953 for(i
=0; i
<d
->num_tables
; i
++) {
2954 if(d
->fatalerrflag
) goto done
;
2955 do_fmtownsicn_table(c
, d
, i
, 32+32*i
);
2962 static void do_fmtownsicn_FJ(deark
*c
, struct fmtownsicn_ctx
*d
)
2965 i64 num_icons_capacity
;
2974 de_dbg(c
, "header at %"I64_FMT
, pos1
);
2975 de_dbg_indent(c
, 1);
2978 bits_per_pixel
= (UI
)dbuf_getu16x(c
->infile
, pos
, d
->is_le
);
2980 de_dbg(c
, "bits per pixel: %u", bits_per_pixel
);
2982 w
= dbuf_getu16x(c
->infile
, pos
, d
->is_le
);
2984 h
= dbuf_getu16x(c
->infile
, pos
, d
->is_le
);
2986 de_dbg_dimensions(c
, w
, h
);
2988 num_icons
= dbuf_getu16x(c
->infile
, pos
, d
->is_le
);
2990 de_dbg(c
, "num icons: %"I64_FMT
, num_icons
);
2992 de_dbg_indent(c
, -1);
2994 if(w
!=32 || h
!=32 || bits_per_pixel
!=4) {
2999 icon_size
= 2+rowspan
*h
;
3001 if(c
->infile
->len
<16 ||
3002 ((c
->infile
->len
-16) % icon_size
)!=0)
3008 num_icons_capacity
= (c
->infile
->len
-16) / icon_size
;
3009 if(num_icons_capacity
< num_icons
) {
3010 de_warn(c
, "Expected %"I64_FMT
" icons, only found %"I64_FMT
,
3011 num_icons
, num_icons_capacity
);
3012 num_icons
= num_icons_capacity
;
3015 for(i
=0; i
<num_icons
; i
++) {
3019 pos
= 16+i
*icon_size
;
3020 de_dbg(c
, "icon at %"I64_FMT
, pos
);
3021 de_dbg_indent(c
, 1);
3022 id
= (UI
)dbuf_getu16x(c
->infile
, pos
, d
->is_le
);
3023 de_dbg(c
, "id: 0x%04x", id
);
3025 img
= de_bitmap_create(c
, w
, h
, 3);
3026 de_convert_image_paletted(c
->infile
, pos
+2, 4, rowspan
,
3027 d
->pal16
, img
, 0x01);
3028 de_bitmap_write_to_file(img
, NULL
, DE_CREATEFLAG_OPT_IMAGE
);
3029 de_bitmap_destroy(img
);
3030 de_dbg_indent(c
, -1);
3036 static void de_run_fmtowns_icn(deark
*c
, de_module_params
*mparams
)
3038 struct fmtownsicn_ctx
*d
= NULL
;
3041 d
= de_malloc(c
, sizeof(struct fmtownsicn_ctx
));
3042 fmtownsicn_make_palettes(c
, d
);
3046 do_fmtownsicn_ICNFILE(c
, d
);
3050 do_fmtownsicn_FJ(c
, d
);
3054 do_fmtownsicn_FJ(c
, d
);
3063 if(d
->need_errmsg
) {
3064 de_err(c
, "Bad or unsupported file");
3070 static int de_identify_fmtowns_icn(deark
*c
)
3074 de_read(buf
, 0, sizeof(buf
));
3075 if(!de_memcmp(buf
, (const void*)"ICNFILE\0\0\x1a", 10)) {
3078 if(!de_memcmp(buf
, (const void*)"CRI-FJ2 ", 8)) {
3081 if(!de_memcmp(buf
, (const void*)"CRI-FUJI", 8)) {
3087 void de_module_fmtowns_icn(deark
*c
, struct deark_module_info
*mi
)
3089 mi
->id
= "fmtowns_icn";
3090 mi
->desc
= "FM Towns icons";
3091 mi
->run_fn
= de_run_fmtowns_icn
;
3092 mi
->identify_fn
= de_identify_fmtowns_icn
;
3095 // **************************************************************************
3096 // PixFolio catalog (Allen C. Kempe) (Win3.x version)
3097 // **************************************************************************
3099 struct pixfolio_ctx
{
3100 de_encoding input_encoding
;
3105 de_ucstring
*tmpstr
;
3108 struct pixfolio_item_ctx
{
3111 struct de_stringreaderdata
*basefn_srd
;
3113 struct de_bmpinfo bi
;
3116 static void pixfolio_item_destroy(deark
*c
, struct pixfolio_item_ctx
*md
)
3119 de_destroy_stringreaderdata(c
, md
->basefn_srd
);
3123 static void read_pixfolio_timestamp(deark
*c
, struct pixfolio_ctx
*d
,
3124 struct pixfolio_item_ctx
*md
)
3126 de_ucstring
*dtstr
= NULL
;
3127 de_ucstring
*tmstr
= NULL
;
3129 dtstr
= ucstring_create(c
);
3130 tmstr
= ucstring_create(c
);
3132 dbuf_read_to_ucstring(c
->infile
, md
->pos
+343, 10, dtstr
, DE_CONVFLAG_STOP_AT_NUL
,
3133 DE_ENCODING_LATIN1
);
3134 dbuf_read_to_ucstring(c
->infile
, md
->pos
+354, 8, tmstr
, DE_CONVFLAG_STOP_AT_NUL
,
3135 DE_ENCODING_LATIN1
);
3136 de_dbg(c
, "timestamp: \"%s %s\"", ucstring_getpsz_d(dtstr
),
3137 ucstring_getpsz_d(tmstr
));
3139 // We don't do anything with the timestamp, because:
3140 // * There are at least 3 different date formats ("MM/DD/YYYY", "DD/MM/YYYY",
3141 // "MM-DD-YYYY") and seemingly no way to tell which was used.
3142 // * The time of day seems to be a 12-hour clock with no AM/PM flag.
3144 ucstring_destroy(tmstr
);
3145 ucstring_destroy(dtstr
);
3148 static void pixfolio_check_blank_name(deark
*c
, struct pixfolio_ctx
*d
,
3149 struct pixfolio_item_ctx
*md
)
3153 if(!md
->basefn_srd
) return;
3154 if(md
->basefn_srd
->sz_strlen
!=12) return;
3156 for(k
=0; k
<12; k
++) {
3157 if(md
->basefn_srd
->sz
[k
]!=0x20) return;
3159 md
->blank_basefn
= 1;
3162 // If successfully parsed, sets md->total_len
3163 static void do_pixfolio_item(deark
*c
, struct pixfolio_ctx
*d
,
3164 struct pixfolio_item_ctx
*md
)
3168 i64 dib_len1
, dib_len2
, dib_len
;
3171 i64 amt_to_copy1
, amt_to_copy2
;
3173 de_finfo
*fi
= NULL
;
3176 int saved_indent_level
;
3178 de_dbg_indent_save(c
, &saved_indent_level
);
3180 de_dbg(c
, "item at %"I64_FMT
, md
->pos
);
3181 de_dbg_indent(c
, 1);
3183 fi
= de_finfo_create(c
);
3184 md
->basefn_srd
= dbuf_read_string(c
->infile
, md
->pos
, 12, 12, DE_CONVFLAG_STOP_AT_NUL
,
3186 de_dbg(c
, "name: \"%s\"", ucstring_getpsz_d(md
->basefn_srd
->str
));
3187 pixfolio_check_blank_name(c
, d
, md
);
3189 ucstring_empty(d
->tmpstr
);
3190 dbuf_read_to_ucstring(c
->infile
, md
->pos
+25, 64, d
->tmpstr
, DE_CONVFLAG_STOP_AT_NUL
,
3192 de_dbg(c
, "path: \"%s\"", ucstring_getpsz_d(d
->tmpstr
));
3194 read_pixfolio_timestamp(c
, d
, md
);
3196 pos
= md
->pos
+ 363;
3197 // TODO: The "dib_len" fields need more research. They are usually equal.
3198 // Sometimes, one of them is 0, so we use the other one.
3199 dib_len1
= de_getu32le_p(&pos
); // Is this 32 or 16 bit?
3200 de_dbg(c
, "dib len1: %"I64_FMT
, dib_len1
);
3201 dib_len2
= de_getu16le_p(&pos
);
3202 de_dbg(c
, "dib len2: %"I64_FMT
, dib_len2
);
3203 if(dib_len1
&& dib_len2
&& (dib_len1
!= dib_len2
)) {
3204 d
->fatalerrflag
= 1;
3208 dib_len
= dib_len2
? dib_len2
: dib_len1
;
3210 descr_len
= de_getu16le_p(&pos
);
3211 de_dbg(c
, "descr len: %"I64_FMT
, descr_len
);
3212 xtra_len
= de_getu16le_p(&pos
); // TODO: What is this segment
3213 de_dbg(c
, "xtra len: %"I64_FMT
, xtra_len
);
3215 md
->total_len
= 373 + descr_len
+ 1 + dib_len
+ xtra_len
;
3216 pos
+= descr_len
+ 1;
3218 de_dbg(c
, "dib pos: %"I64_FMT
, dibpos
);
3219 if(dibpos
+dib_len
> c
->infile
->len
) {
3225 de_dbg(c
, "[no image]");
3229 if(md
->blank_basefn
) {
3230 de_dbg(c
, "[deleted]");
3232 if(!d
->opt_undelete
) goto done
;
3235 // Expecting a 40-byte BITMAPINFOHEADER here. If it's not, assume
3236 // we've gone off the rails.
3237 if((UI
)de_getu32le(dibpos
) != 40) {
3238 d
->fatalerrflag
= 1;
3243 ret
= fmtutil_get_bmpinfo(c
, c
->infile
, &md
->bi
, dibpos
,
3244 c
->infile
->len
- dibpos
, 0);
3250 amt_to_copy1
= dib_len
;
3251 amt_to_copy2
= md
->bi
.size_of_headers_and_pal
+ md
->bi
.sizeImage_field
;
3252 amt_to_copy1
= de_min_int(amt_to_copy1
, amt_to_copy2
);
3254 if(md
->blank_basefn
) {
3255 de_finfo_set_name_from_sz(c
, fi
, "deleted", 0, DE_ENCODING_LATIN1
);
3257 else if(c
->filenames_from_file
) {
3258 de_finfo_set_name_from_ucstring(c
, fi
, md
->basefn_srd
->str
, 0);
3261 outf
= dbuf_create_output_file(c
, "bmp", fi
, 0);
3262 fmtutil_generate_bmpfileheader(c
, outf
, &md
->bi
, 14+amt_to_copy1
);
3263 dbuf_copy(c
->infile
, dibpos
, amt_to_copy1
, outf
);
3266 if(md
->total_len
<=0) {
3267 d
->fatalerrflag
= 1;
3270 de_err(c
, "Failed to decode item at %"I64_FMT
, md
->pos
);
3273 de_finfo_destroy(c
, fi
);
3274 de_dbg_indent_restore(c
, saved_indent_level
);
3277 static void de_run_pixfolio(deark
*c
, de_module_params
*mparams
)
3279 struct pixfolio_ctx
*d
= NULL
;
3280 struct pixfolio_item_ctx
*md
= NULL
;
3283 d
= de_malloc(c
, sizeof(struct pixfolio_ctx
));
3284 d
->input_encoding
= de_get_input_encoding(c
, NULL
, DE_ENCODING_WINDOWS1252
);
3285 d
->opt_undelete
= (u8
)de_get_ext_option_bool(c
, "pixfolio:undelete", 0);
3286 d
->tmpstr
= ucstring_create(c
);
3290 if(d
->fatalerrflag
) goto done
;
3291 if(pos
+373 > c
->infile
->len
) goto done
;
3293 pixfolio_item_destroy(c
, md
);
3296 md
= de_malloc(c
, sizeof(struct pixfolio_item_ctx
));
3298 do_pixfolio_item(c
, d
, md
);
3299 if(md
->total_len
<=0) goto done
;
3300 pos
+= md
->total_len
;
3304 pixfolio_item_destroy(c
, md
);
3306 if(d
->deleted_count
!=0 && !d
->opt_undelete
) {
3307 de_info(c
, "Note: Deleted items found. Use \"-opt pixfolio:undelete\" "
3308 "to extract them.");
3310 if(d
->need_errmsg
) {
3311 de_err(c
, "Bad or unsupported file");
3313 ucstring_destroy(d
->tmpstr
);
3318 static int de_identify_pixfolio(deark
*c
)
3323 // This probably doesn't identify *every* PixFolio CAT file.
3324 // It assumes the first item contains an image, which is quite possibly not
3326 if(de_getbyte(0)<0x20) return 0;
3327 if(!de_input_file_has_ext(c
, "cat")) return 0;
3328 de_read(buf
, 343, 20);
3329 if(buf
[2]!='/' && buf
[2]!='-') return 0;
3330 if(buf
[13]!=':') return 0;
3331 n1
= de_getu16le(369); // Descr len
3332 n2
= de_getu32le(373+n1
+1); // DIB header size
3333 if(n2
!= 40) return 0;
3334 n2
= de_getu16le(373+n1
+1+12); // #planes
3335 if(n2
!= 1) return 0;
3339 static void de_help_pixfolio(deark
*c
)
3341 de_msg(c
, "-opt pixfolio:undelete : Also extract deleted images");
3344 void de_module_pixfolio(deark
*c
, struct deark_module_info
*mi
)
3346 mi
->id
= "pixfolio";
3347 mi
->desc
= "PixFolio catalog";
3348 mi
->run_fn
= de_run_pixfolio
;
3349 mi
->identify_fn
= de_identify_pixfolio
;
3350 mi
->help_fn
= de_help_pixfolio
;
3353 // **************************************************************************
3354 // Apple II icons archive
3355 // **************************************************************************
3357 struct a2icons_ctx
{
3359 de_color maskpal
[16];
3368 static void do_a2i_one_icon(deark
*c
, struct a2icons_ctx
*d
, i64 pos1
)
3370 de_bitmap
*img
= NULL
;
3371 de_bitmap
*mask
= NULL
;
3372 int saved_indent_level
;
3377 de_dbg_indent_save(c
, &saved_indent_level
);
3378 de_dbg(c
, "icon at %"I64_FMT
, pos1
);
3379 de_dbg_indent(c
, 1);
3380 icon_type
= (UI
)de_getu16le(pos1
);
3381 de_dbg(c
, "icon type: 0x%04x", icon_type
);
3382 d
->last_icon_len
= de_getu16le(pos1
+2);
3383 de_dbg(c
, "icon size: %"I64_FMT
, d
->last_icon_len
);
3384 h
= de_getu16le(pos1
+4);
3385 w
= de_getu16le(pos1
+6);
3386 de_dbg_dimensions(c
, w
, h
);
3387 if(!de_good_image_dimensions(c
, w
, h
)) goto done
;
3388 rowspan
= de_pad_to_n(w
*4, 8)/8;
3390 img
= de_bitmap_create(c
, w
, h
, 4);
3391 de_convert_image_paletted(c
->infile
, pos1
+8, 4, rowspan
, d
->pal
, img
, 0);
3393 mask
= de_bitmap_create(c
, w
, h
, 1);
3394 de_convert_image_paletted(c
->infile
, pos1
+8+d
->last_icon_len
, 4,
3395 rowspan
, d
->maskpal
, mask
, 0);
3397 de_bitmap_apply_mask(img
, mask
, 0);
3398 de_bitmap_write_to_file(img
, NULL
, DE_CREATEFLAG_OPT_IMAGE
);
3401 de_bitmap_destroy(img
);
3402 de_bitmap_destroy(mask
);
3403 de_dbg_indent_restore(c
, saved_indent_level
);
3406 #define A2I_GROUP_HDR_SIZE 86
3408 static void do_a2i_icon_group(deark
*c
, struct a2icons_ctx
*d
)
3410 int saved_indent_level
;
3413 de_dbg_indent_save(c
, &saved_indent_level
);
3414 de_dbg(c
, "icon group at %"I64_FMT
, d
->group_startpos
);
3415 de_dbg_indent(c
, 1);
3416 de_dbg(c
, "len: %"I64_FMT
, d
->group_len
);
3418 curpos
= d
->group_startpos
+A2I_GROUP_HDR_SIZE
;
3420 if(curpos
>= d
->group_endpos
) goto done
;
3421 d
->last_icon_len
= 0;
3422 do_a2i_one_icon(c
, d
, curpos
);
3423 if(d
->last_icon_len
==0) goto done
;
3424 curpos
= curpos
+ 8 + d
->last_icon_len
*2;
3428 de_dbg_indent_restore(c
, saved_indent_level
);
3431 static void de_run_apple2icons(deark
*c
, de_module_params
*mparams
)
3433 struct a2icons_ctx
*d
= NULL
;
3436 // Some colors here are just educated guesses.
3437 static const u8 dflt_pal
[16*3] = {
3438 0,0,0, 0,0,128, 128,128,0, 128,128,128,
3439 128,0,0, 128,0,128, 255,128,0, 255,128,128,
3440 0,128,0, 0,128,128, 128,255,0, 128,255,128,
3441 192,192,192, 128,128,255, 255,255,128, 255,255,255 };
3443 d
= de_malloc(c
, sizeof(struct a2icons_ctx
));
3444 de_copy_palette_from_rgb24(dflt_pal
, d
->pal
, 16);
3446 d
->maskpal
[0] = DE_STOCKCOLOR_BLACK
;
3447 for(i
=1; i
<16; i
++) {
3448 d
->maskpal
[i
] = DE_STOCKCOLOR_WHITE
;
3453 if(curpos
+A2I_GROUP_HDR_SIZE
> c
->infile
->len
) goto done
;
3454 d
->group_startpos
= curpos
;
3455 d
->group_len
= de_getu16le(curpos
);
3456 if(d
->group_len
<A2I_GROUP_HDR_SIZE
) goto done
;
3457 d
->group_endpos
= d
->group_startpos
+d
->group_len
;
3458 if(d
->group_endpos
> c
->infile
->len
) goto done
;
3460 do_a2i_icon_group(c
, d
);
3461 curpos
= d
->group_endpos
;
3468 void de_module_apple2icons(deark
*c
, struct deark_module_info
*mi
)
3470 mi
->id
= "apple2icons";
3471 mi
->desc
= "Apple II icons archive";
3472 mi
->run_fn
= de_run_apple2icons
;
3473 mi
->identify_fn
= NULL
;