1 // This file is part of Deark.
2 // Copyright (C) 2017 Jason Summers
3 // See the file COPYING for terms of use.
7 #include <deark-config.h>
8 #include <deark-private.h>
9 #include <deark-fmtutil.h>
10 DE_DECLARE_MODULE(de_module_palmbitmap
);
12 #define PALMBMPFLAG_COMPRESSED 0x8000U
13 #define PALMBMPFLAG_HASCOLORTABLE 0x4000U
14 #define PALMBMPFLAG_HASTRNS 0x2000U
15 #define PALMBMPFLAG_DIRECTCOLOR 0x0400U
18 PCMPR_UNKNOWN
, PCMPR_NONE
, PCMPR_SCANLINE
, PCMPR_RLE
,
19 PCMPR_PACKBITS8
, PCMPR_PACKBITS16
22 #define CMPR_FIELD_SCANLINE 0
23 #define CMPR_FIELD_RLE 1
24 #define CMPR_FIELD_PACKBITS 2
25 #define CMPR_FIELD_NONE 0xff
36 unsigned int cmpr_type_field
;
37 enum palm_cmpr_type cmpr_type
;
41 typedef struct localctx_struct
{
43 int ignore_color_table_flag
;
46 static int de_identify_palmbitmap_internal(deark
*c
, dbuf
*f
, i64 pos
, i64 len
)
53 pixelsize
= de_getbyte(pos
+8);
58 ver
= de_getbyte(pos
+9);
60 w
= dbuf_getu16be(f
, pos
+0);
61 h
= dbuf_getu16be(f
, pos
+2);
62 if(w
==0 || h
==0) return 0;
63 rowbytes
= dbuf_getu16be(f
, pos
+4);
64 pixelsize
= de_getbyte(pos
+8);
65 if((pixelsize
==0 && ver
==0) || pixelsize
==1 || pixelsize
==2 ||
66 pixelsize
==4 || pixelsize
==8 || pixelsize
==16)
73 if(rowbytes
==0 || (rowbytes
&0x1)) return 0;
74 // TODO: Make sure rowbytes is sensible
78 static void do_decompress_scanline_compression(deark
*c
, lctx
*d
, struct page_ctx
*pg
,
79 struct de_dfilter_in_params
*dcmpri
, struct de_dfilter_out_params
*dcmpro
,
80 struct de_dfilter_results
*dres
)
82 i64 srcpos
= dcmpri
->pos
;
90 blocksperrow
= (pg
->rowbytes
+7)/8;
92 for(j
=0; j
<pg
->h
; j
++) {
93 i64 bytes_written_this_row
= 0;
95 for(blocknum
=0; blocknum
<blocksperrow
; blocknum
++) {
96 // For each byte-per-row, we expect a lead byte, which is a
97 // bitfield that tells us which of the next 8 bytes are stored
98 // in the file, versus being copied from the previous row.
99 bf
= dbuf_getbyte(dcmpri
->f
, srcpos
++);
101 if(bytes_written_this_row
>=pg
->rowbytes
) break;
105 dstb
= dbuf_getbyte(dcmpri
->f
, srcpos
++);
108 // copy from previous row
109 dstb
= dbuf_getbyte(dcmpro
->f
, dcmpro
->f
->len
- pg
->rowbytes
);
111 dbuf_writebyte(dcmpro
->f
, dstb
);
113 bytes_written_this_row
++;
119 // Note that this is distinct from ImageViewer RLE compression.
120 static void do_decompress_rle_compression(deark
*c
, struct de_dfilter_in_params
*dcmpri
,
121 struct de_dfilter_out_params
*dcmpro
, struct de_dfilter_results
*dres
)
123 i64 srcpos
= dcmpri
->pos
;
125 while(srcpos
<= (dcmpri
->pos
+ dcmpri
->len
- 2)) {
129 count
= (i64
)dbuf_getbyte_p(dcmpri
->f
, &srcpos
);
130 val
= dbuf_getbyte_p(dcmpri
->f
, &srcpos
);
131 dbuf_write_run(dcmpro
->f
, val
, count
);
135 static void make_stdpal256(deark
*c
, lctx
*d
, u32
*stdpal
)
138 static const u32 supplpal
[15] = {0x111111,
139 0x222222,0x444444,0x555555,0x777777,0x888888,0xaaaaaa,0xbbbbbb,0xdddddd,
140 0xeeeeee,0xc0c0c0,0x800000,0x800080,0x008000,0x008080};
141 static u8 vals
[6] = {0xff, 0xcc, 0x99, 0x66, 0x33, 0x00};
143 for(k
=0; k
<215; k
++) {
145 r
= vals
[(k
%108)/18];
147 b
= vals
[(k
/108)*3 + (k
%18)/6];
148 stdpal
[k
] = DE_MAKE_RGB(r
, g
, b
);
150 for(k
=215; k
<230; k
++) {
151 stdpal
[k
] = DE_MAKE_OPAQUE(supplpal
[k
-215]);
153 for(k
=230; k
<256; k
++) {
154 stdpal
[k
] = DE_STOCKCOLOR_BLACK
;
158 static void do_generate_unc_image(deark
*c
, lctx
*d
, struct page_ctx
*pg
,
167 de_bitmap
*img
= NULL
;
170 has_color
= (pg
->bitsperpixel
>4 || pg
->has_custom_pal
);
172 if(pg
->bitsperpixel
==1 && !has_color
) {
173 de_convert_and_write_image_bilevel2(unc_pixels
, 0, pg
->w
, pg
->h
, pg
->rowbytes
,
174 DE_CVTF_WHITEISZERO
, NULL
, 0);
178 make_stdpal256(c
, d
, stdpal
);
180 pdwidth
= (pg
->rowbytes
*8) / pg
->bitsperpixel
;
181 if(pdwidth
<pg
->w
) pdwidth
= pg
->w
;
183 img
= de_bitmap_create2(c
, pg
->w
, pdwidth
, pg
->h
,
184 (has_color
?3:1) + (pg
->has_trns
?1:0));
186 for(j
=0; j
<pg
->h
; j
++) {
187 for(i
=0; i
<pdwidth
; i
++) {
188 if(pg
->bitsperpixel
==16) {
190 clr1
= (u32
)dbuf_getu16be(unc_pixels
, pg
->rowbytes
*j
+ 2*i
);
191 clr
= de_rgb565_to_888(clr1
);
192 de_bitmap_setpixel_rgb(img
, i
, j
, clr
);
193 if(pg
->has_trns
&& clr1
==pg
->trns_value
) {
194 de_bitmap_setsample(img
, i
, j
, 3, 0);
198 b
= de_get_bits_symbol(unc_pixels
, pg
->bitsperpixel
, pg
->rowbytes
*j
, i
);
200 if(pg
->has_custom_pal
)
201 clr
= pg
->custom_pal
[(unsigned int)b
];
203 clr
= stdpal
[(unsigned int)b
];
206 // TODO: What are the correct colors (esp. for 4bpp)?
207 b_adj
= 255 - de_sample_nbit_to_8bit(pg
->bitsperpixel
, (unsigned int)b
);
208 clr
= DE_MAKE_GRAY(b_adj
);
211 de_bitmap_setpixel_rgb(img
, i
, j
, clr
);
213 if(pg
->has_trns
&& (u32
)b
==pg
->trns_value
) {
214 de_bitmap_setsample(img
, i
, j
, 3, 0);
220 de_bitmap_write_to_file(img
, NULL
, 0);
223 de_bitmap_destroy(img
);
226 static int de_decompress_image(deark
*c
, lctx
*d
, struct page_ctx
*pg
,
227 dbuf
*inf
, i64 pos
, i64 len
, dbuf
*unc_pixels
)
229 struct de_dfilter_in_params dcmpri
;
230 struct de_dfilter_out_params dcmpro
;
231 struct de_dfilter_results dres
;
234 de_dfilter_init_objects(c
, &dcmpri
, &dcmpro
, &dres
);
238 dcmpro
.f
= unc_pixels
;
240 if(pg
->cmpr_type
==PCMPR_SCANLINE
) {
241 do_decompress_scanline_compression(c
, d
, pg
, &dcmpri
, &dcmpro
, &dres
);
243 else if(pg
->cmpr_type
==PCMPR_RLE
) {
244 do_decompress_rle_compression(c
, &dcmpri
, &dcmpro
, &dres
);
246 else if(pg
->cmpr_type
==PCMPR_PACKBITS8
) {
247 fmtutil_decompress_packbits_ex(c
, &dcmpri
, &dcmpro
, &dres
, NULL
);
249 else if(pg
->cmpr_type
==PCMPR_PACKBITS16
) {
250 struct de_packbits_params pbparams
;
252 de_zeromem(&pbparams
, sizeof(struct de_packbits_params
));
253 pbparams
.is_packbits16
= 1;
254 fmtutil_decompress_packbits_ex(c
, &dcmpri
, &dcmpro
, &dres
, &pbparams
);
257 de_err(c
, "Unsupported compression type: %u", pg
->cmpr_type_field
);
262 de_err(c
, "%s", de_dfilter_get_errmsg(c
, &dres
));
266 // TODO: The byte counts in this message are not very accurate.
267 de_dbg(c
, "decompressed %"I64_FMT
" bytes to %"I64_FMT
" bytes", len
,
275 // A wrapper that decompresses the image if necessary, then calls do_generate_unc_image().
276 static void do_generate_image(deark
*c
, lctx
*d
, struct page_ctx
*pg
,
277 dbuf
*inf
, i64 pos
, i64 len
)
279 dbuf
*unc_pixels
= NULL
;
280 i64 expected_num_uncmpr_image_bytes
;
282 expected_num_uncmpr_image_bytes
= pg
->rowbytes
*pg
->h
;
284 if(pg
->cmpr_type
==PCMPR_NONE
) {
285 if(expected_num_uncmpr_image_bytes
> len
) {
286 de_warn(c
, "Not enough data for image");
288 unc_pixels
= dbuf_open_input_subfile(inf
, pos
, len
);
294 if(pg
->bitmapversion
>= 3) {
296 cmpr_len
= dbuf_getu32x(inf
, pos
, d
->is_le
);
300 cmpr_len
= dbuf_getu16x(inf
, pos
, d
->is_le
);
302 de_dbg(c
, "cmpr len: %d", (int)cmpr_len
);
304 // Reduce the number of available bytes, based on the cmpr_len field.
307 // Account for the size of the cmpr_len field.
312 unc_pixels
= dbuf_create_membuf(c
, expected_num_uncmpr_image_bytes
, 1);
314 if(!de_decompress_image(c
, d
, pg
, inf
, pos
, len
, unc_pixels
)) {
319 do_generate_unc_image(c
, d
, pg
, unc_pixels
);
322 dbuf_close(unc_pixels
);
325 static const char *get_cmpr_type_name(enum palm_cmpr_type cmpr_type
)
330 case PCMPR_NONE
: name
= "none"; break;
331 case PCMPR_SCANLINE
: name
= "ScanLine"; break;
332 case PCMPR_RLE
: name
= "RLE"; break;
333 case PCMPR_PACKBITS8
: name
= "PackBits"; break;
334 case PCMPR_PACKBITS16
: name
= "PackBits16"; break;
335 default: name
= "?"; break;
340 static int read_BitmapType_colortable(deark
*c
, lctx
*d
, struct page_ctx
*pg
,
341 i64 pos1
, i64
*bytes_consumed
)
350 de_dbg(c
, "color table at %d", (int)pos1
);
353 num_entries_raw
= dbuf_getu16x(c
->infile
, pos1
, d
->is_le
);
354 num_entries
= num_entries_raw
;
355 // TODO: Documentation says "High bits (numEntries > 256) reserved."
356 // What exactly does that mean?
357 if(num_entries_raw
>256) {
358 // Files with "4096" entries have been observed, but they actually have 256
360 if(num_entries_raw
!=4096) {
361 de_warn(c
, "This image's color table type might not be supported correctly");
365 if(num_entries
==num_entries_raw
) {
366 de_dbg(c
, "number of entries: %d", (int)num_entries
);
369 de_dbg(c
, "number of entries: 0x%04x (assuming %d)", (unsigned int)num_entries_raw
,
376 // The only custom palettes I've seen in the wild have either 0 (!) or
378 // TODO: It might be better to treat all <=8 bit images as paletted:
379 // Start with a default palette, then overlay it with any custom
380 // palette entries that exist.
381 pg
->has_custom_pal
= 1;
384 *bytes_consumed
= 2+4*num_entries
;
386 for(k
=0; k
<num_entries
&& k
<256; k
++) {
387 idx
= (unsigned int)de_getbyte(pos
);
388 de_snprintf(tmps
, sizeof(tmps
), ",idx=%u", idx
);
389 // Not entirely sure if we should set entry #k, or entry #idx.
390 // idx is documented as "The index of this color in the color table."
391 pg
->custom_pal
[idx
] = dbuf_getRGB(c
->infile
, pos
+1, 0);
392 de_dbg_pal_entry2(c
, k
, pg
->custom_pal
[idx
], NULL
, tmps
, NULL
);
396 de_dbg_indent(c
, -1);
400 static void do_BitmapDirectInfoType(deark
*c
, lctx
*d
, struct page_ctx
*pg
,
406 de_dbg(c
, "BitmapDirectInfoType structure at %d", (int)pos
);
408 cbits
[0] = de_getbyte(pos
);
409 cbits
[1] = de_getbyte(pos
+1);
410 cbits
[2] = de_getbyte(pos
+2);
411 de_dbg(c
, "bits/component: %d,%d,%d", (int)cbits
[0], (int)cbits
[1], (int)cbits
[2]);
413 t
[0] = de_getbyte(pos
+4);
414 t
[1] = de_getbyte(pos
+5);
415 t
[2] = de_getbyte(pos
+6);
416 t
[3] = de_getbyte(pos
+7);
417 de_dbg(c
, "transparentColor: (%d,%d,%d,idx=%d)", (int)t
[1], (int)t
[2],
418 (int)t
[3], (int)t
[0]);
420 // The format of this field (RGBColorType) is not the same as that of
421 // the actual pixels, and I can't find documentation that says how the
423 // This appears to work (though it's quick & dirty, and only supports
426 ((((u32
)t
[1])&0xf8)<<8) |
427 ((((u32
)t
[2])&0xfc)<<3) |
428 ((((u32
)t
[3])&0xf8)>>3);
430 de_dbg_indent(c
, -1);
433 static void do_palm_BitmapType_internal(deark
*c
, lctx
*d
, i64 pos1
, i64 len
,
434 i64
*pnextbitmapoffset
)
440 u8 pixelformat
= 0; // V3 only
444 i64 nextbitmapoffs_in_bytes
= 0;
445 const char *cmpr_type_src_name
= "";
446 const char *bpp_src_name
= "";
447 struct page_ctx
*pg
= NULL
;
448 int saved_indent_level
;
449 de_ucstring
*flagsdescr
;
452 de_dbg_indent_save(c
, &saved_indent_level
);
453 pg
= de_malloc(c
, sizeof(struct page_ctx
));
455 de_dbg(c
, "BitmapType at %d, len"DE_CHAR_LEQ
"%d", (int)pos1
, (int)len
);
457 de_dbg(c
, "bitmap header at %d", (int)pos1
);
460 // Look ahead to get the version
461 pg
->bitmapversion
= de_getbyte(pos1
+9);
462 de_dbg(c
, "bitmap version: %d", (int)pg
->bitmapversion
);
464 if(pg
->bitmapversion
>3) {
465 // Note that V3 allows the high bit of the version field to
466 // be set (to mean little-endian), but we don't support that.
467 de_err(c
, "Unsupported bitmap version: %d", (int)pg
->bitmapversion
);
471 pg
->w
= dbuf_geti16x(c
->infile
, pos1
, d
->is_le
);
472 pg
->h
= dbuf_geti16x(c
->infile
, pos1
+2, d
->is_le
);
473 de_dbg_dimensions(c
, pg
->w
, pg
->h
);
475 pg
->rowbytes
= dbuf_getu16x(c
->infile
, pos1
+4, d
->is_le
);
476 de_dbg(c
, "rowBytes: %d", (int)pg
->rowbytes
);
478 bitmapflags
= (u32
)dbuf_getu16x(c
->infile
, pos1
+6, d
->is_le
);
479 flagsdescr
= ucstring_create(c
);
480 if(bitmapflags
&PALMBMPFLAG_COMPRESSED
) ucstring_append_flags_item(flagsdescr
, "compressed");
481 if(bitmapflags
&PALMBMPFLAG_HASCOLORTABLE
) ucstring_append_flags_item(flagsdescr
, "hasColorTable");
482 if(bitmapflags
&PALMBMPFLAG_HASTRNS
) ucstring_append_flags_item(flagsdescr
, "hasTransparency");
483 if(bitmapflags
&PALMBMPFLAG_DIRECTCOLOR
) ucstring_append_flags_item(flagsdescr
, "directColor");
484 if(bitmapflags
==0) ucstring_append_flags_item(flagsdescr
, "none");
485 de_dbg(c
, "bitmap flags: 0x%04x (%s)", (unsigned int)bitmapflags
,
486 ucstring_getpsz(flagsdescr
));
487 ucstring_destroy(flagsdescr
);
488 if((bitmapflags
&PALMBMPFLAG_HASCOLORTABLE
) && d
->ignore_color_table_flag
) {
489 bitmapflags
-= PALMBMPFLAG_HASCOLORTABLE
;
491 if((bitmapflags
&PALMBMPFLAG_HASCOLORTABLE
) && pg
->bitmapversion
<1) {
492 de_warn(c
, "BitmapTypeV%d with a color table is not standard", (int)pg
->bitmapversion
);
495 if(pg
->bitmapversion
>=1) {
496 pixelsize_raw
= de_getbyte(pos1
+8);
497 de_dbg(c
, "pixelSize: %d", (int)pixelsize_raw
);
498 bpp_src_name
= "based on pixelSize field";
499 if(pg
->bitmapversion
<2 && pixelsize_raw
==8) {
500 de_warn(c
, "BitmapTypeV%d with pixelSize=%d is not standard",
501 (int)pg
->bitmapversion
, (int)pixelsize_raw
);
507 if(pixelsize_raw
==0) {
508 pg
->bitsperpixel
= 1;
509 bpp_src_name
= "default";
511 else pg
->bitsperpixel
= (i64
)pixelsize_raw
;
512 de_dbg(c
, "bits/pixel: %d (%s)", (int)pg
->bitsperpixel
, bpp_src_name
);
514 if(pg
->bitmapversion
==1 || pg
->bitmapversion
==2) {
515 x
= dbuf_getu16x(c
->infile
, pos1
+10, d
->is_le
);
516 nextbitmapoffs_in_bytes
= 4*x
;
518 de_snprintf(tmps
, sizeof(tmps
), "none");
521 de_snprintf(tmps
, sizeof(tmps
), "%d + 4"DE_CHAR_TIMES
"%d = %d", (int)pos1
, (int)x
, (int)(pos1
+nextbitmapoffs_in_bytes
));
523 de_dbg(c
, "nextDepthOffset: %d (%s)", (int)x
, tmps
);
526 if(pg
->bitmapversion
<3) {
530 headersize
= (i64
)de_getbyte(pos1
+10);
531 de_dbg(c
, "header size: %d", (int)headersize
);
534 if(pg
->bitmapversion
==3) {
535 pixelformat
= de_getbyte(pos1
+11);
536 de_dbg(c
, "pixel format: %d", (int)pixelformat
);
539 if(pg
->bitmapversion
==2 && (bitmapflags
&PALMBMPFLAG_HASTRNS
)) {
541 pg
->trns_value
= (u32
)de_getbyte(pos1
+12);
542 de_dbg(c
, "transparent color: %u", (unsigned int)pg
->trns_value
);
545 cmpr_type_src_name
= "flags";
546 if(bitmapflags
&PALMBMPFLAG_COMPRESSED
) {
547 if(pg
->bitmapversion
>=2) {
548 pg
->cmpr_type_field
= (unsigned int)de_getbyte(pos1
+13);
549 cmpr_type_src_name
= "flags + compression type field";
550 de_dbg(c
, "compression type field: 0x%02x", pg
->cmpr_type_field
);
551 switch(pg
->cmpr_type_field
) {
552 case CMPR_FIELD_SCANLINE
:
553 pg
->cmpr_type
= PCMPR_SCANLINE
;
556 pg
->cmpr_type
= PCMPR_RLE
;
558 case CMPR_FIELD_PACKBITS
:
559 cmpr_type_src_name
= "flags + compression type field + pixelSize";
560 if(pg
->bitsperpixel
==16) {
561 pg
->cmpr_type
= PCMPR_PACKBITS16
;
564 pg
->cmpr_type
= PCMPR_PACKBITS8
;
568 pg
->cmpr_type
= PCMPR_UNKNOWN
;
572 // V1 & V2 have no cmpr_type field, but can still be compressed.
573 pg
->cmpr_type
= PCMPR_SCANLINE
;
577 pg
->cmpr_type
= PCMPR_NONE
;
580 de_dbg(c
, "compression type: %s (based on %s)", get_cmpr_type_name(pg
->cmpr_type
), cmpr_type_src_name
);
582 if(pg
->bitmapversion
==3) {
584 densitycode
= dbuf_getu16x(c
->infile
, pos1
+14, d
->is_le
);
585 de_dbg(c
, "density: %d", (int)densitycode
);
586 // The density is an indication of the target screen density.
587 // It's tempting to interpet it as pixels per inch, and copy it to the
588 // output image -- though the documentation says it "should not be
589 // interpreted as representing pixels per inch".
592 if(pg
->bitmapversion
==3 && (bitmapflags
&PALMBMPFLAG_HASTRNS
) && headersize
>=20) {
593 // I'm assuming the flag affects this field. The spec is ambiguous.
595 pg
->trns_value
= (u32
)dbuf_getu32x(c
->infile
, pos1
+16, d
->is_le
);
596 de_dbg(c
, "transparent color: 0x%08x", (unsigned int)pg
->trns_value
);
599 if(pg
->bitmapversion
==3 && headersize
>=24) {
600 // Documented as the "number of bytes to the next bitmap", but it doesn't
601 // say where it is measured *from*. I'll assume it's the same logic as
602 // the "nextDepthOffset" field.
603 nextbitmapoffs_in_bytes
= dbuf_getu32x(c
->infile
, pos1
+20, d
->is_le
);
604 if(nextbitmapoffs_in_bytes
==0) {
605 de_snprintf(tmps
, sizeof(tmps
), "none");
608 de_snprintf(tmps
, sizeof(tmps
), "%u + %u = %u", (unsigned int)pos1
,
609 (unsigned int)nextbitmapoffs_in_bytes
, (unsigned int)(pos1
+nextbitmapoffs_in_bytes
));
611 de_dbg(c
, "nextBitmapOffset: %u (%s)", (unsigned int)nextbitmapoffs_in_bytes
, tmps
);
614 // Now that we've read the nextBitmapOffset fields, we can stop processing this
615 // image if it's invalid or unsupported.
617 needed_rowbytes
= (pg
->w
* pg
->bitsperpixel
+7)/8;
618 if(pg
->rowbytes
< needed_rowbytes
) {
619 de_err(c
, "Bad rowBytes value (is %d, need at least %d) or unsupported format version",
620 (int)pg
->rowbytes
, (int)needed_rowbytes
);
624 if(!de_good_image_dimensions(c
, pg
->w
, pg
->h
)) goto done
;
626 de_dbg_indent(c
, -1);
628 if(bitmapflags
&PALMBMPFLAG_DIRECTCOLOR
) {
630 if(pg
->bitmapversion
<2) {
631 de_warn(c
, "BitmapTypeV%d with RGB color is not standard", (int)pg
->bitmapversion
);
635 if(pg
->bitmapversion
>=3) {
637 (pixelformat
==0 && pg
->bitsperpixel
>8) ||
638 (pixelformat
==1 && pg
->bitsperpixel
!=16))
640 de_err(c
, "Unsupported pixelFormat (%d) for this image", (int)pixelformat
);
644 if(pixelformat
==1 && pg
->bitsperpixel
==16) {
645 // This should have already been set, by PALMBMPFLAG_DIRECTCOLOR,
646 // but that flag seems kind of obsolete in V3.
651 if(pg
->bitmapversion
==2 && pg
->bitsperpixel
==16 &&
652 !(bitmapflags
&PALMBMPFLAG_DIRECTCOLOR
) && !(bitmapflags
&PALMBMPFLAG_HASCOLORTABLE
))
654 // I have some images like this. I guess they are standard RGB565, with no
655 // BitmapDirectInfoType header.
657 de_warn(c
, "This type of image (16-bit, without directColor flag) might "
658 "not be decoded correctly");
661 if(pg
->bitsperpixel
!=1 && pg
->bitsperpixel
!=2 && pg
->bitsperpixel
!=4 &&
662 pg
->bitsperpixel
!=8 && pg
->bitsperpixel
!=16)
664 de_err(c
, "Unsupported bits/pixel: %d", (int)pg
->bitsperpixel
);
668 if((pg
->is_rgb
&& pg
->bitsperpixel
!=16) ||
669 (!pg
->is_rgb
&& pg
->bitsperpixel
>8))
671 de_err(c
, "This type of image is not supported");
677 if(pos
>= pos1
+len
) goto done
;
679 if(bitmapflags
&PALMBMPFLAG_HASCOLORTABLE
) {
680 if(!read_BitmapType_colortable(c
, d
, pg
, pos
, &bytes_consumed
)) goto done
;
681 pos
+= bytes_consumed
;
684 // If there is both a color table and a DirectInfo struct, I don't know which
685 // one appears first. But that shouldn't happen.
686 if((bitmapflags
&PALMBMPFLAG_DIRECTCOLOR
) && (pg
->bitmapversion
<=2)) {
687 do_BitmapDirectInfoType(c
, d
, pg
, pos
);
691 if(pos
>= pos1
+len
) {
692 de_err(c
, "Unexpected end of file");
696 de_dbg(c
, "image data at %d", (int)pos
);
698 do_generate_image(c
, d
, pg
, c
->infile
, pos
, pos1
+len
-pos
);
699 de_dbg_indent(c
, -1);
702 *pnextbitmapoffset
= nextbitmapoffs_in_bytes
;
703 de_dbg_indent_restore(c
, saved_indent_level
);
709 static void do_palm_BitmapType(deark
*c
, lctx
*d
, i64 pos1
, i64 len
)
711 i64 nextbitmapoffs
= 0;
715 if(de_getbyte(pos
+8) == 0xff) {
716 de_dbg(c
, "[skipping dummy bitmap header at %d]", (int)pos
);
720 if(pos
> pos1
+len
-16) {
721 de_err(c
, "Bitmap exceeds its bounds");
724 do_palm_BitmapType_internal(c
, d
, pos
, pos1
+len
-pos
, &nextbitmapoffs
);
725 if(nextbitmapoffs
<=0) break;
726 pos
+= nextbitmapoffs
;
730 static void de_run_palmbitmap(deark
*c
, de_module_params
*mparams
)
734 d
= de_malloc(c
, sizeof(lctx
));
735 if(de_get_ext_option(c
, "palm:le")) {
738 if(de_get_ext_option(c
, "palm:nocolortable")) {
739 // Enables a hack, for files that apparently set the hasColorTable flag
741 d
->ignore_color_table_flag
= 1;
743 do_palm_BitmapType(c
, d
, 0, c
->infile
->len
);
747 static int de_identify_palmbitmap(deark
*c
)
749 if(de_input_file_has_ext(c
, "palm")) {
751 x
= de_identify_palmbitmap_internal(c
, c
->infile
, 0, c
->infile
->len
);
757 static void de_help_palmbitmap(deark
*c
)
759 de_msg(c
, "-opt palm:le : Assume little-endian byte order");
760 de_msg(c
, "-opt palm:nocolortable : Ignore the hasColorTable flag, if set");
763 void de_module_palmbitmap(deark
*c
, struct deark_module_info
*mi
)
765 mi
->id
= "palmbitmap";
766 mi
->desc
= "Palm BitmapType";
767 mi
->run_fn
= de_run_palmbitmap
;
768 mi
->identify_fn
= de_identify_palmbitmap
;
769 mi
->help_fn
= de_help_palmbitmap
;