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