Windows BMP file support
[imager.git] / bmp.c
1 #include "image.h"
2 #include <stdarg.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 static int read_packed(io_glue *ig, char *format, ...);
39 static int write_packed(io_glue *ig, char *format, ...);
40 static int write_bmphead(io_glue *ig, i_img *im, int bit_count, 
41                          int data_size);
42 static int write_1bit_data(io_glue *ig, i_img *im);
43 static int write_4bit_data(io_glue *ig, i_img *im);
44 static int write_8bit_data(io_glue *ig, i_img *im);
45 static int write_24bit_data(io_glue *ig, i_img *im);
46 static int read_bmp_pal(io_glue *ig, i_img *im, int count);
47 static i_img *read_1bit_bmp(io_glue *ig, int xsize, int ysize, 
48                             int clr_used);
49 static i_img *read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used, 
50                             int compression);
51 static i_img *read_8bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used, 
52                             int compression);
53 static i_img *read_direct_bmp(io_glue *ig, int xsize, int ysize, 
54                               int bit_count, int clr_used, int compression);
55
56 /* 
57 =item i_writebmp_wiol(im, io_glue)
58
59 Writes the image as a BMP file.  Uses 1-bit, 4-bit, 8-bit or 24-bit
60 formats depending on the image.
61
62 Never compresses the image.
63
64 =cut
65 */
66 int
67 i_writebmp_wiol(i_img *im, io_glue *ig) {
68   io_glue_commit_types(ig);
69   i_clear_error();
70
71   /* pick a format */
72   if (im->type == i_direct_type) {
73     return write_24bit_data(ig, im);
74   }
75   else {
76     int pal_size;
77
78     /* must be paletted */
79     pal_size = i_colorcount(im);
80     if (pal_size <= 2) {
81       return write_1bit_data(ig, im);
82     }
83     else if (pal_size <= 16) {
84       return write_4bit_data(ig, im);
85     }
86     else {
87       return write_8bit_data(ig, im);
88     }
89   }
90 }
91
92 /*
93 =item i_readbmp_wiol(ig)
94
95 Reads a Windows format bitmap from the given file.
96
97 Handles BI_RLE4 and BI_RLE8 compressed images.  Attempts to handle
98 BI_BITFIELDS images too, but I need a test image.
99
100 =cut
101 */
102
103 i_img *
104 i_readbmp_wiol(io_glue *ig) {
105   int b_magic, m_magic, filesize, dummy, infohead_size;
106   int xsize, ysize, planes, bit_count, compression, size_image, xres, yres;
107   int clr_used, clr_important, offbits;
108   i_img *im;
109   
110   io_glue_commit_types(ig);
111   i_clear_error();
112
113   if (!read_packed(ig, "CCVvvVVVVvvVVVVVV", &b_magic, &m_magic, &filesize, 
114                    &dummy, &dummy, &offbits, &infohead_size, 
115                    &xsize, &ysize, &planes,
116                    &bit_count, &compression, &size_image, &xres, &yres, 
117                    &clr_used, &clr_important)) {
118     i_push_error(0, "file too short");
119     return 0;
120   }
121   if (b_magic != 'B' || m_magic != 'M' || infohead_size != INFOHEAD_SIZE
122       || planes != 1) {
123     i_push_error(0, "not a BMP file");
124     return 0;
125   }
126   
127   switch (bit_count) {
128   case 1:
129     im = read_1bit_bmp(ig, xsize, ysize, clr_used);
130     break;
131
132   case 4:
133     im = read_4bit_bmp(ig, xsize, ysize, clr_used, compression);
134     break;
135
136   case 8:
137     im = read_8bit_bmp(ig, xsize, ysize, clr_used, compression);
138     break;
139
140   case 32:
141   case 24:
142   case 16:
143     im = read_direct_bmp(ig, xsize, ysize, bit_count, clr_used, compression);
144     break;
145   }
146
147   /* store the resolution */
148   if (xres && !yres)
149     yres = xres;
150   else if (yres && !xres)
151     xres = yres;
152   if (xres) {
153     i_tags_set_float(&im->tags, "i_xres", 0, xres * 0.0254);
154     i_tags_set_float(&im->tags, "i_yres", 0, yres * 0.0254);
155   }
156   i_tags_addn(&im->tags, "bmp_compression", 0, compression);
157   i_tags_addn(&im->tags, "bmp_important_colors", 0, clr_important);
158
159   return im;
160 }
161
162 /*
163 =back
164
165 =head1 IMPLEMENTATION FUNCTIONS
166
167 Internal functions used in the implementation.
168
169 =over
170
171 =item read_packed(ig, format, ...)
172
173 Reads from the specified "file" the specified sizes.  The format codes
174 match those used by perl's pack() function, though only a few are
175 implemented.  In all cases the vararg arguement is an int *.
176
177 Returns non-zero if all of the arguments were read.
178
179 =cut
180 */
181 static
182 int read_packed(io_glue *ig, char *format, ...) {
183   unsigned char buf[4];
184   va_list ap;
185   int *p;
186
187   va_start(ap, format);
188
189   while (*format) {
190     p = va_arg(ap, int *);
191
192     switch (*format) {
193     case 'v':
194       if (ig->readcb(ig, buf, 2) == -1)
195         return 0;
196       *p = buf[0] + (buf[1] << 8);
197       break;
198
199     case 'V':
200       if (ig->readcb(ig, buf, 4) == -1)
201         return 0;
202       *p = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
203       break;
204
205     case 'C':
206       if (ig->readcb(ig, buf, 1) == -1)
207         return 0;
208       *p = buf[0];
209       break;
210
211     case 'c':
212       if (ig->readcb(ig, buf, 1) == -1)
213         return 0;
214       *p = (char)buf[0];
215       break;
216       
217     case '3': /* extension - 24-bit number */
218       if (ig->readcb(ig, buf, 3) == -1)
219         return 0;
220       *p = buf[0] + (buf[1] << 8) + (buf[2] << 16);
221       break;
222       
223     default:
224       m_fatal(1, "Unknown read_packed format code 0x%02x", *format);
225     }
226     ++format;
227   }
228   return 1;
229 }
230
231 /*
232 =item write_packed(ig, format, ...)
233
234 Writes packed data to the specified io_glue.
235
236 Returns non-zero on success.
237
238 =cut
239 */
240
241 static int
242 write_packed(io_glue *ig, char *format, ...) {
243   unsigned char buf[4];
244   va_list ap;
245   int i;
246
247   va_start(ap, format);
248
249   while (*format) {
250     i = va_arg(ap, unsigned int);
251
252     switch (*format) {
253     case 'v':
254       buf[0] = i & 255;
255       buf[1] = i / 256;
256       if (ig->writecb(ig, buf, 2) == -1)
257         return 0;
258       break;
259
260     case 'V':
261       buf[0] = i & 0xFF;
262       buf[1] = (i >> 8) & 0xFF;
263       buf[2] = (i >> 16) & 0xFF;
264       buf[3] = (i >> 24) & 0xFF;
265       if (ig->writecb(ig, buf, 4) == -1)
266         return 0;
267       break;
268
269     case 'C':
270     case 'c':
271       buf[0] = i & 0xFF;
272       if (ig->writecb(ig, buf, 1) == -1)
273         return 0;
274       break;
275
276     default:
277       m_fatal(1, "Unknown read_packed format code 0x%02x", *format);
278     }
279     ++format;
280   }
281   va_end(ap);
282
283   return 1;
284 }
285
286 /*
287 =item write_bmphead(ig, im, bit_count, data_size)
288
289 Writes a Windows BMP header to the file.
290
291 Returns non-zero on success.
292
293 =cut
294 */
295
296 static
297 int write_bmphead(io_glue *ig, i_img *im, int bit_count, int data_size) {
298   double xres, yres;
299   int got_xres, got_yres, aspect_only;
300   int colors_used = 0;
301   int offset = FILEHEAD_SIZE + INFOHEAD_SIZE;
302
303   got_xres = i_tags_get_float(&im->tags, "i_xres", 0, &xres);
304   got_yres = i_tags_get_float(&im->tags, "i_yres", 0, &yres);
305   if (!i_tags_get_int(&im->tags, "i_aspect_only", 0,&aspect_only))
306     aspect_only = 0;
307   if (!got_xres) {
308     if (!got_yres)
309       xres = yres = 72;
310     else
311       xres = yres;
312   }
313   else {
314     if (!got_yres)
315       yres = xres;
316   }
317   if (xres <= 0 || yres <= 0)
318     xres = yres = 72;
319   if (aspect_only) {
320     /* scale so the smaller value is 72 */
321     double ratio;
322     if (xres < yres) {
323       ratio = 72.0 / xres;
324     }
325     else {
326       ratio = 72.0 / yres;
327     }
328     xres *= ratio;
329     yres *= ratio;
330   }
331   /* now to pels/meter */
332   xres *= 100.0/2.54;
333   yres *= 100.0/2.54;
334
335   if (im->type == i_palette_type) {
336     colors_used = i_colorcount(im);
337     offset += 4 * colors_used;
338   }
339
340   if (!write_packed(ig, "CCVvvVVVVvvVVVVVV", 'B', 'M', data_size+offset, 
341                     0, 0, offset, INFOHEAD_SIZE, im->xsize, im->ysize, 1, 
342                     bit_count, BI_RGB, 0, (int)(xres+0.5), (int)(yres+0.5), 
343                     colors_used, colors_used)){
344     i_push_error(0, "cannot write bmp header");
345     return 0;
346   }
347   if (im->type == i_palette_type) {
348     int i;
349     i_color c;
350
351     for (i = 0; i < colors_used; ++i) {
352       i_getcolors(im, i, &c, 1);
353       if (im->channels >= 3) {
354         if (!write_packed(ig, "CCCC", c.channel[2], c.channel[1], 
355                           c.channel[0], 0)) {
356           i_push_error(0, "cannot write palette entry");
357           return 0;
358         }
359       }
360       else {
361         if (!write_packed(ig, "CCCC", c.channel[0], c.channel[0], 
362                           c.channel[0], 0)) {
363           i_push_error(0, "cannot write palette entry");
364           return 0;
365         }
366       }
367     }
368   }
369
370   return 1;
371 }
372
373 /*
374 =item write_1bit_data(ig, im)
375
376 Writes the image data as a 1-bit/pixel image.
377
378 Returns non-zero on success.
379
380 =cut
381 */
382 static int
383 write_1bit_data(io_glue *ig, i_img *im) {
384   i_palidx *line;
385   unsigned char *packed;
386   int byte;
387   int mask;
388   unsigned char *out;
389   int line_size = (im->xsize+7) / 8;
390   int x, y;
391
392   /* round up to nearest multiple of four */
393   line_size = (line_size + 3) / 4 * 4;
394
395   if (!write_bmphead(ig, im, 1, line_size * im->ysize))
396     return 0;
397
398   line = mymalloc(im->xsize + 8);
399   memset(line + im->xsize, 0, 8);
400   
401   packed = mymalloc(line_size);
402   memset(packed, 0, line_size);
403   
404   for (y = im->ysize-1; y >= 0; --y) {
405     i_gpal(im, 0, im->xsize, y, line);
406     mask = 0x80;
407     byte = 0;
408     out = packed;
409     for (x = 0; x < im->xsize; ++x) {
410       if (line[x])
411         byte |= mask;
412       if ((mask >>= 1) == 0) {
413         *out++ = byte;
414         byte = 0;
415         mask = 0x80;
416       }
417     }
418     if (mask != 0x80) {
419       *out++ = byte;
420     }
421     if (ig->writecb(ig, packed, line_size) < 0) {
422       myfree(packed);
423       myfree(line);
424       i_push_error(0, "writing 1 bit/pixel packed data");
425       return 0;
426     }
427   }
428   myfree(packed);
429   myfree(line);
430
431   return 1;
432 }
433
434 /*
435 =item write_4bit_data(ig, im)
436
437 Writes the image data as a 4-bit/pixel image.
438
439 Returns non-zero on success.
440
441 =cut
442 */
443 static int
444 write_4bit_data(io_glue *ig, i_img *im) {
445   i_palidx *line;
446   unsigned char *packed;
447   unsigned char *out;
448   int line_size = (im->xsize+1) / 2;
449   int x, y;
450
451   /* round up to nearest multiple of four */
452   line_size = (line_size + 3) / 4 * 4;
453
454   if (!write_bmphead(ig, im, 4, line_size * im->ysize))
455     return 0;
456
457   line = mymalloc(im->xsize + 2);
458   memset(line + im->xsize, 0, 2);
459   
460   packed = mymalloc(line_size);
461   memset(packed, 0, line_size);
462   
463   for (y = im->ysize-1; y >= 0; --y) {
464     i_gpal(im, 0, im->xsize, y, line);
465     out = packed;
466     for (x = 0; x < im->xsize; x += 2) {
467       *out++ = (line[x] << 4) + line[x+1];
468     }
469     if (ig->writecb(ig, packed, line_size) < 0) {
470       myfree(packed);
471       myfree(line);
472       i_push_error(0, "writing 4 bit/pixel packed data");
473       return 0;
474     }
475   }
476   myfree(packed);
477   myfree(line);
478
479   return 1;
480 }
481
482 /*
483 =item write_8bit_data(ig, im)
484
485 Writes the image data as a 8-bit/pixel image.
486
487 Returns non-zero on success.
488
489 =cut
490 */
491 static int
492 write_8bit_data(io_glue *ig, i_img *im) {
493   i_palidx *line;
494   int line_size = im->xsize;
495   int x, y;
496
497   /* round up to nearest multiple of four */
498   line_size = (line_size + 3) / 4 * 4;
499
500   if (!write_bmphead(ig, im, 8, line_size * im->ysize))
501     return 0;
502
503   line = mymalloc(im->xsize + 4);
504   memset(line + im->xsize, 0, 4);
505   
506   for (y = im->ysize-1; y >= 0; --y) {
507     i_gpal(im, 0, im->xsize, y, line);
508     if (ig->writecb(ig, line, line_size) < 0) {
509       myfree(line);
510       i_push_error(0, "writing 8 bit/pixel packed data");
511       return 0;
512     }
513   }
514   myfree(line);
515
516   return 1;
517 }
518
519 static int bgr_chans[] = { 2, 1, 0, };
520 static int grey_chans[] = { 0, 0, 0, };
521
522 /*
523 =item write_24bit_data(ig, im)
524
525 Writes the image data as a 24-bit/pixel image.
526
527 Returns non-zero on success.
528
529 =cut
530 */
531 static int
532 write_24bit_data(io_glue *ig, i_img *im) {
533   int *chans;
534   unsigned char *samples;
535   int x, y;
536   int line_size = 3 * im->xsize;
537   
538   line_size = (line_size + 3) / 4 * 4;
539   
540   if (!write_bmphead(ig, im, 24, line_size * im->ysize))
541     return 0;
542   chans = im->channels >= 3 ? bgr_chans : grey_chans;
543   samples = mymalloc(line_size);
544   for (y = im->ysize-1; y >= 0; --y) {
545     i_gsamp(im, 0, im->xsize, y, samples, chans, 3);
546     if (ig->writecb(ig, samples, line_size) < 0) {
547       i_push_error(0, "writing image data");
548       myfree(samples);
549       return 0;
550     }
551   }
552   myfree(samples);
553
554   return 1;
555 }
556
557 /*
558 =item read_bmp_pal(ig, im, count)
559
560 Reads count palette entries from the file and add them to the image.
561
562 Returns non-zero on success.
563
564 =cut
565 */
566 static int
567 read_bmp_pal(io_glue *ig, i_img *im, int count) {
568   int i;
569   int r, g, b, x;
570   i_color c;
571   
572   for (i = 0; i < count; ++i) {
573     if (!read_packed(ig, "CCCC", &b, &g, &r, &x)) {
574       i_push_error(0, "reading BMP palette");
575       return 0;
576     }
577     c.channel[0] = r;
578     c.channel[1] = g;
579     c.channel[2] = b;
580     if (i_addcolors(im, &c, 1) < 0)
581       return 0;
582   }
583   
584   return 1;
585 }
586
587 /*
588 =item read_1bit_bmp(ig, xsize, ysize, clr_used)
589
590 Reads in the palette and image data for a 1-bit/pixel image.
591
592 Returns the image or NULL.
593
594 =cut
595 */
596 static i_img *
597 read_1bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used) {
598   i_img *im;
599   int x, y, lasty, yinc;
600   i_palidx *line, *p;
601   unsigned char *packed;
602   int line_size = (xsize + 7)/8;
603   int byte, bit;
604   unsigned char *in;
605
606   line_size = (line_size+3) / 4 * 4;
607
608   if (ysize > 0) {
609     y = ysize-1;
610     lasty = -1;
611     yinc = -1;
612   }
613   else {
614     /* when ysize is -ve it's a top-down image */
615     ysize = -ysize;
616     y = 0;
617     lasty = ysize;
618     yinc = 1;
619   }
620   im = i_img_pal_new(xsize, ysize, 3, 256);
621   if (!clr_used)
622     clr_used = 2;
623   if (!read_bmp_pal(ig, im, clr_used)) {
624     i_img_destroy(im);
625     return NULL;
626   }
627
628   packed = mymalloc(line_size);
629   line = mymalloc(xsize+8);
630   while (y != lasty) {
631     if (ig->readcb(ig, packed, line_size) != line_size) {
632       myfree(packed);
633       myfree(line);
634       i_push_error(0, "reading 1-bit bmp data");
635       i_img_destroy(im);
636       return NULL;
637     }
638     in = packed;
639     bit = 0x80;
640     p = line;
641     for (x = 0; x < xsize; ++x) {
642       *p++ = (*in & bit) ? 1 : 0;
643       bit >>= 1;
644       if (!bit) {
645         ++in;
646         bit = 0x80;
647       }
648     }
649     i_ppal(im, 0, xsize, y, line);
650     y += yinc;
651   }
652
653   return im;
654 }
655
656 /*
657 =item read_4bit_bmp(ig, xsize, ysize, clr_used, compression)
658
659 Reads in the palette and image data for a 4-bit/pixel image.
660
661 Returns the image or NULL.
662
663 Hopefully this will be combined with the following function at some
664 point.
665
666 =cut
667 */
668 static i_img *
669 read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used, 
670               int compression) {
671   i_img *im;
672   int x, y, lasty, yinc;
673   i_palidx *line, *p;
674   unsigned char *packed;
675   int line_size = (xsize + 1)/2;
676   unsigned char *in;
677   int size, i;
678
679   line_size = (line_size+3) / 4 * 4;
680
681   if (ysize > 0) {
682     y = ysize-1;
683     lasty = -1;
684     yinc = -1;
685   }
686   else {
687     /* when ysize is -ve it's a top-down image */
688     ysize = -ysize;
689     y = 0;
690     lasty = ysize;
691     yinc = 1;
692   }
693   im = i_img_pal_new(xsize, ysize, 3, 256);
694   if (!clr_used)
695     clr_used = 16;
696   if (!read_bmp_pal(ig, im, clr_used)) {
697     i_img_destroy(im);
698     return NULL;
699   }
700
701   if (line_size < 260)
702     packed = mymalloc(260);
703   else
704     packed = mymalloc(line_size);
705   line = mymalloc(xsize+1);
706   if (compression == BI_RGB) {
707     while (y != lasty) {
708       if (ig->readcb(ig, packed, line_size) != line_size) {
709         myfree(packed);
710         myfree(line);
711         i_push_error(0, "reading 4-bit bmp data");
712         i_img_destroy(im);
713         return NULL;
714       }
715       in = packed;
716       p = line;
717       for (x = 0; x < xsize; x+=2) {
718         *p++ = *in >> 4;
719         *p++ = *in & 0x0F;
720         ++in;
721       }
722       i_ppal(im, 0, xsize, y, line);
723       y += yinc;
724     }
725   }
726   else if (compression == BI_RLE4) {
727     int read_size;
728     int want_high;
729     int count;
730
731     x = 0;
732     while (1) {
733       /* there's always at least 2 bytes in a sequence */
734       if (ig->readcb(ig, packed, 2) != 2) {
735         myfree(packed);
736         myfree(line);
737         i_push_error(0, "missing data during decompression");
738         i_img_destroy(im);
739         return NULL;
740       }
741       else if (packed[0]) {
742         line[0] = packed[1] >> 4;
743         line[1] = packed[1] & 0x0F;
744         for (i = 0; i < packed[0]; i += 2) {
745           if (i < packed[0]-1) 
746             i_ppal(im, x, x+2, y, line);
747           else
748             i_ppal(im, x, x+(packed[0]-i), y, line);
749           x += 2;
750         }
751       } else {
752         switch (packed[1]) {
753         case BMPRLE_ENDOFLINE:
754           x = 0;
755           y += yinc;
756           break;
757
758         case BMPRLE_ENDOFBMP:
759           free(packed);
760           free(line);
761           return im;
762
763         case BMPRLE_DELTA:
764           if (ig->readcb(ig, packed, 2) != 2) {
765             myfree(packed);
766             myfree(line);
767             i_push_error(0, "missing data during decompression");
768             i_img_destroy(im);
769             return NULL;
770           }
771           x += packed[0];
772           y += yinc * packed[1];
773           break;
774
775         default:
776           count = packed[1];
777           size = (count + 1) / 2;
778           read_size = (size+1) / 2 * 2;
779           if (ig->readcb(ig, packed, read_size) != read_size) {
780             myfree(packed);
781             myfree(line);
782             i_push_error(0, "missing data during decompression");
783             /*i_img_destroy(im);*/
784             return im;
785           }
786           for (i = 0; i < size; ++i) {
787             line[0] = packed[i] >> 4;
788             line[1] = packed[i] & 0xF;
789             i_ppal(im, x, x+2, y, line);
790             x += 2;
791           }
792           break;
793         }
794       }
795     }
796   }
797   else { /*if (compression == BI_RLE4) {*/
798     myfree(packed);
799     myfree(line);
800     i_push_error(0, "bad compression for 4-bit image");
801     i_img_destroy(im);
802     return NULL;
803   }
804
805   return im;
806 }
807
808 /*
809 =item read_8bit_bmp(ig, xsize, ysize, clr_used, compression)
810
811 Reads in the palette and image data for a 8-bit/pixel image.
812
813 Returns the image or NULL.
814
815 =cut
816 */
817 static i_img *
818 read_8bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used, 
819               int compression) {
820   i_img *im;
821   int x, y, lasty, yinc;
822   i_palidx *line, *p;
823   int line_size = xsize;
824   unsigned char *in;
825
826   line_size = (line_size+3) / 4 * 4;
827
828   if (ysize > 0) {
829     y = ysize-1;
830     lasty = -1;
831     yinc = -1;
832   }
833   else {
834     /* when ysize is -ve it's a top-down image */
835     ysize = -ysize;
836     y = 0;
837     lasty = ysize;
838     yinc = 1;
839   }
840   im = i_img_pal_new(xsize, ysize, 3, 256);
841   if (!clr_used)
842     clr_used = 256;
843   if (!read_bmp_pal(ig, im, clr_used)) {
844     i_img_destroy(im);
845     return NULL;
846   }
847
848   line = mymalloc(line_size);
849   if (compression == BI_RGB) {
850     while (y != lasty) {
851       if (ig->readcb(ig, line, line_size) != line_size) {
852         myfree(line);
853         i_push_error(0, "reading 8-bit bmp data");
854         i_img_destroy(im);
855         return NULL;
856       }
857       i_ppal(im, 0, xsize, y, line);
858       y += yinc;
859     }
860   }
861   else if (compression == BI_RLE8) {
862     int read_size;
863     int want_high;
864     int count;
865     unsigned char packed[2];
866
867     x = 0;
868     while (1) {
869       /* there's always at least 2 bytes in a sequence */
870       if (ig->readcb(ig, packed, 2) != 2) {
871         myfree(line);
872         i_push_error(0, "missing data during decompression");
873         i_img_destroy(im);
874         return NULL;
875       }
876       if (packed[0]) {
877         memset(line, packed[1], packed[0]);
878         i_ppal(im, x, x+packed[0], y, line);
879         x += packed[0];
880       } else {
881         switch (packed[1]) {
882         case BMPRLE_ENDOFLINE:
883           x = 0;
884           y += yinc;
885           break;
886
887         case BMPRLE_ENDOFBMP:
888           free(line);
889           return im;
890
891         case BMPRLE_DELTA:
892           if (ig->readcb(ig, packed, 2) != 2) {
893             myfree(line);
894             i_push_error(0, "missing data during decompression");
895             i_img_destroy(im);
896             return NULL;
897           }
898           x += packed[0];
899           y += yinc * packed[1];
900           break;
901
902         default:
903           count = packed[1];
904           read_size = (count+1) / 2 * 2;
905           if (ig->readcb(ig, line, read_size) != read_size) {
906             myfree(line);
907             i_push_error(0, "missing data during decompression");
908             i_img_destroy(im);
909             return NULL;
910           }
911           i_ppal(im, x, x+count, y, line);
912           x += count;
913           break;
914         }
915       }
916     }
917   }
918   else { 
919     myfree(line);
920     i_push_errorf(0, "unknown 8-bit BMP compression %d", compression);
921     i_img_destroy(im);
922     return NULL;
923   }
924
925   return im;
926 }
927
928 struct bm_masks {
929   unsigned masks[3];
930   int shifts[3];
931 };
932 static struct bm_masks std_masks[] =
933 {
934   { /* 16-bit */
935     { 0770000, 00007700, 00000077, },
936     { 10, 4, -2, },
937   },
938   { /* 24-bit */
939     { 0xFF0000, 0x00FF00, 0x0000FF, },
940     {       16,        8,        0, },
941   },
942   { /* 32-bit */
943     { 0xFF0000, 0x00FF00, 0x0000FF, },
944     {       16,        8,        0, },
945   },
946 };
947
948 /*
949 =item read_direct_bmp(ig, xsize, ysize, bit_count, clr_used, compression)
950
951 Skips the palette and reads in the image data for a direct colour image.
952
953 Returns the image or NULL.
954
955 =cut
956 */
957 static i_img *
958 read_direct_bmp(io_glue *ig, int xsize, int ysize, int bit_count, 
959                 int clr_used, int compression) {
960   i_img *im;
961   int x, y, lasty, yinc;
962   i_color *line, *p;
963   unsigned char *in;
964   int pix_size = bit_count / 8;
965   int line_size = xsize * pix_size;
966   struct bm_masks masks;
967   char unpack_code[2] = "";
968   int i;
969   int extras;
970   char junk[4];
971   
972   unpack_code[0] = *("v3V"+pix_size-2);
973   unpack_code[1] = '\0';
974
975   line_size = (line_size+3) / 4 * 4;
976   extras = line_size - xsize * pix_size;
977
978   if (ysize > 0) {
979     y = ysize-1;
980     lasty = -1;
981     yinc = -1;
982   }
983   else {
984     /* when ysize is -ve it's a top-down image */
985     ysize = -ysize;
986     y = 0;
987     lasty = ysize;
988     yinc = 1;
989   }
990   line = mymalloc(line_size);
991   if (compression == BI_RGB) {
992     masks = std_masks[pix_size-2];
993     
994     /* there's a potential "palette" after the header */
995     for (i = 0; i < clr_used; ++clr_used) {
996       char buf[4];
997       if (ig->readcb(ig, buf, 4) != 4) {
998         i_push_error(0, "skipping colors");
999         return 0;
1000       }
1001     }
1002   }
1003   else if (compression == BI_BITFIELDS) {
1004     int pos, bit;
1005     for (i = 0; i < 3; ++i) {
1006       if (!read_packed(ig, "V", masks.masks+i)) {
1007         i_push_error(0, "reading pixel masks");
1008         return 0;
1009       }
1010       /* work out a shift for the mask */
1011       pos = 0;
1012       bit = masks.masks[i] & -masks.masks[i];
1013       while (bit) {
1014         ++pos;
1015         bit >>= 1;
1016       }
1017       masks.shifts[i] = pos - 8;
1018     }
1019   }
1020
1021   im = i_img_empty(NULL, xsize, ysize);
1022
1023   line = mymalloc(sizeof(i_color) * xsize);
1024   while (y != lasty) {
1025     p = line;
1026     for (x = 0; x < xsize; ++x) {
1027       unsigned pixel;
1028       if (!read_packed(ig, unpack_code, &pixel)) {
1029         i_push_error(0, "reading image data");
1030         myfree(line);
1031         i_img_destroy(im);
1032         return NULL;
1033       }
1034       for (i = 0; i < 3; ++i) {
1035         if (masks.shifts[i] > 0)
1036           p->channel[i] = (pixel & masks.masks[i]) >> masks.shifts[i];
1037         else 
1038           p->channel[i] = (pixel & masks.masks[i]) << -masks.shifts[i];
1039       }
1040       ++p;
1041     }
1042     i_plin(im, 0, xsize, y, line);
1043     if (extras)
1044       ig->readcb(ig, junk, extras);
1045     y += yinc;
1046   }
1047   myfree(line);
1048
1049   return im;
1050 }
1051
1052 /*
1053 =head1 SEE ALSO
1054
1055 Imager(3)
1056
1057 =head1 AUTHOR
1058
1059 Tony Cook <tony@develop-help.com>
1060
1061 =head1 RESTRICTIONS
1062
1063 Cannot save as compressed BMP.
1064
1065 =head1 BUGS
1066
1067 Doesn't handle OS/2 bitmaps.
1068
1069 16-bit/pixel images haven't been tested.  (I need an image).
1070
1071 BI_BITFIELDS compression hasn't been tested (I need an image).
1072
1073 =cut
1074 */