1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 // EPOC MBM, EPOC Sketch, EPOC AIF
7 #include <deark-private.h>
8 DE_DECLARE_MODULE(de_module_epocimage
);
11 #define DE_PFMT_EXPORTED_MBM 2
12 #define DE_PFMT_SKETCH 3
15 static const u32 supplpal
[40] = {
16 0x111111,0x222222,0x444444,0x555555,0x777777,
17 0x110000,0x220000,0x440000,0x550000,0x770000,
18 0x001100,0x002200,0x004400,0x005500,0x007700,
19 0x000011,0x000022,0x000044,0x000055,0x000077,
20 0x000088,0x0000aa,0x0000bb,0x0000dd,0x0000ee,
21 0x008800,0x00aa00,0x00bb00,0x00dd00,0x00ee00,
22 0x880000,0xaa0000,0xbb0000,0xdd0000,0xee0000,
23 0x888888,0xaaaaaa,0xbbbbbb,0xdddddd,0xeeeeee
26 static u32
getpal256(int k
)
31 if(k
<0 || k
>255) return DE_STOCKCOLOR_BLACK
;
33 // The first and last 108 entries together make up the simple palette once
34 // known as the "web safe" palette. The middle 40 entries are
35 // supplementary grayscale and red/green/blue shades.
38 return DE_MAKE_OPAQUE(supplpal
[k
-108]);
44 b
= (u8
)((x
/36)*0x33);
46 return DE_MAKE_RGB(r
,g
,b
);
49 // I believe this is the correct palette (or at least *a* correct palette),
50 // though it has some differences from the one in the Psiconv documentation.
51 static const u32 pal16
[16] = {
52 0x000000,0x555555,0x800000,0x808000,0x008000,0xff0000,0xffff00,0x00ff00,
53 0xff00ff,0x0000ff,0x00ffff,0x800080,0x000080,0x008080,0xaaaaaa,0xffffff
62 typedef struct localctx_struct
{
64 i64 paint_data_section_size
;
68 i64 section_table_offset
;
71 static de_bitmap
*do_create_image(deark
*c
, lctx
*d
, struct page_ctx
*pg
,
72 dbuf
*unc_pixels
, int is_mask
)
74 de_bitmap
*img
= NULL
;
86 if(pg
->bits_per_pixel
==24) {
87 // 24-bit images seem to be 12-byte aligned
88 src_rowspan
= ((pg
->bits_per_pixel
*pg
->width
+95)/96)*12;
90 else if(pg
->bits_per_pixel
==12) {
91 // Our decompression algorithm expands RLE12 to an RGB24 format.
92 // Apparently, rows with an odd number of pixels have one pixel of
93 // padding, which at this stage is 3 bytes.
94 src_rowspan
= 3*pg
->width
;
95 if(pg
->width
%2) src_rowspan
+= 3;
99 // Rows are 4-byte aligned
101 bits_per_row
= de_pad_to_n(pg
->bits_per_pixel
*pg
->width
, 32);
102 src_rowspan
= bits_per_row
/ 8;
103 pdwidth
= bits_per_row
/ pg
->bits_per_pixel
;
106 bypp
= pg
->color_type
? 3 : 1;
107 img
= de_bitmap_create2(c
, pg
->width
, pdwidth
, pg
->height
, bypp
);
108 img
->orig_colortype
= (int)pg
->color_type
;
109 img
->orig_bitdepth
= (int)pg
->bits_per_pixel
;
111 for(j
=0; j
<pg
->height
; j
++) {
112 for(i
=0; i
<pg
->width
; i
++) {
113 switch(pg
->bits_per_pixel
) {
115 b
= de_get_bits_symbol_lsb(unc_pixels
, pg
->bits_per_pixel
, j
*src_rowspan
, i
);
116 de_bitmap_setpixel_gray(img
, i
, j
, b
*255);
119 b
= de_get_bits_symbol_lsb(unc_pixels
, pg
->bits_per_pixel
, j
*src_rowspan
, i
);
120 de_bitmap_setpixel_gray(img
, i
, j
, b
*85);
123 b
= de_get_bits_symbol_lsb(unc_pixels
, pg
->bits_per_pixel
, j
*src_rowspan
, i
);
125 de_bitmap_setpixel_rgb(img
, i
, j
, DE_MAKE_OPAQUE(pal16
[(unsigned int)b
]));
127 de_bitmap_setpixel_gray(img
, i
, j
, b
*17);
130 b
= dbuf_getbyte(unc_pixels
, j
*src_rowspan
+ i
);
132 de_bitmap_setpixel_rgb(img
, i
, j
, getpal256((unsigned int)b
));
135 // I have no 8-bit grayscale samples, so I don't know if this is
136 // correct, or valid.
137 de_bitmap_setpixel_gray(img
, i
, j
, b
);
141 n
= (u32
)dbuf_getu16le(unc_pixels
, j
*src_rowspan
+ i
*2);
144 clr
= DE_MAKE_RGB(cr
, cr
, cr
);
147 clr
= de_rgb565_to_888(n
);
149 de_bitmap_setpixel_rgb(img
, i
, j
, clr
);
153 clr
= dbuf_getRGB(unc_pixels
, j
*src_rowspan
+ i
*3, 0);
154 de_bitmap_setpixel_rgb(img
, i
, j
, clr
);
162 static void do_rle8(deark
*c
, lctx
*d
, dbuf
*unc_pixels
,
170 while(pos
<pos1
+len
) {
171 b0
= de_getbyte(pos
);
175 // Next byte should be repeated b0+1 times.
177 b1
= de_getbyte(pos
);
179 dbuf_write_run(unc_pixels
, b1
, count
);
182 // 256-b0 bytes of uncompressed data.
184 dbuf_copy(c
->infile
, pos
, count
, unc_pixels
);
190 static void do_rle12(deark
*c
, lctx
*d
, dbuf
*unc_pixels
,
199 while(pos
<pos1
+len
) {
200 n
= (unsigned int)de_getu16le_p(&pos
);
201 count
= 1+(i64
)((n
&0xf000)>>12);
202 v
[0] = (u8
)((n
&0x0f00)>>8);
203 v
[1] = (u8
)((n
&0x00f0)>>4);
204 v
[2] = (u8
)(n
&0x000f);
208 for(k
=0; k
<count
; k
++) {
209 dbuf_write(unc_pixels
, v
, 3);
214 static void do_rle16_24(deark
*c
, lctx
*d
, dbuf
*unc_pixels
,
215 i64 pos1
, i64 len
, i64 bytes_per_pixel
)
225 while(pos
<pos1
+len
) {
226 b0
= de_getbyte(pos
);
230 // Next pixel should be repeated b0+1 times.
232 for(k
=0; k
<bytes_per_pixel
; k
++) {
233 v
[k
] = de_getbyte(pos
++);
235 for(i
=0; i
<count
; i
++) {
236 dbuf_write(unc_pixels
, v
, bytes_per_pixel
);
240 // 256-b0 pixels of uncompressed data.
242 dbuf_copy(c
->infile
, pos
, count
*bytes_per_pixel
, unc_pixels
);
243 pos
+= count
*bytes_per_pixel
;
248 static const char *get_cmpr_type_name(i64 t
)
250 const char *s
= NULL
;
252 case 0: s
="none"; break;
253 case 1: s
="RLE8"; break;
254 case 2: s
="RLE12"; break;
255 case 3: s
="RLE16"; break;
256 case 4: s
="RLE24"; break;
261 // Sets d->paint_data_section_size.
263 static de_bitmap
*do_read_paint_data_section(deark
*c
, lctx
*d
,
264 i64 pos1
, int is_mask
)
266 i64 pixel_data_offset
;
268 dbuf
*unc_pixels
= NULL
;
269 i64 compression_type
;
270 i64 cmpr_pixels_size
;
271 de_bitmap
*img
= NULL
;
272 struct page_ctx
*pg
= NULL
;
274 pg
= de_malloc(c
, sizeof(struct page_ctx
));
276 de_dbg(c
, "paint data section at %d", (int)pos1
);
279 d
->paint_data_section_size
= de_getu32le(pos
);
280 de_dbg(c
, "paint data section size: %d", (int)d
->paint_data_section_size
);
282 // offset within "paint data section"
283 pixel_data_offset
= de_getu32le(pos
+4);
284 de_dbg(c
, "pixel data offset: %d", (int)pixel_data_offset
);
286 pg
->width
= de_getu16le(pos
+8);
287 pg
->height
= de_getu16le(pos
+12);
288 de_dbg(c
, "picture dimensions: %d"DE_CHAR_TIMES
"%d", (int)pg
->width
, (int)pg
->height
);
290 pg
->bits_per_pixel
= de_getu32le(pos
+24);
291 de_dbg(c
, "bits/pixel: %d", (int)pg
->bits_per_pixel
);
293 pg
->color_type
= de_getu32le(pos
+28);
294 // 0=grayscale 1=color
295 de_dbg(c
, "color type: %d", (int)pg
->color_type
);
297 compression_type
= de_getu32le(pos
+36);
298 // 0=uncompressed 1=8-bit RLE 2=12-bit RLE 3=16-bit RLE 4=24-bit RLE
299 de_dbg(c
, "compression type: %d (%s)", (int)compression_type
,
300 get_cmpr_type_name(compression_type
));
302 if(pg
->color_type
==0) {
303 if(pg
->bits_per_pixel
!=1 && pg
->bits_per_pixel
!=2 && pg
->bits_per_pixel
!=4 &&
304 pg
->bits_per_pixel
!=8)
306 de_err(c
, "Unsupported bits/pixel (%d) for grayscale image", (int)pg
->bits_per_pixel
);
311 if(pg
->bits_per_pixel
!=4 && pg
->bits_per_pixel
!=8 && pg
->bits_per_pixel
!=12 &&
312 pg
->bits_per_pixel
!=16 && pg
->bits_per_pixel
!=24)
314 de_err(c
, "Unsupported bits/pixel (%d) for color image", (int)pg
->bits_per_pixel
);
317 if(pg
->bits_per_pixel
==12 && compression_type
!=2) {
318 de_err(c
, "12 bits/pixel images are not supported with this compression type (%d)",
319 (int)compression_type
);
321 if(pg
->bits_per_pixel
==16 && !d
->warned_exp
) {
322 de_warn(c
, "Support for this type of 16-bit image is experimental, and may not be correct.");
328 cmpr_pixels_size
= d
->paint_data_section_size
-40;
329 de_dbg(c
, "pixel data at %d", (int)pos
);
331 switch(compression_type
) {
332 case 0: // uncompressed
333 unc_pixels
= dbuf_open_input_subfile(c
->infile
, pos
, c
->infile
->len
- pos
);
336 unc_pixels
= dbuf_create_membuf(c
, 16384, 0);
337 do_rle8(c
, d
, unc_pixels
, pos
, cmpr_pixels_size
);
340 unc_pixels
= dbuf_create_membuf(c
, 16384, 0);
341 do_rle12(c
, d
, unc_pixels
, pos
, cmpr_pixels_size
);
344 unc_pixels
= dbuf_create_membuf(c
, 16384, 0);
345 do_rle16_24(c
, d
, unc_pixels
, pos
, cmpr_pixels_size
, 2);
348 unc_pixels
= dbuf_create_membuf(c
, 16384, 0);
349 do_rle16_24(c
, d
, unc_pixels
, pos
, cmpr_pixels_size
, 3);
352 de_err(c
, "Unsupported compression type: %d", (int)compression_type
);
356 img
= do_create_image(c
, d
, pg
, unc_pixels
, is_mask
);
359 if(unc_pixels
) dbuf_close(unc_pixels
);
360 de_dbg_indent(c
, -1);
365 // Writes the image to a file.
366 // Sets d->paint_data_section_size.
367 static void do_read_and_write_paint_data_section(deark
*c
, lctx
*d
, i64 pos1
)
369 de_bitmap
*img
= NULL
;
371 img
= do_read_paint_data_section(c
, d
, pos1
, 0);
372 de_bitmap_write_to_file(img
, NULL
, 0);
373 de_bitmap_destroy(img
);
376 static void do_combine_and_write_images(deark
*c
, lctx
*d
,
377 de_bitmap
*fg_img
, de_bitmap
*mask_img
)
379 de_bitmap
*img
= NULL
; // The combined image
382 if(!fg_img
) goto done
;
384 de_bitmap_write_to_file(fg_img
, NULL
, 0);
388 // Create a new image (which supports transparency).
389 img
= de_bitmap_create2(c
, fg_img
->unpadded_width
, fg_img
->width
, fg_img
->height
,
390 (fg_img
->bytes_per_pixel
<=2 ? 2 : 4));
392 for(j
=0; j
<img
->height
; j
++) {
393 for(i
=0; i
<img
->width
; i
++) {
397 clr
= de_bitmap_getpixel(fg_img
, i
, j
);
399 if(i
>=fg_img
->unpadded_width
) {
400 // Make all padding pixels opaque. (We don't preserve the mask's padding pixels.)
403 else if(i
<mask_img
->unpadded_width
&& j
<mask_img
->height
) {
407 clrm
= de_bitmap_getpixel(mask_img
, i
, j
);
409 // Some masks have colors that are not quite grayscale.
410 // Guess we'll use the average of the sample values.
411 a1
= (i64
)DE_COLOR_R(clrm
) + (i64
)DE_COLOR_G(clrm
) + (i64
)DE_COLOR_B(clrm
);
412 a
= de_scale_n_to_255(255*3, a1
);
414 if(mask_img
->orig_colortype
==0 && mask_img
->orig_bitdepth
==8) {
419 // Apparently, some masks are smaller than the image, and undefined
420 // pixels should be transparent.
424 de_bitmap_setpixel_rgba(img
, i
, j
, DE_SET_ALPHA(clr
, 255-a
));
427 de_bitmap_write_to_file(img
, NULL
, 0);
430 de_bitmap_destroy(img
);
433 static void do_sketch_section(deark
*c
, lctx
*d
, i64 pos1
)
436 i64 paint_data_section_start
;
443 de_dbg(c
, "sketch section at %d", (int)pos
);
446 s_s_w
= de_getu16le(pos
);
447 s_s_h
= de_getu16le(pos
+2);
448 de_dbg(c
, "sketch section dimensions: %d"DE_CHAR_TIMES
"%d", (int)s_s_w
, (int)s_s_h
);
453 paint_data_section_start
= pos
;
454 do_read_and_write_paint_data_section(c
, d
, paint_data_section_start
);
456 // Some data follows the image, but it doesn't seem to be important,
457 // so we don't have to read it before calling
458 // do_read_and_write_paint_data_section() to convert the image.
460 pos
= paint_data_section_start
+ d
->paint_data_section_size
;
461 x1
= de_getu16le(pos
);
462 x2
= de_getu16le(pos
+2);
463 de_dbg(c
, "magnification: %d"DE_CHAR_TIMES
"%d", (int)x1
, (int)x2
);
464 x1
= de_getu32le(pos
+4);
465 x2
= de_getu32le(pos
+8);
466 de_dbg(c
, "left, right cut: %d, %d", (int)x1
, (int)x2
);
467 x1
= de_getu32le(pos
+12);
468 x2
= de_getu32le(pos
+16);
469 de_dbg(c
, "top, bottom cut: %d, %d", (int)x1
, (int)x2
);
471 de_dbg_indent(c
, -1);
474 static void do_epocsketch_section_table_entry(deark
*c
, lctx
*d
,
475 i64 entry_index
, i64 pos
)
480 section_id
= de_getu32le(pos
);
481 section_loc
= de_getu32le(pos
+4);
482 de_dbg(c
, "section #%d: id=0x%08x, pos=%d", (int)entry_index
,
483 (unsigned int)section_id
, (int)section_loc
);
485 if(section_id
==0x1000007d) {
486 do_sketch_section(c
, d
, section_loc
);
488 de_dbg_indent(c
, -1);
491 static void do_epocsketch_section_table(deark
*c
, lctx
*d
, i64 pos
)
493 u8 section_table_size_code
;
497 // Section table section
498 de_dbg(c
, "section table at %d", (int)pos
);
501 section_table_size_code
= de_getbyte(pos
);
502 // The Section Table is a single "BListL" object. A BlistL starts with a byte
503 // indicating the remaining size in 4-byte Longs. Each entry in the table is 8
504 // bytes, so divide by 2 to get the number of entries.
505 num_sections
= ((int)section_table_size_code
)/2;
507 de_dbg(c
, "section table size: %d (%d entries)", (int)section_table_size_code
,
511 for(i
=0; i
<num_sections
; i
++) {
512 do_epocsketch_section_table_entry(c
, d
, i
, pos
+8*i
);
514 de_dbg_indent(c
, -1);
517 static void do_epocsketch_header(deark
*c
, lctx
*d
, i64 pos
)
519 de_dbg(c
, "header section at %d", (int)pos
);
521 d
->section_table_offset
= de_getu32le(pos
+16);
522 de_dbg(c
, "section table offset: %d", (int)d
->section_table_offset
);
523 de_dbg_indent(c
, -1);
526 static void de_run_epocsketch(deark
*c
, lctx
*d
)
528 do_epocsketch_header(c
, d
, 0);
529 do_epocsketch_section_table(c
, d
, d
->section_table_offset
);
532 static void de_run_epocaif(deark
*c
, lctx
*d
)
537 i64 caption_count_code
;
541 de_bitmap
*fg_img
= NULL
;
542 de_bitmap
*mask_img
= NULL
;
544 de_dbg(c
, "header at %d", 0);
546 table_offset
= de_getu32le(16);
547 de_dbg(c
, "table offset: %d", (int)table_offset
);
548 de_dbg_indent(c
, -1);
551 de_dbg(c
, "table at %d", (int)pos
);
553 // The first byte seems to be 2 times the number of captions.
554 caption_count_code
= de_getbyte(pos
);
555 de_dbg(c
, "caption count code(?): %d", (int)caption_count_code
);
558 // Next, there are 3*caption_count_code partially-unknown bytes
559 // (we know that this includes the position of the captions).
560 pos
+= 3*caption_count_code
;
562 num_images
= de_getbyte(pos
);
563 de_dbg(c
, "bitmap count(?): %d", (int)num_images
);
566 first_image_pos
= de_getu32le(pos
);
567 de_dbg(c
, "offset of first bitmap: %d", (int)first_image_pos
);
569 de_dbg_indent(c
, -1);
571 // Unfortunately, I don't know what the remaining data in the file is for.
572 // (I'm working without specs.) Maybe it indicates which image is a
573 // transparency mask for which other image, or something.
574 // For now, I'll assume that every second image is the transparency mask for
575 // the previous image.
577 img_pos
= first_image_pos
;
579 while(i
<num_images
) {
580 de_dbg(c
, "image #%d", (int)(i
/2));
583 de_dbg(c
, "foreground bitmap at %d", (int)img_pos
);
585 fg_img
= do_read_paint_data_section(c
, d
, img_pos
, 0);
586 if(d
->paint_data_section_size
<=0) break;
587 img_pos
+= d
->paint_data_section_size
;
589 de_dbg_indent(c
, -1);
592 de_dbg(c
, "mask bitmap at %d", (int)img_pos
);
594 mask_img
= do_read_paint_data_section(c
, d
, img_pos
, 1);
595 if(d
->paint_data_section_size
<=0) break;
596 img_pos
+= d
->paint_data_section_size
;
598 de_dbg_indent(c
, -1);
601 do_combine_and_write_images(c
, d
, fg_img
, mask_img
);
602 de_bitmap_destroy(fg_img
);
604 de_bitmap_destroy(mask_img
);
606 de_dbg_indent(c
, -1);
609 de_bitmap_destroy(fg_img
);
610 de_bitmap_destroy(mask_img
);
613 static void do_epocmbm_jumptable_entry(deark
*c
, lctx
*d
, i64 entry_index
,
618 img_pos
= de_getu32le(pos
);
619 de_dbg(c
, "image #%d, pos=%d", (int)entry_index
, (int)pos
);
621 do_read_and_write_paint_data_section(c
, d
, img_pos
);
622 de_dbg_indent(c
, -1);
625 static void do_epocmbm_jumptable(deark
*c
, lctx
*d
, i64 pos
)
630 de_dbg(c
, "MBM jumptable at %d", (int)pos
);
633 num_images
= de_getu32le(pos
);
634 de_dbg(c
, "number of images: %d", (int)num_images
);
635 if(!de_good_image_count(c
, num_images
)) {
636 de_err(c
, "Too many images");
640 for(i
=0; i
<num_images
; i
++) {
641 do_epocmbm_jumptable_entry(c
, d
, i
, pos
+ 4 + 4*i
);
645 de_dbg_indent(c
, -1);
648 static void do_epocmbm_header(deark
*c
, lctx
*d
, i64 pos
)
650 de_dbg(c
, "header section at %d", (int)pos
);
652 d
->jumptable_offset
= de_getu32le(pos
+16);
653 de_dbg(c
, "MBM jumptable offset: %d", (int)d
->jumptable_offset
);
654 de_dbg_indent(c
, -1);
657 static void de_run_epocmbm(deark
*c
, lctx
*d
)
659 do_epocmbm_header(c
, d
, 0);
660 do_epocmbm_jumptable(c
, d
, d
->jumptable_offset
);
663 static int de_identify_epocimage_internal(deark
*c
)
668 if(!de_memcmp(b
, "\x37\x00\x00\x10\x42\x00\x00\x10", 8)) {
669 return DE_PFMT_MBM
; // EPOC MBM
671 if(!de_memcmp(b
, "\x37\x00\x00\x10\x8a\x00\x00\x10", 8)) {
672 return DE_PFMT_EXPORTED_MBM
; // EPOC exported MBM
674 if(!de_memcmp(b
, "\x37\x00\x00\x10\x6D\x00\x00\x10\x7D\x00\x00\x10", 12)) {
675 return DE_PFMT_SKETCH
; // EPOC Sketch
677 if(!de_memcmp(b
, "\x37\x00\x00\x10\x6a\x00\x00\x10", 8)) {
678 return DE_PFMT_AIF
; // EPOC AIF
680 if(!de_memcmp(b
, "\x37\x00\x00\x10\x38\x3a\x00\x10", 8)) {
683 //if(!de_memcmp(b, "\x32\xb0\x1f\x10\x00\x00\x00\x00", 8)) {
689 static void de_run_epocimage(deark
*c
, de_module_params
*mparams
)
693 d
= de_malloc(c
, sizeof(lctx
));
694 d
->fmt
= de_identify_epocimage_internal(c
);
698 de_declare_fmt(c
, "EPOC Sketch");
699 de_run_epocsketch(c
, d
);
702 de_declare_fmt(c
, "EPOC MBM");
703 de_run_epocmbm(c
, d
);
705 case DE_PFMT_EXPORTED_MBM
:
706 de_declare_fmt(c
, "EPOC Exported MBM");
707 de_run_epocmbm(c
, d
);
710 de_declare_fmt(c
, "EPOC AIF");
711 de_run_epocaif(c
, d
);
714 de_internal_err_nonfatal(c
, "Unidentified format");
720 static int de_identify_epocimage(deark
*c
)
724 fmt
= de_identify_epocimage_internal(c
);
725 return (fmt
>0) ? 100 : 0;
728 void de_module_epocimage(deark
*c
, struct deark_module_info
*mi
)
730 mi
->id
= "epocimage";
731 mi
->desc
= "EPOC/Symbian MBM, Sketch, AIF";
732 mi
->run_fn
= de_run_epocimage
;
733 mi
->identify_fn
= de_identify_epocimage
;