switch to using size_t and i_img_dim strictly
[imager.git] / bmp.c
1 #include <stdarg.h>
2 #include "imageri.h"
3
4 /*
5 =head1 NAME
6
7 bmp.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
21 Reads 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
38 #define SIGNBIT32 ((i_upacked_t)1U << 31)
39 #define SIGNBIT16 ((i_upacked_t)1U << 15)
40
41 #define SIGNMAX32 ((1UL << 31) - 1)
42
43 static int read_packed(io_glue *ig, char *format, ...);
44 static int write_packed(io_glue *ig, char *format, ...);
45 static int write_bmphead(io_glue *ig, i_img *im, int bit_count, 
46                          int data_size);
47 static int write_1bit_data(io_glue *ig, i_img *im);
48 static int write_4bit_data(io_glue *ig, i_img *im);
49 static int write_8bit_data(io_glue *ig, i_img *im);
50 static int write_24bit_data(io_glue *ig, i_img *im);
51 static int read_bmp_pal(io_glue *ig, i_img *im, int count);
52 static i_img *read_1bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used, 
53                             int compression, long offbits, int allow_incomplete);
54 static i_img *read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used, 
55                             int compression, long offbits, int allow_incomplete);
56 static i_img *read_8bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used, 
57                             int compression, long offbits, int allow_incomplete);
58 static i_img *read_direct_bmp(io_glue *ig, int xsize, int ysize, 
59                               int bit_count, int clr_used, int compression,
60                               long offbits, int allow_incomplete);
61
62 /* used for the read_packed() and write_packed() functions, an integer
63  * type */
64 typedef long i_packed_t;
65 typedef unsigned long i_upacked_t;
66
67 /* 
68 =item i_writebmp_wiol(im, io_glue)
69
70 Writes the image as a BMP file.  Uses 1-bit, 4-bit, 8-bit or 24-bit
71 formats depending on the image.
72
73 Never compresses the image.
74
75 =cut
76 */
77 int
78 i_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
106 Reads a Windows format bitmap from the given file.
107
108 Handles BI_RLE4 and BI_RLE8 compressed images.  Attempts to handle
109 BI_BITFIELDS images too, but I need a test image.
110
111 =cut
112 */
113
114 i_img *
115 i_readbmp_wiol(io_glue *ig, int allow_incomplete) {
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;
119   i_img *im;
120
121   mm_log((1, "i_readbmp_wiol(ig %p)\n", ig));
122   
123   io_glue_commit_types(ig);
124   i_clear_error();
125
126   if (!read_packed(ig, "CCVvvVVV!V!vvVVVVVV", &b_magic, &m_magic, &filesize, 
127                    &res1, &res2, &offbits, &infohead_size, 
128                    &xsize, &ysize, &planes,
129                    &bit_count, &compression, &size_image, &xres, &yres, 
130                    &clr_used, &clr_important)) {
131     i_push_error(0, "file too short to be a BMP file");
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   }
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 "
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));
146
147   if (!i_int_check_image_file_limits(xsize, abs(ysize), 3, sizeof(i_sample_t))) {
148     mm_log((1, "i_readbmp_wiol: image size exceeds limits\n"));
149     return NULL;
150   }
151   
152   switch (bit_count) {
153   case 1:
154     im = read_1bit_bmp(ig, xsize, ysize, clr_used, compression, offbits, 
155                        allow_incomplete);
156     break;
157
158   case 4:
159     im = read_4bit_bmp(ig, xsize, ysize, clr_used, compression, offbits, 
160                        allow_incomplete);
161     break;
162
163   case 8:
164     im = read_8bit_bmp(ig, xsize, ysize, clr_used, compression, offbits, 
165                        allow_incomplete);
166     break;
167
168   case 32:
169   case 24:
170   case 16:
171     im = read_direct_bmp(ig, xsize, ysize, bit_count, clr_used, compression,
172                          offbits, allow_incomplete);
173     break;
174
175   default:
176     i_push_errorf(0, "unknown bit count for BMP file (%d)", (int)bit_count);
177     return NULL;
178   }
179
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) {
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);
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);
196   }
197
198   return im;
199 }
200
201 /*
202 =back
203
204 =head1 IMPLEMENTATION FUNCTIONS
205
206 Internal functions used in the implementation.
207
208 =over
209
210 =item read_packed(ig, format, ...)
211
212 Reads from the specified "file" the specified sizes.  The format codes
213 match those used by perl's pack() function, though only a few are
214 implemented.  In all cases the vararg arguement is an int *.
215
216 Returns non-zero if all of the arguments were read.
217
218 =cut
219 */
220 static int
221 read_packed(io_glue *ig, char *format, ...) {
222   unsigned char buf[4];
223   va_list ap;
224   i_packed_t *p;
225   i_packed_t work;
226   int code;
227   int shrieking; /* format code has a ! flag */
228
229   va_start(ap, format);
230
231   while (*format) {
232     p = va_arg(ap, i_packed_t *);
233
234     code = *format++;
235     shrieking = *format == '!';
236     if (shrieking) ++format;
237
238     switch (code) {
239     case 'v':
240       if (ig->readcb(ig, buf, 2) != 2)
241         return 0;
242       work = buf[0] + ((i_packed_t)buf[1] << 8);
243       if (shrieking)
244         *p = (work ^ SIGNBIT16) - SIGNBIT16;
245       else
246         *p = work;
247       break;
248
249     case 'V':
250       if (ig->readcb(ig, buf, 4) != 4)
251         return 0;
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;
257       break;
258
259     case 'C':
260       if (ig->readcb(ig, buf, 1) != 1)
261         return 0;
262       *p = buf[0];
263       break;
264
265     case 'c':
266       if (ig->readcb(ig, buf, 1) != 1)
267         return 0;
268       *p = (char)buf[0];
269       break;
270       
271     case '3': /* extension - 24-bit number */
272       if (ig->readcb(ig, buf, 3) != 3)
273         return 0;
274       *p = buf[0] + (buf[1] << 8) + ((i_packed_t)buf[2] << 16);
275       break;
276       
277     default:
278       i_fatal(1, "Unknown read_packed format code 0x%02x", code);
279     }
280   }
281   return 1;
282 }
283
284 /*
285 =item write_packed(ig, format, ...)
286
287 Writes packed data to the specified io_glue.
288
289 Returns non-zero on success.
290
291 =cut
292 */
293
294 static int
295 write_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) {
303     i = va_arg(ap, i_upacked_t);
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:
330       i_fatal(1, "Unknown write_packed format code 0x%02x", *format);
331     }
332     ++format;
333   }
334   va_end(ap);
335
336   return 1;
337 }
338
339 /*
340 =item write_bmphead(ig, im, bit_count, data_size)
341
342 Writes a Windows BMP header to the file.
343
344 Returns non-zero on success.
345
346 =cut
347 */
348
349 static
350 int 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
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
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
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)){
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) {
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)) {
420           i_push_error(0, "cannot write palette entry");
421           return 0;
422         }
423       }
424       else {
425         i_upacked_t v = c.channel[0];
426         if (!write_packed(ig, "CCCC", v, v, v, 0)) {
427           i_push_error(0, "cannot write palette entry");
428           return 0;
429         }
430       }
431     }
432   }
433
434   return 1;
435 }
436
437 /*
438 =item write_1bit_data(ig, im)
439
440 Writes the image data as a 1-bit/pixel image.
441
442 Returns non-zero on success.
443
444 =cut
445 */
446 static int
447 write_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;
455   int unpacked_size;
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
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 */
470   memset(line + im->xsize, 0, 8);
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 */
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
504   ig->closecb(ig);
505
506   return 1;
507 }
508
509 /*
510 =item write_4bit_data(ig, im)
511
512 Writes the image data as a 4-bit/pixel image.
513
514 Returns non-zero on success.
515
516 =cut
517 */
518 static int
519 write_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;
525   int unpacked_size;
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
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 */
540   memset(line + im->xsize, 0, 2);
541   
542   /* size allocated here is always much smaller than xsize, hence
543      can't overflow int */
544   packed = mymalloc(line_size); /* checked 29jun05 tonyc */
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
563   ig->closecb(ig);
564
565   return 1;
566 }
567
568 /*
569 =item write_8bit_data(ig, im)
570
571 Writes the image data as a 8-bit/pixel image.
572
573 Returns non-zero on success.
574
575 =cut
576 */
577 static int
578 write_8bit_data(io_glue *ig, i_img *im) {
579   i_palidx *line;
580   int line_size = im->xsize;
581   int y;
582   int unpacked_size;
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
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 */
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
609   ig->closecb(ig);
610
611   return 1;
612 }
613
614 /*
615 =item write_24bit_data(ig, im)
616
617 Writes the image data as a 24-bit/pixel image.
618
619 Returns non-zero on success.
620
621 =cut
622 */
623 static int
624 write_24bit_data(io_glue *ig, i_img *im) {
625   unsigned char *samples;
626   int y;
627   int line_size = 3 * im->xsize;
628   i_color bg;
629
630   i_get_file_background(im, &bg);
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   }
638   
639   line_size = (line_size + 3) / 4 * 4;
640   
641   if (!write_bmphead(ig, im, 24, line_size * im->ysize))
642     return 0;
643   samples = mymalloc(4 * im->xsize);
644   memset(samples, 0, line_size);
645   for (y = im->ysize-1; y >= 0; --y) {
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     }
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
663   ig->closecb(ig);
664
665   return 1;
666 }
667
668 /*
669 =item read_bmp_pal(ig, im, count)
670
671 Reads count palette entries from the file and add them to the image.
672
673 Returns non-zero on success.
674
675 =cut
676 */
677 static int
678 read_bmp_pal(io_glue *ig, i_img *im, int count) {
679   int i;
680   i_packed_t r, g, b, x;
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;
691     if (i_addcolors(im, &c, 1) < 0) {
692       i_push_error(0, "out of space in image palette");
693       return 0;
694     }
695   }
696   
697   return 1;
698 }
699
700 /*
701 =item read_1bit_bmp(ig, xsize, ysize, clr_used, compression, offbits)
702
703 Reads in the palette and image data for a 1-bit/pixel image.
704
705 Returns the image or NULL.
706
707 =cut
708 */
709 static i_img *
710 read_1bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used, 
711               int compression, long offbits, int allow_incomplete) {
712   i_img *im;
713   int x, y, lasty, yinc, start_y;
714   i_palidx *line, *p;
715   unsigned char *packed;
716   int line_size = (xsize + 7)/8;
717   int bit;
718   unsigned char *in;
719   long base_offset;
720
721   if (compression != BI_RGB) {
722     i_push_errorf(0, "unknown 1-bit BMP compression (%d)", compression);
723     return NULL;
724   }
725
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 */
735   line_size = (line_size+3) / 4 * 4;
736
737   if (ysize > 0) {
738     start_y = ysize-1;
739     lasty = -1;
740     yinc = -1;
741   }
742   else {
743     /* when ysize is -ve it's a top-down image */
744     ysize = -ysize;
745     start_y = 0;
746     lasty = ysize;
747     yinc = 1;
748   }
749   y = start_y;
750   if (!clr_used)
751     clr_used = 2;
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   }
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
763   im = i_img_pal_new(xsize, ysize, 3, 256);
764   if (!im)
765     return NULL;
766   if (!read_bmp_pal(ig, im, clr_used)) {
767     i_img_destroy(im);
768     return NULL;
769   }
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   }
784   
785   i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RGB", -1, 0);
786
787   packed = mymalloc(line_size); /* checked 29jun05 tonyc */
788   line = mymalloc(xsize+8); /* checked 29jun05 tonyc */
789   while (y != lasty) {
790     if (ig->readcb(ig, packed, line_size) != line_size) {
791       myfree(packed);
792       myfree(line);
793       if (allow_incomplete) {
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       }
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
819   myfree(packed);
820   myfree(line);
821   return im;
822 }
823
824 /*
825 =item read_4bit_bmp(ig, xsize, ysize, clr_used, compression)
826
827 Reads in the palette and image data for a 4-bit/pixel image.
828
829 Returns the image or NULL.
830
831 Hopefully this will be combined with the following function at some
832 point.
833
834 =cut
835 */
836 static i_img *
837 read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used, 
838               int compression, long offbits, int allow_incomplete) {
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;
845   int size, i;
846   long base_offset;
847   int starty;
848
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 */
851   line_size = (line_size+3) / 4 * 4;
852
853   if (ysize > 0) {
854     starty = ysize-1;
855     lasty = -1;
856     yinc = -1;
857   }
858   else {
859     /* when ysize is -ve it's a top-down image */
860     ysize = -ysize;
861     starty = 0;
862     lasty = ysize;
863     yinc = 1;
864   }
865   y = starty;
866   if (!clr_used)
867     clr_used = 16;
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
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
880   im = i_img_pal_new(xsize, ysize, 3, 256);
881   if (!im) /* error should have been pushed already */
882     return NULL;
883   if (!read_bmp_pal(ig, im, clr_used)) {
884     i_img_destroy(im);
885     return NULL;
886   }
887
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   
902   if (line_size < 260)
903     packed = mymalloc(260); /* checked 29jun05 tonyc */
904   else
905     packed = mymalloc(line_size); /* checked 29jun05 tonyc */
906   /* xsize won't approach MAXINT */
907   line = mymalloc(xsize+1); /* checked 29jun05 tonyc */
908   if (compression == BI_RGB) {
909     i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RGB", -1, 0);
910     while (y != lasty) {
911       if (ig->readcb(ig, packed, line_size) != line_size) {
912         myfree(packed);
913         myfree(line);
914         if (allow_incomplete) {
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         }
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     }
935     myfree(packed);
936     myfree(line);
937   }
938   else if (compression == BI_RLE4) {
939     int read_size;
940     int count;
941
942     i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RLE4", -1, 0);
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);
949         if (allow_incomplete) {
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         }
959       }
960       else if (packed[0]) {
961         if (x + packed[0] > xsize) {
962           /* this file is corrupt */
963           myfree(packed);
964           myfree(line);
965           i_push_error(0, "invalid data during decompression");
966           i_img_destroy(im);
967           return NULL;
968         }
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:
986           myfree(packed);
987           myfree(line);
988           return im;
989
990         case BMPRLE_DELTA:
991           if (ig->readcb(ig, packed, 2) != 2) {
992             myfree(packed);
993             myfree(line);
994             if (allow_incomplete) {
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             }
1004           }
1005           x += packed[0];
1006           y += yinc * packed[1];
1007           break;
1008
1009         default:
1010           count = packed[1];
1011           if (x + count > xsize) {
1012             /* this file is corrupt */
1013             myfree(packed);
1014             myfree(line);
1015             i_push_error(0, "invalid data during decompression");
1016             i_img_destroy(im);
1017             return NULL;
1018           }
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);
1024             if (allow_incomplete) {
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             }
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);
1049     i_push_errorf(0, "unknown 4-bit BMP compression (%d)", compression);
1050     i_img_destroy(im);
1051     return NULL;
1052   }
1053
1054   return im;
1055 }
1056
1057 /*
1058 =item read_8bit_bmp(ig, xsize, ysize, clr_used, compression, allow_incomplete)
1059
1060 Reads in the palette and image data for a 8-bit/pixel image.
1061
1062 Returns the image or NULL.
1063
1064 =cut
1065 */
1066 static i_img *
1067 read_8bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used, 
1068               int compression, long offbits, int allow_incomplete) {
1069   i_img *im;
1070   int x, y, lasty, yinc, start_y;
1071   i_palidx *line;
1072   int line_size = xsize;
1073   long base_offset;
1074
1075   line_size = (line_size+3) / 4 * 4;
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   }
1080
1081   if (ysize > 0) {
1082     start_y = ysize-1;
1083     lasty = -1;
1084     yinc = -1;
1085   }
1086   else {
1087     /* when ysize is -ve it's a top-down image */
1088     ysize = -ysize;
1089     start_y = 0;
1090     lasty = ysize;
1091     yinc = 1;
1092   }
1093   y = start_y;
1094   if (!clr_used)
1095     clr_used = 256;
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
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
1107   im = i_img_pal_new(xsize, ysize, 3, 256);
1108   if (!im)
1109     return NULL;
1110   if (!read_bmp_pal(ig, im, clr_used)) {
1111     i_img_destroy(im);
1112     return NULL;
1113   }
1114
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   
1129   line = mymalloc(line_size); /* checked 29jun05 tonyc */
1130   if (compression == BI_RGB) {
1131     i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RGB", -1, 0);
1132     while (y != lasty) {
1133       if (ig->readcb(ig, line, line_size) != line_size) {
1134         myfree(line);
1135         if (allow_incomplete) {
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         }
1145       }
1146       i_ppal(im, 0, xsize, y, line);
1147       y += yinc;
1148     }
1149     myfree(line);
1150   }
1151   else if (compression == BI_RLE8) {
1152     int read_size;
1153     int count;
1154     unsigned char packed[2];
1155
1156     i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RLE8", -1, 0);
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);
1162         if (allow_incomplete) {
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         }
1172       }
1173       if (packed[0]) {
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         }
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:
1192           myfree(line);
1193           return im;
1194
1195         case BMPRLE_DELTA:
1196           if (ig->readcb(ig, packed, 2) != 2) {
1197             myfree(line);
1198             if (allow_incomplete) {
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             }
1208           }
1209           x += packed[0];
1210           y += yinc * packed[1];
1211           break;
1212
1213         default:
1214           count = packed[1];
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           }
1223           read_size = (count+1) / 2 * 2;
1224           if (ig->readcb(ig, line, read_size) != read_size) {
1225             myfree(line);
1226             if (allow_incomplete) {
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             }
1236           }
1237           i_ppal(im, x, x+count, y, line);
1238           x += count;
1239           break;
1240         }
1241       }
1242     }
1243   }
1244   else { 
1245     myfree(line);
1246     i_push_errorf(0, "unknown 8-bit BMP compression (%d)", compression);
1247     i_img_destroy(im);
1248     return NULL;
1249   }
1250
1251   return im;
1252 }
1253
1254 struct bm_masks {
1255   unsigned masks[3];
1256   int shifts[3];
1257 };
1258 static 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 /*
1275 =item read_direct_bmp(ig, xsize, ysize, bit_count, clr_used, compression, allow_incomplete)
1276
1277 Skips the palette and reads in the image data for a direct colour image.
1278
1279 Returns the image or NULL.
1280
1281 =cut
1282 */
1283 static i_img *
1284 read_direct_bmp(io_glue *ig, int xsize, int ysize, int bit_count, 
1285                 int clr_used, int compression, long offbits, 
1286                 int allow_incomplete) {
1287   i_img *im;
1288   int x, y, starty, lasty, yinc;
1289   i_color *line, *p;
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];
1297   const char *compression_name;
1298   int bytes;
1299   long base_offset = FILEHEAD_SIZE + INFOHEAD_SIZE;
1300   
1301   unpack_code[0] = *("v3V"+pix_size-2);
1302   unpack_code[1] = '\0';
1303
1304   line_size = (line_size+3) / 4 * 4;
1305   extras = line_size - xsize * pix_size;
1306
1307   if (ysize > 0) {
1308     starty = ysize-1;
1309     lasty = -1;
1310     yinc = -1;
1311   }
1312   else {
1313     /* when ysize is -ve it's a top-down image */
1314     ysize = -ysize;
1315     starty = 0;
1316     lasty = ysize;
1317     yinc = 1;
1318   }
1319   y = starty;
1320   if (compression == BI_RGB) {
1321     compression_name = "BI_RGB";
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       }
1331       base_offset += 4;
1332     }
1333   }
1334   else if (compression == BI_BITFIELDS) {
1335     int pos, bit;
1336     compression_name = "BI_BITFIELDS";
1337
1338     for (i = 0; i < 3; ++i) {
1339       i_packed_t rmask;
1340       if (!read_packed(ig, "V", &rmask)) {
1341         i_push_error(0, "reading pixel masks");
1342         return 0;
1343       }
1344       masks.masks[i] = rmask;
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     }
1354     base_offset += 4 * 4;
1355   }
1356   else {
1357     i_push_errorf(0, "unknown 24-bit BMP compression (%d)", compression);
1358     return NULL;
1359   }
1360
1361   if (offbits < base_offset) {
1362     i_push_errorf(0, "image data offset too small (%ld)", offbits);
1363     return NULL;
1364   }
1365
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) {
1372         i_push_error(0, "failed skipping to image data offset");
1373         return NULL;
1374       }
1375       ++base_offset;
1376     }
1377   }
1378   
1379   im = i_img_empty(NULL, xsize, ysize);
1380   if (!im)
1381     return NULL;
1382
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   }
1393   line = mymalloc(bytes); /* checked 29jun05 tonyc */
1394   while (y != lasty) {
1395     p = line;
1396     for (x = 0; x < xsize; ++x) {
1397       i_packed_t pixel;
1398       if (!read_packed(ig, unpack_code, &pixel)) {
1399         myfree(line);
1400         if (allow_incomplete) {
1401           i_tags_setn(&im->tags, "i_incomplete", 1);
1402           i_tags_setn(&im->tags, "i_lines_read", abs(starty - y));
1403           return im;
1404         }
1405         else {
1406           i_push_error(0, "failed reading image data");
1407           i_img_destroy(im);
1408           return NULL;
1409         }
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;
1423   }
1424   myfree(line);
1425
1426   return im;
1427 }
1428
1429 /*
1430 =head1 SEE ALSO
1431
1432 Imager(3)
1433
1434 =head1 AUTHOR
1435
1436 Tony Cook <tony@develop-help.com>
1437
1438 =head1 RESTRICTIONS
1439
1440 Cannot save as compressed BMP.
1441
1442 =head1 BUGS
1443
1444 Doesn't handle OS/2 bitmaps.
1445
1446 16-bit/pixel images haven't been tested.  (I need an image).
1447
1448 BI_BITFIELDS compression hasn't been tested (I need an image).
1449
1450 The header handling for paletted images needs to be refactored
1451
1452 =cut
1453 */