report basic information to the log for one scanline overflow
[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
TC
942 int count;
943
662e3c02 944 i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RLE4", -1, 0);
705fd961
TC
945 x = 0;
946 while (1) {
947 /* there's always at least 2 bytes in a sequence */
6d5c85a2 948 if (i_io_read(ig, packed, 2) != 2) {
705fd961
TC
949 myfree(packed);
950 myfree(line);
d87dc9a4 951 if (allow_incomplete) {
9c106321
TC
952 i_tags_setn(&im->tags, "i_incomplete", 1);
953 i_tags_setn(&im->tags, "i_lines_read", abs(y - starty));
954 return im;
955 }
956 else {
957 i_push_error(0, "missing data during decompression");
958 i_img_destroy(im);
959 return NULL;
960 }
705fd961
TC
961 }
962 else if (packed[0]) {
4be2df8a
TC
963 int count = packed[0];
964 if (x + count > xsize) {
bb5712de 965 /* this file is corrupt */
02576e8d 966 myfree(packed);
bb5712de
TC
967 myfree(line);
968 i_push_error(0, "invalid data during decompression");
4be2df8a
TC
969 mm_log((1, "read 4-bit: scanline overflow x %d + count %d vs xsize %d (y %d)\n",
970 (int)x, count, (int)xsize, (int)y));
bb5712de
TC
971 i_img_destroy(im);
972 return NULL;
973 }
705fd961
TC
974 line[0] = packed[1] >> 4;
975 line[1] = packed[1] & 0x0F;
4be2df8a
TC
976 for (i = 0; i < count; i += 2) {
977 if (i < count-1)
705fd961
TC
978 i_ppal(im, x, x+2, y, line);
979 else
4be2df8a 980 i_ppal(im, x, x+(count-i), y, line);
705fd961
TC
981 x += 2;
982 }
983 } else {
984 switch (packed[1]) {
985 case BMPRLE_ENDOFLINE:
986 x = 0;
987 y += yinc;
988 break;
989
990 case BMPRLE_ENDOFBMP:
4dfa5522
AMH
991 myfree(packed);
992 myfree(line);
705fd961
TC
993 return im;
994
995 case BMPRLE_DELTA:
6d5c85a2 996 if (i_io_read(ig, packed, 2) != 2) {
705fd961
TC
997 myfree(packed);
998 myfree(line);
d87dc9a4 999 if (allow_incomplete) {
9c106321
TC
1000 i_tags_setn(&im->tags, "i_incomplete", 1);
1001 i_tags_setn(&im->tags, "i_lines_read", abs(y - starty));
1002 return im;
1003 }
1004 else {
1005 i_push_error(0, "missing data during decompression");
1006 i_img_destroy(im);
1007 return NULL;
1008 }
705fd961
TC
1009 }
1010 x += packed[0];
1011 y += yinc * packed[1];
1012 break;
1013
1014 default:
1015 count = packed[1];
bb5712de
TC
1016 if (x + count > xsize) {
1017 /* this file is corrupt */
02576e8d 1018 myfree(packed);
bb5712de
TC
1019 myfree(line);
1020 i_push_error(0, "invalid data during decompression");
1021 i_img_destroy(im);
1022 return NULL;
1023 }
705fd961
TC
1024 size = (count + 1) / 2;
1025 read_size = (size+1) / 2 * 2;
6d5c85a2 1026 if (i_io_read(ig, packed, read_size) != read_size) {
705fd961
TC
1027 myfree(packed);
1028 myfree(line);
d87dc9a4 1029 if (allow_incomplete) {
9c106321
TC
1030 i_tags_setn(&im->tags, "i_incomplete", 1);
1031 i_tags_setn(&im->tags, "i_lines_read", abs(y - starty));
1032 return im;
1033 }
1034 else {
1035 i_push_error(0, "missing data during decompression");
1036 i_img_destroy(im);
1037 return NULL;
1038 }
705fd961
TC
1039 }
1040 for (i = 0; i < size; ++i) {
1041 line[0] = packed[i] >> 4;
1042 line[1] = packed[i] & 0xF;
1043 i_ppal(im, x, x+2, y, line);
1044 x += 2;
1045 }
1046 break;
1047 }
1048 }
1049 }
1050 }
1051 else { /*if (compression == BI_RLE4) {*/
1052 myfree(packed);
1053 myfree(line);
662e3c02 1054 i_push_errorf(0, "unknown 4-bit BMP compression (%d)", compression);
705fd961
TC
1055 i_img_destroy(im);
1056 return NULL;
261f91c5
TC
1057 }
1058
1059 return im;
1060}
1061
705fd961 1062/*
d87dc9a4 1063=item read_8bit_bmp(ig, xsize, ysize, clr_used, compression, allow_incomplete)
261f91c5 1064
705fd961
TC
1065Reads in the palette and image data for a 8-bit/pixel image.
1066
1067Returns the image or NULL.
1068
1069=cut
1070*/
1071static i_img *
1072read_8bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
d87dc9a4 1073 int compression, long offbits, int allow_incomplete) {
261f91c5 1074 i_img *im;
9c106321 1075 int x, y, lasty, yinc, start_y;
a659442a 1076 i_palidx *line;
705fd961 1077 int line_size = xsize;
403946c6 1078 long base_offset;
261f91c5 1079
705fd961 1080 line_size = (line_size+3) / 4 * 4;
f0960b14
TC
1081 if (line_size < xsize) { /* if it overflowed (unlikely, but check) */
1082 i_push_error(0, "integer overflow during memory allocation");
1083 return NULL;
1084 }
705fd961
TC
1085
1086 if (ysize > 0) {
9c106321 1087 start_y = ysize-1;
705fd961
TC
1088 lasty = -1;
1089 yinc = -1;
261f91c5 1090 }
705fd961
TC
1091 else {
1092 /* when ysize is -ve it's a top-down image */
1093 ysize = -ysize;
9c106321 1094 start_y = 0;
705fd961
TC
1095 lasty = ysize;
1096 yinc = 1;
261f91c5 1097 }
9c106321 1098 y = start_y;
705fd961
TC
1099 if (!clr_used)
1100 clr_used = 256;
662e3c02
TC
1101 if (clr_used > 256 || clr_used < 0) {
1102 i_push_errorf(0, "out of range colors used (%d)", clr_used);
1103 return NULL;
1104 }
1105
403946c6
TC
1106 base_offset = FILEHEAD_SIZE + INFOHEAD_SIZE + clr_used * 4;
1107 if (offbits < base_offset) {
1108 i_push_errorf(0, "image data offset too small (%ld)", offbits);
1109 return NULL;
1110 }
1111
662e3c02
TC
1112 im = i_img_pal_new(xsize, ysize, 3, 256);
1113 if (!im)
1114 return NULL;
705fd961
TC
1115 if (!read_bmp_pal(ig, im, clr_used)) {
1116 i_img_destroy(im);
1117 return NULL;
1118 }
1119
403946c6
TC
1120 if (offbits > base_offset) {
1121 /* this will be slow if the offset is large, but that should be
1122 rare */
1123 char buffer;
1124 while (base_offset < offbits) {
6d5c85a2 1125 if (i_io_read(ig, &buffer, 1) != 1) {
403946c6
TC
1126 i_img_destroy(im);
1127 i_push_error(0, "failed skipping to image data offset");
1128 return NULL;
1129 }
1130 ++base_offset;
1131 }
1132 }
1133
f0960b14 1134 line = mymalloc(line_size); /* checked 29jun05 tonyc */
705fd961 1135 if (compression == BI_RGB) {
662e3c02 1136 i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RGB", -1, 0);
705fd961 1137 while (y != lasty) {
6d5c85a2 1138 if (i_io_read(ig, line, line_size) != line_size) {
705fd961 1139 myfree(line);
d87dc9a4 1140 if (allow_incomplete) {
9c106321
TC
1141 i_tags_setn(&im->tags, "i_incomplete", 1);
1142 i_tags_setn(&im->tags, "i_lines_read", abs(start_y - y));
1143 return im;
1144 }
1145 else {
1146 i_push_error(0, "failed reading 8-bit bmp data");
1147 i_img_destroy(im);
1148 return NULL;
1149 }
705fd961
TC
1150 }
1151 i_ppal(im, 0, xsize, y, line);
1152 y += yinc;
1153 }
12d25826 1154 myfree(line);
705fd961
TC
1155 }
1156 else if (compression == BI_RLE8) {
1157 int read_size;
705fd961
TC
1158 int count;
1159 unsigned char packed[2];
1160
662e3c02 1161 i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RLE8", -1, 0);
705fd961
TC
1162 x = 0;
1163 while (1) {
1164 /* there's always at least 2 bytes in a sequence */
6d5c85a2 1165 if (i_io_read(ig, packed, 2) != 2) {
705fd961 1166 myfree(line);
d87dc9a4 1167 if (allow_incomplete) {
9c106321
TC
1168 i_tags_setn(&im->tags, "i_incomplete", 1);
1169 i_tags_setn(&im->tags, "i_lines_read", abs(start_y-y));
1170 return im;
1171 }
1172 else {
1173 i_push_error(0, "missing data during decompression");
1174 i_img_destroy(im);
1175 return NULL;
1176 }
705fd961
TC
1177 }
1178 if (packed[0]) {
bb5712de
TC
1179 if (x + packed[0] > xsize) {
1180 /* this file isn't incomplete, it's corrupt */
1181 myfree(line);
1182 i_push_error(0, "invalid data during decompression");
1183 i_img_destroy(im);
1184 return NULL;
1185 }
705fd961
TC
1186 memset(line, packed[1], packed[0]);
1187 i_ppal(im, x, x+packed[0], y, line);
1188 x += packed[0];
1189 } else {
1190 switch (packed[1]) {
1191 case BMPRLE_ENDOFLINE:
1192 x = 0;
1193 y += yinc;
1194 break;
1195
1196 case BMPRLE_ENDOFBMP:
4dfa5522 1197 myfree(line);
705fd961
TC
1198 return im;
1199
1200 case BMPRLE_DELTA:
6d5c85a2 1201 if (i_io_read(ig, packed, 2) != 2) {
705fd961 1202 myfree(line);
d87dc9a4 1203 if (allow_incomplete) {
9c106321
TC
1204 i_tags_setn(&im->tags, "i_incomplete", 1);
1205 i_tags_setn(&im->tags, "i_lines_read", abs(start_y-y));
1206 return im;
1207 }
1208 else {
1209 i_push_error(0, "missing data during decompression");
1210 i_img_destroy(im);
1211 return NULL;
1212 }
705fd961
TC
1213 }
1214 x += packed[0];
1215 y += yinc * packed[1];
1216 break;
1217
1218 default:
1219 count = packed[1];
bb5712de
TC
1220 if (x + count > xsize) {
1221 /* runs shouldn't cross a line boundary */
1222 /* this file isn't incomplete, it's corrupt */
1223 myfree(line);
1224 i_push_error(0, "invalid data during decompression");
1225 i_img_destroy(im);
1226 return NULL;
1227 }
705fd961 1228 read_size = (count+1) / 2 * 2;
6d5c85a2 1229 if (i_io_read(ig, line, read_size) != read_size) {
705fd961 1230 myfree(line);
d87dc9a4 1231 if (allow_incomplete) {
9c106321
TC
1232 i_tags_setn(&im->tags, "i_incomplete", 1);
1233 i_tags_setn(&im->tags, "i_lines_read", abs(start_y-y));
1234 return im;
1235 }
1236 else {
1237 i_push_error(0, "missing data during decompression");
1238 i_img_destroy(im);
1239 return NULL;
1240 }
705fd961
TC
1241 }
1242 i_ppal(im, x, x+count, y, line);
1243 x += count;
1244 break;
1245 }
1246 }
1247 }
1248 }
1249 else {
1250 myfree(line);
662e3c02 1251 i_push_errorf(0, "unknown 8-bit BMP compression (%d)", compression);
705fd961
TC
1252 i_img_destroy(im);
1253 return NULL;
1254 }
1255
1256 return im;
1257}
1258
1259struct bm_masks {
1260 unsigned masks[3];
1261 int shifts[3];
1cd4eef3 1262 int bits[3];
705fd961
TC
1263};
1264static struct bm_masks std_masks[] =
1265{
1266 { /* 16-bit */
1cd4eef3
TC
1267 { 0076000, 00001740, 00000037, },
1268 { 10, 5, 0, },
1269 { 5, 5, 5, }
705fd961
TC
1270 },
1271 { /* 24-bit */
1272 { 0xFF0000, 0x00FF00, 0x0000FF, },
1273 { 16, 8, 0, },
1cd4eef3 1274 { 8, 8, 8, },
705fd961
TC
1275 },
1276 { /* 32-bit */
1277 { 0xFF0000, 0x00FF00, 0x0000FF, },
1278 { 16, 8, 0, },
1cd4eef3 1279 { 8, 8, 8, },
705fd961
TC
1280 },
1281};
1282
1cd4eef3
TC
1283/* multiplier and shift for converting from N bits to 8 bits */
1284struct bm_sampconverts {
1285 int mult;
1286 int shift;
1287};
1288static struct bm_sampconverts samp_converts[] = {
1289 { 0xff, 0 }, /* 1 bit samples */
1290 { 0x55, 0 },
1291 { 0111, 1 },
1292 { 0x11, 0 },
1293 { 0x21, 2 },
1294 { 0x41, 4 },
1295 { 0x81, 6 } /* 7 bit samples */
1296};
1297
705fd961 1298/*
d87dc9a4 1299=item read_direct_bmp(ig, xsize, ysize, bit_count, clr_used, compression, allow_incomplete)
705fd961
TC
1300
1301Skips the palette and reads in the image data for a direct colour image.
1302
1303Returns the image or NULL.
1304
1305=cut
1306*/
1307static i_img *
1308read_direct_bmp(io_glue *ig, int xsize, int ysize, int bit_count,
9c106321 1309 int clr_used, int compression, long offbits,
d87dc9a4 1310 int allow_incomplete) {
705fd961 1311 i_img *im;
bea6bcd7 1312 int x, y, starty, lasty, yinc;
705fd961 1313 i_color *line, *p;
705fd961
TC
1314 int pix_size = bit_count / 8;
1315 int line_size = xsize * pix_size;
1316 struct bm_masks masks;
1317 char unpack_code[2] = "";
1318 int i;
1319 int extras;
1320 char junk[4];
662e3c02
TC
1321 const char *compression_name;
1322 int bytes;
403946c6 1323 long base_offset = FILEHEAD_SIZE + INFOHEAD_SIZE;
261f91c5 1324
705fd961
TC
1325 unpack_code[0] = *("v3V"+pix_size-2);
1326 unpack_code[1] = '\0';
261f91c5 1327
705fd961
TC
1328 line_size = (line_size+3) / 4 * 4;
1329 extras = line_size - xsize * pix_size;
261f91c5 1330
705fd961 1331 if (ysize > 0) {
bea6bcd7 1332 starty = ysize-1;
705fd961
TC
1333 lasty = -1;
1334 yinc = -1;
1335 }
1336 else {
1337 /* when ysize is -ve it's a top-down image */
1338 ysize = -ysize;
bea6bcd7 1339 starty = 0;
705fd961
TC
1340 lasty = ysize;
1341 yinc = 1;
1342 }
bea6bcd7 1343 y = starty;
705fd961 1344 if (compression == BI_RGB) {
662e3c02 1345 compression_name = "BI_RGB";
705fd961
TC
1346 masks = std_masks[pix_size-2];
1347
1348 /* there's a potential "palette" after the header */
1349 for (i = 0; i < clr_used; ++clr_used) {
1350 char buf[4];
6d5c85a2 1351 if (i_io_read(ig, buf, 4) != 4) {
705fd961
TC
1352 i_push_error(0, "skipping colors");
1353 return 0;
1354 }
403946c6 1355 base_offset += 4;
705fd961
TC
1356 }
1357 }
1358 else if (compression == BI_BITFIELDS) {
1cd4eef3
TC
1359 int pos;
1360 unsigned bits;
662e3c02
TC
1361 compression_name = "BI_BITFIELDS";
1362
705fd961 1363 for (i = 0; i < 3; ++i) {
8d14daab
TC
1364 i_packed_t rmask;
1365 if (!read_packed(ig, "V", &rmask)) {
705fd961
TC
1366 i_push_error(0, "reading pixel masks");
1367 return 0;
1368 }
1cd4eef3
TC
1369 if (rmask == 0) {
1370 i_push_errorf(0, "Zero mask for channel %d", i);
1371 return NULL;
1372 }
8d14daab 1373 masks.masks[i] = rmask;
705fd961
TC
1374 /* work out a shift for the mask */
1375 pos = 0;
1cd4eef3
TC
1376 bits = masks.masks[i];
1377 while (!(bits & 1)) {
705fd961 1378 ++pos;
1cd4eef3 1379 bits >>= 1;
705fd961 1380 }
1cd4eef3
TC
1381 masks.shifts[i] = pos;
1382 pos = 0;
1383 while (bits & 1) {
1384 ++pos;
1385 bits >>= 1;
1386 }
1387 masks.bits[i] = pos;
1388 /*fprintf(stderr, "%d: mask %08x shift %d bits %d\n", i, masks.masks[i], masks.shifts[i], masks.bits[i]);*/
705fd961 1389 }
1cd4eef3
TC
1390 /* account for the masks */
1391 base_offset += 3 * 4;
705fd961 1392 }
662e3c02
TC
1393 else {
1394 i_push_errorf(0, "unknown 24-bit BMP compression (%d)", compression);
1395 return NULL;
1396 }
261f91c5 1397
ae12796a
TC
1398 if (offbits < base_offset) {
1399 i_push_errorf(0, "image data offset too small (%ld)", offbits);
1400 return NULL;
1401 }
1402
403946c6
TC
1403 if (offbits > base_offset) {
1404 /* this will be slow if the offset is large, but that should be
1405 rare */
1406 char buffer;
1407 while (base_offset < offbits) {
6d5c85a2 1408 if (i_io_read(ig, &buffer, 1) != 1) {
403946c6
TC
1409 i_push_error(0, "failed skipping to image data offset");
1410 return NULL;
1411 }
1412 ++base_offset;
1413 }
1414 }
1415
705fd961 1416 im = i_img_empty(NULL, xsize, ysize);
662e3c02
TC
1417 if (!im)
1418 return NULL;
705fd961 1419
662e3c02
TC
1420 i_tags_add(&im->tags, "bmp_compression_name", 0, compression_name, -1, 0);
1421
1422 /* I wasn't able to make this overflow in testing, but better to be
1423 safe */
1424 bytes = sizeof(i_color) * xsize;
1425 if (bytes / sizeof(i_color) != xsize) {
1426 i_img_destroy(im);
1427 i_push_error(0, "integer overflow calculating buffer size");
1428 return NULL;
1429 }
f0960b14 1430 line = mymalloc(bytes); /* checked 29jun05 tonyc */
705fd961
TC
1431 while (y != lasty) {
1432 p = line;
1433 for (x = 0; x < xsize; ++x) {
8d14daab 1434 i_packed_t pixel;
705fd961 1435 if (!read_packed(ig, unpack_code, &pixel)) {
705fd961 1436 myfree(line);
d87dc9a4 1437 if (allow_incomplete) {
9c106321 1438 i_tags_setn(&im->tags, "i_incomplete", 1);
bea6bcd7 1439 i_tags_setn(&im->tags, "i_lines_read", abs(starty - y));
9c106321
TC
1440 return im;
1441 }
1442 else {
1443 i_push_error(0, "failed reading image data");
1444 i_img_destroy(im);
1445 return NULL;
1446 }
705fd961
TC
1447 }
1448 for (i = 0; i < 3; ++i) {
1cd4eef3
TC
1449 int sample = (pixel & masks.masks[i]) >> masks.shifts[i];
1450 int bits = masks.bits[i];
1451 if (bits < 8) {
1452 sample = (sample * samp_converts[bits-1].mult) >> samp_converts[bits-1].shift;
1453 }
1454 else if (bits) {
1455 sample >>= bits - 8;
1456 }
1457 p->channel[i] = sample;
705fd961
TC
1458 }
1459 ++p;
1460 }
1461 i_plin(im, 0, xsize, y, line);
1462 if (extras)
6d5c85a2 1463 i_io_read(ig, junk, extras);
705fd961 1464 y += yinc;
261f91c5 1465 }
705fd961
TC
1466 myfree(line);
1467
1468 return im;
261f91c5 1469}
705fd961
TC
1470
1471/*
1472=head1 SEE ALSO
1473
1474Imager(3)
1475
1476=head1 AUTHOR
1477
1478Tony Cook <tony@develop-help.com>
1479
1480=head1 RESTRICTIONS
1481
1482Cannot save as compressed BMP.
1483
1484=head1 BUGS
1485
1486Doesn't handle OS/2 bitmaps.
1487
148816-bit/pixel images haven't been tested. (I need an image).
1489
1490BI_BITFIELDS compression hasn't been tested (I need an image).
1491
403946c6
TC
1492The header handling for paletted images needs to be refactored
1493
705fd961
TC
1494=cut
1495*/