blob: db30efd9b26a0c6fc00999e0864c9420e96dfc79 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% DDDD IIIII BBBB %
7% D D I B B %
8% D D I BBBB %
9% D D I B B %
10% DDDD IIIII BBBB %
11% %
12% %
13% Read/Write Windows DIB Image Format %
14% %
15% Software Design %
16% John Cristy %
17% July 1992 %
18% %
19% %
cristy16af1cb2009-12-11 21:38:29 +000020% Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
42#include "magick/studio.h"
43#include "magick/blob.h"
44#include "magick/blob-private.h"
45#include "magick/cache.h"
46#include "magick/color.h"
cristy316d5172009-09-17 19:31:25 +000047#include "magick/colormap-private.h"
cristy3ed852e2009-09-05 21:47:34 +000048#include "magick/color-private.h"
49#include "magick/colorspace.h"
50#include "magick/draw.h"
51#include "magick/exception.h"
52#include "magick/exception-private.h"
53#include "magick/geometry.h"
54#include "magick/image.h"
55#include "magick/image-private.h"
56#include "magick/list.h"
57#include "magick/log.h"
58#include "magick/magick.h"
59#include "magick/memory_.h"
60#include "magick/monitor.h"
61#include "magick/monitor-private.h"
62#include "magick/quantum-private.h"
63#include "magick/static.h"
64#include "magick/string_.h"
65#include "magick/module.h"
66#include "magick/transform.h"
67
68/*
69 Typedef declarations.
70*/
71typedef struct _DIBInfo
72{
73 unsigned long
74 size;
75
76 long
77 width,
78 height;
79
80 unsigned short
81 planes,
82 bits_per_pixel;
83
84 unsigned long
85 compression,
86 image_size,
87 x_pixels,
88 y_pixels,
89 number_colors,
90 red_mask,
91 green_mask,
92 blue_mask,
93 alpha_mask,
94 colors_important;
95
96 long
97 colorspace;
98
99 PointInfo
100 red_primary,
101 green_primary,
102 blue_primary,
103 gamma_scale;
104} DIBInfo;
105
106/*
107 Forward declarations.
108*/
109static MagickBooleanType
110 WriteDIBImage(const ImageInfo *,Image *);
111
112/*
113%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
114% %
115% %
116% %
117% D e c o d e I m a g e %
118% %
119% %
120% %
121%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
122%
123% DecodeImage unpacks the packed image pixels into runlength-encoded
124% pixel packets.
125%
126% The format of the DecodeImage method is:
127%
128% MagickBooleanType DecodeImage(Image *image,
129% const MagickBooleanType compression,unsigned char *pixels)
130%
131% A description of each parameter follows:
132%
133% o image: the address of a structure of type Image.
134%
135% o compression: A value of 1 means the compressed pixels are runlength
136% encoded for a 256-color bitmap. A value of 2 means a 16-color bitmap.
137%
138% o pixels: The address of a byte (8 bits) array of pixel data created by
139% the decoding process.
140%
141*/
142
143static inline size_t MagickMin(const size_t x,const size_t y)
144{
145 if (x < y)
146 return(x);
147 return(y);
148}
149
150static MagickBooleanType DecodeImage(Image *image,
151 const MagickBooleanType compression,unsigned char *pixels)
152{
153#if !defined(__WINDOWS__) || defined(__MINGW32__)
154#define BI_RGB 0
155#define BI_RLE8 1
156#define BI_RLE4 2
157#define BI_BITFIELDS 3
158#endif
159
160 int
161 count;
162
163 long
164 y;
165
166 register long
167 i,
168 x;
169
170 register unsigned char
171 *p,
172 *q;
173
174 unsigned char
175 byte;
176
177 assert(image != (Image *) NULL);
178 assert(image->signature == MagickSignature);
179 if (image->debug != MagickFalse)
180 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
181 assert(pixels != (unsigned char *) NULL);
182 (void) ResetMagickMemory(pixels,0,(size_t) image->columns*image->rows*
183 sizeof(*pixels));
184 byte=0;
185 x=0;
186 p=pixels;
187 q=pixels+(size_t) image->columns*image->rows;
188 for (y=0; y < (long) image->rows; )
189 {
190 if ((p < pixels) || (p >= q))
191 break;
192 count=ReadBlobByte(image);
193 if (count == EOF)
194 break;
195 if (count != 0)
196 {
197 count=(int) MagickMin((size_t) count,(size_t) (q-p));
198 /*
199 Encoded mode.
200 */
201 byte=(unsigned char) ReadBlobByte(image);
202 if (compression == BI_RLE8)
203 {
204 for (i=0; i < count; i++)
205 *p++=(unsigned char) byte;
206 }
207 else
208 {
209 for (i=0; i < count; i++)
210 *p++=(unsigned char)
211 ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
212 }
213 x+=count;
214 }
215 else
216 {
217 /*
218 Escape mode.
219 */
220 count=ReadBlobByte(image);
221 if (count == 0x01)
222 return(MagickTrue);
223 switch (count)
224 {
225 case 0x00:
226 {
227 /*
228 End of line.
229 */
230 x=0;
231 y++;
232 p=pixels+y*image->columns;
233 break;
234 }
235 case 0x02:
236 {
237 /*
238 Delta mode.
239 */
240 x+=ReadBlobByte(image);
241 y+=ReadBlobByte(image);
242 p=pixels+y*image->columns+x;
243 break;
244 }
245 default:
246 {
247 /*
248 Absolute mode.
249 */
250 count=(int) MagickMin((size_t) count,(size_t) (q-p));
251 if (compression == BI_RLE8)
252 for (i=0; i < count; i++)
253 *p++=(unsigned char) ReadBlobByte(image);
254 else
255 for (i=0; i < count; i++)
256 {
257 if ((i & 0x01) == 0)
258 byte=(unsigned char) ReadBlobByte(image);
259 *p++=(unsigned char)
260 ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
261 }
262 x+=count;
263 /*
264 Read pad byte.
265 */
266 if (compression == BI_RLE8)
267 {
268 if ((count & 0x01) != 0)
269 (void) ReadBlobByte(image);
270 }
271 else
272 if (((count & 0x03) == 1) || ((count & 0x03) == 2))
273 (void) ReadBlobByte(image);
274 break;
275 }
276 }
277 }
278 if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
279 break;
280 }
281 (void) ReadBlobByte(image); /* end of line */
282 (void) ReadBlobByte(image);
283 return(MagickTrue);
284}
285
286/*
287%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288% %
289% %
290% %
291% E n c o d e I m a g e %
292% %
293% %
294% %
295%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296%
297% EncodeImage compresses pixels using a runlength encoded format.
298%
299% The format of the EncodeImage method is:
300%
301% static MagickBooleanType EncodeImage(Image *image,
302% const unsigned long bytes_per_line,const unsigned char *pixels,
303% unsigned char *compressed_pixels)
304%
305% A description of each parameter follows:
306%
307% o image: The image.
308%
309% o bytes_per_line: the number of bytes in a scanline of compressed pixels
310%
311% o pixels: The address of a byte (8 bits) array of pixel data created by
312% the compression process.
313%
314% o compressed_pixels: The address of a byte (8 bits) array of compressed
315% pixel data.
316%
317*/
318static size_t EncodeImage(Image *image,const unsigned long bytes_per_line,
319 const unsigned char *pixels,unsigned char *compressed_pixels)
320{
321 long
322 y;
323
324 register const unsigned char
325 *p;
326
327 register long
328 i,
329 x;
330
331 register unsigned char
332 *q;
333
334 /*
335 Runlength encode pixels.
336 */
337 assert(image != (Image *) NULL);
338 assert(image->signature == MagickSignature);
339 if (image->debug != MagickFalse)
340 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
341 assert(pixels != (const unsigned char *) NULL);
342 assert(compressed_pixels != (unsigned char *) NULL);
343 p=pixels;
344 q=compressed_pixels;
345 i=0;
346 for (y=0; y < (long) image->rows; y++)
347 {
348 for (x=0; x < (long) bytes_per_line; x+=i)
349 {
350 /*
351 Determine runlength.
352 */
353 for (i=1; ((x+i) < (long) bytes_per_line); i++)
354 if ((*(p+i) != *p) || (i == 255))
355 break;
356 *q++=(unsigned char) i;
357 *q++=(*p);
358 p+=i;
359 }
360 /*
361 End of line.
362 */
363 *q++=0x00;
364 *q++=0x00;
365 if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
366 break;
367 }
368 /*
369 End of bitmap.
370 */
371 *q++=0;
372 *q++=0x01;
373 return((size_t) (q-compressed_pixels));
374}
375
376/*
377%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
378% %
379% %
380% %
381% I s D I B %
382% %
383% %
384% %
385%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
386%
387% IsDIB() returns MagickTrue if the image format type, identified by the
388% magick string, is DIB.
389%
390% The format of the IsDIB method is:
391%
392% MagickBooleanType IsDIB(const unsigned char *magick,const size_t length)
393%
394% A description of each parameter follows:
395%
396% o magick: compare image format pattern against these bytes.
397%
398% o length: Specifies the length of the magick string.
399%
400*/
401static MagickBooleanType IsDIB(const unsigned char *magick,const size_t length)
402{
403 if (length < 2)
404 return(MagickFalse);
405 if (memcmp(magick,"\050\000",2) == 0)
406 return(MagickTrue);
407 return(MagickFalse);
408}
409
410/*
411%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
412% %
413% %
414% %
415% R e a d D I B I m a g e %
416% %
417% %
418% %
419%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
420%
421% ReadDIBImage() reads a Microsoft Windows bitmap image file and
422% returns it. It allocates the memory necessary for the new Image structure
423% and returns a pointer to the new image.
424%
425% The format of the ReadDIBImage method is:
426%
427% image=ReadDIBImage(image_info)
428%
429% A description of each parameter follows:
430%
431% o image_info: the image info.
432%
433% o exception: return any errors or warnings in this structure.
434%
435*/
436
437static inline long MagickAbsoluteValue(const long x)
438{
439 if (x < 0)
440 return(-x);
441 return(x);
442}
443
444static inline size_t MagickMax(const size_t x,const size_t y)
445{
446 if (x > y)
447 return(x);
448 return(y);
449}
450
451static Image *ReadDIBImage(const ImageInfo *image_info,ExceptionInfo *exception)
452{
453 DIBInfo
454 dib_info;
455
456 Image
457 *image;
458
459 IndexPacket
460 index;
461
462 long
463 bit,
464 y;
465
466 MagickBooleanType
467 status;
468
469 register IndexPacket
470 *indexes;
471
472 register long
473 x;
474
475 register PixelPacket
476 *q;
477
478 register long
479 i;
480
481 register unsigned char
482 *p;
483
484 size_t
485 length;
486
487 ssize_t
488 count;
489
490 unsigned char
491 *pixels;
492
493 unsigned long
494 bytes_per_line;
495
496 /*
497 Open image file.
498 */
499 assert(image_info != (const ImageInfo *) NULL);
500 assert(image_info->signature == MagickSignature);
501 if (image_info->debug != MagickFalse)
502 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
503 image_info->filename);
504 assert(exception != (ExceptionInfo *) NULL);
505 assert(exception->signature == MagickSignature);
506 image=AcquireImage(image_info);
507 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
508 if (status == MagickFalse)
509 {
510 image=DestroyImageList(image);
511 return((Image *) NULL);
512 }
513 /*
514 Determine if this a DIB file.
515 */
516 (void) ResetMagickMemory(&dib_info,0,sizeof(dib_info));
517 dib_info.size=ReadBlobLSBLong(image);
518 if (dib_info.size!=40)
519 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
520 /*
521 Microsoft Windows 3.X DIB image file.
522 */
523 dib_info.width=(short) ReadBlobLSBLong(image);
524 dib_info.height=(short) ReadBlobLSBLong(image);
525 dib_info.planes=ReadBlobLSBShort(image);
526 dib_info.bits_per_pixel=ReadBlobLSBShort(image);
527 dib_info.compression=ReadBlobLSBLong(image);
528 dib_info.image_size=ReadBlobLSBLong(image);
529 dib_info.x_pixels=ReadBlobLSBLong(image);
530 dib_info.y_pixels=ReadBlobLSBLong(image);
531 dib_info.number_colors=ReadBlobLSBLong(image);
532 dib_info.colors_important=ReadBlobLSBLong(image);
533 if ((dib_info.compression == BI_BITFIELDS) &&
534 ((dib_info.bits_per_pixel == 16) || (dib_info.bits_per_pixel == 32)))
535 {
536 dib_info.red_mask=ReadBlobLSBLong(image);
537 dib_info.green_mask=ReadBlobLSBLong(image);
538 dib_info.blue_mask=ReadBlobLSBLong(image);
539 }
540 image->matte=dib_info.bits_per_pixel == 32 ? MagickTrue : MagickFalse;
541 image->columns=(unsigned long) MagickAbsoluteValue(dib_info.width);
542 image->rows=(unsigned long) MagickAbsoluteValue(dib_info.height);
543 image->depth=8;
544 if ((dib_info.number_colors != 0) || (dib_info.bits_per_pixel < 16))
545 {
546 image->storage_class=PseudoClass;
547 image->colors=dib_info.number_colors;
548 if (image->colors == 0)
549 image->colors=1L << dib_info.bits_per_pixel;
550 }
551 if (image_info->size)
552 {
553 RectangleInfo
554 geometry;
555
556 MagickStatusType
557 flags;
558
559 flags=ParseAbsoluteGeometry(image_info->size,&geometry);
560 if (flags & WidthValue)
561 if ((geometry.width != 0) && (geometry.width < image->columns))
562 image->columns=geometry.width;
563 if (flags & HeightValue)
564 if ((geometry.height != 0) && (geometry.height < image->rows))
565 image->rows=geometry.height;
566 }
567 if (image->storage_class == PseudoClass)
568 {
569 size_t
570 length,
571 packet_size;
572
573 unsigned char
574 *dib_colormap;
575
576 /*
577 Read DIB raster colormap.
578 */
579 if (AcquireImageColormap(image,image->colors) == MagickFalse)
580 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
581 length=(size_t) image->colors;
582 dib_colormap=(unsigned char *) AcquireQuantumMemory(length,
583 4*sizeof(*dib_colormap));
584 if (dib_colormap == (unsigned char *) NULL)
585 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
586 packet_size=4;
587 count=ReadBlob(image,packet_size*image->colors,dib_colormap);
588 if (count != (ssize_t) (packet_size*image->colors))
589 ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
590 p=dib_colormap;
591 for (i=0; i < (long) image->colors; i++)
592 {
593 image->colormap[i].blue=ScaleCharToQuantum(*p++);
594 image->colormap[i].green=ScaleCharToQuantum(*p++);
595 image->colormap[i].red=ScaleCharToQuantum(*p++);
596 if (packet_size == 4)
597 p++;
598 }
599 dib_colormap=(unsigned char *) RelinquishMagickMemory(dib_colormap);
600 }
601 /*
602 Read image data.
603 */
604 if (dib_info.compression == BI_RLE4)
605 dib_info.bits_per_pixel<<=1;
606 bytes_per_line=4*((image->columns*dib_info.bits_per_pixel+31)/32);
607 length=bytes_per_line*image->rows;
608 pixels=(unsigned char *) AcquireQuantumMemory((size_t) image->rows,
609 MagickMax(bytes_per_line,image->columns+256UL)*sizeof(*pixels));
610 if (pixels == (unsigned char *) NULL)
611 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
612 if ((dib_info.compression == BI_RGB) ||
613 (dib_info.compression == BI_BITFIELDS))
614 {
615 count=ReadBlob(image,length,pixels);
616 if (count != (ssize_t) (length))
617 ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
618 }
619 else
620 {
621 /*
622 Convert run-length encoded raster pixels.
623 */
624 status=DecodeImage(image,dib_info.compression ? MagickTrue : MagickFalse,
625 pixels);
626 if (status == MagickFalse)
627 ThrowReaderException(CorruptImageError,"UnableToRunlengthDecodeImage");
628 }
629 /*
630 Initialize image structure.
631 */
632 image->units=PixelsPerCentimeterResolution;
633 image->x_resolution=(double) dib_info.x_pixels/100.0;
634 image->y_resolution=(double) dib_info.y_pixels/100.0;
635 /*
636 Convert DIB raster image to pixel packets.
637 */
638 switch (dib_info.bits_per_pixel)
639 {
640 case 1:
641 {
642 /*
643 Convert bitmap scanline.
644 */
645 for (y=(long) image->rows-1; y >= 0; y--)
646 {
647 p=pixels+(image->rows-y-1)*bytes_per_line;
648 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
649 if (q == (PixelPacket *) NULL)
650 break;
651 indexes=GetAuthenticIndexQueue(image);
652 for (x=0; x < ((long) image->columns-7); x+=8)
653 {
654 for (bit=0; bit < 8; bit++)
655 {
656 index=(IndexPacket) ((*p) & (0x80 >> bit) ? 0x01 : 0x00);
657 indexes[x+bit]=index;
658 *q++=image->colormap[(long) index];
659 }
660 p++;
661 }
662 if ((image->columns % 8) != 0)
663 {
664 for (bit=0; bit < (long) (image->columns % 8); bit++)
665 {
666 index=(IndexPacket) ((*p) & (0x80 >> bit) ? 0x01 : 0x00);
667 indexes[x+bit]=index;
668 *q++=image->colormap[(long) index];
669 }
670 p++;
671 }
672 if (SyncAuthenticPixels(image,exception) == MagickFalse)
673 break;
674 if (image->previous == (Image *) NULL)
675 {
676 status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
677 image->rows);
678 if (status == MagickFalse)
679 break;
680 }
681 }
682 break;
683 }
684 case 4:
685 {
686 /*
687 Convert PseudoColor scanline.
688 */
689 for (y=(long) image->rows-1; y >= 0; y--)
690 {
691 p=pixels+(image->rows-y-1)*bytes_per_line;
692 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
693 if (q == (PixelPacket *) NULL)
694 break;
695 indexes=GetAuthenticIndexQueue(image);
696 for (x=0; x < ((long) image->columns-1); x+=2)
697 {
698 index=ConstrainColormapIndex(image,(*p >> 4) & 0xf);
699 indexes[x]=index;
700 *q++=image->colormap[(long) index];
701 index=ConstrainColormapIndex(image,*p & 0xf);
702 indexes[x+1]=index;
703 *q++=image->colormap[(long) index];
704 p++;
705 }
706 if ((image->columns % 2) != 0)
707 {
708 index=ConstrainColormapIndex(image,(*p >> 4) & 0xf);
709 indexes[x]=index;
710 *q++=image->colormap[(long) index];
711 p++;
712 }
713 if (SyncAuthenticPixels(image,exception) == MagickFalse)
714 break;
715 if (image->previous == (Image *) NULL)
716 {
717 status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
718 image->rows);
719 if (status == MagickFalse)
720 break;
721 }
722 }
723 break;
724 }
725 case 8:
726 {
727 /*
728 Convert PseudoColor scanline.
729 */
730 if ((dib_info.compression == BI_RLE8) ||
731 (dib_info.compression == BI_RLE4))
732 bytes_per_line=image->columns;
733 for (y=(long) image->rows-1; y >= 0; y--)
734 {
735 p=pixels+(image->rows-y-1)*bytes_per_line;
736 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
737 if (q == (PixelPacket *) NULL)
738 break;
739 indexes=GetAuthenticIndexQueue(image);
740 for (x=0; x < (long) image->columns; x++)
741 {
742 index=ConstrainColormapIndex(image,*p);
743 indexes[x]=index;
744 *q=image->colormap[(long) index];
745 p++;
746 q++;
747 }
748 if (SyncAuthenticPixels(image,exception) == MagickFalse)
749 break;
750 if (image->previous == (Image *) NULL)
751 {
752 status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
753 image->rows);
754 if (status == MagickFalse)
755 break;
756 }
757 }
758 break;
759 }
760 case 16:
761 {
762 unsigned short
763 word;
764
765 /*
766 Convert PseudoColor scanline.
767 */
768 image->storage_class=DirectClass;
769 if (dib_info.compression == BI_RLE8)
770 bytes_per_line=2*image->columns;
771 for (y=(long) image->rows-1; y >= 0; y--)
772 {
773 p=pixels+(image->rows-y-1)*bytes_per_line;
774 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
775 if (q == (PixelPacket *) NULL)
776 break;
777 for (x=0; x < (long) image->columns; x++)
778 {
779 word=(*p++);
780 word|=(*p++ << 8);
781 if (dib_info.red_mask == 0)
782 {
783 q->red=ScaleCharToQuantum(ScaleColor5to8((unsigned char)
784 ((word >> 10) & 0x1f)));
785 q->green=ScaleCharToQuantum(ScaleColor5to8((unsigned char)
786 ((word >> 5) & 0x1f)));
787 q->blue=ScaleCharToQuantum(ScaleColor5to8((unsigned char)
788 (word & 0x1f)));
789 }
790 else
791 {
792 q->red=ScaleCharToQuantum(ScaleColor5to8((unsigned char)
793 ((word >> 11) & 0x1f)));
794 q->green=ScaleCharToQuantum(ScaleColor6to8((unsigned char)
795 ((word >> 5) & 0x3f)));
796 q->blue=ScaleCharToQuantum(ScaleColor5to8((unsigned char)
797 (word & 0x1f)));
798 }
799 q++;
800 }
801 if (SyncAuthenticPixels(image,exception) == MagickFalse)
802 break;
803 if (image->previous == (Image *) NULL)
804 {
805 status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
806 image->rows);
807 if (status == MagickFalse)
808 break;
809 }
810 }
811 break;
812 }
813 case 24:
814 case 32:
815 {
816 /*
817 Convert DirectColor scanline.
818 */
819 for (y=(long) image->rows-1; y >= 0; y--)
820 {
821 p=pixels+(image->rows-y-1)*bytes_per_line;
822 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
823 if (q == (PixelPacket *) NULL)
824 break;
825 for (x=0; x < (long) image->columns; x++)
826 {
827 q->blue=ScaleCharToQuantum(*p++);
828 q->green=ScaleCharToQuantum(*p++);
829 q->red=ScaleCharToQuantum(*p++);
830 if (image->matte != MagickFalse)
831 q->opacity=ScaleCharToQuantum(*p++);
832 q++;
833 }
834 if (SyncAuthenticPixels(image,exception) == MagickFalse)
835 break;
836 if (image->previous == (Image *) NULL)
837 {
838 status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
839 image->rows);
840 if (status == MagickFalse)
841 break;
842 }
843 }
844 break;
845 }
846 default:
847 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
848 }
849 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
850 if (EOFBlob(image) != MagickFalse)
851 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
852 image->filename);
853 if (dib_info.height < 0)
854 {
855 Image
856 *flipped_image;
857
858 /*
859 Correct image orientation.
860 */
861 flipped_image=FlipImage(image,exception);
862 if (flipped_image == (Image *) NULL)
863 {
864 image=DestroyImageList(image);
865 return((Image *) NULL);
866 }
867 DuplicateBlob(flipped_image,image);
868 image=DestroyImage(image);
869 image=flipped_image;
870 }
871 (void) CloseBlob(image);
872 return(GetFirstImageInList(image));
873}
874
875/*
876%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
877% %
878% %
879% %
880% R e g i s t e r D I B I m a g e %
881% %
882% %
883% %
884%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
885%
886% RegisterDIBImage() adds attributes for the DIB image format to
887% the list of supported formats. The attributes include the image format
888% tag, a method to read and/or write the format, whether the format
889% supports the saving of more than one frame to the same file or blob,
890% whether the format supports native in-memory I/O, and a brief
891% description of the format.
892%
893% The format of the RegisterDIBImage method is:
894%
895% unsigned long RegisterDIBImage(void)
896%
897*/
898ModuleExport unsigned long RegisterDIBImage(void)
899{
900 MagickInfo
901 *entry;
902
903 entry=SetMagickInfo("DIB");
904 entry->decoder=(DecodeImageHandler *) ReadDIBImage;
905 entry->encoder=(EncodeImageHandler *) WriteDIBImage;
906 entry->magick=(IsImageFormatHandler *) IsDIB;
907 entry->adjoin=MagickFalse;
908 entry->stealth=MagickTrue;
909 entry->description=ConstantString(
910 "Microsoft Windows 3.X Packed Device-Independent Bitmap");
911 entry->module=ConstantString("DIB");
912 (void) RegisterMagickInfo(entry);
913 return(MagickImageCoderSignature);
914}
915
916/*
917%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
918% %
919% %
920% %
921% U n r e g i s t e r D I B I m a g e %
922% %
923% %
924% %
925%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
926%
927% UnregisterDIBImage() removes format registrations made by the
928% DIB module from the list of supported formats.
929%
930% The format of the UnregisterDIBImage method is:
931%
932% UnregisterDIBImage(void)
933%
934*/
935ModuleExport void UnregisterDIBImage(void)
936{
937 (void) UnregisterMagickInfo("DIB");
938}
939
940/*
941%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
942% %
943% %
944% %
945% W r i t e D I B I m a g e %
946% %
947% %
948% %
949%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
950%
951% WriteDIBImage() writes an image in Microsoft Windows bitmap encoded
952% image format.
953%
954% The format of the WriteDIBImage method is:
955%
956% MagickBooleanType WriteDIBImage(const ImageInfo *image_info,Image *image)
957%
958% A description of each parameter follows.
959%
960% o image_info: the image info.
961%
962% o image: The image.
963%
964*/
965static MagickBooleanType WriteDIBImage(const ImageInfo *image_info,Image *image)
966{
967 DIBInfo
968 dib_info;
969
970 long
971 y;
972
973 MagickBooleanType
974 status;
975
976 register const IndexPacket
977 *indexes;
978
979 register const PixelPacket
980 *p;
981
982 register long
983 i,
984 x;
985
986 register unsigned char
987 *q;
988
989 unsigned char
990 *dib_data,
991 *pixels;
992
993 unsigned long
994 bytes_per_line;
995
996 /*
997 Open output image file.
998 */
999 assert(image_info != (const ImageInfo *) NULL);
1000 assert(image_info->signature == MagickSignature);
1001 assert(image != (Image *) NULL);
1002 assert(image->signature == MagickSignature);
1003 if (image->debug != MagickFalse)
1004 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1005 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1006 if (status == MagickFalse)
1007 return(status);
1008 /*
1009 Initialize DIB raster file header.
1010 */
1011 if (image->colorspace != RGBColorspace)
1012 (void) TransformImageColorspace(image,RGBColorspace);
1013 if (image->storage_class == DirectClass)
1014 {
1015 /*
1016 Full color DIB raster.
1017 */
1018 dib_info.number_colors=0;
1019 dib_info.bits_per_pixel=(unsigned short) (image->matte ? 32 : 24);
1020 }
1021 else
1022 {
1023 /*
1024 Colormapped DIB raster.
1025 */
1026 dib_info.bits_per_pixel=8;
1027 if (image_info->depth > 8)
1028 dib_info.bits_per_pixel=16;
1029 if (IsMonochromeImage(image,&image->exception) != MagickFalse)
1030 dib_info.bits_per_pixel=1;
1031 dib_info.number_colors=(dib_info.bits_per_pixel == 16) ? 0 :
1032 (1UL << dib_info.bits_per_pixel);
1033 }
1034 bytes_per_line=4*((image->columns*dib_info.bits_per_pixel+31)/32);
1035 dib_info.size=40;
1036 dib_info.width=(long) image->columns;
1037 dib_info.height=(long) image->rows;
1038 dib_info.planes=1;
1039 dib_info.compression=(unsigned long) (dib_info.bits_per_pixel == 16 ?
1040 BI_BITFIELDS : BI_RGB);
1041 dib_info.image_size=bytes_per_line*image->rows;
1042 dib_info.x_pixels=75*39;
1043 dib_info.y_pixels=75*39;
1044 switch (image->units)
1045 {
1046 case UndefinedResolution:
1047 case PixelsPerInchResolution:
1048 {
1049 dib_info.x_pixels=(unsigned long) (100.0*image->x_resolution/2.54);
1050 dib_info.y_pixels=(unsigned long) (100.0*image->y_resolution/2.54);
1051 break;
1052 }
1053 case PixelsPerCentimeterResolution:
1054 {
1055 dib_info.x_pixels=(unsigned long) (100.0*image->x_resolution);
1056 dib_info.y_pixels=(unsigned long) (100.0*image->y_resolution);
1057 break;
1058 }
1059 }
1060 dib_info.colors_important=dib_info.number_colors;
1061 /*
1062 Convert MIFF to DIB raster pixels.
1063 */
1064 pixels=(unsigned char *) AcquireQuantumMemory(dib_info.image_size,
1065 sizeof(*pixels));
1066 if (pixels == (unsigned char *) NULL)
1067 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1068 (void) ResetMagickMemory(pixels,0,dib_info.image_size);
1069 switch (dib_info.bits_per_pixel)
1070 {
1071 case 1:
1072 {
1073 register unsigned char
1074 bit,
1075 byte;
1076
1077 /*
1078 Convert PseudoClass image to a DIB monochrome image.
1079 */
1080 for (y=0; y < (long) image->rows; y++)
1081 {
1082 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1083 if (p == (const PixelPacket *) NULL)
1084 break;
1085 indexes=GetVirtualIndexQueue(image);
1086 q=pixels+(image->rows-y-1)*bytes_per_line;
1087 bit=0;
1088 byte=0;
1089 for (x=0; x < (long) image->columns; x++)
1090 {
1091 byte<<=1;
1092 byte|=indexes[x] != 0 ? 0x01 : 0x00;
1093 bit++;
1094 if (bit == 8)
1095 {
1096 *q++=byte;
1097 bit=0;
1098 byte=0;
1099 }
1100 p++;
1101 }
1102 if (bit != 0)
1103 {
1104 *q++=(unsigned char) (byte << (8-bit));
1105 x++;
1106 }
1107 for (x=(long) (image->columns+7)/8; x < (long) bytes_per_line; x++)
1108 *q++=0x00;
1109 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1110 if (status == MagickFalse)
1111 break;
1112 }
1113 break;
1114 }
1115 case 8:
1116 {
1117 /*
1118 Convert PseudoClass packet to DIB pixel.
1119 */
1120 for (y=0; y < (long) image->rows; y++)
1121 {
1122 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1123 if (p == (const PixelPacket *) NULL)
1124 break;
1125 indexes=GetVirtualIndexQueue(image);
1126 q=pixels+(image->rows-y-1)*bytes_per_line;
1127 for (x=0; x < (long) image->columns; x++)
1128 *q++=(unsigned char) indexes[x];
1129 for ( ; x < (long) bytes_per_line; x++)
1130 *q++=0x00;
1131 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1132 if (status == MagickFalse)
1133 break;
1134 }
1135 break;
1136 }
1137 case 16:
1138 {
1139 unsigned short
1140 word;
1141 /*
1142 Convert PseudoClass packet to DIB pixel.
1143 */
1144 for (y=0; y < (long) image->rows; y++)
1145 {
1146 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1147 if (p == (const PixelPacket *) NULL)
1148 break;
1149 q=pixels+(image->rows-y-1)*bytes_per_line;
1150 for (x=0; x < (long) image->columns; x++)
1151 {
1152 word=(unsigned short) ((ScaleColor8to5((unsigned char)
1153 ScaleQuantumToChar(p->red)) << 11) | (ScaleColor8to6((unsigned char)
1154 ScaleQuantumToChar(p->green)) << 5) | (ScaleColor8to5(
1155 (unsigned char) ScaleQuantumToChar((unsigned char) p->blue) << 0)));
1156 *q++=(unsigned char)(word & 0xff);
1157 *q++=(unsigned char)(word >> 8);
1158 p++;
1159 }
1160 for (x=2L*image->columns; x < (long) bytes_per_line; x++)
1161 *q++=0x00;
1162 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1163 if (status == MagickFalse)
1164 break;
1165 }
1166 break;
1167 }
1168 case 24:
1169 case 32:
1170 {
1171 /*
1172 Convert DirectClass packet to DIB RGB pixel.
1173 */
1174 for (y=0; y < (long) image->rows; y++)
1175 {
1176 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1177 if (p == (const PixelPacket *) NULL)
1178 break;
1179 q=pixels+(image->rows-y-1)*bytes_per_line;
1180 for (x=0; x < (long) image->columns; x++)
1181 {
1182 *q++=ScaleQuantumToChar(p->blue);
1183 *q++=ScaleQuantumToChar(p->green);
1184 *q++=ScaleQuantumToChar(p->red);
1185 if (image->matte != MagickFalse)
1186 *q++=ScaleQuantumToChar(p->opacity);
1187 p++;
1188 }
1189 if (dib_info.bits_per_pixel == 24)
1190 for (x=3L*image->columns; x < (long) bytes_per_line; x++)
1191 *q++=0x00;
1192 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1193 if (status == MagickFalse)
1194 break;
1195 }
1196 break;
1197 }
1198 }
1199 if (dib_info.bits_per_pixel == 8)
1200 if (image_info->compression != NoCompression)
1201 {
1202 size_t
1203 length;
1204
1205 /*
1206 Convert run-length encoded raster pixels.
1207 */
1208 length=2UL*(bytes_per_line+2UL)+2UL;
1209 dib_data=(unsigned char *) AcquireQuantumMemory(length,
1210 (image->rows+2UL)*sizeof(*dib_data));
1211 if (pixels == (unsigned char *) NULL)
1212 {
1213 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1214 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1215 }
1216 dib_info.image_size=(unsigned long) EncodeImage(image,bytes_per_line,
1217 pixels,dib_data);
1218 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1219 pixels=dib_data;
1220 dib_info.compression = BI_RLE8;
1221 }
1222 /*
1223 Write DIB header.
1224 */
1225 (void) WriteBlobLSBLong(image,dib_info.size);
1226 (void) WriteBlobLSBLong(image,(unsigned long) dib_info.width);
1227 (void) WriteBlobLSBLong(image,(unsigned short) dib_info.height);
1228 (void) WriteBlobLSBShort(image,(unsigned short) dib_info.planes);
1229 (void) WriteBlobLSBShort(image,dib_info.bits_per_pixel);
1230 (void) WriteBlobLSBLong(image,dib_info.compression);
1231 (void) WriteBlobLSBLong(image,dib_info.image_size);
1232 (void) WriteBlobLSBLong(image,dib_info.x_pixels);
1233 (void) WriteBlobLSBLong(image,dib_info.y_pixels);
1234 (void) WriteBlobLSBLong(image,dib_info.number_colors);
1235 (void) WriteBlobLSBLong(image,dib_info.colors_important);
1236 if (image->storage_class == PseudoClass)
1237 {
1238 if (dib_info.bits_per_pixel <= 8)
1239 {
1240 unsigned char
1241 *dib_colormap;
1242
1243 /*
1244 Dump colormap to file.
1245 */
1246 dib_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
1247 (1UL << dib_info.bits_per_pixel),4*sizeof(dib_colormap));
1248 if (dib_colormap == (unsigned char *) NULL)
1249 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1250 q=dib_colormap;
1251 for (i=0; i < (long) MagickMin(image->colors,dib_info.number_colors); i++)
1252 {
1253 *q++=ScaleQuantumToChar(image->colormap[i].blue);
1254 *q++=ScaleQuantumToChar(image->colormap[i].green);
1255 *q++=ScaleQuantumToChar(image->colormap[i].red);
1256 *q++=(Quantum) 0x0;
1257 }
1258 for ( ; i < (long) (1L << dib_info.bits_per_pixel); i++)
1259 {
1260 *q++=(Quantum) 0x0;
1261 *q++=(Quantum) 0x0;
1262 *q++=(Quantum) 0x0;
1263 *q++=(Quantum) 0x0;
1264 }
1265 (void) WriteBlob(image,(size_t) (4*(1 << dib_info.bits_per_pixel)),
1266 dib_colormap);
1267 dib_colormap=(unsigned char *) RelinquishMagickMemory(dib_colormap);
1268 }
1269 else
1270 if ((dib_info.bits_per_pixel == 16) &&
1271 (dib_info.compression == BI_BITFIELDS))
1272 {
1273 (void) WriteBlobLSBLong(image,0xf800);
1274 (void) WriteBlobLSBLong(image,0x07e0);
1275 (void) WriteBlobLSBLong(image,0x001f);
1276 }
1277 }
1278 (void) WriteBlob(image,dib_info.image_size,pixels);
1279 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1280 (void) CloseBlob(image);
1281 return(MagickTrue);
1282}