odd run lengths for BI_RLE4 compressed BMP files were handled incorrectly
[imager.git] / bmp.c
CommitLineData
261f91c5 1#include <stdarg.h>
92bda632 2#include "imageri.h"
261f91c5 3
705fd961
TC
4/*
5=head1 NAME
261f91c5 6
705fd961
TC
7bmp.c - read and write windows BMP files
8
9=head1 SYNOPSIS
10
11 i_img *im;
12 io_glue *ig;
13
14 if (!i_writebmp_wiol(im, ig)) {
15 ... error ...
16 }
17 im = i_readbmp(ig);
18
19=head1 DESCRIPTION
20
21Reads and writes Windows BMP files.
22
23=over
24
25=cut
26*/
27
28#define FILEHEAD_SIZE 14
29#define INFOHEAD_SIZE 40
30#define BI_RGB 0
31#define BI_RLE8 1
32#define BI_RLE4 2
33#define BI_BITFIELDS 3
34#define BMPRLE_ENDOFLINE 0
35#define BMPRLE_ENDOFBMP 1
36#define BMPRLE_DELTA 2
37
8d14daab
TC
38#define SIGNBIT32 ((i_upacked_t)1U << 31)
39#define SIGNBIT16 ((i_upacked_t)1U << 15)
40
41#define SIGNMAX32 ((1UL << 31) - 1)
42
705fd961
TC
43static int read_packed(io_glue *ig, char *format, ...);
44static int write_packed(io_glue *ig, char *format, ...);
45static int write_bmphead(io_glue *ig, i_img *im, int bit_count,
46 int data_size);
47static int write_1bit_data(io_glue *ig, i_img *im);
48static int write_4bit_data(io_glue *ig, i_img *im);
49static int write_8bit_data(io_glue *ig, i_img *im);
50static int write_24bit_data(io_glue *ig, i_img *im);
51static int read_bmp_pal(io_glue *ig, i_img *im, int count);
662e3c02 52static i_img *read_1bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
d87dc9a4 53 int compression, long offbits, int allow_incomplete);
705fd961 54static i_img *read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
d87dc9a4 55 int compression, long offbits, int allow_incomplete);
705fd961 56static i_img *read_8bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
d87dc9a4 57 int compression, long offbits, int allow_incomplete);
705fd961 58static i_img *read_direct_bmp(io_glue *ig, int xsize, int ysize,
403946c6 59 int bit_count, int clr_used, int compression,
d87dc9a4 60 long offbits, int allow_incomplete);
705fd961 61
8d14daab
TC
62/* used for the read_packed() and write_packed() functions, an integer
63 * type */
64typedef long i_packed_t;
65typedef unsigned long i_upacked_t;
66
705fd961
TC
67/*
68=item i_writebmp_wiol(im, io_glue)
69
70Writes the image as a BMP file. Uses 1-bit, 4-bit, 8-bit or 24-bit
71formats depending on the image.
72
73Never compresses the image.
74
75=cut
76*/
77int
78i_writebmp_wiol(i_img *im, io_glue *ig) {
705fd961
TC
79 i_clear_error();
80
81 /* pick a format */
82 if (im->type == i_direct_type) {
83 return write_24bit_data(ig, im);
84 }
85 else {
86 int pal_size;
87
88 /* must be paletted */
89 pal_size = i_colorcount(im);
90 if (pal_size <= 2) {
91 return write_1bit_data(ig, im);
92 }
93 else if (pal_size <= 16) {
94 return write_4bit_data(ig, im);
95 }
96 else {
97 return write_8bit_data(ig, im);
98 }
99 }
100}
101
102/*
103=item i_readbmp_wiol(ig)
104
105Reads a Windows format bitmap from the given file.
106
107Handles BI_RLE4 and BI_RLE8 compressed images. Attempts to handle
108BI_BITFIELDS images too, but I need a test image.
109
110=cut
111*/
112
113i_img *
d87dc9a4 114i_readbmp_wiol(io_glue *ig, int allow_incomplete) {
8d14daab
TC
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;
705fd961 118 i_img *im;
662e3c02
TC
119
120 mm_log((1, "i_readbmp_wiol(ig %p)\n", ig));
705fd961 121
705fd961
TC
122 i_clear_error();
123
8d14daab 124 if (!read_packed(ig, "CCVvvVVV!V!vvVVVVVV", &b_magic, &m_magic, &filesize,
662e3c02 125 &res1, &res2, &offbits, &infohead_size,
705fd961
TC
126 &xsize, &ysize, &planes,
127 &bit_count, &compression, &size_image, &xres, &yres,
128 &clr_used, &clr_important)) {
d87dc9a4 129 i_push_error(0, "file too short to be a BMP file");
705fd961
TC
130 return 0;
131 }
132 if (b_magic != 'B' || m_magic != 'M' || infohead_size != INFOHEAD_SIZE
133 || planes != 1) {
134 i_push_error(0, "not a BMP file");
135 return 0;
136 }
662e3c02
TC
137
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 "
8d14daab
TC
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));
77157728 144
ae12796a 145 if (!i_int_check_image_file_limits(xsize, abs(ysize), 3, sizeof(i_sample_t))) {
77157728
TC
146 mm_log((1, "i_readbmp_wiol: image size exceeds limits\n"));
147 return NULL;
148 }
705fd961
TC
149
150 switch (bit_count) {
151 case 1:
9c106321 152 im = read_1bit_bmp(ig, xsize, ysize, clr_used, compression, offbits,
d87dc9a4 153 allow_incomplete);
705fd961
TC
154 break;
155
156 case 4:
9c106321 157 im = read_4bit_bmp(ig, xsize, ysize, clr_used, compression, offbits,
d87dc9a4 158 allow_incomplete);
705fd961
TC
159 break;
160
161 case 8:
9c106321 162 im = read_8bit_bmp(ig, xsize, ysize, clr_used, compression, offbits,
d87dc9a4 163 allow_incomplete);
705fd961
TC
164 break;
165
166 case 32:
167 case 24:
168 case 16:
403946c6 169 im = read_direct_bmp(ig, xsize, ysize, bit_count, clr_used, compression,
d87dc9a4 170 offbits, allow_incomplete);
705fd961 171 break;
efdc2568
TC
172
173 default:
8d14daab 174 i_push_errorf(0, "unknown bit count for BMP file (%d)", (int)bit_count);
efdc2568 175 return NULL;
705fd961
TC
176 }
177
662e3c02
TC
178 if (im) {
179 /* store the resolution */
180 if (xres && !yres)
181 yres = xres;
182 else if (yres && !xres)
183 xres = yres;
184 if (xres) {
2e41e30b
TC
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);
662e3c02
TC
187 }
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);
705fd961 194 }
705fd961
TC
195
196 return im;
197}
198
199/*
200=back
201
202=head1 IMPLEMENTATION FUNCTIONS
203
204Internal functions used in the implementation.
205
206=over
207
208=item read_packed(ig, format, ...)
209
210Reads from the specified "file" the specified sizes. The format codes
211match those used by perl's pack() function, though only a few are
212implemented. In all cases the vararg arguement is an int *.
213
214Returns non-zero if all of the arguments were read.
215
216=cut
261f91c5 217*/
8d14daab
TC
218static int
219read_packed(io_glue *ig, char *format, ...) {
261f91c5
TC
220 unsigned char buf[4];
221 va_list ap;
8d14daab
TC
222 i_packed_t *p;
223 i_packed_t work;
224 int code;
225 int shrieking; /* format code has a ! flag */
261f91c5
TC
226
227 va_start(ap, format);
228
229 while (*format) {
8d14daab 230 p = va_arg(ap, i_packed_t *);
261f91c5 231
8d14daab
TC
232 code = *format++;
233 shrieking = *format == '!';
234 if (shrieking) ++format;
235
236 switch (code) {
261f91c5 237 case 'v':
6d5c85a2 238 if (i_io_read(ig, buf, 2) != 2)
261f91c5 239 return 0;
8d14daab
TC
240 work = buf[0] + ((i_packed_t)buf[1] << 8);
241 if (shrieking)
242 *p = (work ^ SIGNBIT16) - SIGNBIT16;
243 else
244 *p = work;
261f91c5
TC
245 break;
246
247 case 'V':
6d5c85a2 248 if (i_io_read(ig, buf, 4) != 4)
261f91c5 249 return 0;
8d14daab
TC
250 work = buf[0] + (buf[1] << 8) + ((i_packed_t)buf[2] << 16) + ((i_packed_t)buf[3] << 24);
251 if (shrieking)
252 *p = (work ^ SIGNBIT32) - SIGNBIT32;
253 else
254 *p = work;
261f91c5
TC
255 break;
256
257 case 'C':
6d5c85a2 258 if (i_io_read(ig, buf, 1) != 1)
261f91c5
TC
259 return 0;
260 *p = buf[0];
261 break;
262
263 case 'c':
6d5c85a2 264 if (i_io_read(ig, buf, 1) != 1)
261f91c5
TC
265 return 0;
266 *p = (char)buf[0];
267 break;
268
705fd961 269 case '3': /* extension - 24-bit number */
6d5c85a2 270 if (i_io_read(ig, buf, 3) != 3)
705fd961 271 return 0;
8d14daab 272 *p = buf[0] + (buf[1] << 8) + ((i_packed_t)buf[2] << 16);
705fd961
TC
273 break;
274
261f91c5 275 default:
8d14daab 276 i_fatal(1, "Unknown read_packed format code 0x%02x", code);
261f91c5 277 }
261f91c5
TC
278 }
279 return 1;
280}
281
705fd961
TC
282/*
283=item write_packed(ig, format, ...)
284
285Writes packed data to the specified io_glue.
286
287Returns non-zero on success.
288
289=cut
290*/
291
261f91c5
TC
292static int
293write_packed(io_glue *ig, char *format, ...) {
294 unsigned char buf[4];
295 va_list ap;
296 int i;
297
298 va_start(ap, format);
299
300 while (*format) {
8d14daab 301 i = va_arg(ap, i_upacked_t);
261f91c5
TC
302
303 switch (*format) {
304 case 'v':
305 buf[0] = i & 255;
306 buf[1] = i / 256;
6d5c85a2 307 if (i_io_write(ig, buf, 2) == -1)
261f91c5
TC
308 return 0;
309 break;
310
311 case 'V':
312 buf[0] = i & 0xFF;
313 buf[1] = (i >> 8) & 0xFF;
314 buf[2] = (i >> 16) & 0xFF;
315 buf[3] = (i >> 24) & 0xFF;
6d5c85a2 316 if (i_io_write(ig, buf, 4) == -1)
261f91c5
TC
317 return 0;
318 break;
319
320 case 'C':
321 case 'c':
322 buf[0] = i & 0xFF;
6d5c85a2 323 if (i_io_write(ig, buf, 1) == -1)
261f91c5
TC
324 return 0;
325 break;
326
327 default:
b1e96952 328 i_fatal(1, "Unknown write_packed format code 0x%02x", *format);
261f91c5
TC
329 }
330 ++format;
331 }
332 va_end(ap);
333
334 return 1;
335}
336
705fd961
TC
337/*
338=item write_bmphead(ig, im, bit_count, data_size)
339
340Writes a Windows BMP header to the file.
341
342Returns non-zero on success.
343
344=cut
345*/
261f91c5
TC
346
347static
348int write_bmphead(io_glue *ig, i_img *im, int bit_count, int data_size) {
349 double xres, yres;
350 int got_xres, got_yres, aspect_only;
351 int colors_used = 0;
352 int offset = FILEHEAD_SIZE + INFOHEAD_SIZE;
353
8d14daab
TC
354 if (im->xsize > SIGNMAX32 || im->ysize > SIGNMAX32) {
355 i_push_error(0, "image too large to write to BMP");
356 return 0;
357 }
358
261f91c5
TC
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))
362 aspect_only = 0;
363 if (!got_xres) {
364 if (!got_yres)
365 xres = yres = 72;
366 else
367 xres = yres;
368 }
369 else {
370 if (!got_yres)
371 yres = xres;
372 }
373 if (xres <= 0 || yres <= 0)
374 xres = yres = 72;
375 if (aspect_only) {
376 /* scale so the smaller value is 72 */
377 double ratio;
378 if (xres < yres) {
379 ratio = 72.0 / xres;
380 }
381 else {
382 ratio = 72.0 / yres;
383 }
384 xres *= ratio;
385 yres *= ratio;
386 }
387 /* now to pels/meter */
388 xres *= 100.0/2.54;
389 yres *= 100.0/2.54;
390
391 if (im->type == i_palette_type) {
392 colors_used = i_colorcount(im);
393 offset += 4 * colors_used;
394 }
395
8d14daab
TC
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)){
261f91c5
TC
405 i_push_error(0, "cannot write bmp header");
406 return 0;
407 }
408 if (im->type == i_palette_type) {
409 int i;
410 i_color c;
411
412 for (i = 0; i < colors_used; ++i) {
413 i_getcolors(im, i, &c, 1);
414 if (im->channels >= 3) {
8d14daab
TC
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)) {
261f91c5
TC
418 i_push_error(0, "cannot write palette entry");
419 return 0;
420 }
421 }
422 else {
8d14daab
TC
423 i_upacked_t v = c.channel[0];
424 if (!write_packed(ig, "CCCC", v, v, v, 0)) {
261f91c5
TC
425 i_push_error(0, "cannot write palette entry");
426 return 0;
427 }
428 }
429 }
430 }
431
432 return 1;
433}
434
705fd961
TC
435/*
436=item write_1bit_data(ig, im)
437
438Writes the image data as a 1-bit/pixel image.
439
440Returns non-zero on success.
441
442=cut
443*/
261f91c5
TC
444static int
445write_1bit_data(io_glue *ig, i_img *im) {
446 i_palidx *line;
447 unsigned char *packed;
448 int byte;
449 int mask;
450 unsigned char *out;
451 int line_size = (im->xsize+7) / 8;
452 int x, y;
f0960b14 453 int unpacked_size;
261f91c5
TC
454
455 /* round up to nearest multiple of four */
456 line_size = (line_size + 3) / 4 * 4;
457
458 if (!write_bmphead(ig, im, 1, line_size * im->ysize))
459 return 0;
460
f0960b14
TC
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");
465 return 0;
466 }
467 line = mymalloc(unpacked_size); /* checked 29jun05 tonyc */
261f91c5 468 memset(line + im->xsize, 0, 8);
f0960b14
TC
469
470 /* size allocated here is always much smaller than xsize, hence
471 can't overflow int */
472 packed = mymalloc(line_size); /* checked 29jun05 tonyc */
261f91c5
TC
473 memset(packed, 0, line_size);
474
475 for (y = im->ysize-1; y >= 0; --y) {
476 i_gpal(im, 0, im->xsize, y, line);
477 mask = 0x80;
478 byte = 0;
479 out = packed;
480 for (x = 0; x < im->xsize; ++x) {
481 if (line[x])
482 byte |= mask;
483 if ((mask >>= 1) == 0) {
484 *out++ = byte;
485 byte = 0;
486 mask = 0x80;
487 }
488 }
489 if (mask != 0x80) {
490 *out++ = byte;
491 }
6d5c85a2 492 if (i_io_write(ig, packed, line_size) < 0) {
261f91c5
TC
493 myfree(packed);
494 myfree(line);
495 i_push_error(0, "writing 1 bit/pixel packed data");
496 return 0;
497 }
498 }
499 myfree(packed);
500 myfree(line);
501
6d5c85a2
TC
502 if (i_io_close(ig))
503 return 0;
10461f9a 504
261f91c5
TC
505 return 1;
506}
507
705fd961
TC
508/*
509=item write_4bit_data(ig, im)
510
511Writes the image data as a 4-bit/pixel image.
512
513Returns non-zero on success.
514
515=cut
516*/
261f91c5
TC
517static int
518write_4bit_data(io_glue *ig, i_img *im) {
519 i_palidx *line;
520 unsigned char *packed;
521 unsigned char *out;
522 int line_size = (im->xsize+1) / 2;
523 int x, y;
f0960b14 524 int unpacked_size;
261f91c5
TC
525
526 /* round up to nearest multiple of four */
527 line_size = (line_size + 3) / 4 * 4;
528
529 if (!write_bmphead(ig, im, 4, line_size * im->ysize))
530 return 0;
531
f0960b14
TC
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");
536 return 0;
537 }
538 line = mymalloc(unpacked_size); /* checked 29jun05 tonyc */
261f91c5
TC
539 memset(line + im->xsize, 0, 2);
540
f0960b14
TC
541 /* size allocated here is always much smaller than xsize, hence
542 can't overflow int */
543 packed = mymalloc(line_size); /* checked 29jun05 tonyc */
261f91c5
TC
544 memset(packed, 0, line_size);
545
546 for (y = im->ysize-1; y >= 0; --y) {
547 i_gpal(im, 0, im->xsize, y, line);
548 out = packed;
549 for (x = 0; x < im->xsize; x += 2) {
550 *out++ = (line[x] << 4) + line[x+1];
551 }
6d5c85a2 552 if (i_io_write(ig, packed, line_size) < 0) {
261f91c5
TC
553 myfree(packed);
554 myfree(line);
555 i_push_error(0, "writing 4 bit/pixel packed data");
556 return 0;
557 }
558 }
559 myfree(packed);
560 myfree(line);
561
6d5c85a2
TC
562 if (i_io_close(ig))
563 return 0;
10461f9a 564
261f91c5
TC
565 return 1;
566}
567
705fd961
TC
568/*
569=item write_8bit_data(ig, im)
570
571Writes the image data as a 8-bit/pixel image.
572
573Returns non-zero on success.
574
575=cut
576*/
261f91c5
TC
577static int
578write_8bit_data(io_glue *ig, i_img *im) {
579 i_palidx *line;
580 int line_size = im->xsize;
a659442a 581 int y;
f0960b14 582 int unpacked_size;
261f91c5
TC
583
584 /* round up to nearest multiple of four */
585 line_size = (line_size + 3) / 4 * 4;
586
587 if (!write_bmphead(ig, im, 8, line_size * im->ysize))
588 return 0;
589
f0960b14
TC
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");
594 return 0;
595 }
596 line = mymalloc(unpacked_size); /* checked 29jun05 tonyc */
261f91c5
TC
597 memset(line + im->xsize, 0, 4);
598
599 for (y = im->ysize-1; y >= 0; --y) {
600 i_gpal(im, 0, im->xsize, y, line);
6d5c85a2 601 if (i_io_write(ig, line, line_size) < 0) {
261f91c5
TC
602 myfree(line);
603 i_push_error(0, "writing 8 bit/pixel packed data");
604 return 0;
605 }
606 }
607 myfree(line);
608
6d5c85a2
TC
609 if (i_io_close(ig))
610 return 0;
10461f9a 611
261f91c5
TC
612 return 1;
613}
614
705fd961
TC
615/*
616=item write_24bit_data(ig, im)
617
618Writes the image data as a 24-bit/pixel image.
619
620Returns non-zero on success.
621
622=cut
623*/
261f91c5
TC
624static int
625write_24bit_data(io_glue *ig, i_img *im) {
261f91c5 626 unsigned char *samples;
a659442a 627 int y;
261f91c5 628 int line_size = 3 * im->xsize;
07d9c639
TC
629 i_color bg;
630
631 i_get_file_background(im, &bg);
f0960b14
TC
632
633 /* just in case we implement a direct format with 2bytes/pixel
634 (unlikely though) */
635 if (line_size / 3 != im->xsize) {
636 i_push_error(0, "integer overflow during memory allocation");
637 return 0;
638 }
261f91c5
TC
639
640 line_size = (line_size + 3) / 4 * 4;
641
642 if (!write_bmphead(ig, im, 24, line_size * im->ysize))
643 return 0;
07d9c639 644 samples = mymalloc(4 * im->xsize);
10461f9a 645 memset(samples, 0, line_size);
261f91c5 646 for (y = im->ysize-1; y >= 0; --y) {
07d9c639
TC
647 unsigned char *samplep = samples;
648 int x;
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];
653 samplep[0] = tmp;
654 samplep += 3;
655 }
6d5c85a2 656 if (i_io_write(ig, samples, line_size) < 0) {
261f91c5
TC
657 i_push_error(0, "writing image data");
658 myfree(samples);
659 return 0;
660 }
661 }
662 myfree(samples);
663
6d5c85a2
TC
664 if (i_io_close(ig))
665 return 0;
10461f9a 666
261f91c5
TC
667 return 1;
668}
669
705fd961
TC
670/*
671=item read_bmp_pal(ig, im, count)
261f91c5 672
705fd961 673Reads count palette entries from the file and add them to the image.
261f91c5 674
705fd961 675Returns non-zero on success.
261f91c5 676
705fd961
TC
677=cut
678*/
261f91c5
TC
679static int
680read_bmp_pal(io_glue *ig, i_img *im, int count) {
681 int i;
8d14daab 682 i_packed_t r, g, b, x;
261f91c5
TC
683 i_color c;
684
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");
688 return 0;
689 }
690 c.channel[0] = r;
691 c.channel[1] = g;
692 c.channel[2] = b;
662e3c02
TC
693 if (i_addcolors(im, &c, 1) < 0) {
694 i_push_error(0, "out of space in image palette");
261f91c5 695 return 0;
662e3c02 696 }
261f91c5
TC
697 }
698
699 return 1;
700}
701
705fd961 702/*
403946c6 703=item read_1bit_bmp(ig, xsize, ysize, clr_used, compression, offbits)
705fd961
TC
704
705Reads in the palette and image data for a 1-bit/pixel image.
706
707Returns the image or NULL.
708
709=cut
710*/
261f91c5 711static i_img *
662e3c02 712read_1bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
d87dc9a4 713 int compression, long offbits, int allow_incomplete) {
261f91c5 714 i_img *im;
9c106321 715 int x, y, lasty, yinc, start_y;
261f91c5
TC
716 i_palidx *line, *p;
717 unsigned char *packed;
718 int line_size = (xsize + 7)/8;
a659442a 719 int bit;
261f91c5 720 unsigned char *in;
403946c6 721 long base_offset;
261f91c5 722
662e3c02
TC
723 if (compression != BI_RGB) {
724 i_push_errorf(0, "unknown 1-bit BMP compression (%d)", compression);
725 return NULL;
726 }
727
f0960b14
TC
728 if (xsize + 8 < xsize) { /* if there was overflow */
729 /* we check with 8 because we allocate that much for the decoded
730 line buffer */
731 i_push_error(0, "integer overflow during memory allocation");
732 return NULL;
733 }
734
735 /* if xsize+7 is ok then (xsize+7)/8 will be and the minor
736 adjustments below won't make it overflow */
261f91c5
TC
737 line_size = (line_size+3) / 4 * 4;
738
739 if (ysize > 0) {
9c106321 740 start_y = ysize-1;
261f91c5
TC
741 lasty = -1;
742 yinc = -1;
743 }
744 else {
745 /* when ysize is -ve it's a top-down image */
746 ysize = -ysize;
9c106321 747 start_y = 0;
261f91c5
TC
748 lasty = ysize;
749 yinc = 1;
750 }
9c106321 751 y = start_y;
705fd961
TC
752 if (!clr_used)
753 clr_used = 2;
662e3c02
TC
754 if (clr_used < 0 || clr_used > 2) {
755 i_push_errorf(0, "out of range colors used (%d)", clr_used);
756 return NULL;
757 }
403946c6
TC
758
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);
762 return NULL;
763 }
764
662e3c02
TC
765 im = i_img_pal_new(xsize, ysize, 3, 256);
766 if (!im)
767 return NULL;
261f91c5
TC
768 if (!read_bmp_pal(ig, im, clr_used)) {
769 i_img_destroy(im);
770 return NULL;
771 }
403946c6
TC
772
773 if (offbits > base_offset) {
774 /* this will be slow if the offset is large, but that should be
775 rare */
776 char buffer;
777 while (base_offset < offbits) {
6d5c85a2 778 if (i_io_read(ig, &buffer, 1) != 1) {
403946c6
TC
779 i_img_destroy(im);
780 i_push_error(0, "failed skipping to image data offset");
781 return NULL;
782 }
783 ++base_offset;
784 }
785 }
662e3c02
TC
786
787 i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RGB", -1, 0);
261f91c5 788
f0960b14
TC
789 packed = mymalloc(line_size); /* checked 29jun05 tonyc */
790 line = mymalloc(xsize+8); /* checked 29jun05 tonyc */
261f91c5 791 while (y != lasty) {
6d5c85a2 792 if (i_io_read(ig, packed, line_size) != line_size) {
261f91c5
TC
793 myfree(packed);
794 myfree(line);
d87dc9a4 795 if (allow_incomplete) {
9c106321
TC
796 i_tags_setn(&im->tags, "i_incomplete", 1);
797 i_tags_setn(&im->tags, "i_lines_read", abs(start_y - y));
798 return im;
799 }
800 else {
801 i_push_error(0, "failed reading 1-bit bmp data");
802 i_img_destroy(im);
803 return NULL;
804 }
261f91c5
TC
805 }
806 in = packed;
807 bit = 0x80;
808 p = line;
809 for (x = 0; x < xsize; ++x) {
810 *p++ = (*in & bit) ? 1 : 0;
811 bit >>= 1;
812 if (!bit) {
813 ++in;
814 bit = 0x80;
815 }
816 }
817 i_ppal(im, 0, xsize, y, line);
818 y += yinc;
819 }
820
4b0f812c
AMH
821 myfree(packed);
822 myfree(line);
261f91c5
TC
823 return im;
824}
261f91c5 825
705fd961
TC
826/*
827=item read_4bit_bmp(ig, xsize, ysize, clr_used, compression)
828
829Reads in the palette and image data for a 4-bit/pixel image.
830
831Returns the image or NULL.
832
833Hopefully this will be combined with the following function at some
834point.
835
836=cut
837*/
261f91c5 838static i_img *
705fd961 839read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
d87dc9a4 840 int compression, long offbits, int allow_incomplete) {
261f91c5
TC
841 i_img *im;
842 int x, y, lasty, yinc;
843 i_palidx *line, *p;
844 unsigned char *packed;
845 int line_size = (xsize + 1)/2;
846 unsigned char *in;
705fd961 847 int size, i;
403946c6 848 long base_offset;
9c106321 849 int starty;
261f91c5 850
f0960b14
TC
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 */
261f91c5
TC
853 line_size = (line_size+3) / 4 * 4;
854
855 if (ysize > 0) {
9c106321 856 starty = ysize-1;
261f91c5
TC
857 lasty = -1;
858 yinc = -1;
859 }
860 else {
861 /* when ysize is -ve it's a top-down image */
862 ysize = -ysize;
9c106321 863 starty = 0;
261f91c5
TC
864 lasty = ysize;
865 yinc = 1;
866 }
9c106321 867 y = starty;
705fd961
TC
868 if (!clr_used)
869 clr_used = 16;
662e3c02
TC
870
871 if (clr_used > 16 || clr_used < 0) {
872 i_push_errorf(0, "out of range colors used (%d)", clr_used);
873 return NULL;
874 }
875
403946c6
TC
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);
879 return NULL;
880 }
881
662e3c02
TC
882 im = i_img_pal_new(xsize, ysize, 3, 256);
883 if (!im) /* error should have been pushed already */
884 return NULL;
261f91c5
TC
885 if (!read_bmp_pal(ig, im, clr_used)) {
886 i_img_destroy(im);
887 return NULL;
888 }
889
403946c6
TC
890 if (offbits > base_offset) {
891 /* this will be slow if the offset is large, but that should be
892 rare */
893 char buffer;
894 while (base_offset < offbits) {
6d5c85a2 895 if (i_io_read(ig, &buffer, 1) != 1) {
403946c6
TC
896 i_img_destroy(im);
897 i_push_error(0, "failed skipping to image data offset");
898 return NULL;
899 }
900 ++base_offset;
901 }
902 }
903
705fd961 904 if (line_size < 260)
f0960b14 905 packed = mymalloc(260); /* checked 29jun05 tonyc */
705fd961 906 else
f0960b14
TC
907 packed = mymalloc(line_size); /* checked 29jun05 tonyc */
908 /* xsize won't approach MAXINT */
909 line = mymalloc(xsize+1); /* checked 29jun05 tonyc */
261f91c5 910 if (compression == BI_RGB) {
662e3c02 911 i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RGB", -1, 0);
261f91c5 912 while (y != lasty) {
6d5c85a2 913 if (i_io_read(ig, packed, line_size) != line_size) {
261f91c5
TC
914 myfree(packed);
915 myfree(line);
d87dc9a4 916 if (allow_incomplete) {
9c106321
TC
917 i_tags_setn(&im->tags, "i_incomplete", 1);
918 i_tags_setn(&im->tags, "i_lines_read", abs(y - starty));
919 return im;
920 }
921 else {
922 i_push_error(0, "failed reading 4-bit bmp data");
923 i_img_destroy(im);
924 return NULL;
925 }
261f91c5
TC
926 }
927 in = packed;
928 p = line;
929 for (x = 0; x < xsize; x+=2) {
930 *p++ = *in >> 4;
931 *p++ = *in & 0x0F;
932 ++in;
933 }
934 i_ppal(im, 0, xsize, y, line);
935 y += yinc;
936 }
4b0f812c
AMH
937 myfree(packed);
938 myfree(line);
261f91c5
TC
939 }
940 else if (compression == BI_RLE4) {
705fd961 941 int read_size;
705fd961 942 int count;
5e3e4fa6 943 i_img_dim xlimit = (xsize + 1) / 2 * 2; /* rounded up */
705fd961 944
662e3c02 945 i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RLE4", -1, 0);
705fd961
TC
946 x = 0;
947 while (1) {
948 /* there's always at least 2 bytes in a sequence */
6d5c85a2 949 if (i_io_read(ig, packed, 2) != 2) {
705fd961
TC
950 myfree(packed);
951 myfree(line);
d87dc9a4 952 if (allow_incomplete) {
9c106321
TC
953 i_tags_setn(&im->tags, "i_incomplete", 1);
954 i_tags_setn(&im->tags, "i_lines_read", abs(y - starty));
955 return im;
956 }
957 else {
958 i_push_error(0, "missing data during decompression");
959 i_img_destroy(im);
960 return NULL;
961 }
705fd961
TC
962 }
963 else if (packed[0]) {
4be2df8a 964 int count = packed[0];
5e3e4fa6 965 if (x + count > xlimit) {
bb5712de 966 /* this file is corrupt */
02576e8d 967 myfree(packed);
bb5712de
TC
968 myfree(line);
969 i_push_error(0, "invalid data during decompression");
77dc32e0
TC
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));
bb5712de
TC
972 i_img_destroy(im);
973 return NULL;
974 }
77dc32e0
TC
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);
981 x += count;
705fd961
TC
982 } else {
983 switch (packed[1]) {
984 case BMPRLE_ENDOFLINE:
985 x = 0;
986 y += yinc;
987 break;
988
989 case BMPRLE_ENDOFBMP:
4dfa5522
AMH
990 myfree(packed);
991 myfree(line);
705fd961
TC
992 return im;
993
994 case BMPRLE_DELTA:
6d5c85a2 995 if (i_io_read(ig, packed, 2) != 2) {
705fd961
TC
996 myfree(packed);
997 myfree(line);
d87dc9a4 998 if (allow_incomplete) {
9c106321
TC
999 i_tags_setn(&im->tags, "i_incomplete", 1);
1000 i_tags_setn(&im->tags, "i_lines_read", abs(y - starty));
1001 return im;
1002 }
1003 else {
1004 i_push_error(0, "missing data during decompression");
1005 i_img_destroy(im);
1006 return NULL;
1007 }
705fd961
TC
1008 }
1009 x += packed[0];
1010 y += yinc * packed[1];
1011 break;
1012
1013 default:
1014 count = packed[1];
5e3e4fa6 1015 if (x + count > xlimit) {
bb5712de 1016 /* this file is corrupt */
02576e8d 1017 myfree(packed);
bb5712de
TC
1018 myfree(line);
1019 i_push_error(0, "invalid data during decompression");
77dc32e0
TC
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));
bb5712de
TC
1022 i_img_destroy(im);
1023 return NULL;
1024 }
705fd961
TC
1025 size = (count + 1) / 2;
1026 read_size = (size+1) / 2 * 2;
6d5c85a2 1027 if (i_io_read(ig, packed, read_size) != read_size) {
705fd961
TC
1028 myfree(packed);
1029 myfree(line);
d87dc9a4 1030 if (allow_incomplete) {
9c106321
TC
1031 i_tags_setn(&im->tags, "i_incomplete", 1);
1032 i_tags_setn(&im->tags, "i_lines_read", abs(y - starty));
1033 return im;
1034 }
1035 else {
1036 i_push_error(0, "missing data during decompression");
1037 i_img_destroy(im);
1038 return NULL;
1039 }
705fd961
TC
1040 }
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);
1045 x += 2;
1046 }
1047 break;
1048 }
1049 }
1050 }
1051 }
1052 else { /*if (compression == BI_RLE4) {*/
1053 myfree(packed);
1054 myfree(line);
662e3c02 1055 i_push_errorf(0, "unknown 4-bit BMP compression (%d)", compression);
705fd961
TC
1056 i_img_destroy(im);
1057 return NULL;
261f91c5
TC
1058 }
1059
1060 return im;
1061}
1062
705fd961 1063/*
d87dc9a4 1064=item read_8bit_bmp(ig, xsize, ysize, clr_used, compression, allow_incomplete)
261f91c5 1065
705fd961
TC
1066Reads in the palette and image data for a 8-bit/pixel image.
1067
1068Returns the image or NULL.
1069
1070=cut
1071*/
1072static i_img *
1073read_8bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
d87dc9a4 1074 int compression, long offbits, int allow_incomplete) {
261f91c5 1075 i_img *im;
9c106321 1076 int x, y, lasty, yinc, start_y;
a659442a 1077 i_palidx *line;
705fd961 1078 int line_size = xsize;
403946c6 1079 long base_offset;
261f91c5 1080
705fd961 1081 line_size = (line_size+3) / 4 * 4;
f0960b14
TC
1082 if (line_size < xsize) { /* if it overflowed (unlikely, but check) */
1083 i_push_error(0, "integer overflow during memory allocation");
1084 return NULL;
1085 }
705fd961
TC
1086
1087 if (ysize > 0) {
9c106321 1088 start_y = ysize-1;
705fd961
TC
1089 lasty = -1;
1090 yinc = -1;
261f91c5 1091 }
705fd961
TC
1092 else {
1093 /* when ysize is -ve it's a top-down image */
1094 ysize = -ysize;
9c106321 1095 start_y = 0;
705fd961
TC
1096 lasty = ysize;
1097 yinc = 1;
261f91c5 1098 }
9c106321 1099 y = start_y;
705fd961
TC
1100 if (!clr_used)
1101 clr_used = 256;
662e3c02
TC
1102 if (clr_used > 256 || clr_used < 0) {
1103 i_push_errorf(0, "out of range colors used (%d)", clr_used);
1104 return NULL;
1105 }
1106
403946c6
TC
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);
1110 return NULL;
1111 }
1112
662e3c02
TC
1113 im = i_img_pal_new(xsize, ysize, 3, 256);
1114 if (!im)
1115 return NULL;
705fd961
TC
1116 if (!read_bmp_pal(ig, im, clr_used)) {
1117 i_img_destroy(im);
1118 return NULL;
1119 }
1120
403946c6
TC
1121 if (offbits > base_offset) {
1122 /* this will be slow if the offset is large, but that should be
1123 rare */
1124 char buffer;
1125 while (base_offset < offbits) {
6d5c85a2 1126 if (i_io_read(ig, &buffer, 1) != 1) {
403946c6
TC
1127 i_img_destroy(im);
1128 i_push_error(0, "failed skipping to image data offset");
1129 return NULL;
1130 }
1131 ++base_offset;
1132 }
1133 }
1134
f0960b14 1135 line = mymalloc(line_size); /* checked 29jun05 tonyc */
705fd961 1136 if (compression == BI_RGB) {
662e3c02 1137 i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RGB", -1, 0);
705fd961 1138 while (y != lasty) {
6d5c85a2 1139 if (i_io_read(ig, line, line_size) != line_size) {
705fd961 1140 myfree(line);
d87dc9a4 1141 if (allow_incomplete) {
9c106321
TC
1142 i_tags_setn(&im->tags, "i_incomplete", 1);
1143 i_tags_setn(&im->tags, "i_lines_read", abs(start_y - y));
1144 return im;
1145 }
1146 else {
1147 i_push_error(0, "failed reading 8-bit bmp data");
1148 i_img_destroy(im);
1149 return NULL;
1150 }
705fd961
TC
1151 }
1152 i_ppal(im, 0, xsize, y, line);
1153 y += yinc;
1154 }
12d25826 1155 myfree(line);
705fd961
TC
1156 }
1157 else if (compression == BI_RLE8) {
1158 int read_size;
705fd961
TC
1159 int count;
1160 unsigned char packed[2];
1161
662e3c02 1162 i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RLE8", -1, 0);
705fd961
TC
1163 x = 0;
1164 while (1) {
1165 /* there's always at least 2 bytes in a sequence */
6d5c85a2 1166 if (i_io_read(ig, packed, 2) != 2) {
705fd961 1167 myfree(line);
d87dc9a4 1168 if (allow_incomplete) {
9c106321
TC
1169 i_tags_setn(&im->tags, "i_incomplete", 1);
1170 i_tags_setn(&im->tags, "i_lines_read", abs(start_y-y));
1171 return im;
1172 }
1173 else {
1174 i_push_error(0, "missing data during decompression");
1175 i_img_destroy(im);
1176 return NULL;
1177 }
705fd961
TC
1178 }
1179 if (packed[0]) {
bb5712de
TC
1180 if (x + packed[0] > xsize) {
1181 /* this file isn't incomplete, it's corrupt */
1182 myfree(line);
1183 i_push_error(0, "invalid data during decompression");
1184 i_img_destroy(im);
1185 return NULL;
1186 }
705fd961
TC
1187 memset(line, packed[1], packed[0]);
1188 i_ppal(im, x, x+packed[0], y, line);
1189 x += packed[0];
1190 } else {
1191 switch (packed[1]) {
1192 case BMPRLE_ENDOFLINE:
1193 x = 0;
1194 y += yinc;
1195 break;
1196
1197 case BMPRLE_ENDOFBMP:
4dfa5522 1198 myfree(line);
705fd961
TC
1199 return im;
1200
1201 case BMPRLE_DELTA:
6d5c85a2 1202 if (i_io_read(ig, packed, 2) != 2) {
705fd961 1203 myfree(line);
d87dc9a4 1204 if (allow_incomplete) {
9c106321
TC
1205 i_tags_setn(&im->tags, "i_incomplete", 1);
1206 i_tags_setn(&im->tags, "i_lines_read", abs(start_y-y));
1207 return im;
1208 }
1209 else {
1210 i_push_error(0, "missing data during decompression");
1211 i_img_destroy(im);
1212 return NULL;
1213 }
705fd961
TC
1214 }
1215 x += packed[0];
1216 y += yinc * packed[1];
1217 break;
1218
1219 default:
1220 count = packed[1];
bb5712de
TC
1221 if (x + count > xsize) {
1222 /* runs shouldn't cross a line boundary */
1223 /* this file isn't incomplete, it's corrupt */
1224 myfree(line);
1225 i_push_error(0, "invalid data during decompression");
1226 i_img_destroy(im);
1227 return NULL;
1228 }
705fd961 1229 read_size = (count+1) / 2 * 2;
6d5c85a2 1230 if (i_io_read(ig, line, read_size) != read_size) {
705fd961 1231 myfree(line);
d87dc9a4 1232 if (allow_incomplete) {
9c106321
TC
1233 i_tags_setn(&im->tags, "i_incomplete", 1);
1234 i_tags_setn(&im->tags, "i_lines_read", abs(start_y-y));
1235 return im;
1236 }
1237 else {
1238 i_push_error(0, "missing data during decompression");
1239 i_img_destroy(im);
1240 return NULL;
1241 }
705fd961
TC
1242 }
1243 i_ppal(im, x, x+count, y, line);
1244 x += count;
1245 break;
1246 }
1247 }
1248 }
1249 }
1250 else {
1251 myfree(line);
662e3c02 1252 i_push_errorf(0, "unknown 8-bit BMP compression (%d)", compression);
705fd961
TC
1253 i_img_destroy(im);
1254 return NULL;
1255 }
1256
1257 return im;
1258}
1259
1260struct bm_masks {
1261 unsigned masks[3];
1262 int shifts[3];
1cd4eef3 1263 int bits[3];
705fd961
TC
1264};
1265static struct bm_masks std_masks[] =
1266{
1267 { /* 16-bit */
1cd4eef3
TC
1268 { 0076000, 00001740, 00000037, },
1269 { 10, 5, 0, },
1270 { 5, 5, 5, }
705fd961
TC
1271 },
1272 { /* 24-bit */
1273 { 0xFF0000, 0x00FF00, 0x0000FF, },
1274 { 16, 8, 0, },
1cd4eef3 1275 { 8, 8, 8, },
705fd961
TC
1276 },
1277 { /* 32-bit */
1278 { 0xFF0000, 0x00FF00, 0x0000FF, },
1279 { 16, 8, 0, },
1cd4eef3 1280 { 8, 8, 8, },
705fd961
TC
1281 },
1282};
1283
1cd4eef3
TC
1284/* multiplier and shift for converting from N bits to 8 bits */
1285struct bm_sampconverts {
1286 int mult;
1287 int shift;
1288};
1289static struct bm_sampconverts samp_converts[] = {
1290 { 0xff, 0 }, /* 1 bit samples */
1291 { 0x55, 0 },
1292 { 0111, 1 },
1293 { 0x11, 0 },
1294 { 0x21, 2 },
1295 { 0x41, 4 },
1296 { 0x81, 6 } /* 7 bit samples */
1297};
1298
705fd961 1299/*
d87dc9a4 1300=item read_direct_bmp(ig, xsize, ysize, bit_count, clr_used, compression, allow_incomplete)
705fd961
TC
1301
1302Skips the palette and reads in the image data for a direct colour image.
1303
1304Returns the image or NULL.
1305
1306=cut
1307*/
1308static i_img *
1309read_direct_bmp(io_glue *ig, int xsize, int ysize, int bit_count,
9c106321 1310 int clr_used, int compression, long offbits,
d87dc9a4 1311 int allow_incomplete) {
705fd961 1312 i_img *im;
bea6bcd7 1313 int x, y, starty, lasty, yinc;
705fd961 1314 i_color *line, *p;
705fd961
TC
1315 int pix_size = bit_count / 8;
1316 int line_size = xsize * pix_size;
1317 struct bm_masks masks;
1318 char unpack_code[2] = "";
1319 int i;
1320 int extras;
1321 char junk[4];
662e3c02
TC
1322 const char *compression_name;
1323 int bytes;
403946c6 1324 long base_offset = FILEHEAD_SIZE + INFOHEAD_SIZE;
261f91c5 1325
705fd961
TC
1326 unpack_code[0] = *("v3V"+pix_size-2);
1327 unpack_code[1] = '\0';
261f91c5 1328
705fd961
TC
1329 line_size = (line_size+3) / 4 * 4;
1330 extras = line_size - xsize * pix_size;
261f91c5 1331
705fd961 1332 if (ysize > 0) {
bea6bcd7 1333 starty = ysize-1;
705fd961
TC
1334 lasty = -1;
1335 yinc = -1;
1336 }
1337 else {
1338 /* when ysize is -ve it's a top-down image */
1339 ysize = -ysize;
bea6bcd7 1340 starty = 0;
705fd961
TC
1341 lasty = ysize;
1342 yinc = 1;
1343 }
bea6bcd7 1344 y = starty;
705fd961 1345 if (compression == BI_RGB) {
662e3c02 1346 compression_name = "BI_RGB";
705fd961
TC
1347 masks = std_masks[pix_size-2];
1348
1349 /* there's a potential "palette" after the header */
1350 for (i = 0; i < clr_used; ++clr_used) {
1351 char buf[4];
6d5c85a2 1352 if (i_io_read(ig, buf, 4) != 4) {
705fd961
TC
1353 i_push_error(0, "skipping colors");
1354 return 0;
1355 }
403946c6 1356 base_offset += 4;
705fd961
TC
1357 }
1358 }
1359 else if (compression == BI_BITFIELDS) {
1cd4eef3
TC
1360 int pos;
1361 unsigned bits;
662e3c02
TC
1362 compression_name = "BI_BITFIELDS";
1363
705fd961 1364 for (i = 0; i < 3; ++i) {
8d14daab
TC
1365 i_packed_t rmask;
1366 if (!read_packed(ig, "V", &rmask)) {
705fd961
TC
1367 i_push_error(0, "reading pixel masks");
1368 return 0;
1369 }
1cd4eef3
TC
1370 if (rmask == 0) {
1371 i_push_errorf(0, "Zero mask for channel %d", i);
1372 return NULL;
1373 }
8d14daab 1374 masks.masks[i] = rmask;
705fd961
TC
1375 /* work out a shift for the mask */
1376 pos = 0;
1cd4eef3
TC
1377 bits = masks.masks[i];
1378 while (!(bits & 1)) {
705fd961 1379 ++pos;
1cd4eef3 1380 bits >>= 1;
705fd961 1381 }
1cd4eef3
TC
1382 masks.shifts[i] = pos;
1383 pos = 0;
1384 while (bits & 1) {
1385 ++pos;
1386 bits >>= 1;
1387 }
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]);*/
705fd961 1390 }
1cd4eef3
TC
1391 /* account for the masks */
1392 base_offset += 3 * 4;
705fd961 1393 }
662e3c02
TC
1394 else {
1395 i_push_errorf(0, "unknown 24-bit BMP compression (%d)", compression);
1396 return NULL;
1397 }
261f91c5 1398
ae12796a
TC
1399 if (offbits < base_offset) {
1400 i_push_errorf(0, "image data offset too small (%ld)", offbits);
1401 return NULL;
1402 }
1403
403946c6
TC
1404 if (offbits > base_offset) {
1405 /* this will be slow if the offset is large, but that should be
1406 rare */
1407 char buffer;
1408 while (base_offset < offbits) {
6d5c85a2 1409 if (i_io_read(ig, &buffer, 1) != 1) {
403946c6
TC
1410 i_push_error(0, "failed skipping to image data offset");
1411 return NULL;
1412 }
1413 ++base_offset;
1414 }
1415 }
1416
705fd961 1417 im = i_img_empty(NULL, xsize, ysize);
662e3c02
TC
1418 if (!im)
1419 return NULL;
705fd961 1420
662e3c02
TC
1421 i_tags_add(&im->tags, "bmp_compression_name", 0, compression_name, -1, 0);
1422
1423 /* I wasn't able to make this overflow in testing, but better to be
1424 safe */
1425 bytes = sizeof(i_color) * xsize;
1426 if (bytes / sizeof(i_color) != xsize) {
1427 i_img_destroy(im);
1428 i_push_error(0, "integer overflow calculating buffer size");
1429 return NULL;
1430 }
f0960b14 1431 line = mymalloc(bytes); /* checked 29jun05 tonyc */
705fd961
TC
1432 while (y != lasty) {
1433 p = line;
1434 for (x = 0; x < xsize; ++x) {
8d14daab 1435 i_packed_t pixel;
705fd961 1436 if (!read_packed(ig, unpack_code, &pixel)) {
705fd961 1437 myfree(line);
d87dc9a4 1438 if (allow_incomplete) {
9c106321 1439 i_tags_setn(&im->tags, "i_incomplete", 1);
bea6bcd7 1440 i_tags_setn(&im->tags, "i_lines_read", abs(starty - y));
9c106321
TC
1441 return im;
1442 }
1443 else {
1444 i_push_error(0, "failed reading image data");
1445 i_img_destroy(im);
1446 return NULL;
1447 }
705fd961
TC
1448 }
1449 for (i = 0; i < 3; ++i) {
1cd4eef3
TC
1450 int sample = (pixel & masks.masks[i]) >> masks.shifts[i];
1451 int bits = masks.bits[i];
1452 if (bits < 8) {
1453 sample = (sample * samp_converts[bits-1].mult) >> samp_converts[bits-1].shift;
1454 }
1455 else if (bits) {
1456 sample >>= bits - 8;
1457 }
1458 p->channel[i] = sample;
705fd961
TC
1459 }
1460 ++p;
1461 }
1462 i_plin(im, 0, xsize, y, line);
1463 if (extras)
6d5c85a2 1464 i_io_read(ig, junk, extras);
705fd961 1465 y += yinc;
261f91c5 1466 }
705fd961
TC
1467 myfree(line);
1468
1469 return im;
261f91c5 1470}
705fd961
TC
1471
1472/*
1473=head1 SEE ALSO
1474
1475Imager(3)
1476
1477=head1 AUTHOR
1478
1479Tony Cook <tony@develop-help.com>
1480
1481=head1 RESTRICTIONS
1482
1483Cannot save as compressed BMP.
1484
1485=head1 BUGS
1486
1487Doesn't handle OS/2 bitmaps.
1488
148916-bit/pixel images haven't been tested. (I need an image).
1490
1491BI_BITFIELDS compression hasn't been tested (I need an image).
1492
403946c6
TC
1493The header handling for paletted images needs to be refactored
1494
705fd961
TC
1495=cut
1496*/