7 bmp.c - read and write windows BMP files
14 if (!i_writebmp_wiol(im, ig)) {
21 Reads and writes Windows BMP files.
28 #define FILEHEAD_SIZE 14
29 #define INFOHEAD_SIZE 40
33 #define BI_BITFIELDS 3
34 #define BMPRLE_ENDOFLINE 0
35 #define BMPRLE_ENDOFBMP 1
36 #define BMPRLE_DELTA 2
38 #define SIGNBIT32 ((i_upacked_t)1U << 31)
39 #define SIGNBIT16 ((i_upacked_t)1U << 15)
41 #define SIGNMAX32 ((1UL << 31) - 1)
43 static int read_packed(io_glue *ig, char *format, ...);
44 static int write_packed(io_glue *ig, char *format, ...);
45 static int write_bmphead(io_glue *ig, i_img *im, int bit_count,
47 static int write_1bit_data(io_glue *ig, i_img *im);
48 static int write_4bit_data(io_glue *ig, i_img *im);
49 static int write_8bit_data(io_glue *ig, i_img *im);
50 static int write_24bit_data(io_glue *ig, i_img *im);
51 static int read_bmp_pal(io_glue *ig, i_img *im, int count);
52 static i_img *read_1bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
53 int compression, long offbits, int allow_incomplete);
54 static i_img *read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
55 int compression, long offbits, int allow_incomplete);
56 static i_img *read_8bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
57 int compression, long offbits, int allow_incomplete);
58 static i_img *read_direct_bmp(io_glue *ig, int xsize, int ysize,
59 int bit_count, int clr_used, int compression,
60 long offbits, int allow_incomplete);
62 /* used for the read_packed() and write_packed() functions, an integer
64 typedef long i_packed_t;
65 typedef unsigned long i_upacked_t;
68 =item i_writebmp_wiol(im, io_glue)
70 Writes the image as a BMP file. Uses 1-bit, 4-bit, 8-bit or 24-bit
71 formats depending on the image.
73 Never compresses the image.
78 i_writebmp_wiol(i_img *im, io_glue *ig) {
82 if (im->type == i_direct_type) {
83 return write_24bit_data(ig, im);
88 /* must be paletted */
89 pal_size = i_colorcount(im);
91 return write_1bit_data(ig, im);
93 else if (pal_size <= 16) {
94 return write_4bit_data(ig, im);
97 return write_8bit_data(ig, im);
103 =item i_readbmp_wiol(ig)
105 Reads a Windows format bitmap from the given file.
107 Handles BI_RLE4 and BI_RLE8 compressed images. Attempts to handle
108 BI_BITFIELDS images too, but I need a test image.
114 i_readbmp_wiol(io_glue *ig, int allow_incomplete) {
115 i_packed_t b_magic, m_magic, filesize, res1, res2, infohead_size;
116 i_packed_t xsize, ysize, planes, bit_count, compression, size_image, xres, yres;
117 i_packed_t clr_used, clr_important, offbits;
120 mm_log((1, "i_readbmp_wiol(ig %p)\n", ig));
124 if (!read_packed(ig, "CCVvvVVV!V!vvVVVVVV", &b_magic, &m_magic, &filesize,
125 &res1, &res2, &offbits, &infohead_size,
126 &xsize, &ysize, &planes,
127 &bit_count, &compression, &size_image, &xres, &yres,
128 &clr_used, &clr_important)) {
129 i_push_error(0, "file too short to be a BMP file");
132 if (b_magic != 'B' || m_magic != 'M' || infohead_size != INFOHEAD_SIZE
134 i_push_error(0, "not a BMP file");
138 mm_log((1, " bmp header: filesize %d offbits %d xsize %d ysize %d planes %d "
139 "bit_count %d compression %d size %d xres %d yres %d clr_used %d "
140 "clr_important %d\n", (int)filesize, (int)offbits, (int)xsize,
141 (int)ysize, (int)planes, (int)bit_count, (int)compression,
142 (int)size_image, (int)xres, (int)yres, (int)clr_used,
143 (int)clr_important));
145 if (!i_int_check_image_file_limits(xsize, abs(ysize), 3, sizeof(i_sample_t))) {
146 mm_log((1, "i_readbmp_wiol: image size exceeds limits\n"));
152 im = read_1bit_bmp(ig, xsize, ysize, clr_used, compression, offbits,
157 im = read_4bit_bmp(ig, xsize, ysize, clr_used, compression, offbits,
162 im = read_8bit_bmp(ig, xsize, ysize, clr_used, compression, offbits,
169 im = read_direct_bmp(ig, xsize, ysize, bit_count, clr_used, compression,
170 offbits, allow_incomplete);
174 i_push_errorf(0, "unknown bit count for BMP file (%d)", (int)bit_count);
179 /* store the resolution */
182 else if (yres && !xres)
185 i_tags_set_float2(&im->tags, "i_xres", 0, xres * 0.0254, 4);
186 i_tags_set_float2(&im->tags, "i_yres", 0, yres * 0.0254, 4);
188 i_tags_addn(&im->tags, "bmp_compression", 0, compression);
189 i_tags_addn(&im->tags, "bmp_important_colors", 0, clr_important);
190 i_tags_addn(&im->tags, "bmp_used_colors", 0, clr_used);
191 i_tags_addn(&im->tags, "bmp_filesize", 0, filesize);
192 i_tags_addn(&im->tags, "bmp_bit_count", 0, bit_count);
193 i_tags_add(&im->tags, "i_format", 0, "bmp", 3, 0);
202 =head1 IMPLEMENTATION FUNCTIONS
204 Internal functions used in the implementation.
208 =item read_packed(ig, format, ...)
210 Reads from the specified "file" the specified sizes. The format codes
211 match those used by perl's pack() function, though only a few are
212 implemented. In all cases the vararg arguement is an int *.
214 Returns non-zero if all of the arguments were read.
219 read_packed(io_glue *ig, char *format, ...) {
220 unsigned char buf[4];
225 int shrieking; /* format code has a ! flag */
227 va_start(ap, format);
230 p = va_arg(ap, i_packed_t *);
233 shrieking = *format == '!';
234 if (shrieking) ++format;
238 if (i_io_read(ig, buf, 2) != 2)
240 work = buf[0] + ((i_packed_t)buf[1] << 8);
242 *p = (work ^ SIGNBIT16) - SIGNBIT16;
248 if (i_io_read(ig, buf, 4) != 4)
250 work = buf[0] + (buf[1] << 8) + ((i_packed_t)buf[2] << 16) + ((i_packed_t)buf[3] << 24);
252 *p = (work ^ SIGNBIT32) - SIGNBIT32;
258 if (i_io_read(ig, buf, 1) != 1)
264 if (i_io_read(ig, buf, 1) != 1)
269 case '3': /* extension - 24-bit number */
270 if (i_io_read(ig, buf, 3) != 3)
272 *p = buf[0] + (buf[1] << 8) + ((i_packed_t)buf[2] << 16);
276 i_fatal(1, "Unknown read_packed format code 0x%02x", code);
283 =item write_packed(ig, format, ...)
285 Writes packed data to the specified io_glue.
287 Returns non-zero on success.
293 write_packed(io_glue *ig, char *format, ...) {
294 unsigned char buf[4];
298 va_start(ap, format);
301 i = va_arg(ap, i_upacked_t);
307 if (i_io_write(ig, buf, 2) == -1)
313 buf[1] = (i >> 8) & 0xFF;
314 buf[2] = (i >> 16) & 0xFF;
315 buf[3] = (i >> 24) & 0xFF;
316 if (i_io_write(ig, buf, 4) == -1)
323 if (i_io_write(ig, buf, 1) == -1)
328 i_fatal(1, "Unknown write_packed format code 0x%02x", *format);
338 =item write_bmphead(ig, im, bit_count, data_size)
340 Writes a Windows BMP header to the file.
342 Returns non-zero on success.
348 int write_bmphead(io_glue *ig, i_img *im, int bit_count, int data_size) {
350 int got_xres, got_yres, aspect_only;
352 int offset = FILEHEAD_SIZE + INFOHEAD_SIZE;
354 if (im->xsize > SIGNMAX32 || im->ysize > SIGNMAX32) {
355 i_push_error(0, "image too large to write to BMP");
359 got_xres = i_tags_get_float(&im->tags, "i_xres", 0, &xres);
360 got_yres = i_tags_get_float(&im->tags, "i_yres", 0, &yres);
361 if (!i_tags_get_int(&im->tags, "i_aspect_only", 0,&aspect_only))
373 if (xres <= 0 || yres <= 0)
376 /* scale so the smaller value is 72 */
387 /* now to pels/meter */
391 if (im->type == i_palette_type) {
392 colors_used = i_colorcount(im);
393 offset += 4 * colors_used;
396 if (!write_packed(ig, "CCVvvVVVVvvVVVVVV", 'B', 'M',
397 (i_upacked_t)(data_size+offset),
398 (i_upacked_t)0, (i_upacked_t)0, (i_upacked_t)offset,
399 (i_upacked_t)INFOHEAD_SIZE, (i_upacked_t)im->xsize,
400 (i_upacked_t)im->ysize, (i_upacked_t)1,
401 (i_upacked_t)bit_count, (i_upacked_t)BI_RGB,
402 (i_upacked_t)data_size,
403 (i_upacked_t)(xres+0.5), (i_upacked_t)(yres+0.5),
404 (i_upacked_t)colors_used, (i_upacked_t)colors_used)){
405 i_push_error(0, "cannot write bmp header");
408 if (im->type == i_palette_type) {
412 for (i = 0; i < colors_used; ++i) {
413 i_getcolors(im, i, &c, 1);
414 if (im->channels >= 3) {
415 if (!write_packed(ig, "CCCC", (i_upacked_t)(c.channel[2]),
416 (i_upacked_t)(c.channel[1]),
417 (i_upacked_t)(c.channel[0]), (i_upacked_t)0)) {
418 i_push_error(0, "cannot write palette entry");
423 i_upacked_t v = c.channel[0];
424 if (!write_packed(ig, "CCCC", v, v, v, 0)) {
425 i_push_error(0, "cannot write palette entry");
436 =item write_1bit_data(ig, im)
438 Writes the image data as a 1-bit/pixel image.
440 Returns non-zero on success.
445 write_1bit_data(io_glue *ig, i_img *im) {
447 unsigned char *packed;
451 int line_size = (im->xsize+7) / 8;
455 /* round up to nearest multiple of four */
456 line_size = (line_size + 3) / 4 * 4;
458 if (!write_bmphead(ig, im, 1, line_size * im->ysize))
461 /* this shouldn't be an issue, but let's be careful */
462 unpacked_size = im->xsize + 8;
463 if (unpacked_size < im->xsize) {
464 i_push_error(0, "integer overflow during memory allocation");
467 line = mymalloc(unpacked_size); /* checked 29jun05 tonyc */
468 memset(line + im->xsize, 0, 8);
470 /* size allocated here is always much smaller than xsize, hence
471 can't overflow int */
472 packed = mymalloc(line_size); /* checked 29jun05 tonyc */
473 memset(packed, 0, line_size);
475 for (y = im->ysize-1; y >= 0; --y) {
476 i_gpal(im, 0, im->xsize, y, line);
480 for (x = 0; x < im->xsize; ++x) {
483 if ((mask >>= 1) == 0) {
492 if (i_io_write(ig, packed, line_size) < 0) {
495 i_push_error(0, "writing 1 bit/pixel packed data");
509 =item write_4bit_data(ig, im)
511 Writes the image data as a 4-bit/pixel image.
513 Returns non-zero on success.
518 write_4bit_data(io_glue *ig, i_img *im) {
520 unsigned char *packed;
522 int line_size = (im->xsize+1) / 2;
526 /* round up to nearest multiple of four */
527 line_size = (line_size + 3) / 4 * 4;
529 if (!write_bmphead(ig, im, 4, line_size * im->ysize))
532 /* this shouldn't be an issue, but let's be careful */
533 unpacked_size = im->xsize + 2;
534 if (unpacked_size < im->xsize) {
535 i_push_error(0, "integer overflow during memory allocation");
538 line = mymalloc(unpacked_size); /* checked 29jun05 tonyc */
539 memset(line + im->xsize, 0, 2);
541 /* size allocated here is always much smaller than xsize, hence
542 can't overflow int */
543 packed = mymalloc(line_size); /* checked 29jun05 tonyc */
544 memset(packed, 0, line_size);
546 for (y = im->ysize-1; y >= 0; --y) {
547 i_gpal(im, 0, im->xsize, y, line);
549 for (x = 0; x < im->xsize; x += 2) {
550 *out++ = (line[x] << 4) + line[x+1];
552 if (i_io_write(ig, packed, line_size) < 0) {
555 i_push_error(0, "writing 4 bit/pixel packed data");
569 =item write_8bit_data(ig, im)
571 Writes the image data as a 8-bit/pixel image.
573 Returns non-zero on success.
578 write_8bit_data(io_glue *ig, i_img *im) {
580 int line_size = im->xsize;
584 /* round up to nearest multiple of four */
585 line_size = (line_size + 3) / 4 * 4;
587 if (!write_bmphead(ig, im, 8, line_size * im->ysize))
590 /* this shouldn't be an issue, but let's be careful */
591 unpacked_size = im->xsize + 4;
592 if (unpacked_size < im->xsize) {
593 i_push_error(0, "integer overflow during memory allocation");
596 line = mymalloc(unpacked_size); /* checked 29jun05 tonyc */
597 memset(line + im->xsize, 0, 4);
599 for (y = im->ysize-1; y >= 0; --y) {
600 i_gpal(im, 0, im->xsize, y, line);
601 if (i_io_write(ig, line, line_size) < 0) {
603 i_push_error(0, "writing 8 bit/pixel packed data");
616 =item write_24bit_data(ig, im)
618 Writes the image data as a 24-bit/pixel image.
620 Returns non-zero on success.
625 write_24bit_data(io_glue *ig, i_img *im) {
626 unsigned char *samples;
628 int line_size = 3 * im->xsize;
631 i_get_file_background(im, &bg);
633 /* just in case we implement a direct format with 2bytes/pixel
635 if (line_size / 3 != im->xsize) {
636 i_push_error(0, "integer overflow during memory allocation");
640 line_size = (line_size + 3) / 4 * 4;
642 if (!write_bmphead(ig, im, 24, line_size * im->ysize))
644 samples = mymalloc(4 * im->xsize);
645 memset(samples, 0, line_size);
646 for (y = im->ysize-1; y >= 0; --y) {
647 unsigned char *samplep = samples;
649 i_gsamp_bg(im, 0, im->xsize, y, samples, 3, &bg);
650 for (x = 0; x < im->xsize; ++x) {
651 unsigned char tmp = samplep[2];
652 samplep[2] = samplep[0];
656 if (i_io_write(ig, samples, line_size) < 0) {
657 i_push_error(0, "writing image data");
671 =item read_bmp_pal(ig, im, count)
673 Reads count palette entries from the file and add them to the image.
675 Returns non-zero on success.
680 read_bmp_pal(io_glue *ig, i_img *im, int count) {
682 i_packed_t r, g, b, x;
685 for (i = 0; i < count; ++i) {
686 if (!read_packed(ig, "CCCC", &b, &g, &r, &x)) {
687 i_push_error(0, "reading BMP palette");
693 if (i_addcolors(im, &c, 1) < 0) {
694 i_push_error(0, "out of space in image palette");
703 =item read_1bit_bmp(ig, xsize, ysize, clr_used, compression, offbits)
705 Reads in the palette and image data for a 1-bit/pixel image.
707 Returns the image or NULL.
712 read_1bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
713 int compression, long offbits, int allow_incomplete) {
715 int x, y, lasty, yinc, start_y;
717 unsigned char *packed;
718 int line_size = (xsize + 7)/8;
723 if (compression != BI_RGB) {
724 i_push_errorf(0, "unknown 1-bit BMP compression (%d)", compression);
728 if (xsize + 8 < xsize) { /* if there was overflow */
729 /* we check with 8 because we allocate that much for the decoded
731 i_push_error(0, "integer overflow during memory allocation");
735 /* if xsize+7 is ok then (xsize+7)/8 will be and the minor
736 adjustments below won't make it overflow */
737 line_size = (line_size+3) / 4 * 4;
745 /* when ysize is -ve it's a top-down image */
754 if (clr_used < 0 || clr_used > 2) {
755 i_push_errorf(0, "out of range colors used (%d)", clr_used);
759 base_offset = FILEHEAD_SIZE + INFOHEAD_SIZE + clr_used * 4;
760 if (offbits < base_offset) {
761 i_push_errorf(0, "image data offset too small (%ld)", offbits);
765 im = i_img_pal_new(xsize, ysize, 3, 256);
768 if (!read_bmp_pal(ig, im, clr_used)) {
773 if (offbits > base_offset) {
774 /* this will be slow if the offset is large, but that should be
777 while (base_offset < offbits) {
778 if (i_io_read(ig, &buffer, 1) != 1) {
780 i_push_error(0, "failed skipping to image data offset");
787 i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RGB", -1, 0);
789 packed = mymalloc(line_size); /* checked 29jun05 tonyc */
790 line = mymalloc(xsize+8); /* checked 29jun05 tonyc */
792 if (i_io_read(ig, packed, line_size) != line_size) {
795 if (allow_incomplete) {
796 i_tags_setn(&im->tags, "i_incomplete", 1);
797 i_tags_setn(&im->tags, "i_lines_read", abs(start_y - y));
801 i_push_error(0, "failed reading 1-bit bmp data");
809 for (x = 0; x < xsize; ++x) {
810 *p++ = (*in & bit) ? 1 : 0;
817 i_ppal(im, 0, xsize, y, line);
827 =item read_4bit_bmp(ig, xsize, ysize, clr_used, compression)
829 Reads in the palette and image data for a 4-bit/pixel image.
831 Returns the image or NULL.
833 Hopefully this will be combined with the following function at some
839 read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
840 int compression, long offbits, int allow_incomplete) {
842 int x, y, lasty, yinc;
844 unsigned char *packed;
845 int line_size = (xsize + 1)/2;
851 /* line_size is going to be smaller than xsize in most cases (and
852 when it's not, xsize is itself small), and hence not overflow */
853 line_size = (line_size+3) / 4 * 4;
861 /* when ysize is -ve it's a top-down image */
871 if (clr_used > 16 || clr_used < 0) {
872 i_push_errorf(0, "out of range colors used (%d)", clr_used);
876 base_offset = FILEHEAD_SIZE + INFOHEAD_SIZE + clr_used * 4;
877 if (offbits < base_offset) {
878 i_push_errorf(0, "image data offset too small (%ld)", offbits);
882 im = i_img_pal_new(xsize, ysize, 3, 256);
883 if (!im) /* error should have been pushed already */
885 if (!read_bmp_pal(ig, im, clr_used)) {
890 if (offbits > base_offset) {
891 /* this will be slow if the offset is large, but that should be
894 while (base_offset < offbits) {
895 if (i_io_read(ig, &buffer, 1) != 1) {
897 i_push_error(0, "failed skipping to image data offset");
905 packed = mymalloc(260); /* checked 29jun05 tonyc */
907 packed = mymalloc(line_size); /* checked 29jun05 tonyc */
908 /* xsize won't approach MAXINT */
909 line = mymalloc(xsize+1); /* checked 29jun05 tonyc */
910 if (compression == BI_RGB) {
911 i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RGB", -1, 0);
913 if (i_io_read(ig, packed, line_size) != line_size) {
916 if (allow_incomplete) {
917 i_tags_setn(&im->tags, "i_incomplete", 1);
918 i_tags_setn(&im->tags, "i_lines_read", abs(y - starty));
922 i_push_error(0, "failed reading 4-bit bmp data");
929 for (x = 0; x < xsize; x+=2) {
934 i_ppal(im, 0, xsize, y, line);
940 else if (compression == BI_RLE4) {
943 i_img_dim xlimit = (xsize + 1) / 2 * 2; /* rounded up */
945 i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RLE4", -1, 0);
948 /* there's always at least 2 bytes in a sequence */
949 if (i_io_read(ig, packed, 2) != 2) {
952 if (allow_incomplete) {
953 i_tags_setn(&im->tags, "i_incomplete", 1);
954 i_tags_setn(&im->tags, "i_lines_read", abs(y - starty));
958 i_push_error(0, "missing data during decompression");
963 else if (packed[0]) {
964 int count = packed[0];
965 if (x + count > xlimit) {
966 /* this file is corrupt */
969 i_push_error(0, "invalid data during decompression");
970 mm_log((1, "read 4-bit: scanline overflow x %d + count %d vs xlimit %d (y %d)\n",
971 (int)x, count, (int)xlimit, (int)y));
975 /* fill in the line */
976 for (i = 0; i < count; i += 2)
977 line[i] = packed[1] >> 4;
978 for (i = 1; i < count; i += 2)
979 line[i] = packed[1] & 0x0F;
980 i_ppal(im, x, x+count, y, line);
984 case BMPRLE_ENDOFLINE:
989 case BMPRLE_ENDOFBMP:
995 if (i_io_read(ig, packed, 2) != 2) {
998 if (allow_incomplete) {
999 i_tags_setn(&im->tags, "i_incomplete", 1);
1000 i_tags_setn(&im->tags, "i_lines_read", abs(y - starty));
1004 i_push_error(0, "missing data during decompression");
1010 y += yinc * packed[1];
1015 if (x + count > xlimit) {
1016 /* this file is corrupt */
1019 i_push_error(0, "invalid data during decompression");
1020 mm_log((1, "read 4-bit: scanline overflow (unpacked) x %d + count %d vs xlimit %d (y %d)\n",
1021 (int)x, count, (int)xlimit, (int)y));
1025 size = (count + 1) / 2;
1026 read_size = (size+1) / 2 * 2;
1027 if (i_io_read(ig, packed, read_size) != read_size) {
1030 if (allow_incomplete) {
1031 i_tags_setn(&im->tags, "i_incomplete", 1);
1032 i_tags_setn(&im->tags, "i_lines_read", abs(y - starty));
1036 i_push_error(0, "missing data during decompression");
1041 for (i = 0; i < size; ++i) {
1042 line[0] = packed[i] >> 4;
1043 line[1] = packed[i] & 0xF;
1044 i_ppal(im, x, x+2, y, line);
1052 else { /*if (compression == BI_RLE4) {*/
1055 i_push_errorf(0, "unknown 4-bit BMP compression (%d)", compression);
1064 =item read_8bit_bmp(ig, xsize, ysize, clr_used, compression, allow_incomplete)
1066 Reads in the palette and image data for a 8-bit/pixel image.
1068 Returns the image or NULL.
1073 read_8bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
1074 int compression, long offbits, int allow_incomplete) {
1076 int x, y, lasty, yinc, start_y;
1078 int line_size = xsize;
1081 line_size = (line_size+3) / 4 * 4;
1082 if (line_size < xsize) { /* if it overflowed (unlikely, but check) */
1083 i_push_error(0, "integer overflow during memory allocation");
1093 /* when ysize is -ve it's a top-down image */
1102 if (clr_used > 256 || clr_used < 0) {
1103 i_push_errorf(0, "out of range colors used (%d)", clr_used);
1107 base_offset = FILEHEAD_SIZE + INFOHEAD_SIZE + clr_used * 4;
1108 if (offbits < base_offset) {
1109 i_push_errorf(0, "image data offset too small (%ld)", offbits);
1113 im = i_img_pal_new(xsize, ysize, 3, 256);
1116 if (!read_bmp_pal(ig, im, clr_used)) {
1121 if (offbits > base_offset) {
1122 /* this will be slow if the offset is large, but that should be
1125 while (base_offset < offbits) {
1126 if (i_io_read(ig, &buffer, 1) != 1) {
1128 i_push_error(0, "failed skipping to image data offset");
1135 line = mymalloc(line_size); /* checked 29jun05 tonyc */
1136 if (compression == BI_RGB) {
1137 i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RGB", -1, 0);
1138 while (y != lasty) {
1139 if (i_io_read(ig, line, line_size) != line_size) {
1141 if (allow_incomplete) {
1142 i_tags_setn(&im->tags, "i_incomplete", 1);
1143 i_tags_setn(&im->tags, "i_lines_read", abs(start_y - y));
1147 i_push_error(0, "failed reading 8-bit bmp data");
1152 i_ppal(im, 0, xsize, y, line);
1157 else if (compression == BI_RLE8) {
1160 unsigned char packed[2];
1162 i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RLE8", -1, 0);
1165 /* there's always at least 2 bytes in a sequence */
1166 if (i_io_read(ig, packed, 2) != 2) {
1168 if (allow_incomplete) {
1169 i_tags_setn(&im->tags, "i_incomplete", 1);
1170 i_tags_setn(&im->tags, "i_lines_read", abs(start_y-y));
1174 i_push_error(0, "missing data during decompression");
1180 if (x + packed[0] > xsize) {
1181 /* this file isn't incomplete, it's corrupt */
1183 i_push_error(0, "invalid data during decompression");
1187 memset(line, packed[1], packed[0]);
1188 i_ppal(im, x, x+packed[0], y, line);
1191 switch (packed[1]) {
1192 case BMPRLE_ENDOFLINE:
1197 case BMPRLE_ENDOFBMP:
1202 if (i_io_read(ig, packed, 2) != 2) {
1204 if (allow_incomplete) {
1205 i_tags_setn(&im->tags, "i_incomplete", 1);
1206 i_tags_setn(&im->tags, "i_lines_read", abs(start_y-y));
1210 i_push_error(0, "missing data during decompression");
1216 y += yinc * packed[1];
1221 if (x + count > xsize) {
1222 /* runs shouldn't cross a line boundary */
1223 /* this file isn't incomplete, it's corrupt */
1225 i_push_error(0, "invalid data during decompression");
1229 read_size = (count+1) / 2 * 2;
1230 if (i_io_read(ig, line, read_size) != read_size) {
1232 if (allow_incomplete) {
1233 i_tags_setn(&im->tags, "i_incomplete", 1);
1234 i_tags_setn(&im->tags, "i_lines_read", abs(start_y-y));
1238 i_push_error(0, "missing data during decompression");
1243 i_ppal(im, x, x+count, y, line);
1252 i_push_errorf(0, "unknown 8-bit BMP compression (%d)", compression);
1265 static struct bm_masks std_masks[] =
1268 { 0076000, 00001740, 00000037, },
1273 { 0xFF0000, 0x00FF00, 0x0000FF, },
1278 { 0xFF0000, 0x00FF00, 0x0000FF, },
1284 /* multiplier and shift for converting from N bits to 8 bits */
1285 struct bm_sampconverts {
1289 static struct bm_sampconverts samp_converts[] = {
1290 { 0xff, 0 }, /* 1 bit samples */
1296 { 0x81, 6 } /* 7 bit samples */
1300 =item read_direct_bmp(ig, xsize, ysize, bit_count, clr_used, compression, allow_incomplete)
1302 Skips the palette and reads in the image data for a direct colour image.
1304 Returns the image or NULL.
1309 read_direct_bmp(io_glue *ig, int xsize, int ysize, int bit_count,
1310 int clr_used, int compression, long offbits,
1311 int allow_incomplete) {
1313 int x, y, starty, lasty, yinc;
1315 int pix_size = bit_count / 8;
1316 int line_size = xsize * pix_size;
1317 struct bm_masks masks;
1318 char unpack_code[2] = "";
1322 const char *compression_name;
1324 long base_offset = FILEHEAD_SIZE + INFOHEAD_SIZE;
1326 unpack_code[0] = *("v3V"+pix_size-2);
1327 unpack_code[1] = '\0';
1329 line_size = (line_size+3) / 4 * 4;
1330 extras = line_size - xsize * pix_size;
1338 /* when ysize is -ve it's a top-down image */
1345 if (compression == BI_RGB) {
1346 compression_name = "BI_RGB";
1347 masks = std_masks[pix_size-2];
1349 /* there's a potential "palette" after the header */
1350 for (i = 0; i < clr_used; ++clr_used) {
1352 if (i_io_read(ig, buf, 4) != 4) {
1353 i_push_error(0, "skipping colors");
1359 else if (compression == BI_BITFIELDS) {
1362 compression_name = "BI_BITFIELDS";
1364 for (i = 0; i < 3; ++i) {
1366 if (!read_packed(ig, "V", &rmask)) {
1367 i_push_error(0, "reading pixel masks");
1371 i_push_errorf(0, "Zero mask for channel %d", i);
1374 masks.masks[i] = rmask;
1375 /* work out a shift for the mask */
1377 bits = masks.masks[i];
1378 while (!(bits & 1)) {
1382 masks.shifts[i] = pos;
1388 masks.bits[i] = pos;
1389 /*fprintf(stderr, "%d: mask %08x shift %d bits %d\n", i, masks.masks[i], masks.shifts[i], masks.bits[i]);*/
1391 /* account for the masks */
1392 base_offset += 3 * 4;
1395 i_push_errorf(0, "unknown 24-bit BMP compression (%d)", compression);
1399 if (offbits < base_offset) {
1400 i_push_errorf(0, "image data offset too small (%ld)", offbits);
1404 if (offbits > base_offset) {
1405 /* this will be slow if the offset is large, but that should be
1408 while (base_offset < offbits) {
1409 if (i_io_read(ig, &buffer, 1) != 1) {
1410 i_push_error(0, "failed skipping to image data offset");
1417 im = i_img_empty(NULL, xsize, ysize);
1421 i_tags_add(&im->tags, "bmp_compression_name", 0, compression_name, -1, 0);
1423 /* I wasn't able to make this overflow in testing, but better to be
1425 bytes = sizeof(i_color) * xsize;
1426 if (bytes / sizeof(i_color) != xsize) {
1428 i_push_error(0, "integer overflow calculating buffer size");
1431 line = mymalloc(bytes); /* checked 29jun05 tonyc */
1432 while (y != lasty) {
1434 for (x = 0; x < xsize; ++x) {
1436 if (!read_packed(ig, unpack_code, &pixel)) {
1438 if (allow_incomplete) {
1439 i_tags_setn(&im->tags, "i_incomplete", 1);
1440 i_tags_setn(&im->tags, "i_lines_read", abs(starty - y));
1444 i_push_error(0, "failed reading image data");
1449 for (i = 0; i < 3; ++i) {
1450 int sample = (pixel & masks.masks[i]) >> masks.shifts[i];
1451 int bits = masks.bits[i];
1453 sample = (sample * samp_converts[bits-1].mult) >> samp_converts[bits-1].shift;
1456 sample >>= bits - 8;
1458 p->channel[i] = sample;
1462 i_plin(im, 0, xsize, y, line);
1464 i_io_read(ig, junk, extras);
1479 Tony Cook <tony@develop-help.com>
1483 Cannot save as compressed BMP.
1487 Doesn't handle OS/2 bitmaps.
1489 16-bit/pixel images haven't been tested. (I need an image).
1491 BI_BITFIELDS compression hasn't been tested (I need an image).
1493 The header handling for paletted images needs to be refactored