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