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