New "videomaster" module
[deark.git] / modules / bmp.c
blob07744ab699afb83686b476ecb9da2e0d66328588
1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 // Windows BMP image
7 #include <deark-config.h>
8 #include <deark-private.h>
9 #include <deark-fmtutil.h>
10 DE_DECLARE_MODULE(de_module_bmp);
11 DE_DECLARE_MODULE(de_module_dib);
12 DE_DECLARE_MODULE(de_module_ddb);
14 #define FILEHEADER_SIZE 14
16 #define CODE_LINK 0x4c494e4bU
17 #define CODE_MBED 0x4d424544U
19 struct bitfieldsinfo {
20 u32 mask;
21 unsigned int shift;
22 double scale; // Amount to multiply the sample value by, to scale it to [0..255]
25 typedef struct localctx_struct {
26 #define DE_BMPVER_OS2V1 1 // OS2v1 or Windows v2
27 #define DE_BMPVER_OS2V2 2
28 #define DE_BMPVER_WINV345 3 // Windows v3+
29 int version;
31 de_finfo *fi;
32 i64 fsize; // The "file size" field in the file header
33 i64 bits_offset; // The bfOffBits field in the file header
34 i64 infohdrsize;
35 i64 bitcount;
36 u32 compression_field;
37 i64 size_image; // biSizeImage
38 i64 width, pdwidth, height;
39 int top_down;
40 UI extra_createflags;
41 i64 pal_entries; // Actual number stored in file. 0 means no palette.
42 i64 pal_pos;
43 i64 bytes_per_pal_entry;
44 int pal_is_grayscale;
46 #define BF_NONE 0 // Bitfields are not applicable
47 #define BF_DEFAULT 1 // Use the default bitfields for this bit depth
48 #define BF_SEGMENT 2 // Use the bitfields segment in the file
49 #define BF_IN_HEADER 3 // Use the bitfields fields in the infoheader
50 int bitfields_type;
51 i64 bitfields_segment_len; // Used if bitfields_type==BF_SEGMENT
53 i64 xpelspermeter, ypelspermeter;
55 #define CMPR_NONE 0
56 #define CMPR_RLE4 11
57 #define CMPR_RLE8 12
58 #define CMPR_RLE24 13
59 #define CMPR_JPEG 14
60 #define CMPR_PNG 15
61 #define CMPR_HUFFMAN1D 16
62 int compression_type;
64 struct de_fourcc cstype4cc;
65 i64 profile_offset_raw;
66 i64 profile_offset;
67 i64 profile_size;
69 i64 rowspan;
70 struct bitfieldsinfo bitfield[4];
71 u32 pal[256];
72 } lctx;
74 static i64 get_bits_size(deark *c, lctx *d)
76 if(d->size_image>0 && d->bits_offset+d->size_image <= c->infile->len) {
77 return d->size_image;
79 return c->infile->len - d->bits_offset;
82 // Sets d->version, and certain header fields.
83 static int detect_bmp_version(deark *c, lctx *d)
85 i64 pos;
87 pos = 0;
88 d->fsize = de_getu32le(pos+2);
90 pos += FILEHEADER_SIZE;
91 d->infohdrsize = de_getu32le(pos);
93 if(d->infohdrsize<=12) {
94 d->bitcount = de_getu16le(pos+10);
96 else {
97 d->bitcount = de_getu16le(pos+14);
100 if(d->infohdrsize==12) {
101 d->version = DE_BMPVER_OS2V1;
102 return 1;
104 if(d->infohdrsize<16) {
105 return 0;
108 if(d->infohdrsize>=20) {
109 d->compression_field = (u32)de_getu32le(pos+16);
112 if(d->infohdrsize>=16 && d->infohdrsize<=64) {
113 if(d->fsize==FILEHEADER_SIZE+d->infohdrsize) {
114 d->version = DE_BMPVER_OS2V2;
115 return 1;
118 if((d->compression_field==3 && d->bitcount==1) ||
119 (d->compression_field==4 && d->bitcount==24))
121 d->version = DE_BMPVER_OS2V2;
122 return 1;
125 if(d->infohdrsize!=40 && d->infohdrsize!=52 && d->infohdrsize!=56) {
126 d->version = DE_BMPVER_OS2V2;
127 return 1;
131 d->version = DE_BMPVER_WINV345;
132 return 1;
135 static int read_fileheader(deark *c, lctx *d, i64 pos)
137 de_dbg(c, "file header at %d", (int)pos);
138 de_dbg_indent(c, 1);
139 de_dbg(c, "bfSize: %d", (int)d->fsize);
140 d->bits_offset = de_getu32le(pos+10);
141 de_dbg(c, "bfOffBits: %d", (int)d->bits_offset);
142 de_dbg_indent(c, -1);
143 return 1;
146 // Calculate .shift and .scale
147 static void update_bitfields_info(deark *c, lctx *d)
149 i64 k;
150 u32 tmpmask;
152 for(k=0; k<4; k++) {
153 tmpmask = d->bitfield[k].mask;
154 if(tmpmask==0) continue;
155 while((tmpmask & 0x1) == 0) {
156 d->bitfield[k].shift++;
157 tmpmask >>= 1;
159 d->bitfield[k].scale = 255.0 / (double)tmpmask;
163 static void do_read_bitfields(deark *c, lctx *d, i64 pos, i64 len)
165 i64 k;
167 if(len>16) len=16;
168 for(k=0; 4*k<len; k++) {
169 d->bitfield[k].mask = (u32)de_getu32le(pos+4*k);
170 de_dbg(c, "mask[%d]: 0x%08x", (int)k, (unsigned int)d->bitfield[k].mask);
172 update_bitfields_info(c, d);
175 static void set_default_bitfields(deark *c, lctx *d)
177 if(d->bitcount==16) {
178 d->bitfield[0].mask = 0x000007c00U;
179 d->bitfield[1].mask = 0x0000003e0U;
180 d->bitfield[2].mask = 0x00000001fU;
181 update_bitfields_info(c, d);
183 else if(d->bitcount==32) {
184 d->bitfield[0].mask = 0x00ff0000U;
185 d->bitfield[1].mask = 0x0000ff00U;
186 d->bitfield[2].mask = 0x000000ffU;
187 update_bitfields_info(c, d);
191 static void get_cstype_descr_dbgstr(struct de_fourcc *cstype4cc, char *s_dbgstr, size_t s_len)
193 // The ID might be a FOURCC, or not.
194 if(cstype4cc->id>0xffffU) {
195 de_snprintf(s_dbgstr, s_len, "0x%08x ('%s')", (unsigned int)cstype4cc->id,
196 cstype4cc->id_dbgstr);
198 else {
199 const char *name = "?";
200 switch(cstype4cc->id) {
201 case 0: name = "LCS_CALIBRATED_RGB"; break;
203 de_snprintf(s_dbgstr, s_len, "%u (%s)", (unsigned int)cstype4cc->id, name);
207 // Read any version of BITMAPINFOHEADER.
209 // Note: Some of this BMP parsing code is duplicated in the
210 // de_fmtutil_get_bmpinfo() library function. The BMP module's needs are
211 // not quite aligned with what that function is intended for, and it
212 // would be too messy to try to add the necessary features to it.
213 static int read_infoheader(deark *c, lctx *d, i64 pos)
215 i64 height_raw;
216 i64 clr_used_raw;
217 int cmpr_ok;
218 int retval = 0;
219 i64 nplanes;
221 de_dbg(c, "info header at %d", (int)pos);
222 de_dbg_indent(c, 1);
223 de_dbg(c, "info header size: %d", (int)d->infohdrsize);
225 if(d->version==DE_BMPVER_OS2V1) {
226 d->width = de_getu16le(pos+4);
227 d->height = de_getu16le(pos+6);
228 nplanes = de_getu16le(pos+8);
230 else {
231 d->width = de_geti32le(pos+4);
232 height_raw = de_geti32le(pos+8);
233 if(height_raw<0) {
234 d->top_down = 1;
235 d->height = -height_raw;
237 else {
238 d->height = height_raw;
240 nplanes = de_getu16le(pos+12);
242 d->pdwidth = d->width; // Default "padded width"
243 de_dbg_dimensions(c, d->width, d->height);
244 if(!de_good_image_dimensions(c, d->width, d->height)) {
245 goto done;
247 if(d->top_down) {
248 de_dbg(c, "orientation: top-down");
250 else {
251 d->extra_createflags |= DE_CREATEFLAG_FLIP_IMAGE;
254 de_dbg(c, "planes: %d", (int)nplanes);
256 // Already read, in detect_bmp_version()
257 de_dbg(c, "bits/pixel: %d", (int)d->bitcount);
259 if(d->bitcount!=0 && d->bitcount!=1 && d->bitcount!=2 && d->bitcount!=4 &&
260 d->bitcount!=8 && d->bitcount!=16 && d->bitcount!=24 && d->bitcount!=32)
262 de_err(c, "Bad bits/pixel: %d", (int)d->bitcount);
263 goto done;
266 if(d->version==DE_BMPVER_OS2V1) {
267 d->bytes_per_pal_entry = 3;
269 else {
270 char cmprname[80];
271 // d->compression_field was already read, in detect_bmp_version()
272 fmtutil_get_bmp_compression_name(d->compression_field, cmprname, sizeof(cmprname),
273 (d->version==DE_BMPVER_OS2V2));
274 de_dbg(c, "compression (etc.): %u (%s)", (unsigned int)d->compression_field, cmprname);
275 d->bytes_per_pal_entry = 4;
278 d->compression_type = CMPR_NONE; // Temporary default
280 cmpr_ok = 0;
281 switch(d->compression_field) {
282 case 0: // BI_RGB
283 if(d->bitcount==16 || d->bitcount==32) {
284 d->bitfields_type = BF_DEFAULT;
286 d->compression_type = CMPR_NONE;
287 cmpr_ok = 1;
288 break;
289 case 1: // BI_RLE8
290 d->compression_type=CMPR_RLE8;
291 cmpr_ok = 1;
292 break;
293 case 2: // BI_RLE4
294 d->compression_type=CMPR_RLE4;
295 cmpr_ok = 1;
296 break;
297 case 3: // BI_BITFIELDS or Huffman_1D
298 if(d->version==DE_BMPVER_OS2V2) {
299 if(d->bitcount==1) {
300 d->compression_type=CMPR_HUFFMAN1D;
301 cmpr_ok = 1;
304 else if(d->bitcount==16 || d->bitcount==32) {
305 d->compression_type = CMPR_NONE;
306 cmpr_ok = 1;
307 if(d->infohdrsize>=52) {
308 d->bitfields_type = BF_IN_HEADER;
310 else {
311 d->bitfields_type = BF_SEGMENT;
312 d->bitfields_segment_len = 12;
315 break;
316 case 4: // BI_JPEG or RLE24
317 if(d->version==DE_BMPVER_OS2V2) {
318 if(d->bitcount==24) {
319 d->compression_type=CMPR_RLE24;
320 cmpr_ok = 1;
323 else {
324 d->compression_type=CMPR_JPEG;
325 cmpr_ok = 1;
327 break;
328 case 5: // BI_PNG
329 d->compression_type=CMPR_PNG;
330 cmpr_ok = 1;
331 break;
332 case 6: // BI_ALPHABITFIELDS
333 if(d->bitcount==16 || d->bitcount==32) {
334 d->compression_type = CMPR_NONE;
335 cmpr_ok = 1;
336 if(d->infohdrsize>=56) {
337 d->bitfields_type = BF_IN_HEADER;
339 else {
340 d->bitfields_type = BF_SEGMENT;
341 d->bitfields_segment_len = 16;
344 break;
347 if(!cmpr_ok) {
348 de_err(c, "Unsupported compression type: %d", (int)d->compression_field);
349 goto done;
352 if(d->infohdrsize>=24) {
353 d->size_image = de_getu32le(pos+20);
354 de_dbg(c, "biSizeImage: %d", (int)d->size_image);
357 if(d->infohdrsize>=32) {
358 d->xpelspermeter = de_geti32le(pos+24);
359 d->ypelspermeter = de_geti32le(pos+28);
360 de_dbg(c, "density: %d"DE_CHAR_TIMES"%d pixels/meter", (int)d->xpelspermeter, (int)d->ypelspermeter);
361 if(d->xpelspermeter>0 && d->ypelspermeter>0) {
362 d->fi->density.code = DE_DENSITY_DPI;
363 d->fi->density.xdens = (double)d->xpelspermeter * 0.0254;
364 d->fi->density.ydens = (double)d->ypelspermeter * 0.0254;
368 if(d->infohdrsize>=36)
369 clr_used_raw = de_getu32le(pos+32);
370 else
371 clr_used_raw = 0;
373 if(d->bitcount>=1 && d->bitcount<=8 && clr_used_raw==0) {
374 d->pal_entries = ((i64)1)<<d->bitcount;
376 else {
377 d->pal_entries = clr_used_raw;
379 de_dbg(c, "number of palette colors: %d", (int)d->pal_entries);
381 // Note that after 40 bytes, WINV345 and OS2V2 header fields are different,
382 // so we have to pay more attention to the version.
384 if(d->bitfields_type==BF_IN_HEADER) {
385 do_read_bitfields(c, d, pos+40, d->infohdrsize>=56 ? 16 : 12);
388 if(d->bitfields_type==BF_DEFAULT) {
389 set_default_bitfields(c, d);
392 if(d->version==DE_BMPVER_WINV345 && d->infohdrsize>=108) {
393 char cstype_descr_dbgstr[80];
394 dbuf_read_fourcc(c->infile, pos+56, &d->cstype4cc, 4, DE_4CCFLAG_REVERSED);
395 get_cstype_descr_dbgstr(&d->cstype4cc, cstype_descr_dbgstr, sizeof(cstype_descr_dbgstr));
396 de_dbg(c, "CSType: %s", cstype_descr_dbgstr);
399 if(d->version==DE_BMPVER_WINV345 && d->infohdrsize>=124) {
400 u32 intent;
401 intent = (u32)de_getu32le(pos+108);
402 de_dbg(c, "intent: %u", (unsigned int)intent);
405 if(d->version==DE_BMPVER_WINV345 && d->infohdrsize>=124 &&
406 (d->cstype4cc.id==CODE_MBED || d->cstype4cc.id==CODE_LINK))
408 d->profile_offset_raw = de_getu32le(pos+112);
409 de_dbg(c, "profile offset: %d+%d", FILEHEADER_SIZE,
410 (int)d->profile_offset_raw);
411 d->profile_size = de_getu32le(pos+116);
412 de_dbg(c, "profile size: %d", (int)d->profile_size);
415 retval = 1;
416 done:
417 de_dbg_indent(c, -1);
418 return retval;
421 static void do_read_linked_profile(deark *c, lctx *d)
423 de_ucstring *fname = NULL;
425 de_dbg(c, "linked profile filename at %d", (int)d->profile_offset);
426 fname = ucstring_create(c);
427 dbuf_read_to_ucstring_n(c->infile, d->profile_offset,
428 d->profile_size, DE_DBG_MAX_STRLEN, fname,
429 DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_WINDOWS1252);
430 de_dbg_indent(c, 1);
431 de_dbg(c, "profile filename: \"%s\"", ucstring_getpsz(fname));
432 de_dbg_indent(c, -1);
433 ucstring_destroy(fname);
436 static void do_read_embedded_profile(deark *c, lctx *d)
438 de_dbg(c, "embedded profile at %d, size=%d", (int)d->profile_offset,
439 (int)d->profile_size);
440 de_dbg_indent(c, 1);
441 dbuf_create_file_from_slice(c->infile, d->profile_offset, d->profile_size, "icc",
442 NULL, DE_CREATEFLAG_IS_AUX);
443 de_dbg_indent(c, -1);
446 static void do_read_profile(deark *c, lctx *d)
448 if(d->version!=DE_BMPVER_WINV345) return;
449 if(d->infohdrsize<124) return;
450 if(d->profile_offset_raw==0 || d->profile_size==0) return;
451 d->profile_offset = FILEHEADER_SIZE + d->profile_offset_raw;
452 if(d->profile_offset+d->profile_size > c->infile->len) return;
453 if(d->cstype4cc.id==CODE_LINK) {
454 do_read_linked_profile(c, d);
456 else if(d->cstype4cc.id==CODE_MBED) {
457 do_read_embedded_profile(c, d);
461 // Some OS/2v2 files exist with bad (3-bytes/color) palettes.
462 // Try to detect them.
463 static void do_os2v2_bad_palette(deark *c, lctx *d)
465 i64 pal_space_avail;
466 i64 pal_bytes_if_3bpc;
467 i64 pal_bytes_if_4bpc;
468 int nonzero_rsvd;
469 int i;
471 if(d->version!=DE_BMPVER_OS2V2) return;
472 if(d->pal_entries<1) return;
474 pal_space_avail = d->bits_offset - d->pal_pos;
475 pal_bytes_if_4bpc = 4*d->pal_entries;
476 pal_bytes_if_3bpc = 3*d->pal_entries;
478 if(pal_space_avail>=pal_bytes_if_4bpc) return;
479 if(pal_space_avail<pal_bytes_if_3bpc || pal_space_avail>(pal_bytes_if_3bpc+1)) return;
481 // Look for nonzero 'reserved' bytes
482 nonzero_rsvd = 0;
483 for(i=0; i<pal_bytes_if_3bpc; i+=4) {
484 if(de_getbyte(d->pal_pos + i + 3) != 0) {
485 nonzero_rsvd = 1;
486 break;
489 if(!nonzero_rsvd) return;
491 de_warn(c, "Assuming palette has 3 bytes per entry, instead of 4");
492 d->bytes_per_pal_entry = 3;
495 static void do_read_palette(deark *c, lctx *d)
497 i64 pal_size_in_bytes;
499 if(d->pal_entries<1) return;
501 pal_size_in_bytes = d->pal_entries*d->bytes_per_pal_entry;
502 if(d->pal_pos+pal_size_in_bytes > d->bits_offset) {
503 de_warn(c, "Palette at %d (size %d) overlaps bitmap at %d",
504 (int)d->pal_pos, (int)pal_size_in_bytes, (int)d->bits_offset);
505 if(d->version==DE_BMPVER_OS2V2) {
506 do_os2v2_bad_palette(c, d);
510 de_dbg(c, "color table at %d, %d entries", (int)d->pal_pos, (int)d->pal_entries);
512 de_dbg_indent(c, 1);
513 de_read_palette_rgb(c->infile, d->pal_pos, d->pal_entries, d->bytes_per_pal_entry,
514 d->pal, 256, DE_GETRGBFLAG_BGR);
516 d->pal_is_grayscale = de_is_grayscale_palette(d->pal, d->pal_entries);
517 de_dbg_indent(c, -1);
520 // A wrapper for de_bitmap_create()
521 static de_bitmap *bmp_bitmap_create(deark *c, lctx *d, int bypp)
523 de_bitmap *img;
525 img = de_bitmap_create2(c, d->width, d->pdwidth, d->height, bypp);
526 return img;
529 static void do_image_paletted(deark *c, lctx *d, dbuf *bits, i64 bits_offset)
531 de_bitmap *img = NULL;
533 img = bmp_bitmap_create(c, d, d->pal_is_grayscale?1:3);
534 de_convert_image_paletted(bits, bits_offset,
535 d->bitcount, d->rowspan, d->pal, img, 0);
536 de_bitmap_write_to_file_finfo(img, d->fi, d->extra_createflags);
537 de_bitmap_destroy(img);
540 static void do_image_24bit(deark *c, lctx *d, dbuf *bits, i64 bits_offset)
542 de_bitmap *img = NULL;
543 i64 i, j;
544 u32 clr;
546 img = bmp_bitmap_create(c, d, 3);
547 for(j=0; j<d->height; j++) {
548 i64 rowpos = bits_offset + j*d->rowspan;
549 i64 pos_in_this_row = 0;
550 u8 cbuf[3];
552 for(i=0; i<d->pdwidth; i++) {
553 dbuf_read(bits, cbuf, rowpos + pos_in_this_row, 3);
554 if(pos_in_this_row+3 > d->rowspan) {
555 // If -padpix was used, a partial pixel at the end of the row is
556 // possible. Happens when width == 1 or 2 (mod 4).
557 // To handle that, zero out the byte(s) that we shouldn't have read.
558 cbuf[2] = 0;
559 if(pos_in_this_row+2 > d->rowspan) {
560 cbuf[1] = 0;
563 clr = DE_MAKE_RGB(cbuf[2], cbuf[1], cbuf[0]);
564 de_bitmap_setpixel_rgb(img, i, j, clr);
565 pos_in_this_row += 3;
569 de_bitmap_write_to_file_finfo(img, d->fi, d->extra_createflags);
570 de_bitmap_destroy(img);
573 static void do_image_16_32bit(deark *c, lctx *d, dbuf *bits, i64 bits_offset)
575 de_bitmap *img = NULL;
576 i64 i, j;
577 int has_transparency;
578 u32 v;
579 i64 k;
580 u8 sm[4];
582 if(d->bitfields_type==BF_SEGMENT) {
583 has_transparency = (d->bitfields_segment_len>=16 && d->bitfield[3].mask!=0);
585 else if(d->bitfields_type==BF_IN_HEADER) {
586 has_transparency = (d->bitfield[3].mask!=0);
588 else {
589 has_transparency = 0;
592 img = bmp_bitmap_create(c, d, has_transparency?4:3);
593 for(j=0; j<d->height; j++) {
594 for(i=0; i<d->pdwidth; i++) {
595 if(d->bitcount==16) {
596 v = (u32)dbuf_getu16le(bits, bits_offset + j*d->rowspan + 2*i);
598 else {
599 v = (u32)dbuf_getu32le(bits, bits_offset + j*d->rowspan + 4*i);
602 for(k=0; k<4; k++) {
603 if(d->bitfield[k].mask!=0) {
604 sm[k] = (u8)(0.5 + d->bitfield[k].scale * (double)((v&d->bitfield[k].mask) >> d->bitfield[k].shift));
606 else {
607 if(k==3)
608 sm[k] = 255; // Default alpha sample = opaque
609 else
610 sm[k] = 0; // Default other samples = 0
613 de_bitmap_setpixel_rgba(img, i, j, DE_MAKE_RGBA(sm[0], sm[1], sm[2], sm[3]));
617 de_bitmap_write_to_file_finfo(img, d->fi, d->extra_createflags);
618 de_bitmap_destroy(img);
621 static void do_image_rle_4_8_24(deark *c, lctx *d, dbuf *bits, i64 bits_offset)
623 i64 pos;
624 i64 xpos, ypos;
625 u8 b1, b2;
626 u8 b;
627 u8 cr, cg, cb;
628 de_bitmap *img = NULL;
629 u32 clr1, clr2;
630 i64 num_bytes;
631 i64 num_pixels;
632 i64 k;
633 int bypp;
635 if(d->pal_is_grayscale && d->compression_type!=CMPR_RLE24) {
636 bypp = 2;
638 else {
639 bypp = 4;
642 img = bmp_bitmap_create(c, d, bypp);
644 pos = bits_offset;
645 xpos = 0;
646 ypos = 0;
647 while(1) {
648 // Stop if we reach the end of the input file.
649 if(pos>=c->infile->len) break;
651 // Stop if we reach the end of the output image.
652 if(ypos>=d->height) break;
653 if(ypos==(d->height-1) && xpos>=d->pdwidth) break;
655 // Read the next two bytes from the input file.
656 b1 = dbuf_getbyte(bits, pos++);
657 b2 = dbuf_getbyte(bits, pos++);
659 if(b1==0 && b2==0) { // End of line
660 xpos = 0;
661 ypos++;
663 else if(b1==0 && b2==1) { // End of bitmap
664 break;
666 else if(b1==0 && b2==2) { // Delta
667 b = dbuf_getbyte(bits, pos++);
668 xpos += (i64)b;
669 b = dbuf_getbyte(bits, pos++);
670 ypos += (i64)b;
672 else if(b1==0) { // b2 uncompressed pixels follow
673 num_pixels = (i64)b2;
674 if(d->compression_type==CMPR_RLE4) {
675 i64 pixels_copied = 0;
676 // There are 4 bits per pixel, but padded to a multiple of 16 bits.
677 num_bytes = ((num_pixels+3)/4)*2;
678 for(k=0; k<num_bytes; k++) {
679 b = dbuf_getbyte(bits, pos++);
680 if(pixels_copied>=num_pixels) continue;
681 clr1 = d->pal[((unsigned int)b)>>4];
682 de_bitmap_setpixel_rgba(img, xpos++, ypos, clr1);
683 pixels_copied++;
684 if(pixels_copied>=num_pixels) continue;
685 clr2 = d->pal[((unsigned int)b)&0x0f];
686 de_bitmap_setpixel_rgba(img, xpos++, ypos, clr2);
687 pixels_copied++;
690 else if(d->compression_type==CMPR_RLE24) {
691 for(k=0; k<num_pixels; k++) {
692 cb = dbuf_getbyte_p(bits, &pos);
693 cg = dbuf_getbyte_p(bits, &pos);
694 cr = dbuf_getbyte_p(bits, &pos);
695 clr1 = DE_MAKE_RGB(cr, cg, cb);
696 de_bitmap_setpixel_rgba(img, xpos++, ypos, clr1);
698 if(num_pixels%2) {
699 pos++; // Pad to a multiple of 16 bits
702 else { // CMPR_RLE8
703 num_bytes = num_pixels;
704 if(num_bytes%2) num_bytes++; // Pad to a multiple of 16 bits
705 for(k=0; k<num_bytes; k++) {
706 b = dbuf_getbyte(bits, pos++);
707 if(k>=num_pixels) continue;
708 clr1 = d->pal[(unsigned int)b];
709 de_bitmap_setpixel_rgba(img, xpos++, ypos, clr1);
713 else { // Compressed pixels
714 num_pixels = (i64)b1;
715 if(d->compression_type==CMPR_RLE4) {
716 // b1 pixels alternating between the colors in b2
717 clr1 = d->pal[((unsigned int)b2)>>4];
718 clr2 = d->pal[((unsigned int)b2)&0x0f];
719 for(k=0; k<num_pixels; k++) {
720 de_bitmap_setpixel_rgba(img, xpos++, ypos, (k%2)?clr2:clr1);
723 else if(d->compression_type==CMPR_RLE24) {
724 cb = b2;
725 cg = dbuf_getbyte_p(bits, &pos);
726 cr = dbuf_getbyte_p(bits, &pos);
727 clr1 = DE_MAKE_RGB(cr, cg, cb);
728 for(k=0; k<num_pixels; k++) {
729 de_bitmap_setpixel_rgba(img, xpos++, ypos, clr1);
732 else { // CMPR_RLE8
733 // b1 pixels of color b2
734 clr1 = d->pal[(unsigned int)b2];
735 for(k=0; k<num_pixels; k++) {
736 de_bitmap_setpixel_rgba(img, xpos++, ypos, clr1);
742 de_bitmap_write_to_file_finfo(img, d->fi, DE_CREATEFLAG_OPT_IMAGE | d->extra_createflags);
743 de_bitmap_destroy(img);
746 static void do_image_huffman1d(deark *c, lctx *d)
748 dbuf *unc_pixels = NULL;
749 struct de_dfilter_in_params dcmpri;
750 struct de_dfilter_out_params dcmpro;
751 struct de_dfilter_results dres;
752 struct de_fax34_params fax34params;
754 // Caution: These settings might be wrong. I need more information about this format.
755 de_zeromem(&fax34params, sizeof(struct de_fax34_params));
756 fax34params.image_width = d->width;
757 fax34params.image_height = d->height;
758 fax34params.out_rowspan = d->rowspan;
759 fax34params.tiff_cmpr_meth = 3;
760 fax34params.t4options = 0;
761 fax34params.is_lsb = (u8)de_get_ext_option_bool(c, "bmp:huffmanlsb", 0);
763 unc_pixels = dbuf_create_membuf(c, d->rowspan*d->height, 0x1);
765 de_dfilter_init_objects(c, &dcmpri, &dcmpro, &dres);
766 dcmpri.f = c->infile;
767 dcmpri.pos = d->bits_offset;
768 dcmpri.len = get_bits_size(c, d);
769 dcmpro.f = unc_pixels;
770 dcmpro.len_known = 1;
771 dcmpro.expected_len = d->rowspan*d->height;
773 fmtutil_fax34_codectype1(c, &dcmpri, &dcmpro, &dres,
774 (void*)&fax34params);
776 do_image_paletted(c, d, unc_pixels, 0);
778 dbuf_close(unc_pixels);
781 static void extract_embedded_image(deark *c, lctx *d, const char *ext)
783 i64 nbytes;
785 nbytes = get_bits_size(c, d);
786 if(nbytes<1) return;
788 dbuf_create_file_from_slice(c->infile, d->bits_offset, nbytes, ext, NULL, 0);
791 static void do_image(deark *c, lctx *d)
793 de_dbg(c, "bitmap at %d", (int)d->bits_offset);
795 if(d->bits_offset >= c->infile->len) {
796 de_err(c, "Bad bits-offset field");
797 goto done;
800 d->rowspan = ((d->bitcount*d->width +31)/32)*4;
801 if(d->compression_type==CMPR_NONE) {
802 if(c->padpix && d->bitcount==24) {
803 // The 24-bit decoder can handle partial pixels.
804 d->pdwidth = (d->rowspan+2)/3;
806 else {
807 // By default, ignore a partial-pixel's worth of padding.
808 // bits-per-row / bits-per-pixel
809 d->pdwidth = (d->rowspan*8) / d->bitcount;
813 if(d->bitcount>=1 && d->bitcount<=8 && d->compression_type==CMPR_NONE) {
814 do_image_paletted(c, d, c->infile, d->bits_offset);
816 else if(d->bitcount==24 && d->compression_type==CMPR_NONE) {
817 do_image_24bit(c, d, c->infile, d->bits_offset);
819 else if((d->bitcount==16 || d->bitcount==32) && d->compression_type==CMPR_NONE) {
820 do_image_16_32bit(c, d, c->infile, d->bits_offset);
822 else if(d->bitcount==8 && d->compression_type==CMPR_RLE8) {
823 do_image_rle_4_8_24(c, d, c->infile, d->bits_offset);
825 else if(d->bitcount==4 && d->compression_type==CMPR_RLE4) {
826 do_image_rle_4_8_24(c, d, c->infile, d->bits_offset);
828 else if(d->bitcount==24 && d->compression_type==CMPR_RLE24) {
829 do_image_rle_4_8_24(c, d, c->infile, d->bits_offset);
831 else if(d->compression_type==CMPR_JPEG) {
832 extract_embedded_image(c, d, "jpg");
834 else if(d->compression_type==CMPR_PNG) {
835 extract_embedded_image(c, d, "png");
837 else if(d->bitcount==1 && d->compression_type==CMPR_HUFFMAN1D) {
838 do_image_huffman1d(c, d);
840 else {
841 de_err(c, "This type of BMP image is not supported");
844 done:
848 static void de_run_bmp(deark *c, de_module_params *mparams)
850 lctx *d = NULL;
851 i64 pos;
853 d = de_malloc(c, sizeof(lctx));
854 d->fi = de_finfo_create(c);
856 if(dbuf_memcmp(c->infile, 0, "BM", 2)) {
857 de_err(c, "Not a BMP file.");
858 goto done;
861 if(!detect_bmp_version(c, d)) {
862 de_err(c, "Unidentified BMP version.");
863 goto done;
866 switch(d->version) {
867 case DE_BMPVER_OS2V1:
868 if(d->fsize==26) {
869 de_declare_fmt(c, "BMP, OS/2 v1");
871 else {
872 de_declare_fmt(c, "BMP, OS/2 v1 or Windows v2");
874 break;
875 case DE_BMPVER_OS2V2: de_declare_fmt(c, "BMP, OS/2 v2"); break;
876 case DE_BMPVER_WINV345:
877 switch(d->infohdrsize) {
878 case 40: de_declare_fmt(c, "BMP, Windows v3"); break;
879 case 108: de_declare_fmt(c, "BMP, Windows v4"); break;
880 case 124: de_declare_fmt(c, "BMP, Windows v5"); break;
881 default: de_declare_fmt(c, "BMP, Windows v3+");
883 break;
886 pos = 0;
887 if(!read_fileheader(c, d, pos)) goto done;
888 pos += FILEHEADER_SIZE;
889 if(!read_infoheader(c, d, pos)) goto done;
890 pos += d->infohdrsize;
891 if(d->bitfields_type==BF_SEGMENT) {
892 de_dbg(c, "bitfields segment at %d, len=%d", (int)pos, (int)d->bitfields_segment_len);
893 if(pos+d->bitfields_segment_len > d->bits_offset) {
894 de_warn(c, "BITFIELDS segment at %d (size %d) overlaps bitmap at %d",
895 (int)pos, (int)d->bitfields_segment_len, (int)d->bits_offset);
897 de_dbg_indent(c, 1);
898 do_read_bitfields(c, d, pos, d->bitfields_segment_len);
899 de_dbg_indent(c, -1);
900 pos += d->bitfields_segment_len;
902 d->pal_pos = pos;
903 do_read_palette(c, d);
904 do_image(c, d);
905 do_read_profile(c, d);
907 done:
908 if(d) {
909 de_finfo_destroy(c, d->fi);
910 de_free(c, d);
914 // Note that this function must work together with de_identify_vbm().
915 static int de_identify_bmp(deark *c)
917 i64 fsize;
918 i64 bits_offset;
919 i64 infohdrsize;
920 int bmp_ext;
921 u8 buf[6];
923 de_read(buf, 0, sizeof(buf));
924 if(de_memcmp(buf, "BM", 2)) {
925 return 0;
928 bmp_ext = de_input_file_has_ext(c, "bmp");
929 fsize = de_getu32le_direct(&buf[2]);
930 bits_offset = de_getu32le(10);
931 infohdrsize = de_getu32le(14);
933 if(infohdrsize<12) return 0;
934 if(infohdrsize>256) return 0;
935 if(bits_offset>=c->infile->len) return 0;
936 if(bits_offset<14+infohdrsize) return 0;
937 if(fsize==c->infile->len && bmp_ext) return 100;
938 if(buf[2]==0xcb) {
939 // Possible VBM file.
940 // Windows BMP files are highly unlikely to start with 'B' 'M' \xcb,
941 // because that would imply the file is an odd number of bytes in size,
942 // which is legal but silly.
943 if(bmp_ext) return 90;
944 return 5;
947 if(bmp_ext) return 100;
948 if(infohdrsize==12 || infohdrsize==40 || infohdrsize==108 ||
949 infohdrsize==124)
951 return 100;
953 return 90;
956 void de_module_bmp(deark *c, struct deark_module_info *mi)
958 mi->id = "bmp";
959 mi->desc = "BMP (Windows or OS/2 bitmap)";
960 mi->run_fn = de_run_bmp;
961 mi->identify_fn = de_identify_bmp;
964 static void de_run_dib(deark *c, de_module_params *mparams)
966 struct de_bmpinfo bi;
967 unsigned int createflags = 0;
968 dbuf *outf = NULL;
969 int implicit_size = 0;
970 i64 dib_len;
971 const char *ext = "bmp";
973 if(mparams) {
974 // If flags&0x01, try to calculate the proper file size, instead of trusting
975 // the length of the input file.
976 if(mparams->in_params.flags & 0x01) implicit_size = 1;
978 if(mparams->in_params.flags & 0x80) ext = "preview.bmp";
981 if(de_havemodcode(c, mparams, 'X')) {
982 createflags |= DE_CREATEFLAG_IS_AUX;
985 if(!fmtutil_get_bmpinfo(c, c->infile, &bi, 0, c->infile->len, 0)) {
986 de_err(c, "Invalid DIB, or not a DIB file");
987 goto done;
990 if(implicit_size) {
991 dib_len = bi.total_size;
992 if(dib_len > c->infile->len) {
993 dib_len = c->infile->len;
996 else {
997 dib_len = c->infile->len;
1000 outf = dbuf_create_output_file(c, ext, NULL, createflags);
1002 de_dbg(c, "writing a BMP FILEHEADER");
1003 fmtutil_generate_bmpfileheader(c, outf, &bi, 14+dib_len);
1005 de_dbg(c, "copying DIB file");
1006 dbuf_copy(c->infile, 0, dib_len, outf);
1008 done:
1009 dbuf_close(outf);
1012 static int de_identify_dib(deark *c)
1014 i64 n;
1016 n = de_getu32le(0); // biSize
1017 if(n!=40) return 0;
1018 n = de_getu16le(12); // biPlanes
1019 if(n!=1) return 0;
1020 n = de_getu16le(14); // biBitCount
1021 if(n==1 || n==4 || n==8 || n==16 || n==24 || n==32) return 15;
1022 return 0;
1025 // BMP file without a file header.
1026 // This module constructs a BMP file header.
1027 void de_module_dib(deark *c, struct deark_module_info *mi)
1029 mi->id = "dib";
1030 mi->desc = "DIB (raw Windows bitmap)";
1031 mi->run_fn = de_run_dib;
1032 mi->identify_fn = de_identify_dib;
1035 // **************************************************************************
1036 // DDB / "BMP v1"
1037 // **************************************************************************
1039 struct ddbctx_struct {
1040 i64 bmWidthBytes;
1041 UI createflags;
1042 de_finfo *fi;
1045 static void ddb_convert_pal4planar(deark *c, struct ddbctx_struct *d,
1046 i64 fpos, de_bitmap *img)
1048 const i64 nplanes = 4;
1049 i64 i, j, plane;
1050 i64 rowspan;
1051 u8 *rowbuf = NULL;
1052 static const u32 pal16[16] = {
1053 0x000000,0x800000,0x008000,0x808000,0x000080,0x800080,0x008080,0x808080,
1054 0xc0c0c0,0xff0000,0x00ff00,0xffff00,0x0000ff,0xff00ff,0x00ffff,0xffffff
1057 rowspan = d->bmWidthBytes * nplanes;
1058 rowbuf = de_malloc(c, rowspan);
1060 // The usual order seems to be
1061 // row0_plane0x1, row0_plane0x2, row0_plane0x4, row0_plane0x8,
1062 // row1_plane0x1, row1_plane0x2, row1_plane0x4, row1_plane0x8,
1063 // ...
1064 // But I have seen another, and I see no way to detect/support it.
1066 for(j=0; j<img->height; j++) {
1067 de_read(rowbuf, fpos+j*rowspan, rowspan);
1069 for(i=0; i<img->width; i++) {
1070 unsigned int palent = 0;
1071 u32 clr;
1073 for(plane=0; plane<nplanes; plane++) {
1074 unsigned int n = 0;
1075 i64 idx;
1077 idx = d->bmWidthBytes*plane + i/8;
1078 if(idx<rowspan) n = rowbuf[idx];
1079 if(n & (1<<(7-i%8))) {
1080 palent |= (1<<plane);
1084 clr = DE_MAKE_OPAQUE(pal16[palent]);
1085 de_bitmap_setpixel_rgb(img, i, j, clr);
1089 de_free(c, rowbuf);
1092 static void ddb_convert_pal8(deark *c, struct ddbctx_struct *d,
1093 i64 fpos, de_bitmap *img)
1095 i64 i, j;
1096 int badcolorflag = 0;
1097 // Palette is from libwps (except I might have red/blue swapped it).
1098 // I haven't confirmed that it's correct.
1099 static const u32 pal_part1[8] = {
1100 0x000000,0x800000,0x008000,0x808000,0x000080,0x800080,0x008080,0xc0c0c0
1102 static const u32 pal_part2[8] = {
1103 0x808080,0xff0000,0x00ff00,0xffff00,0x0000ff,0xff00ff,0x00ffff,0xffffff
1106 for(j=0; j<img->height; j++) {
1107 for(i=0; i<img->width; i++) {
1108 unsigned int palent;
1109 u32 clr;
1111 palent = de_getbyte(fpos+j*d->bmWidthBytes+i);
1112 if(palent<8) {
1113 clr = pal_part1[palent];
1115 else if(palent>=248) {
1116 clr = pal_part2[palent-248];
1118 else {
1119 clr = DE_MAKE_RGB(254,palent,254); // Just an arbitrary color
1120 badcolorflag = 1;
1122 de_bitmap_setpixel_rgb(img, i, j, clr);
1125 if(badcolorflag) {
1126 de_warn(c, "Image uses nonportable colors");
1130 static void do_ddb_bitmap(deark *c, struct ddbctx_struct *d, i64 pos1)
1132 i64 pos = pos1;
1133 unsigned int bmType;
1134 i64 bmWidth, bmHeight;
1135 i64 pdwidth;
1136 i64 bmPlanes;
1137 i64 bmBitsPixel;
1138 i64 src_realbitsperpixel;
1139 de_bitmap *img = NULL;
1141 bmType = (unsigned int)de_getu16le_p(&pos);
1142 de_dbg(c, "bmType: %u", bmType);
1144 bmWidth = de_getu16le_p(&pos);
1145 bmHeight = de_getu16le_p(&pos);
1146 de_dbg_dimensions(c, bmWidth, bmHeight);
1148 d->bmWidthBytes = de_getu16le_p(&pos);
1149 de_dbg(c, "bytes/row: %d", (int)d->bmWidthBytes);
1151 bmPlanes = (i64)de_getbyte_p(&pos);
1152 de_dbg(c, "planes: %d", (int)bmPlanes);
1154 bmBitsPixel = (i64)de_getbyte_p(&pos);
1155 de_dbg(c, "bmBitsPixel: %d", (int)bmBitsPixel);
1157 pos += 4; // Placeholder for a pointer?
1159 if((bmBitsPixel==1 && bmPlanes==1) ||
1160 (bmBitsPixel==1 && bmPlanes==4) ||
1161 (bmBitsPixel==8 && bmPlanes==1))
1165 else {
1166 de_err(c, "This type of DDB bitmap is not supported "
1167 "(bmBitsPixel=%d, planes=%d)", (int)bmBitsPixel, (int)bmPlanes);
1168 goto done;
1171 de_dbg(c, "pixels at %"I64_FMT, pos);
1173 src_realbitsperpixel = bmBitsPixel * bmPlanes;
1174 if(!de_good_image_dimensions(c, bmWidth, bmHeight)) goto done;
1176 pdwidth = (d->bmWidthBytes*8) / bmBitsPixel;
1177 img = de_bitmap_create2(c, bmWidth, pdwidth, bmHeight, (src_realbitsperpixel==1)?1:3);
1179 if(bmBitsPixel==1 && bmPlanes==1) {
1180 de_convert_image_bilevel(c->infile, pos, d->bmWidthBytes, img, 0);
1182 else if(bmBitsPixel==1 || bmPlanes==4) {
1183 ddb_convert_pal4planar(c, d, pos, img);
1185 else if(bmBitsPixel==8 || bmPlanes==1) {
1186 ddb_convert_pal8(c, d, pos, img);
1189 de_bitmap_write_to_file_finfo(img, d->fi, d->createflags);
1191 done:
1192 de_bitmap_destroy(img);
1196 static void de_run_ddb(deark *c, de_module_params *mparams)
1198 int has_filetype = 1;
1199 struct ddbctx_struct *d = NULL;
1200 i64 pos = 0;
1202 d = de_malloc(c, sizeof(struct ddbctx_struct));
1203 d->createflags = 0;
1205 if(de_havemodcode(c, mparams, 'N')) {
1206 has_filetype = 0;
1208 if(de_havemodcode(c, mparams, 'X')) {
1209 d->createflags |= DE_CREATEFLAG_IS_AUX;
1211 if(mparams && mparams->in_params.fi) {
1212 d->fi = mparams->in_params.fi;
1215 if(has_filetype) {
1216 unsigned int file_type;
1217 file_type = (unsigned int)de_getu16le_p(&pos);
1218 de_dbg(c, "file type: 0x%04x", file_type);
1221 do_ddb_bitmap(c, d, pos);
1223 de_free(c, d);
1226 void de_module_ddb(deark *c, struct deark_module_info *mi)
1228 mi->id = "ddb";
1229 mi->desc = "Windows DDB bitmap";
1230 mi->run_fn = de_run_ddb;
1231 mi->identify_fn = NULL;
1232 mi->flags |= DE_MODFLAG_HIDDEN;