1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 // Amiga Workbench icons, including "Newicons" and "Glowicons" formats
7 #include <deark-config.h>
8 #include <deark-private.h>
9 #include <deark-fmtutil.h>
10 DE_DECLARE_MODULE(de_module_amigaicon
);
12 typedef struct localctx_struct
{
23 // Newicons-specific data
25 dbuf
*newicons_data
[2];
27 int pending_data_bits_used
;
28 int newicons_bits_per_pixel
;
29 int newicons_line_count
;
31 // Glowicons-specific data
34 i64 glowicons_width
, glowicons_height
;
35 u32 glowicons_palette
[256];
38 static const u32 rev1pal
[4] = { 0x55aaff,0x000000,0xffffff,0xff8800 }; // http://krashan.ppa.pl/articles/amigaicons/
39 //static const u32 rev1pal[4] = { 0x0055aa,0x000020,0xffffff,0xff8a00 }; // Netpbm
41 static const u32 rev2pal
[4] = { 0x959595,0xffffff,0x000000,0x3b67a2 }; // http://krashan.ppa.pl/articles/amigaicons/
42 //static const u32 rev2pal[4] = { 0xaaaaaa,0xffffff,0x000000,0x556699 }; // XnView
44 static const u32 magicwbpal
[8] = {
45 0x959595,0x7b7b7b,0xffffff,0xaa907c,0x000000,0xafafaf,0x3b67a2,0xffa997 // http://krashan.ppa.pl/articles/amigaicons/ fixed? (& Wikipedia)
46 //0xaaaaaa,0x999999,0xffffff,0xbbaa99,0x000000,0xbbbbbb,0x556699,0xffbbaa // XnView
49 static void do_newicons_append_bit(deark
*c
, lctx
*d
, dbuf
*f
, u8 b
)
51 if(d
->pending_data_bits_used
==0) {
54 d
->pending_data
= (d
->pending_data
<<1) | (b
& 0x1);
55 d
->pending_data_bits_used
++;
57 if(d
->newicons_line_count
==0) {
58 // We're still reading palette samples, which are always 8 bits.
59 if(d
->pending_data_bits_used
==8) {
60 dbuf_writebyte(f
, d
->pending_data
);
61 d
->pending_data_bits_used
=0;
66 if(d
->pending_data_bits_used
>= d
->newicons_bits_per_pixel
) {
67 dbuf_writebyte(f
, d
->pending_data
);
68 d
->pending_data_bits_used
=0;
72 // Decode one NewIcons image. (There are usually two such images per file.)
73 // The raw data from the relevant ToolTypes table items must first be
75 static void do_decode_newicons(deark
*c
, lctx
*d
,
76 dbuf
*f
, int newicons_num
)
78 u8 trns_code
, width_code
, height_code
;
80 de_bitmap
*img
= NULL
;
86 i64 bitmap_start_pos
= 0;
89 int saved_indent_level
;
92 de_dbg_indent_save(c
, &saved_indent_level
);
93 de_dbg(c
, "decoding NewIcons[%d], len=%"I64_FMT
, newicons_num
, f
->len
);
96 trns_code
= dbuf_getbyte(f
, 0);
97 has_trns
= (trns_code
=='B');
98 width_code
= dbuf_getbyte(f
, 1);
99 height_code
= dbuf_getbyte(f
, 2);
101 b0
= dbuf_getbyte(f
, 3);
102 b1
= dbuf_getbyte(f
, 4);
103 ncolors
= ((((i64
)b0
)-0x21)<<6) + (((i64
)b1
)-0x21);
104 if(ncolors
<1) ncolors
=1;
105 if(ncolors
>256) ncolors
=256;
107 width
= (i64
)width_code
- 0x21;
108 height
= (i64
)height_code
- 0x21;
110 de_dbg_dimensions(c
, width
, height
);
111 if(!de_good_image_dimensions(c
, width
, height
)) goto done
;
112 de_dbg(c
, "transparency: %d", has_trns
);
113 de_dbg(c
, "colors: %d", (int)ncolors
);
115 decoded
= dbuf_create_membuf(c
, 2048, 0);
118 d
->pending_data_bits_used
= 0;
120 d
->newicons_bits_per_pixel
= (int)de_log2_rounded_up(ncolors
);
122 // We decode both the palette and the bitmap into the same buffer, and
123 // keep track of where in the buffer the bitmap starts.
125 // Count the number of lines (EOL represented by 0x00 byte).
126 // This is only needed because the bitmap starts on the second line.
127 d
->newicons_line_count
=0;
129 for(srcpos
=5; srcpos
<f
->len
; srcpos
++) {
130 b0
= dbuf_getbyte(f
, srcpos
);
131 if((b0
>=0x20 && b0
<=0x6f) || (b0
>=0xa1 && b0
<=0xd0)) {
132 if(b0
<=0x6f) b1
= b0
-0x20;
133 else b1
= 0x50 + (b0
-0xa1);
136 tmpb
= (b1
>>(6-i
))&0x01;
137 do_newicons_append_bit(c
, d
, decoded
, tmpb
);
141 // RLE compression for "0" bits
143 rle_len
= 7*(i64
)(b0
-0xd0);
144 for(i
=0; i
<rle_len
; i
++) {
145 do_newicons_append_bit(c
, d
, decoded
, tmpb
);
150 // Throw away any bits we've decoded that haven't been used yet.
151 d
->pending_data_bits_used
= 0;
153 if(d
->newicons_line_count
==0) {
154 // The bitmap will start at this position. Remember that.
155 bitmap_start_pos
= decoded
->len
;
157 d
->newicons_line_count
++;
161 de_dbg(c
, "decompressed to %d bytes", (int)decoded
->len
);
163 // The first ncolors*3 bytes are the palette
164 de_dbg2(c
, "NewIcons palette");
166 for(i
=0; i
<ncolors
; i
++) {
168 pal
[i
] = dbuf_getRGB(decoded
, i
*3, 0);
170 // Educated guess: If the transparency flag is set, it means
171 // palette entry 0 is transparent.
173 pal
[i
] = DE_SET_ALPHA(pal
[i
], 0x00);
175 de_dbg_pal_entry(c
, i
, pal
[i
]);
177 de_dbg_indent(c
, -1);
179 img
= de_bitmap_create(c
, width
, height
, 4);
180 de_convert_image_paletted(decoded
, bitmap_start_pos
,
181 8, width
, pal
, img
, 0);
182 de_bitmap_write_to_file(img
, c
->filenames_from_file
?"n":NULL
,
183 d
->has_glowicons
?DE_CREATEFLAG_IS_AUX
:0);
187 de_bitmap_destroy(img
);
188 de_dbg_indent_restore(c
, saved_indent_level
);
191 // Read enough of a main icon's header to determine how many bytes it uses.
192 static void get_main_icon_size(deark
*c
, lctx
*d
, i64 pos
, i64
*pbytesused
)
196 i64 src_rowspan
, src_planespan
;
198 width
= de_getu16be(pos
+4);
199 height
= de_getu16be(pos
+6);
200 depth
= de_getu16be(pos
+8);
201 src_rowspan
= ((width
+15)/16)*2;
202 src_planespan
= src_rowspan
* height
;
204 *pbytesused
= 20 + src_planespan
* depth
;
207 static int do_read_main_icon(deark
*c
, lctx
*d
,
208 i64 pos
, i64 icon_index
)
213 i64 src_rowspan
, src_planespan
;
216 de_bitmap
*img
= NULL
;
220 de_dbg(c
, "main icon #%d at %"I64_FMT
, (int)icon_index
, pos
);
223 // 20-byte header, followed by one or more bitmap "planes".
224 npwidth
= de_getu16be(pos
+4);
225 height
= de_getu16be(pos
+6);
226 depth
= de_getu16be(pos
+8);
227 de_dbg_dimensions(c
, npwidth
, height
);
228 de_dbg(c
, "depth: %d", (int)depth
);
230 if(depth
<1 || depth
>8) {
231 de_err(c
, "Unsupported bit depth (%d)", (int)depth
);
235 pdwidth
= de_pad_to_n(npwidth
, 16);
236 src_rowspan
= pdwidth
/8;
237 src_planespan
= src_rowspan
* height
;
239 img
= de_bitmap_create2(c
, npwidth
, pdwidth
, height
, 3);
241 // Figure out what palette to use
243 // Start with a meaningless grayscale palette.
244 de_make_grayscale_palette(pal
, 256, 0x0);
247 // The only 1-bit images I've seen are dummy images.
248 // I don't know how they're supposed to be handled, but this should do.
249 pal
[0] = DE_STOCKCOLOR_BLACK
;
250 pal
[1] = DE_STOCKCOLOR_WHITE
;
251 if(!d
->has_newicons
&& !d
->has_glowicons
) {
252 de_warn(c
, "Don't know how to handle 1-bit images");
255 else if(d
->icon_revision
==0 && depth
==2) {
256 for(i
=0; i
<4; i
++) pal
[i
] = rev1pal
[i
];
259 for(i
=0; i
<4; i
++) pal
[i
] = rev2pal
[i
];
262 for(i
=0; i
<8; i
++) pal
[i
] = magicwbpal
[i
];
266 for(i
=0; i
<16; i
++) pal
[i
] = magicwbpal
[i
>>1];
269 // Don't ask me. Just doing what other apps seem to do.
270 for(i
=0; i
<256; i
++) pal
[i
] = magicwbpal
[i
>>5];
273 de_warn(c
, "Don't know how to handle images with bit depth %d", (int)depth
);
278 for(j
=0; j
<height
; j
++) {
279 for(i
=0; i
<pdwidth
; i
++) {
281 for(plane
=0; plane
<depth
; plane
++) {
282 b1
= de_get_bits_symbol(c
->infile
, 1, pos
+plane
*src_planespan
+ j
*src_rowspan
, i
);
283 b
= (b
<<1) | (b1
& 0x1);
285 de_bitmap_setpixel_rgb(img
, i
, j
, pal
[b
]);
289 de_bitmap_write_to_file(img
, NULL
, (d
->has_newicons
||d
->has_glowicons
)?DE_CREATEFLAG_IS_AUX
:0);
294 de_bitmap_destroy(img
);
295 de_dbg_indent(c
, -1);
299 static void do_one_tooltype(deark
*c
, lctx
*d
, i64 tpos
, i64 tlen
)
303 struct de_stringreaderdata
*ttstr
= NULL
;
305 n
= de_min_int(tlen
, 64);
306 ttstr
= dbuf_read_string(c
->infile
, tpos
, n
, n
, 0, DE_ENCODING_ASCII
);
307 de_dbg(c
, "data: \"%s\"", ucstring_getpsz_d(ttstr
->str
));
309 // The rest of this function is for identifying and recording NewIcons data.
312 // Too small to contain NewIcons data.
318 if(ttstr
->sz
[0]=='I' && ttstr
->sz
[1]=='M' && ttstr
->sz
[3]=='=') {
319 if(ttstr
->sz
[2]=='1') newicons_num
= 0;
320 else if(ttstr
->sz
[2]=='2') newicons_num
= 1;
322 if(newicons_num
== -1) {
328 // Write NewIcons data to membufs, for later decoding.
330 if(!d
->newicons_data
[newicons_num
]) {
331 de_dbg(c
, "NewIcons data [%d] starts at %"I64_FMT
, newicons_num
, tpos
);
332 d
->newicons_data
[newicons_num
] = dbuf_create_membuf(c
, 2048, 0);
333 // The data we copy includes the terminating NUL.
336 de_dbg2(c
, "NewIcons data [%d] continues at %"I64_FMT
, newicons_num
, tpos
);
338 dbuf_copy(c
->infile
, tpos
+4, tlen
-4, d
->newicons_data
[newicons_num
]);
341 de_destroy_stringreaderdata(c
, ttstr
);
344 static int do_read_tooltypes_table(deark
*c
, lctx
*d
,
345 i64 pos1
, i64
*pbytesused
)
352 int saved_indent_level
;
354 de_dbg_indent_save(c
, &saved_indent_level
);
356 de_dbg(c
, "tool types table at %"I64_FMT
, pos
);
359 num_entries_raw
= de_getu32be_p(&pos
);
360 num_entries
= num_entries_raw
/4 - 1;
361 de_dbg(c
, "number of tool types: %d", (int)num_entries
);
362 if(num_entries
<0 || num_entries
>1000) {
366 for(i
=0; i
<num_entries
; i
++) {
372 tlen
= de_getu32be_p(&pos
);
374 de_dbg(c
, "tooltype[%d] at %"I64_FMT
", dpos=%"I64_FMT
", dlen=%"I64_FMT
,
375 (int)i
, entry_pos
, tpos
, tlen
);
377 de_err(c
, "Bad ToolTypes data");
382 do_one_tooltype(c
, d
, tpos
, tlen
);
383 de_dbg_indent(c
, -1);
390 *pbytesused
= pos
- pos1
;
391 de_dbg_indent_restore(c
, saved_indent_level
);
395 // Uncompress a slice of f, and append to outf.
396 // The algorithm is the same as PackBits, except that the data elements may
397 // be less than 8 bits.
398 static void glowdata_uncompress(dbuf
*f
, i64 pos
, i64 len
,
399 dbuf
*outf
, int bits_per_pixel
)
408 // Continue as long as at least 8 bits remain.
409 while(bitpos
<= (len
-1)*8) {
410 b
= de_get_bits_symbol2(f
, 8, pos
, bitpos
);
414 // 1+b literal pixels
417 b2
= de_get_bits_symbol2(f
, bits_per_pixel
, pos
, bitpos
);
418 bitpos
+= bits_per_pixel
;
419 dbuf_writebyte(outf
, b2
);
423 // 257-b repeated pixels
425 b2
= de_get_bits_symbol2(f
, bits_per_pixel
, pos
, bitpos
);
426 bitpos
+= bits_per_pixel
;
428 dbuf_writebyte(outf
, b2
);
434 static void do_glowicons_IMAG(deark
*c
, lctx
*d
,
437 de_bitmap
*img
= NULL
;
444 u8 pal_cmpr_type
= 0;
446 i64 image_size_in_bytes
;
447 i64 pal_size_in_bytes
;
453 if(d
->glowicons_width
<1) {
454 // We must not have found a FACE chunk yet.
455 de_err(c
, "Invalid GlowIcons data");
459 trns_color
= de_getbyte(pos
);
460 de_dbg(c
, "transparent color: 0x%02x", (int)trns_color
);
461 num_colors
= 1+(i64
)de_getbyte(pos
+1);
462 de_dbg(c
, "number of colors: %d", (int)num_colors
);
463 flags
= de_getbyte(pos
+2);
464 has_trns
= (flags
& 0x01)?1:0;
465 has_palette
= (flags
& 0x02)?1:0;
466 de_dbg(c
, "has transparency: %d", has_trns
);
467 de_dbg(c
, "has palette: %d", has_palette
);
469 cmpr_type
= de_getbyte(pos
+3);
470 de_dbg(c
, "compression type: %d", cmpr_type
);
471 if(cmpr_type
!=0 && cmpr_type
!=1) {
472 de_err(c
, "Unsupported compression type");
477 // TODO uncompressed images (Need sample files. I don't know how
478 // they are structured.)
479 de_err(c
, "Uncompressed images are not supported");
484 pal_cmpr_type
= de_getbyte(pos
+4);
485 de_dbg(c
, "palette compression type: %d", pal_cmpr_type
);
486 if(pal_cmpr_type
!=0 && pal_cmpr_type
!=1) {
487 de_err(c
, "Unsupported palette compression type");
492 bits_per_pixel
= (i64
)de_getbyte(pos
+5);
493 de_dbg(c
, "bits per pixel: %d", (int)bits_per_pixel
);
495 if(bits_per_pixel
<1 || bits_per_pixel
>8) {
496 de_err(c
, "Invalid or unsupported bits per pixel (%d)", (int)bits_per_pixel
);
500 image_size_in_bytes
= 1+de_getu16be(pos
+6);
501 pal_size_in_bytes
= 1+de_getu16be(pos
+8);
504 tmpbuf
= dbuf_create_membuf(c
, 10240, 0);
507 pal_pos
= image_pos
+image_size_in_bytes
;
508 de_dbg(c
, "image data at %d, len=%d", (int)image_pos
, (int)image_size_in_bytes
);
511 de_dbg(c
, "palette data at %d, len=%d", (int)pal_pos
, (int)pal_size_in_bytes
);
514 if(pal_cmpr_type
==1) {
515 glowdata_uncompress(c
->infile
, pal_pos
, pal_size_in_bytes
, tmpbuf
, 8);
518 dbuf_copy(c
->infile
, pal_pos
, pal_size_in_bytes
, tmpbuf
);
521 for(k
=0; k
<256; k
++) {
523 d
->glowicons_palette
[k
] = dbuf_getRGB(tmpbuf
, k
*3, 0);
524 if(has_trns
&& k
==(i64
)trns_color
) {
525 d
->glowicons_palette
[k
] = DE_SET_ALPHA(d
->glowicons_palette
[k
], 0x00);
527 de_dbg_pal_entry(c
, k
, d
->glowicons_palette
[k
]);
530 d
->glowicons_palette
[k
] = DE_STOCKCOLOR_BLACK
;
534 de_dbg_indent(c
, -1);
537 // Uncompress the pixels
539 glowdata_uncompress(c
->infile
, image_pos
, image_size_in_bytes
, tmpbuf
, (int)bits_per_pixel
);
541 img
= de_bitmap_create(c
, d
->glowicons_width
, d
->glowicons_height
, has_trns
?4:3);
543 de_convert_image_paletted(tmpbuf
, 0,
544 8, d
->glowicons_width
, d
->glowicons_palette
, img
, 0);
546 de_bitmap_write_to_file(img
, c
->filenames_from_file
?"g":NULL
, 0);
549 if(tmpbuf
) dbuf_close(tmpbuf
);
550 if(img
) de_bitmap_destroy(img
);
553 // GlowIcons chunk types:
554 #define CODE_FORM 0x464f524dU
555 #define CODE_FACE 0x46414345U
556 #define CODE_IMAG 0x494d4147U
558 #define CODE_ICON 0x49434f4eU
560 static int do_detect_glowicons(deark
*c
, lctx
*d
, i64 pos
)
566 gsize
= c
->infile
->len
- pos
;
567 if(gsize
<=0) return 0;
570 chunk_id
= (u32
)de_getu32be(pos
);
571 form_type
= (u32
)de_getu32be(pos
+8);
572 if(chunk_id
==CODE_FORM
&& form_type
==CODE_ICON
) {
573 de_dbg(c
, "GlowIcons data found at %d", (int)pos
);
578 de_warn(c
, "Extra data found at end of file, but not identified as GlowIcons format.");
582 static int my_iff_chunk_handler(struct de_iffctx
*ictx
)
585 lctx
*d
= (lctx
*)ictx
->userdata
;
588 if(ictx
->chunkctx
->chunk4cc
.id
== CODE_FORM
) {
589 ictx
->is_std_container
= 1;
597 if(ictx
->curr_container_contentstype4cc
.id
!= CODE_ICON
) {
601 dpos
= ictx
->chunkctx
->dpos
;
602 dlen
= ictx
->chunkctx
->dlen
;
604 switch(ictx
->chunkctx
->chunk4cc
.id
) {
605 case CODE_FACE
: // FACE (parameters)
607 d
->glowicons_width
= 1+(i64
)dbuf_getbyte(ictx
->f
, dpos
);
608 d
->glowicons_height
= 1+(i64
)dbuf_getbyte(ictx
->f
, dpos
+1);
609 de_dbg_dimensions(c
, d
->glowicons_width
, d
->glowicons_height
);
611 case CODE_IMAG
: // IMAG (one of the images that make up this icon)
613 do_glowicons_IMAG(c
, d
, dpos
, dlen
);
620 static void do_glowicons(deark
*c
, lctx
*d
, i64 pos1
)
622 struct de_iffctx
*ictx
= NULL
;
623 int saved_indent_level
;
625 ictx
= fmtutil_create_iff_decoder(c
);
626 de_dbg_indent_save(c
, &saved_indent_level
);
628 de_dbg(c
, "GlowIcons data at offset %d", (int)pos1
);
631 ictx
->userdata
= (void*)d
;
632 ictx
->handle_chunk_fn
= my_iff_chunk_handler
;
634 fmtutil_read_iff_format(ictx
, pos1
, c
->infile
->len
- pos1
);
636 de_dbg_indent_restore(c
, saved_indent_level
);
637 fmtutil_destroy_iff_decoder(ictx
);
640 static const char *get_icon_type_name(u8 t
)
642 const char *tn
= NULL
;
645 case 1: tn
="disk"; break;
646 case 2: tn
="drawer"; break;
647 case 3: tn
="tool"; break;
648 case 4: tn
="project"; break;
649 case 6: tn
="device"; break;
650 case 7: tn
="kick"; break;
655 static void do_scan_file(deark
*c
, lctx
*d
)
664 int saved_indent_level
;
666 de_dbg_indent_save(c
, &saved_indent_level
);
667 de_dbg(c
, "DiskObject at %d, len=%d", 0, 78);
670 version
= de_getu16be(2);
671 de_dbg(c
, "version: %d", (int)version
);
673 de_dbg(c
, "Gadget at %d, len=%d", 4, 44);
676 main_width
= de_getu16be(12);
677 main_height
= de_getu16be(14);
678 de_dbg(c
, "main canvas size: %d"DE_CHAR_TIMES
"%d", (int)main_width
, (int)main_height
);
681 de_dbg(c
, "SelectRender: 0x%08x", (unsigned int)x
);
682 d
->num_main_icons
= (x
==0) ? 1 : 2;
684 de_dbg(c
, "number of (original) icons: %d", (int)d
->num_main_icons
);
685 de_dbg_indent(c
, -1);
687 d
->icon_revision
= de_getu32be(44) & 0xff;
688 de_dbg(c
, "icon revision: %d", (int)d
->icon_revision
);
690 de_dbg_indent(c
, -1); // end of embedded "Gadget" object
692 d
->icon_type
= de_getbyte(48);
693 de_dbg(c
, "icon type: %d (%s)", (int)d
->icon_type
, get_icon_type_name(d
->icon_type
));
696 d
->has_defaulttool
= (x
!=0);
697 de_dbg(c
, "defaulttool: 0x%08x", (unsigned int)x
);
700 d
->has_tooltypes
= (x
!=0);
701 de_dbg(c
, "tooltypes: 0x%08x", (unsigned int)x
);
704 d
->has_drawerdata
= (x
!=0);
705 de_dbg(c
, "drawerdata: 0x%08x", (unsigned int)x
);
708 d
->has_toolwindow
= (x
!=0);
709 de_dbg(c
, "toolwindow: 0x%08x", (unsigned int)x
);
711 de_dbg_indent(c
, -1);
715 // DrawerData segment
716 if(d
->has_drawerdata
) {
717 const i64 ddlen
= 56;
718 de_dbg(c
, "DrawerData at %"I64_FMT
", len=%"I64_FMT
, pos
, ddlen
);
719 if(c
->debug_level
>=2) {
721 de_dbg_hexdump(c
, c
->infile
, pos
, ddlen
, 256, NULL
, 0x1);
722 de_dbg_indent(c
, -1);
727 // Record the location of the main (original-style) icons
728 for(i
=0; i
<d
->num_main_icons
; i
++) {
729 d
->main_icon_pos
[i
] = pos
;
730 get_main_icon_size(c
, d
, pos
, &bytesused
);
731 de_dbg(c
, "main icon #%d data at %"I64_FMT
", len=%"I64_FMT
, (int)i
,
732 d
->main_icon_pos
[i
], bytesused
);
736 // DefaultTool segment
737 if(d
->has_defaulttool
) {
738 x
= de_getu32be(pos
);
739 de_dbg(c
, "DefaultTool at %"I64_FMT
", dpos=%"I64_FMT
", dlen=%"I64_FMT
,
742 if(c
->debug_level
>=2) {
744 de_dbg_hexdump(c
, c
->infile
, pos
, x
, 256, NULL
, 0x1);
745 de_dbg_indent(c
, -1);
750 if(d
->has_tooltypes
) {
751 // This will also read NewIcons-style icons.
752 if(!do_read_tooltypes_table(c
, d
, pos
, &bytesused
))
757 // Skip the ToolWindow segment (untested)
758 if(d
->has_toolwindow
) {
759 x
= de_getu32be(pos
);
760 de_dbg(c
, "ToolWindow: %d bytes at %d", (int)(4+x
), (int)pos
);
765 if(d
->has_drawerdata
&& d
->icon_revision
==1) {
766 const i64 dd2len
= 6;
767 de_dbg(c
, "DrawerData2 at %"I64_FMT
", len=%"I64_FMT
, pos
, dd2len
);
768 if(c
->debug_level
>=2) {
770 de_dbg_hexdump(c
, c
->infile
, pos
, dd2len
, 256, NULL
, 0x1);
771 de_dbg_indent(c
, -1);
776 if(do_detect_glowicons(c
, d
, pos
)) {
777 d
->has_glowicons
= 1;
778 d
->glowicons_pos
= pos
;
782 de_dbg_indent_restore(c
, saved_indent_level
);
785 static void de_run_amigaicon(deark
*c
, de_module_params
*mparams
)
790 d
= de_malloc(c
, sizeof(lctx
));
794 if(d
->has_glowicons
) {
795 de_declare_fmt(c
, "Amiga Workbench Icon, GlowIcons");
797 else if(d
->has_newicons
) {
798 de_declare_fmt(c
, "Amiga Workbench Icon, NewIcons");
801 de_declare_fmt(c
, "Amiga Workbench Icon");
804 de_dbg(c
, "finished scanning file, now extracting icons");
806 // Original format icons
807 for(i
=0; i
<d
->num_main_icons
; i
++) {
808 do_read_main_icon(c
, d
, d
->main_icon_pos
[i
], i
);
813 if(d
->newicons_data
[i
]) {
814 do_decode_newicons(c
, d
, d
->newicons_data
[i
], (int)i
);
819 if(d
->has_glowicons
) {
820 do_glowicons(c
, d
, d
->glowicons_pos
);
823 if(d
->newicons_data
[0]) dbuf_close(d
->newicons_data
[0]);
824 if(d
->newicons_data
[1]) dbuf_close(d
->newicons_data
[1]);
828 static int de_identify_amigaicon(deark
*c
)
830 if(!dbuf_memcmp(c
->infile
, 0, "\xe3\x10", 2))
835 void de_module_amigaicon(deark
*c
, struct deark_module_info
*mi
)
837 mi
->id
= "amigaicon";
838 mi
->desc
= "Amiga Workbench icon (.info), NewIcons, GlowIcons";
839 mi
->run_fn
= de_run_amigaicon
;
840 mi
->identify_fn
= de_identify_amigaicon
;