blob: c6ac3329c62907bf2faa5bc1ecf00b2bb7a0f1f1 [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);
cristybbfd4cd2010-04-13 21:54:39 +0000862 if (flipped_image != (Image *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000863 {
cristybbfd4cd2010-04-13 21:54:39 +0000864 DuplicateBlob(flipped_image,image);
865 image=DestroyImage(image);
866 image=flipped_image;
cristy3ed852e2009-09-05 21:47:34 +0000867 }
cristy3ed852e2009-09-05 21:47:34 +0000868 }
869 (void) CloseBlob(image);
870 return(GetFirstImageInList(image));
871}
872
873/*
874%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
875% %
876% %
877% %
878% R e g i s t e r D I B I m a g e %
879% %
880% %
881% %
882%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
883%
884% RegisterDIBImage() adds attributes for the DIB image format to
885% the list of supported formats. The attributes include the image format
886% tag, a method to read and/or write the format, whether the format
887% supports the saving of more than one frame to the same file or blob,
888% whether the format supports native in-memory I/O, and a brief
889% description of the format.
890%
891% The format of the RegisterDIBImage method is:
892%
893% unsigned long RegisterDIBImage(void)
894%
895*/
896ModuleExport unsigned long RegisterDIBImage(void)
897{
898 MagickInfo
899 *entry;
900
901 entry=SetMagickInfo("DIB");
902 entry->decoder=(DecodeImageHandler *) ReadDIBImage;
903 entry->encoder=(EncodeImageHandler *) WriteDIBImage;
904 entry->magick=(IsImageFormatHandler *) IsDIB;
905 entry->adjoin=MagickFalse;
906 entry->stealth=MagickTrue;
907 entry->description=ConstantString(
908 "Microsoft Windows 3.X Packed Device-Independent Bitmap");
909 entry->module=ConstantString("DIB");
910 (void) RegisterMagickInfo(entry);
911 return(MagickImageCoderSignature);
912}
913
914/*
915%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
916% %
917% %
918% %
919% U n r e g i s t e r D I B I m a g e %
920% %
921% %
922% %
923%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
924%
925% UnregisterDIBImage() removes format registrations made by the
926% DIB module from the list of supported formats.
927%
928% The format of the UnregisterDIBImage method is:
929%
930% UnregisterDIBImage(void)
931%
932*/
933ModuleExport void UnregisterDIBImage(void)
934{
935 (void) UnregisterMagickInfo("DIB");
936}
937
938/*
939%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
940% %
941% %
942% %
943% W r i t e D I B I m a g e %
944% %
945% %
946% %
947%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
948%
949% WriteDIBImage() writes an image in Microsoft Windows bitmap encoded
950% image format.
951%
952% The format of the WriteDIBImage method is:
953%
954% MagickBooleanType WriteDIBImage(const ImageInfo *image_info,Image *image)
955%
956% A description of each parameter follows.
957%
958% o image_info: the image info.
959%
960% o image: The image.
961%
962*/
963static MagickBooleanType WriteDIBImage(const ImageInfo *image_info,Image *image)
964{
965 DIBInfo
966 dib_info;
967
968 long
969 y;
970
971 MagickBooleanType
972 status;
973
974 register const IndexPacket
975 *indexes;
976
977 register const PixelPacket
978 *p;
979
980 register long
981 i,
982 x;
983
984 register unsigned char
985 *q;
986
987 unsigned char
988 *dib_data,
989 *pixels;
990
991 unsigned long
992 bytes_per_line;
993
994 /*
995 Open output image file.
996 */
997 assert(image_info != (const ImageInfo *) NULL);
998 assert(image_info->signature == MagickSignature);
999 assert(image != (Image *) NULL);
1000 assert(image->signature == MagickSignature);
1001 if (image->debug != MagickFalse)
1002 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1003 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1004 if (status == MagickFalse)
1005 return(status);
1006 /*
1007 Initialize DIB raster file header.
1008 */
1009 if (image->colorspace != RGBColorspace)
1010 (void) TransformImageColorspace(image,RGBColorspace);
1011 if (image->storage_class == DirectClass)
1012 {
1013 /*
1014 Full color DIB raster.
1015 */
1016 dib_info.number_colors=0;
1017 dib_info.bits_per_pixel=(unsigned short) (image->matte ? 32 : 24);
1018 }
1019 else
1020 {
1021 /*
1022 Colormapped DIB raster.
1023 */
1024 dib_info.bits_per_pixel=8;
1025 if (image_info->depth > 8)
1026 dib_info.bits_per_pixel=16;
1027 if (IsMonochromeImage(image,&image->exception) != MagickFalse)
1028 dib_info.bits_per_pixel=1;
1029 dib_info.number_colors=(dib_info.bits_per_pixel == 16) ? 0 :
1030 (1UL << dib_info.bits_per_pixel);
1031 }
1032 bytes_per_line=4*((image->columns*dib_info.bits_per_pixel+31)/32);
1033 dib_info.size=40;
1034 dib_info.width=(long) image->columns;
1035 dib_info.height=(long) image->rows;
1036 dib_info.planes=1;
1037 dib_info.compression=(unsigned long) (dib_info.bits_per_pixel == 16 ?
1038 BI_BITFIELDS : BI_RGB);
1039 dib_info.image_size=bytes_per_line*image->rows;
1040 dib_info.x_pixels=75*39;
1041 dib_info.y_pixels=75*39;
1042 switch (image->units)
1043 {
1044 case UndefinedResolution:
1045 case PixelsPerInchResolution:
1046 {
1047 dib_info.x_pixels=(unsigned long) (100.0*image->x_resolution/2.54);
1048 dib_info.y_pixels=(unsigned long) (100.0*image->y_resolution/2.54);
1049 break;
1050 }
1051 case PixelsPerCentimeterResolution:
1052 {
1053 dib_info.x_pixels=(unsigned long) (100.0*image->x_resolution);
1054 dib_info.y_pixels=(unsigned long) (100.0*image->y_resolution);
1055 break;
1056 }
1057 }
1058 dib_info.colors_important=dib_info.number_colors;
1059 /*
1060 Convert MIFF to DIB raster pixels.
1061 */
1062 pixels=(unsigned char *) AcquireQuantumMemory(dib_info.image_size,
1063 sizeof(*pixels));
1064 if (pixels == (unsigned char *) NULL)
1065 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1066 (void) ResetMagickMemory(pixels,0,dib_info.image_size);
1067 switch (dib_info.bits_per_pixel)
1068 {
1069 case 1:
1070 {
1071 register unsigned char
1072 bit,
1073 byte;
1074
1075 /*
1076 Convert PseudoClass image to a DIB monochrome image.
1077 */
1078 for (y=0; y < (long) image->rows; y++)
1079 {
1080 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1081 if (p == (const PixelPacket *) NULL)
1082 break;
1083 indexes=GetVirtualIndexQueue(image);
1084 q=pixels+(image->rows-y-1)*bytes_per_line;
1085 bit=0;
1086 byte=0;
1087 for (x=0; x < (long) image->columns; x++)
1088 {
1089 byte<<=1;
1090 byte|=indexes[x] != 0 ? 0x01 : 0x00;
1091 bit++;
1092 if (bit == 8)
1093 {
1094 *q++=byte;
1095 bit=0;
1096 byte=0;
1097 }
1098 p++;
1099 }
1100 if (bit != 0)
1101 {
1102 *q++=(unsigned char) (byte << (8-bit));
1103 x++;
1104 }
1105 for (x=(long) (image->columns+7)/8; x < (long) bytes_per_line; x++)
1106 *q++=0x00;
1107 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1108 if (status == MagickFalse)
1109 break;
1110 }
1111 break;
1112 }
1113 case 8:
1114 {
1115 /*
1116 Convert PseudoClass packet to DIB pixel.
1117 */
1118 for (y=0; y < (long) image->rows; y++)
1119 {
1120 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1121 if (p == (const PixelPacket *) NULL)
1122 break;
1123 indexes=GetVirtualIndexQueue(image);
1124 q=pixels+(image->rows-y-1)*bytes_per_line;
1125 for (x=0; x < (long) image->columns; x++)
1126 *q++=(unsigned char) indexes[x];
1127 for ( ; x < (long) bytes_per_line; x++)
1128 *q++=0x00;
1129 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1130 if (status == MagickFalse)
1131 break;
1132 }
1133 break;
1134 }
1135 case 16:
1136 {
1137 unsigned short
1138 word;
1139 /*
1140 Convert PseudoClass packet to DIB pixel.
1141 */
1142 for (y=0; y < (long) image->rows; y++)
1143 {
1144 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1145 if (p == (const PixelPacket *) NULL)
1146 break;
1147 q=pixels+(image->rows-y-1)*bytes_per_line;
1148 for (x=0; x < (long) image->columns; x++)
1149 {
1150 word=(unsigned short) ((ScaleColor8to5((unsigned char)
cristyce70c172010-01-07 17:15:30 +00001151 ScaleQuantumToChar(GetRedPixelComponent(p))) << 11) | (ScaleColor8to6((unsigned char)
1152 ScaleQuantumToChar(GetGreenPixelComponent(p))) << 5) | (ScaleColor8to5(
1153 (unsigned char) ScaleQuantumToChar((unsigned char) GetBluePixelComponent(p)) << 0)));
cristy3ed852e2009-09-05 21:47:34 +00001154 *q++=(unsigned char)(word & 0xff);
1155 *q++=(unsigned char)(word >> 8);
1156 p++;
1157 }
1158 for (x=2L*image->columns; x < (long) bytes_per_line; x++)
1159 *q++=0x00;
1160 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1161 if (status == MagickFalse)
1162 break;
1163 }
1164 break;
1165 }
1166 case 24:
1167 case 32:
1168 {
1169 /*
1170 Convert DirectClass packet to DIB RGB pixel.
1171 */
1172 for (y=0; y < (long) image->rows; y++)
1173 {
1174 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1175 if (p == (const PixelPacket *) NULL)
1176 break;
1177 q=pixels+(image->rows-y-1)*bytes_per_line;
1178 for (x=0; x < (long) image->columns; x++)
1179 {
cristyce70c172010-01-07 17:15:30 +00001180 *q++=ScaleQuantumToChar(GetBluePixelComponent(p));
1181 *q++=ScaleQuantumToChar(GetGreenPixelComponent(p));
1182 *q++=ScaleQuantumToChar(GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00001183 if (image->matte != MagickFalse)
cristyce70c172010-01-07 17:15:30 +00001184 *q++=ScaleQuantumToChar(GetOpacityPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00001185 p++;
1186 }
1187 if (dib_info.bits_per_pixel == 24)
1188 for (x=3L*image->columns; x < (long) bytes_per_line; x++)
1189 *q++=0x00;
1190 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1191 if (status == MagickFalse)
1192 break;
1193 }
1194 break;
1195 }
1196 }
1197 if (dib_info.bits_per_pixel == 8)
1198 if (image_info->compression != NoCompression)
1199 {
1200 size_t
1201 length;
1202
1203 /*
1204 Convert run-length encoded raster pixels.
1205 */
1206 length=2UL*(bytes_per_line+2UL)+2UL;
1207 dib_data=(unsigned char *) AcquireQuantumMemory(length,
1208 (image->rows+2UL)*sizeof(*dib_data));
1209 if (pixels == (unsigned char *) NULL)
1210 {
1211 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1212 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1213 }
1214 dib_info.image_size=(unsigned long) EncodeImage(image,bytes_per_line,
1215 pixels,dib_data);
1216 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1217 pixels=dib_data;
1218 dib_info.compression = BI_RLE8;
1219 }
1220 /*
1221 Write DIB header.
1222 */
1223 (void) WriteBlobLSBLong(image,dib_info.size);
1224 (void) WriteBlobLSBLong(image,(unsigned long) dib_info.width);
1225 (void) WriteBlobLSBLong(image,(unsigned short) dib_info.height);
1226 (void) WriteBlobLSBShort(image,(unsigned short) dib_info.planes);
1227 (void) WriteBlobLSBShort(image,dib_info.bits_per_pixel);
1228 (void) WriteBlobLSBLong(image,dib_info.compression);
1229 (void) WriteBlobLSBLong(image,dib_info.image_size);
1230 (void) WriteBlobLSBLong(image,dib_info.x_pixels);
1231 (void) WriteBlobLSBLong(image,dib_info.y_pixels);
1232 (void) WriteBlobLSBLong(image,dib_info.number_colors);
1233 (void) WriteBlobLSBLong(image,dib_info.colors_important);
1234 if (image->storage_class == PseudoClass)
1235 {
1236 if (dib_info.bits_per_pixel <= 8)
1237 {
1238 unsigned char
1239 *dib_colormap;
1240
1241 /*
1242 Dump colormap to file.
1243 */
1244 dib_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
1245 (1UL << dib_info.bits_per_pixel),4*sizeof(dib_colormap));
1246 if (dib_colormap == (unsigned char *) NULL)
1247 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1248 q=dib_colormap;
1249 for (i=0; i < (long) MagickMin(image->colors,dib_info.number_colors); i++)
1250 {
1251 *q++=ScaleQuantumToChar(image->colormap[i].blue);
1252 *q++=ScaleQuantumToChar(image->colormap[i].green);
1253 *q++=ScaleQuantumToChar(image->colormap[i].red);
1254 *q++=(Quantum) 0x0;
1255 }
1256 for ( ; i < (long) (1L << dib_info.bits_per_pixel); i++)
1257 {
1258 *q++=(Quantum) 0x0;
1259 *q++=(Quantum) 0x0;
1260 *q++=(Quantum) 0x0;
1261 *q++=(Quantum) 0x0;
1262 }
1263 (void) WriteBlob(image,(size_t) (4*(1 << dib_info.bits_per_pixel)),
1264 dib_colormap);
1265 dib_colormap=(unsigned char *) RelinquishMagickMemory(dib_colormap);
1266 }
1267 else
1268 if ((dib_info.bits_per_pixel == 16) &&
1269 (dib_info.compression == BI_BITFIELDS))
1270 {
1271 (void) WriteBlobLSBLong(image,0xf800);
1272 (void) WriteBlobLSBLong(image,0x07e0);
1273 (void) WriteBlobLSBLong(image,0x001f);
1274 }
1275 }
1276 (void) WriteBlob(image,dib_info.image_size,pixels);
1277 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1278 (void) CloseBlob(image);
1279 return(MagickTrue);
1280}