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