nrg: Improved support for v2
[deark.git] / modules / epocimage.c
blob6942b8e0826537da4403c4a0d9ed755a33e955ef
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);
10 #define DE_PFMT_MBM 1
11 #define DE_PFMT_EXPORTED_MBM 2
12 #define DE_PFMT_SKETCH 3
13 #define DE_PFMT_AIF 4
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)
28 int x;
29 u8 r, g, b;
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.
37 if(k>=108 && k<148) {
38 return DE_MAKE_OPAQUE(supplpal[k-108]);
41 x = k<108 ? k : k-40;
42 r = (x%6)*0x33;
43 g = ((x%36)/6)*0x33;
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
56 struct page_ctx {
57 i64 width, height;
58 i64 color_type;
59 i64 bits_per_pixel;
62 typedef struct localctx_struct {
63 int fmt;
64 i64 paint_data_section_size;
65 int warned_exp;
67 i64 jumptable_offset;
68 i64 section_table_offset;
69 } lctx;
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;
75 i64 i, j;
76 i64 src_rowspan;
77 i64 pdwidth;
78 u8 b;
79 u8 cr;
80 u32 n;
81 u32 clr;
82 int bypp;
84 pdwidth = pg->width;
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;
97 else {
98 i64 bits_per_row;
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) {
114 case 1:
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);
117 break;
118 case 2:
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);
121 break;
122 case 4:
123 b = de_get_bits_symbol_lsb(unc_pixels, pg->bits_per_pixel, j*src_rowspan, i);
124 if(pg->color_type)
125 de_bitmap_setpixel_rgb(img, i, j, DE_MAKE_OPAQUE(pal16[(unsigned int)b]));
126 else
127 de_bitmap_setpixel_gray(img, i, j, b*17);
128 break;
129 case 8:
130 b = dbuf_getbyte(unc_pixels, j*src_rowspan + i);
131 if(pg->color_type) {
132 de_bitmap_setpixel_rgb(img, i, j, getpal256((unsigned int)b));
134 else {
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);
139 break;
140 case 16:
141 n = (u32)dbuf_getu16le(unc_pixels, j*src_rowspan + i*2);
142 if(is_mask) {
143 cr = (u8)(n>>8);
144 clr = DE_MAKE_RGB(cr, cr, cr);
146 else {
147 clr = de_rgb565_to_888(n);
149 de_bitmap_setpixel_rgb(img, i, j, clr);
150 break;
151 case 12:
152 case 24:
153 clr = dbuf_getRGB(unc_pixels, j*src_rowspan + i*3, 0);
154 de_bitmap_setpixel_rgb(img, i, j, clr);
155 break;
159 return img;
162 static void do_rle8(deark *c, lctx *d, dbuf *unc_pixels,
163 i64 pos1, i64 len)
165 u8 b0, b1;
166 i64 pos;
167 i64 count;
169 pos = pos1;
170 while(pos<pos1+len) {
171 b0 = de_getbyte(pos);
172 pos++;
174 if(b0<=0x7f) {
175 // Next byte should be repeated b0+1 times.
176 count = 1+(i64)b0;
177 b1 = de_getbyte(pos);
178 pos++;
179 dbuf_write_run(unc_pixels, b1, count);
181 else {
182 // 256-b0 bytes of uncompressed data.
183 count = 256-(i64)b0;
184 dbuf_copy(c->infile, pos, count, unc_pixels);
185 pos += count;
190 static void do_rle12(deark *c, lctx *d, dbuf *unc_pixels,
191 i64 pos1, i64 len)
193 i64 pos = pos1;
194 i64 count;
195 i64 k;
196 unsigned int n;
197 u8 v[3];
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);
205 v[0] *= 17;
206 v[1] *= 17;
207 v[2] *= 17;
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)
217 i64 i;
218 i64 k;
219 u8 b0;
220 i64 pos;
221 i64 count;
222 u8 v[3];
224 pos = pos1;
225 while(pos<pos1+len) {
226 b0 = de_getbyte(pos);
227 pos++;
229 if(b0<=0x7f) {
230 // Next pixel should be repeated b0+1 times.
231 count = 1+(i64)b0;
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);
239 else {
240 // 256-b0 pixels of uncompressed data.
241 count = 256-(i64)b0;
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;
251 switch(t) {
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;
258 return s?s:"?";
261 // Sets d->paint_data_section_size.
262 // Returns a bitmap.
263 static de_bitmap *do_read_paint_data_section(deark *c, lctx *d,
264 i64 pos1, int is_mask)
266 i64 pixel_data_offset;
267 i64 pos;
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));
275 pos = pos1;
276 de_dbg(c, "paint data section at %d", (int)pos1);
277 de_dbg_indent(c, 1);
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);
307 goto done;
310 else {
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);
315 goto done;
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.");
323 d->warned_exp = 1;
327 pos += 40;
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);
334 break;
335 case 1: // RLE8
336 unc_pixels = dbuf_create_membuf(c, 16384, 0);
337 do_rle8(c, d, unc_pixels, pos, cmpr_pixels_size);
338 break;
339 case 2: // RLE12
340 unc_pixels = dbuf_create_membuf(c, 16384, 0);
341 do_rle12(c, d, unc_pixels, pos, cmpr_pixels_size);
342 break;
343 case 3: // RLE16
344 unc_pixels = dbuf_create_membuf(c, 16384, 0);
345 do_rle16_24(c, d, unc_pixels, pos, cmpr_pixels_size, 2);
346 break;
347 case 4: // RLE24
348 unc_pixels = dbuf_create_membuf(c, 16384, 0);
349 do_rle16_24(c, d, unc_pixels, pos, cmpr_pixels_size, 3);
350 break;
351 default:
352 de_err(c, "Unsupported compression type: %d", (int)compression_type);
353 goto done;
356 img = do_create_image(c, d, pg, unc_pixels, is_mask);
358 done:
359 if(unc_pixels) dbuf_close(unc_pixels);
360 de_dbg_indent(c, -1);
361 de_free(c, pg);
362 return img;
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
380 i64 i, j;
382 if(!fg_img) goto done;
383 if(!mask_img) {
384 de_bitmap_write_to_file(fg_img, NULL, 0);
385 goto done;
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++) {
394 de_color clr;
395 de_colorsample a;
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.)
401 a = 0;
403 else if(i<mask_img->unpadded_width && j<mask_img->height) {
404 de_color clrm;
405 i64 a1;
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) {
415 a = 255-a;
418 else {
419 // Apparently, some masks are smaller than the image, and undefined
420 // pixels should be transparent.
421 a = 0xff;
424 de_bitmap_setpixel_rgba(img, i, j, DE_SET_ALPHA(clr, 255-a));
427 de_bitmap_write_to_file(img, NULL, 0);
429 done:
430 de_bitmap_destroy(img);
433 static void do_sketch_section(deark *c, lctx *d, i64 pos1)
435 i64 pos;
436 i64 paint_data_section_start;
437 i64 s_s_w, s_s_h;
438 i64 x1, x2;
440 pos = pos1;
442 // 18-byte header
443 de_dbg(c, "sketch section at %d", (int)pos);
444 de_dbg_indent(c, 1);
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);
450 pos += 18;
452 // The image itself
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)
477 i64 section_id;
478 i64 section_loc;
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);
484 de_dbg_indent(c, 1);
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;
494 int num_sections;
495 i64 i;
497 // Section table section
498 de_dbg(c, "section table at %d", (int)pos);
499 de_dbg_indent(c, 1);
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,
508 (int)num_sections);
509 pos++;
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);
520 de_dbg_indent(c, 1);
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)
534 i64 table_offset;
535 i64 pos;
536 i64 i;
537 i64 caption_count_code;
538 i64 num_images;
539 i64 first_image_pos;
540 i64 img_pos;
541 de_bitmap *fg_img = NULL;
542 de_bitmap *mask_img = NULL;
544 de_dbg(c, "header at %d", 0);
545 de_dbg_indent(c, 1);
546 table_offset = de_getu32le(16);
547 de_dbg(c, "table offset: %d", (int)table_offset);
548 de_dbg_indent(c, -1);
550 pos = table_offset;
551 de_dbg(c, "table at %d", (int)pos);
552 de_dbg_indent(c, 1);
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);
556 pos++;
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);
564 pos++;
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;
578 i = 0;
579 while(i<num_images) {
580 de_dbg(c, "image #%d", (int)(i/2));
581 de_dbg_indent(c, 1);
583 de_dbg(c, "foreground bitmap at %d", (int)img_pos);
584 de_dbg_indent(c, 1);
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;
588 i++;
589 de_dbg_indent(c, -1);
591 if(i<num_images) {
592 de_dbg(c, "mask bitmap at %d", (int)img_pos);
593 de_dbg_indent(c, 1);
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;
597 i++;
598 de_dbg_indent(c, -1);
601 do_combine_and_write_images(c, d, fg_img, mask_img);
602 de_bitmap_destroy(fg_img);
603 fg_img = NULL;
604 de_bitmap_destroy(mask_img);
605 mask_img = NULL;
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,
614 i64 pos)
616 i64 img_pos;
618 img_pos = de_getu32le(pos);
619 de_dbg(c, "image #%d, pos=%d", (int)entry_index, (int)pos);
620 de_dbg_indent(c, 1);
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)
627 i64 num_images;
628 i64 i;
630 de_dbg(c, "MBM jumptable at %d", (int)pos);
631 de_dbg_indent(c, 1);
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");
637 goto done;
640 for(i=0; i<num_images; i++) {
641 do_epocmbm_jumptable_entry(c, d, i, pos + 4 + 4*i);
644 done:
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);
651 de_dbg_indent(c, 1);
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)
665 u8 b[12];
666 de_read(b, 0, 12);
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)) {
681 return DE_PFMT_AIF;
683 //if(!de_memcmp(b, "\x32\xb0\x1f\x10\x00\x00\x00\x00", 8)) {
684 // return DE_PFMT_?;
686 return 0;
689 static void de_run_epocimage(deark *c, de_module_params *mparams)
691 lctx *d = NULL;
693 d = de_malloc(c, sizeof(lctx));
694 d->fmt = de_identify_epocimage_internal(c);
696 switch(d->fmt) {
697 case DE_PFMT_SKETCH:
698 de_declare_fmt(c, "EPOC Sketch");
699 de_run_epocsketch(c, d);
700 break;
701 case DE_PFMT_MBM:
702 de_declare_fmt(c, "EPOC MBM");
703 de_run_epocmbm(c, d);
704 break;
705 case DE_PFMT_EXPORTED_MBM:
706 de_declare_fmt(c, "EPOC Exported MBM");
707 de_run_epocmbm(c, d);
708 break;
709 case DE_PFMT_AIF:
710 de_declare_fmt(c, "EPOC AIF");
711 de_run_epocaif(c, d);
712 break;
713 default:
714 de_internal_err_nonfatal(c, "Unidentified format");
717 de_free(c, d);
720 static int de_identify_epocimage(deark *c)
722 int fmt;
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;