1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                            BBBB   M   M  PPPP                               %
7 %                            B   B  MM MM  P   P                              %
8 %                            BBBB   M M M  PPPP                               %
9 %                            B   B  M   M  P                                  %
10 %                            BBBB   M   M  P                                  %
11 %                                                                             %
12 %                                                                             %
13 %             Read/Write Microsoft Windows Bitmap Image Format                %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                   Cristy                                    %
17 %                            Glenn Randers-Pehrson                            %
18 %                               December 2001                                 %
19 %                                                                             %
20 %                                                                             %
21 %  Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization      %
22 %  dedicated to making software imaging solutions freely available.           %
23 %                                                                             %
24 %  You may not use this file except in compliance with the License.  You may  %
25 %  obtain a copy of the License at                                            %
26 %                                                                             %
27 %    https://imagemagick.org/script/license.php                               %
28 %                                                                             %
29 %  Unless required by applicable law or agreed to in writing, software        %
30 %  distributed under the License is distributed on an "AS IS" BASIS,          %
31 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
32 %  See the License for the specific language governing permissions and        %
33 %  limitations under the License.                                             %
34 %                                                                             %
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 %
37 %
38 */
39 
40 /*
41   Include declarations.
42 */
43 #include "MagickCore/studio.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/blob-private.h"
46 #include "MagickCore/cache.h"
47 #include "MagickCore/colormap-private.h"
48 #include "MagickCore/color-private.h"
49 #include "MagickCore/colormap.h"
50 #include "MagickCore/colorspace.h"
51 #include "MagickCore/colorspace-private.h"
52 #include "MagickCore/exception.h"
53 #include "MagickCore/exception-private.h"
54 #include "MagickCore/image.h"
55 #include "MagickCore/image-private.h"
56 #include "MagickCore/list.h"
57 #include "MagickCore/log.h"
58 #include "MagickCore/magick.h"
59 #include "MagickCore/memory_.h"
60 #include "MagickCore/monitor.h"
61 #include "MagickCore/monitor-private.h"
62 #include "MagickCore/option.h"
63 #include "MagickCore/pixel-accessor.h"
64 #include "MagickCore/profile.h"
65 #include "MagickCore/quantum-private.h"
66 #include "MagickCore/static.h"
67 #include "MagickCore/string_.h"
68 #include "MagickCore/module.h"
69 #include "MagickCore/transform.h"
70 
71 /*
72   Macro definitions (from Windows wingdi.h).
73 */
74 #undef BI_JPEG
75 #define BI_JPEG  4
76 #undef BI_PNG
77 #define BI_PNG  5
78 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__)
79 #undef BI_RGB
80 #define BI_RGB  0
81 #undef BI_RLE8
82 #define BI_RLE8  1
83 #undef BI_RLE4
84 #define BI_RLE4  2
85 #undef BI_BITFIELDS
86 #define BI_BITFIELDS  3
87 
88 #undef LCS_CALIBRATED_RBG
89 #define LCS_CALIBRATED_RBG  0
90 #undef LCS_sRGB
91 #define LCS_sRGB  1
92 #undef LCS_WINDOWS_COLOR_SPACE
93 #define LCS_WINDOWS_COLOR_SPACE  2
94 #undef PROFILE_LINKED
95 #define PROFILE_LINKED  3
96 #undef PROFILE_EMBEDDED
97 #define PROFILE_EMBEDDED  4
98 
99 #undef LCS_GM_BUSINESS
100 #define LCS_GM_BUSINESS  1  /* Saturation */
101 #undef LCS_GM_GRAPHICS
102 #define LCS_GM_GRAPHICS  2  /* Relative */
103 #undef LCS_GM_IMAGES
104 #define LCS_GM_IMAGES  4  /* Perceptual */
105 #undef LCS_GM_ABS_COLORIMETRIC
106 #define LCS_GM_ABS_COLORIMETRIC  8  /* Absolute */
107 #endif
108 
109 /*
110   Enumerated declaractions.
111 */
112 typedef enum
113 {
114   UndefinedSubtype,
115   RGB555,
116   RGB565,
117   ARGB4444,
118   ARGB1555
119 } BMPSubtype;
120 
121 /*
122   Typedef declarations.
123 */
124 typedef struct _BMPInfo
125 {
126   unsigned int
127     file_size,
128     ba_offset,
129     offset_bits,
130     size;
131 
132   ssize_t
133     width,
134     height;
135 
136   unsigned short
137     planes,
138     bits_per_pixel;
139 
140   unsigned int
141     compression,
142     image_size,
143     x_pixels,
144     y_pixels,
145     number_colors,
146     red_mask,
147     green_mask,
148     blue_mask,
149     alpha_mask,
150     colors_important;
151 
152   long
153     colorspace;
154 
155   PrimaryInfo
156     red_primary,
157     green_primary,
158     blue_primary,
159     gamma_scale;
160 } BMPInfo;
161 
162 /*
163   Forward declarations.
164 */
165 static MagickBooleanType
166   WriteBMPImage(const ImageInfo *,Image *,ExceptionInfo *);
167 
168 /*
169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170 %                                                                             %
171 %                                                                             %
172 %                                                                             %
173 %   D e c o d e I m a g e                                                     %
174 %                                                                             %
175 %                                                                             %
176 %                                                                             %
177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
178 %
179 %  DecodeImage unpacks the packed image pixels into runlength-encoded
180 %  pixel packets.
181 %
182 %  The format of the DecodeImage method is:
183 %
184 %      MagickBooleanType DecodeImage(Image *image,const size_t compression,
185 %        unsigned char *pixels,const size_t number_pixels)
186 %
187 %  A description of each parameter follows:
188 %
189 %    o image: the address of a structure of type Image.
190 %
191 %    o compression:  Zero means uncompressed.  A value of 1 means the
192 %      compressed pixels are runlength encoded for a 256-color bitmap.
193 %      A value of 2 means a 16-color bitmap.  A value of 3 means bitfields
194 %      encoding.
195 %
196 %    o pixels:  The address of a byte (8 bits) array of pixel data created by
197 %      the decoding process.
198 %
199 %    o number_pixels:  The number of pixels.
200 %
201 */
DecodeImage(Image * image,const size_t compression,unsigned char * pixels,const size_t number_pixels)202 static MagickBooleanType DecodeImage(Image *image,const size_t compression,
203   unsigned char *pixels,const size_t number_pixels)
204 {
205   int
206     byte,
207     count;
208 
209   register ssize_t
210     i,
211     x;
212 
213   register unsigned char
214     *p,
215     *q;
216 
217   ssize_t
218     y;
219 
220   assert(image != (Image *) NULL);
221   assert(image->signature == MagickCoreSignature);
222   if (image->debug != MagickFalse)
223     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
224   assert(pixels != (unsigned char *) NULL);
225   (void) memset(pixels,0,number_pixels*sizeof(*pixels));
226   byte=0;
227   x=0;
228   p=pixels;
229   q=pixels+number_pixels;
230   for (y=0; y < (ssize_t) image->rows; )
231   {
232     MagickBooleanType
233       status;
234 
235     if ((p < pixels) || (p > q))
236       break;
237     count=ReadBlobByte(image);
238     if (count == EOF)
239       break;
240     if (count > 0)
241       {
242         /*
243           Encoded mode.
244         */
245         count=(int) MagickMin((ssize_t) count,(ssize_t) (q-p));
246         byte=ReadBlobByte(image);
247         if (byte == EOF)
248           break;
249         if (compression == BI_RLE8)
250           {
251             for (i=0; i < (ssize_t) count; i++)
252               *p++=(unsigned char) byte;
253           }
254         else
255           {
256             for (i=0; i < (ssize_t) count; i++)
257               *p++=(unsigned char)
258                 ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
259           }
260         x+=count;
261       }
262     else
263       {
264         /*
265           Escape mode.
266         */
267         count=ReadBlobByte(image);
268         if (count == EOF)
269           break;
270         if (count == 0x01)
271           return(MagickTrue);
272         switch (count)
273         {
274           case 0x00:
275           {
276             /*
277               End of line.
278             */
279             x=0;
280             y++;
281             p=pixels+y*image->columns;
282             break;
283           }
284           case 0x02:
285           {
286             /*
287               Delta mode.
288             */
289             x+=ReadBlobByte(image);
290             y+=ReadBlobByte(image);
291             p=pixels+y*image->columns+x;
292             break;
293           }
294           default:
295           {
296             /*
297               Absolute mode.
298             */
299             count=(int) MagickMin((ssize_t) count,(ssize_t) (q-p));
300             if (compression == BI_RLE8)
301               for (i=0; i < (ssize_t) count; i++)
302               {
303                 byte=ReadBlobByte(image);
304                 if (byte == EOF)
305                   break;
306                 *p++=(unsigned char) byte;
307               }
308             else
309               for (i=0; i < (ssize_t) count; i++)
310               {
311                 if ((i & 0x01) == 0)
312                   {
313                     byte=ReadBlobByte(image);
314                     if (byte == EOF)
315                       break;
316                   }
317                 *p++=(unsigned char)
318                   ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
319               }
320             x+=count;
321             /*
322               Read pad byte.
323             */
324             if (compression == BI_RLE8)
325               {
326                 if ((count & 0x01) != 0)
327                   if (ReadBlobByte(image) == EOF)
328                     break;
329               }
330             else
331               if (((count & 0x03) == 1) || ((count & 0x03) == 2))
332                 if (ReadBlobByte(image) == EOF)
333                   break;
334             break;
335           }
336         }
337       }
338     status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
339       image->rows);
340     if (status == MagickFalse)
341       break;
342   }
343   (void) ReadBlobByte(image);  /* end of line */
344   (void) ReadBlobByte(image);
345   return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
346 }
347 
348 /*
349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
350 %                                                                             %
351 %                                                                             %
352 %                                                                             %
353 %   E n c o d e I m a g e                                                     %
354 %                                                                             %
355 %                                                                             %
356 %                                                                             %
357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
358 %
359 %  EncodeImage compresses pixels using a runlength encoded format.
360 %
361 %  The format of the EncodeImage method is:
362 %
363 %    static MagickBooleanType EncodeImage(Image *image,
364 %      const size_t bytes_per_line,const unsigned char *pixels,
365 %      unsigned char *compressed_pixels)
366 %
367 %  A description of each parameter follows:
368 %
369 %    o image:  The image.
370 %
371 %    o bytes_per_line: the number of bytes in a scanline of compressed pixels
372 %
373 %    o pixels:  The address of a byte (8 bits) array of pixel data created by
374 %      the compression process.
375 %
376 %    o compressed_pixels:  The address of a byte (8 bits) array of compressed
377 %      pixel data.
378 %
379 */
EncodeImage(Image * image,const size_t bytes_per_line,const unsigned char * pixels,unsigned char * compressed_pixels)380 static size_t EncodeImage(Image *image,const size_t bytes_per_line,
381   const unsigned char *pixels,unsigned char *compressed_pixels)
382 {
383   MagickBooleanType
384     status;
385 
386   register const unsigned char
387     *p;
388 
389   register ssize_t
390     i,
391     x;
392 
393   register unsigned char
394     *q;
395 
396   ssize_t
397     y;
398 
399   /*
400     Runlength encode pixels.
401   */
402   assert(image != (Image *) NULL);
403   assert(image->signature == MagickCoreSignature);
404   if (image->debug != MagickFalse)
405     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
406   assert(pixels != (const unsigned char *) NULL);
407   assert(compressed_pixels != (unsigned char *) NULL);
408   p=pixels;
409   q=compressed_pixels;
410   i=0;
411   for (y=0; y < (ssize_t) image->rows; y++)
412   {
413     for (x=0; x < (ssize_t) bytes_per_line; x+=i)
414     {
415       /*
416         Determine runlength.
417       */
418       for (i=1; ((x+i) < (ssize_t) bytes_per_line); i++)
419         if ((i == 255) || (*(p+i) != *p))
420           break;
421       *q++=(unsigned char) i;
422       *q++=(*p);
423       p+=i;
424     }
425     /*
426       End of line.
427     */
428     *q++=(unsigned char) 0x00;
429     *q++=(unsigned char) 0x00;
430     status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
431       image->rows);
432     if (status == MagickFalse)
433       break;
434   }
435   /*
436     End of bitmap.
437   */
438   *q++=(unsigned char) 0x00;
439   *q++=(unsigned char) 0x01;
440   return((size_t) (q-compressed_pixels));
441 }
442 
443 /*
444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
445 %                                                                             %
446 %                                                                             %
447 %                                                                             %
448 %   I s B M P                                                                 %
449 %                                                                             %
450 %                                                                             %
451 %                                                                             %
452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
453 %
454 %  IsBMP() returns MagickTrue if the image format type, identified by the
455 %  magick string, is BMP.
456 %
457 %  The format of the IsBMP method is:
458 %
459 %      MagickBooleanType IsBMP(const unsigned char *magick,const size_t length)
460 %
461 %  A description of each parameter follows:
462 %
463 %    o magick: compare image format pattern against these bytes.
464 %
465 %    o length: Specifies the length of the magick string.
466 %
467 */
IsBMP(const unsigned char * magick,const size_t length)468 static MagickBooleanType IsBMP(const unsigned char *magick,const size_t length)
469 {
470   if (length < 2)
471     return(MagickFalse);
472   if ((LocaleNCompare((char *) magick,"BA",2) == 0) ||
473       (LocaleNCompare((char *) magick,"BM",2) == 0) ||
474       (LocaleNCompare((char *) magick,"IC",2) == 0) ||
475       (LocaleNCompare((char *) magick,"PI",2) == 0) ||
476       (LocaleNCompare((char *) magick,"CI",2) == 0) ||
477       (LocaleNCompare((char *) magick,"CP",2) == 0))
478     return(MagickTrue);
479   return(MagickFalse);
480 }
481 
482 /*
483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
484 %                                                                             %
485 %                                                                             %
486 %                                                                             %
487 %   R e a d B M P I m a g e                                                   %
488 %                                                                             %
489 %                                                                             %
490 %                                                                             %
491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
492 %
493 %  ReadBMPImage() reads a Microsoft Windows bitmap image file, Version
494 %  2, 3 (for Windows or NT), or 4, and  returns it.  It allocates the memory
495 %  necessary for the new Image structure and returns a pointer to the new
496 %  image.
497 %
498 %  The format of the ReadBMPImage method is:
499 %
500 %      image=ReadBMPImage(image_info)
501 %
502 %  A description of each parameter follows:
503 %
504 %    o image_info: the image info.
505 %
506 %    o exception: return any errors or warnings in this structure.
507 %
508 */
509 
ReadBMPImage(const ImageInfo * image_info,ExceptionInfo * exception)510 static Image *ReadBMPImage(const ImageInfo *image_info,ExceptionInfo *exception)
511 {
512   BMPInfo
513     bmp_info;
514 
515   Image
516     *image;
517 
518   MagickBooleanType
519     status;
520 
521   MagickOffsetType
522     offset,
523     profile_data,
524     profile_size,
525     start_position;
526 
527   MemoryInfo
528     *pixel_info;
529 
530   Quantum
531     index;
532 
533   register Quantum
534     *q;
535 
536   register ssize_t
537     i,
538     x;
539 
540   register unsigned char
541     *p;
542 
543   size_t
544     bit,
545     bytes_per_line,
546     length;
547 
548   ssize_t
549     count,
550     y;
551 
552   unsigned char
553     magick[12],
554     *pixels;
555 
556   unsigned int
557     blue,
558     green,
559     offset_bits,
560     red;
561 
562   /*
563     Open image file.
564   */
565   assert(image_info != (const ImageInfo *) NULL);
566   assert(image_info->signature == MagickCoreSignature);
567   if (image_info->debug != MagickFalse)
568     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
569       image_info->filename);
570   assert(exception != (ExceptionInfo *) NULL);
571   assert(exception->signature == MagickCoreSignature);
572   image=AcquireImage(image_info,exception);
573   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
574   if (status == MagickFalse)
575     {
576       image=DestroyImageList(image);
577       return((Image *) NULL);
578     }
579   /*
580     Determine if this a BMP file.
581   */
582   (void) memset(&bmp_info,0,sizeof(bmp_info));
583   bmp_info.ba_offset=0;
584   start_position=0;
585   offset_bits=0;
586   count=ReadBlob(image,2,magick);
587   if (count != 2)
588     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
589   do
590   {
591     PixelInfo
592       quantum_bits;
593 
594     PixelPacket
595       shift;
596 
597     /*
598       Verify BMP identifier.
599     */
600     start_position=TellBlob(image)-2;
601     bmp_info.ba_offset=0;
602     while (LocaleNCompare((char *) magick,"BA",2) == 0)
603     {
604       bmp_info.file_size=ReadBlobLSBLong(image);
605       bmp_info.ba_offset=ReadBlobLSBLong(image);
606       bmp_info.offset_bits=ReadBlobLSBLong(image);
607       count=ReadBlob(image,2,magick);
608       if (count != 2)
609         break;
610     }
611     if (image->debug != MagickFalse)
612       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  Magick: %c%c",
613         magick[0],magick[1]);
614     if ((count != 2) || ((LocaleNCompare((char *) magick,"BM",2) != 0) &&
615         (LocaleNCompare((char *) magick,"CI",2) != 0)))
616       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
617     bmp_info.file_size=ReadBlobLSBLong(image);
618     (void) ReadBlobLSBLong(image);
619     bmp_info.offset_bits=ReadBlobLSBLong(image);
620     bmp_info.size=ReadBlobLSBLong(image);
621     if (image->debug != MagickFalse)
622       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  BMP size: %u",
623         bmp_info.size);
624     profile_data=0;
625     profile_size=0;
626     if (bmp_info.size == 12)
627       {
628         /*
629           OS/2 BMP image file.
630         */
631         (void) CopyMagickString(image->magick,"BMP2",MagickPathExtent);
632         bmp_info.width=(ssize_t) ((short) ReadBlobLSBShort(image));
633         bmp_info.height=(ssize_t) ((short) ReadBlobLSBShort(image));
634         bmp_info.planes=ReadBlobLSBShort(image);
635         bmp_info.bits_per_pixel=ReadBlobLSBShort(image);
636         bmp_info.x_pixels=0;
637         bmp_info.y_pixels=0;
638         bmp_info.number_colors=0;
639         bmp_info.compression=BI_RGB;
640         bmp_info.image_size=0;
641         bmp_info.alpha_mask=0;
642         if (image->debug != MagickFalse)
643           {
644             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
645               "  Format: OS/2 Bitmap");
646             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
647               "  Geometry: %.20gx%.20g",(double) bmp_info.width,(double)
648               bmp_info.height);
649           }
650       }
651     else
652       {
653         /*
654           Microsoft Windows BMP image file.
655         */
656         if (bmp_info.size < 40)
657           ThrowReaderException(CorruptImageError,"NonOS2HeaderSizeError");
658         bmp_info.width=(ssize_t) ReadBlobLSBSignedLong(image);
659         bmp_info.height=(ssize_t) ReadBlobLSBSignedLong(image);
660         bmp_info.planes=ReadBlobLSBShort(image);
661         bmp_info.bits_per_pixel=ReadBlobLSBShort(image);
662         bmp_info.compression=ReadBlobLSBLong(image);
663         bmp_info.image_size=ReadBlobLSBLong(image);
664         bmp_info.x_pixels=ReadBlobLSBLong(image);
665         bmp_info.y_pixels=ReadBlobLSBLong(image);
666         bmp_info.number_colors=ReadBlobLSBLong(image);
667         if ((MagickSizeType) bmp_info.number_colors > GetBlobSize(image))
668           ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
669         bmp_info.colors_important=ReadBlobLSBLong(image);
670         if (image->debug != MagickFalse)
671           {
672             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
673               "  Format: MS Windows bitmap");
674             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
675               "  Geometry: %.20gx%.20g",(double) bmp_info.width,(double)
676               bmp_info.height);
677             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
678               "  Bits per pixel: %.20g",(double) bmp_info.bits_per_pixel);
679             switch (bmp_info.compression)
680             {
681               case BI_RGB:
682               {
683                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
684                   "  Compression: BI_RGB");
685                 break;
686               }
687               case BI_RLE4:
688               {
689                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
690                   "  Compression: BI_RLE4");
691                 break;
692               }
693               case BI_RLE8:
694               {
695                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
696                   "  Compression: BI_RLE8");
697                 break;
698               }
699               case BI_BITFIELDS:
700               {
701                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
702                   "  Compression: BI_BITFIELDS");
703                 break;
704               }
705               case BI_PNG:
706               {
707                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
708                   "  Compression: BI_PNG");
709                 break;
710               }
711               case BI_JPEG:
712               {
713                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
714                   "  Compression: BI_JPEG");
715                 break;
716               }
717               default:
718               {
719                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
720                   "  Compression: UNKNOWN (%u)",bmp_info.compression);
721               }
722             }
723             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
724               "  Number of colors: %u",bmp_info.number_colors);
725           }
726         bmp_info.red_mask=ReadBlobLSBLong(image);
727         bmp_info.green_mask=ReadBlobLSBLong(image);
728         bmp_info.blue_mask=ReadBlobLSBLong(image);
729         if (bmp_info.size > 40)
730           {
731             double
732               gamma;
733 
734             /*
735               Read color management information.
736             */
737             bmp_info.alpha_mask=ReadBlobLSBLong(image);
738             bmp_info.colorspace=ReadBlobLSBSignedLong(image);
739             /*
740               Decode 2^30 fixed point formatted CIE primaries.
741             */
742 #           define BMP_DENOM ((double) 0x40000000)
743             bmp_info.red_primary.x=(double) ReadBlobLSBLong(image)/BMP_DENOM;
744             bmp_info.red_primary.y=(double) ReadBlobLSBLong(image)/BMP_DENOM;
745             bmp_info.red_primary.z=(double) ReadBlobLSBLong(image)/BMP_DENOM;
746             bmp_info.green_primary.x=(double) ReadBlobLSBLong(image)/BMP_DENOM;
747             bmp_info.green_primary.y=(double) ReadBlobLSBLong(image)/BMP_DENOM;
748             bmp_info.green_primary.z=(double) ReadBlobLSBLong(image)/BMP_DENOM;
749             bmp_info.blue_primary.x=(double) ReadBlobLSBLong(image)/BMP_DENOM;
750             bmp_info.blue_primary.y=(double) ReadBlobLSBLong(image)/BMP_DENOM;
751             bmp_info.blue_primary.z=(double) ReadBlobLSBLong(image)/BMP_DENOM;
752 
753             gamma=bmp_info.red_primary.x+bmp_info.red_primary.y+
754               bmp_info.red_primary.z;
755             gamma=PerceptibleReciprocal(gamma);
756             bmp_info.red_primary.x*=gamma;
757             bmp_info.red_primary.y*=gamma;
758             image->chromaticity.red_primary.x=bmp_info.red_primary.x;
759             image->chromaticity.red_primary.y=bmp_info.red_primary.y;
760 
761             gamma=bmp_info.green_primary.x+bmp_info.green_primary.y+
762               bmp_info.green_primary.z;
763             gamma=PerceptibleReciprocal(gamma);
764             bmp_info.green_primary.x*=gamma;
765             bmp_info.green_primary.y*=gamma;
766             image->chromaticity.green_primary.x=bmp_info.green_primary.x;
767             image->chromaticity.green_primary.y=bmp_info.green_primary.y;
768 
769             gamma=bmp_info.blue_primary.x+bmp_info.blue_primary.y+
770               bmp_info.blue_primary.z;
771             gamma=PerceptibleReciprocal(gamma);
772             bmp_info.blue_primary.x*=gamma;
773             bmp_info.blue_primary.y*=gamma;
774             image->chromaticity.blue_primary.x=bmp_info.blue_primary.x;
775             image->chromaticity.blue_primary.y=bmp_info.blue_primary.y;
776 
777             /*
778               Decode 16^16 fixed point formatted gamma_scales.
779             */
780             bmp_info.gamma_scale.x=(double) ReadBlobLSBLong(image)/0x10000;
781             bmp_info.gamma_scale.y=(double) ReadBlobLSBLong(image)/0x10000;
782             bmp_info.gamma_scale.z=(double) ReadBlobLSBLong(image)/0x10000;
783             /*
784               Compute a single gamma from the BMP 3-channel gamma.
785             */
786             image->gamma=(bmp_info.gamma_scale.x+bmp_info.gamma_scale.y+
787               bmp_info.gamma_scale.z)/3.0;
788           }
789         else
790           (void) CopyMagickString(image->magick,"BMP3",MagickPathExtent);
791 
792         if (bmp_info.size > 108)
793           {
794             size_t
795               intent;
796 
797             /*
798               Read BMP Version 5 color management information.
799             */
800             intent=ReadBlobLSBLong(image);
801             switch ((int) intent)
802             {
803               case LCS_GM_BUSINESS:
804               {
805                 image->rendering_intent=SaturationIntent;
806                 break;
807               }
808               case LCS_GM_GRAPHICS:
809               {
810                 image->rendering_intent=RelativeIntent;
811                 break;
812               }
813               case LCS_GM_IMAGES:
814               {
815                 image->rendering_intent=PerceptualIntent;
816                 break;
817               }
818               case LCS_GM_ABS_COLORIMETRIC:
819               {
820                 image->rendering_intent=AbsoluteIntent;
821                 break;
822               }
823             }
824             profile_data=(MagickOffsetType)ReadBlobLSBLong(image);
825             profile_size=(MagickOffsetType)ReadBlobLSBLong(image);
826             (void) ReadBlobLSBLong(image);  /* Reserved byte */
827           }
828       }
829     if ((MagickSizeType) bmp_info.file_size > GetBlobSize(image))
830       (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
831         "LengthAndFilesizeDoNotMatch","`%s'",image->filename);
832     else
833       if ((MagickSizeType) bmp_info.file_size < GetBlobSize(image))
834         (void) ThrowMagickException(exception,GetMagickModule(),
835           CorruptImageWarning,"LengthAndFilesizeDoNotMatch","`%s'",
836           image->filename);
837     if (bmp_info.width <= 0)
838       ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
839     if (bmp_info.height == 0)
840       ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
841     if (bmp_info.planes != 1)
842       ThrowReaderException(CorruptImageError,"StaticPlanesValueNotEqualToOne");
843     if ((bmp_info.bits_per_pixel != 1) && (bmp_info.bits_per_pixel != 4) &&
844         (bmp_info.bits_per_pixel != 8) && (bmp_info.bits_per_pixel != 16) &&
845         (bmp_info.bits_per_pixel != 24) && (bmp_info.bits_per_pixel != 32))
846       ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel");
847     if (bmp_info.bits_per_pixel < 16 &&
848         bmp_info.number_colors > (1U << bmp_info.bits_per_pixel))
849       ThrowReaderException(CorruptImageError,"UnrecognizedNumberOfColors");
850     if ((bmp_info.compression == 1) && (bmp_info.bits_per_pixel != 8))
851       ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel");
852     if ((bmp_info.compression == 2) && (bmp_info.bits_per_pixel != 4))
853       ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel");
854     if ((bmp_info.compression == 3) && (bmp_info.bits_per_pixel < 16))
855       ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel");
856     switch (bmp_info.compression)
857     {
858       case BI_RGB:
859         image->compression=NoCompression;
860         break;
861       case BI_RLE8:
862       case BI_RLE4:
863         image->compression=RLECompression;
864         break;
865       case BI_BITFIELDS:
866         break;
867       case BI_JPEG:
868         ThrowReaderException(CoderError,"JPEGCompressNotSupported");
869       case BI_PNG:
870         ThrowReaderException(CoderError,"PNGCompressNotSupported");
871       default:
872         ThrowReaderException(CorruptImageError,"UnrecognizedImageCompression");
873     }
874     image->columns=(size_t) MagickAbsoluteValue(bmp_info.width);
875     image->rows=(size_t) MagickAbsoluteValue(bmp_info.height);
876     image->depth=bmp_info.bits_per_pixel <= 8 ? bmp_info.bits_per_pixel : 8;
877     image->alpha_trait=((bmp_info.alpha_mask != 0) &&
878       (bmp_info.compression == BI_BITFIELDS)) ? BlendPixelTrait :
879       UndefinedPixelTrait;
880     if (bmp_info.bits_per_pixel < 16)
881       {
882         size_t
883           one;
884 
885         image->storage_class=PseudoClass;
886         image->colors=bmp_info.number_colors;
887         one=1;
888         if (image->colors == 0)
889           image->colors=one << bmp_info.bits_per_pixel;
890       }
891     image->resolution.x=(double) bmp_info.x_pixels/100.0;
892     image->resolution.y=(double) bmp_info.y_pixels/100.0;
893     image->units=PixelsPerCentimeterResolution;
894     if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
895       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
896         break;
897     status=SetImageExtent(image,image->columns,image->rows,exception);
898     if (status == MagickFalse)
899       return(DestroyImageList(image));
900     if (image->storage_class == PseudoClass)
901       {
902         unsigned char
903           *bmp_colormap;
904 
905         size_t
906           packet_size;
907 
908         /*
909           Read BMP raster colormap.
910         */
911         if (image->debug != MagickFalse)
912           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
913             "  Reading colormap of %.20g colors",(double) image->colors);
914         if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
915           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
916         bmp_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
917           image->colors,4*sizeof(*bmp_colormap));
918         if (bmp_colormap == (unsigned char *) NULL)
919           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
920         if ((bmp_info.size == 12) || (bmp_info.size == 64))
921           packet_size=3;
922         else
923           packet_size=4;
924         offset=SeekBlob(image,start_position+14+bmp_info.size,SEEK_SET);
925         if (offset < 0)
926           {
927             bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);
928             ThrowReaderException(CorruptImageError,"ImproperImageHeader");
929           }
930         count=ReadBlob(image,packet_size*image->colors,bmp_colormap);
931         if (count != (ssize_t) (packet_size*image->colors))
932           {
933             bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);
934             ThrowReaderException(CorruptImageError,
935               "InsufficientImageDataInFile");
936           }
937         p=bmp_colormap;
938         for (i=0; i < (ssize_t) image->colors; i++)
939         {
940           image->colormap[i].blue=(MagickRealType) ScaleCharToQuantum(*p++);
941           image->colormap[i].green=(MagickRealType) ScaleCharToQuantum(*p++);
942           image->colormap[i].red=(MagickRealType) ScaleCharToQuantum(*p++);
943           if (packet_size == 4)
944             p++;
945         }
946         bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);
947       }
948     /*
949       Read image data.
950     */
951     if (bmp_info.offset_bits == offset_bits)
952       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
953     offset_bits=bmp_info.offset_bits;
954     offset=SeekBlob(image,start_position+bmp_info.offset_bits,SEEK_SET);
955     if (offset < 0)
956       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
957     if (bmp_info.compression == BI_RLE4)
958       bmp_info.bits_per_pixel<<=1;
959     bytes_per_line=4*((image->columns*bmp_info.bits_per_pixel+31)/32);
960     length=(size_t) bytes_per_line*image->rows;
961     if ((MagickSizeType) (length/256) > GetBlobSize(image))
962       ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
963     if ((bmp_info.compression == BI_RGB) ||
964         (bmp_info.compression == BI_BITFIELDS))
965       {
966         pixel_info=AcquireVirtualMemory(image->rows,
967           MagickMax(bytes_per_line,image->columns+256UL)*sizeof(*pixels));
968         if (pixel_info == (MemoryInfo *) NULL)
969           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
970         pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
971         if (image->debug != MagickFalse)
972           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
973             "  Reading pixels (%.20g bytes)",(double) length);
974         count=ReadBlob(image,length,pixels);
975         if (count != (ssize_t) length)
976           {
977             pixel_info=RelinquishVirtualMemory(pixel_info);
978             ThrowReaderException(CorruptImageError,
979               "InsufficientImageDataInFile");
980           }
981       }
982     else
983       {
984         /*
985           Convert run-length encoded raster pixels.
986         */
987         pixel_info=AcquireVirtualMemory(image->rows,
988           MagickMax(bytes_per_line,image->columns+256UL)*sizeof(*pixels));
989         if (pixel_info == (MemoryInfo *) NULL)
990           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
991         pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
992         status=DecodeImage(image,bmp_info.compression,pixels,
993           image->columns*image->rows);
994         if (status == MagickFalse)
995           {
996             pixel_info=RelinquishVirtualMemory(pixel_info);
997             ThrowReaderException(CorruptImageError,
998               "UnableToRunlengthDecodeImage");
999           }
1000       }
1001     /*
1002       Convert BMP raster image to pixel packets.
1003     */
1004     if (bmp_info.compression == BI_RGB)
1005       {
1006         /*
1007           We should ignore the alpha value in BMP3 files but there have been
1008           reports about 32 bit files with alpha. We do a quick check to see if
1009           the alpha channel contains a value that is not zero (default value).
1010           If we find a non zero value we asume the program that wrote the file
1011           wants to use the alpha channel.
1012         */
1013         if ((image->alpha_trait == UndefinedPixelTrait) &&
1014             (bmp_info.size == 40) && (bmp_info.bits_per_pixel == 32))
1015           {
1016             bytes_per_line=4*(image->columns);
1017             for (y=(ssize_t) image->rows-1; y >= 0; y--)
1018             {
1019               p=pixels+(image->rows-y-1)*bytes_per_line;
1020               for (x=0; x < (ssize_t) image->columns; x++)
1021               {
1022                 if (*(p+3) != 0)
1023                   {
1024                     image->alpha_trait=BlendPixelTrait;
1025                     y=-1;
1026                     break;
1027                   }
1028                 p+=4;
1029               }
1030             }
1031           }
1032         bmp_info.alpha_mask=image->alpha_trait != UndefinedPixelTrait ?
1033           0xff000000U : 0U;
1034         bmp_info.red_mask=0x00ff0000U;
1035         bmp_info.green_mask=0x0000ff00U;
1036         bmp_info.blue_mask=0x000000ffU;
1037         if (bmp_info.bits_per_pixel == 16)
1038           {
1039             /*
1040               RGB555.
1041             */
1042             bmp_info.red_mask=0x00007c00U;
1043             bmp_info.green_mask=0x000003e0U;
1044             bmp_info.blue_mask=0x0000001fU;
1045           }
1046       }
1047     (void) memset(&shift,0,sizeof(shift));
1048     (void) memset(&quantum_bits,0,sizeof(quantum_bits));
1049     if ((bmp_info.bits_per_pixel == 16) || (bmp_info.bits_per_pixel == 32))
1050       {
1051         register unsigned int
1052           sample;
1053 
1054         /*
1055           Get shift and quantum bits info from bitfield masks.
1056         */
1057         if (bmp_info.red_mask != 0)
1058           while (((bmp_info.red_mask << shift.red) & 0x80000000UL) == 0)
1059           {
1060             shift.red++;
1061             if (shift.red >= 32U)
1062               break;
1063           }
1064         if (bmp_info.green_mask != 0)
1065           while (((bmp_info.green_mask << shift.green) & 0x80000000UL) == 0)
1066           {
1067             shift.green++;
1068             if (shift.green >= 32U)
1069               break;
1070           }
1071         if (bmp_info.blue_mask != 0)
1072           while (((bmp_info.blue_mask << shift.blue) & 0x80000000UL) == 0)
1073           {
1074             shift.blue++;
1075             if (shift.blue >= 32U)
1076               break;
1077           }
1078         if (bmp_info.alpha_mask != 0)
1079           while (((bmp_info.alpha_mask << shift.alpha) & 0x80000000UL) == 0)
1080           {
1081             shift.alpha++;
1082             if (shift.alpha >= 32U)
1083               break;
1084           }
1085         sample=shift.red;
1086         while (((bmp_info.red_mask << sample) & 0x80000000UL) != 0)
1087         {
1088           sample++;
1089           if (sample >= 32U)
1090             break;
1091         }
1092         quantum_bits.red=(MagickRealType) (sample-shift.red);
1093         sample=shift.green;
1094         while (((bmp_info.green_mask << sample) & 0x80000000UL) != 0)
1095         {
1096           sample++;
1097           if (sample >= 32U)
1098             break;
1099         }
1100         quantum_bits.green=(MagickRealType) (sample-shift.green);
1101         sample=shift.blue;
1102         while (((bmp_info.blue_mask << sample) & 0x80000000UL) != 0)
1103         {
1104           sample++;
1105           if (sample >= 32U)
1106             break;
1107         }
1108         quantum_bits.blue=(MagickRealType) (sample-shift.blue);
1109         sample=shift.alpha;
1110         while (((bmp_info.alpha_mask << sample) & 0x80000000UL) != 0)
1111         {
1112           sample++;
1113           if (sample >= 32U)
1114             break;
1115         }
1116         quantum_bits.alpha=(MagickRealType) (sample-shift.alpha);
1117       }
1118     switch (bmp_info.bits_per_pixel)
1119     {
1120       case 1:
1121       {
1122         /*
1123           Convert bitmap scanline.
1124         */
1125         for (y=(ssize_t) image->rows-1; y >= 0; y--)
1126         {
1127           p=pixels+(image->rows-y-1)*bytes_per_line;
1128           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1129           if (q == (Quantum *) NULL)
1130             break;
1131           for (x=0; x < ((ssize_t) image->columns-7); x+=8)
1132           {
1133             for (bit=0; bit < 8; bit++)
1134             {
1135               index=(Quantum) (((*p) & (0x80 >> bit)) != 0 ? 0x01 : 0x00);
1136               SetPixelIndex(image,index,q);
1137               q+=GetPixelChannels(image);
1138             }
1139             p++;
1140           }
1141           if ((image->columns % 8) != 0)
1142             {
1143               for (bit=0; bit < (image->columns % 8); bit++)
1144               {
1145                 index=(Quantum) (((*p) & (0x80 >> bit)) != 0 ? 0x01 : 0x00);
1146                 SetPixelIndex(image,index,q);
1147                 q+=GetPixelChannels(image);
1148               }
1149               p++;
1150             }
1151           if (SyncAuthenticPixels(image,exception) == MagickFalse)
1152             break;
1153           if (image->previous == (Image *) NULL)
1154             {
1155               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
1156                 (image->rows-y),image->rows);
1157               if (status == MagickFalse)
1158                 break;
1159             }
1160         }
1161         (void) SyncImage(image,exception);
1162         break;
1163       }
1164       case 4:
1165       {
1166         /*
1167           Convert PseudoColor scanline.
1168         */
1169         for (y=(ssize_t) image->rows-1; y >= 0; y--)
1170         {
1171           p=pixels+(image->rows-y-1)*bytes_per_line;
1172           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1173           if (q == (Quantum *) NULL)
1174             break;
1175           for (x=0; x < ((ssize_t) image->columns-1); x+=2)
1176           {
1177             ValidateColormapValue(image,(ssize_t) ((*p >> 4) & 0x0f),&index,
1178               exception);
1179             SetPixelIndex(image,index,q);
1180             q+=GetPixelChannels(image);
1181             ValidateColormapValue(image,(ssize_t) (*p & 0x0f),&index,exception);
1182             SetPixelIndex(image,index,q);
1183             q+=GetPixelChannels(image);
1184             p++;
1185           }
1186           if ((image->columns % 2) != 0)
1187             {
1188               ValidateColormapValue(image,(ssize_t) ((*p >> 4) & 0xf),&index,
1189                 exception);
1190               SetPixelIndex(image,index,q);
1191               q+=GetPixelChannels(image);
1192               p++;
1193               x++;
1194             }
1195           if (x < (ssize_t) image->columns)
1196             break;
1197           if (SyncAuthenticPixels(image,exception) == MagickFalse)
1198             break;
1199           if (image->previous == (Image *) NULL)
1200             {
1201               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
1202                 (image->rows-y),image->rows);
1203               if (status == MagickFalse)
1204                 break;
1205             }
1206         }
1207         (void) SyncImage(image,exception);
1208         break;
1209       }
1210       case 8:
1211       {
1212         /*
1213           Convert PseudoColor scanline.
1214         */
1215         if ((bmp_info.compression == BI_RLE8) ||
1216             (bmp_info.compression == BI_RLE4))
1217           bytes_per_line=image->columns;
1218         for (y=(ssize_t) image->rows-1; y >= 0; y--)
1219         {
1220           p=pixels+(image->rows-y-1)*bytes_per_line;
1221           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1222           if (q == (Quantum *) NULL)
1223             break;
1224           for (x=(ssize_t) image->columns; x != 0; --x)
1225           {
1226             ValidateColormapValue(image,(ssize_t) *p++,&index,exception);
1227             SetPixelIndex(image,index,q);
1228             q+=GetPixelChannels(image);
1229           }
1230           if (SyncAuthenticPixels(image,exception) == MagickFalse)
1231             break;
1232           offset=(MagickOffsetType) (image->rows-y-1);
1233           if (image->previous == (Image *) NULL)
1234             {
1235               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
1236                 (image->rows-y),image->rows);
1237               if (status == MagickFalse)
1238                 break;
1239             }
1240         }
1241         (void) SyncImage(image,exception);
1242         break;
1243       }
1244       case 16:
1245       {
1246         unsigned int
1247           alpha,
1248           pixel;
1249 
1250         /*
1251           Convert bitfield encoded 16-bit PseudoColor scanline.
1252         */
1253         if ((bmp_info.compression != BI_RGB) &&
1254             (bmp_info.compression != BI_BITFIELDS))
1255           {
1256             pixel_info=RelinquishVirtualMemory(pixel_info);
1257             ThrowReaderException(CorruptImageError,
1258               "UnrecognizedImageCompression");
1259           }
1260         bytes_per_line=2*(image->columns+image->columns % 2);
1261         image->storage_class=DirectClass;
1262         for (y=(ssize_t) image->rows-1; y >= 0; y--)
1263         {
1264           p=pixels+(image->rows-y-1)*bytes_per_line;
1265           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1266           if (q == (Quantum *) NULL)
1267             break;
1268           for (x=0; x < (ssize_t) image->columns; x++)
1269           {
1270             pixel=(unsigned int) (*p++);
1271             pixel|=(*p++) << 8;
1272             red=((pixel & bmp_info.red_mask) << shift.red) >> 16;
1273             if (quantum_bits.red == 5)
1274               red|=((red & 0xe000) >> 5);
1275             if (quantum_bits.red <= 8)
1276               red|=((red & 0xff00) >> 8);
1277             green=((pixel & bmp_info.green_mask) << shift.green) >> 16;
1278             if (quantum_bits.green == 5)
1279               green|=((green & 0xe000) >> 5);
1280             if (quantum_bits.green == 6)
1281               green|=((green & 0xc000) >> 6);
1282             if (quantum_bits.green <= 8)
1283               green|=((green & 0xff00) >> 8);
1284             blue=((pixel & bmp_info.blue_mask) << shift.blue) >> 16;
1285             if (quantum_bits.blue == 5)
1286               blue|=((blue & 0xe000) >> 5);
1287             if (quantum_bits.blue <= 8)
1288               blue|=((blue & 0xff00) >> 8);
1289             SetPixelRed(image,ScaleShortToQuantum((unsigned short) red),q);
1290             SetPixelGreen(image,ScaleShortToQuantum((unsigned short) green),q);
1291             SetPixelBlue(image,ScaleShortToQuantum((unsigned short) blue),q);
1292             SetPixelAlpha(image,OpaqueAlpha,q);
1293             if (image->alpha_trait != UndefinedPixelTrait)
1294               {
1295                 alpha=((pixel & bmp_info.alpha_mask) << shift.alpha) >> 16;
1296                 if (quantum_bits.alpha <= 8)
1297                   alpha|=((alpha & 0xff00) >> 8);
1298                 SetPixelAlpha(image,ScaleShortToQuantum(
1299                   (unsigned short) alpha),q);
1300               }
1301             q+=GetPixelChannels(image);
1302           }
1303           if (SyncAuthenticPixels(image,exception) == MagickFalse)
1304             break;
1305           offset=(MagickOffsetType) (image->rows-y-1);
1306           if (image->previous == (Image *) NULL)
1307             {
1308               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
1309                 (image->rows-y),image->rows);
1310               if (status == MagickFalse)
1311                 break;
1312             }
1313         }
1314         break;
1315       }
1316       case 24:
1317       {
1318         /*
1319           Convert DirectColor scanline.
1320         */
1321         bytes_per_line=4*((image->columns*24+31)/32);
1322         for (y=(ssize_t) image->rows-1; y >= 0; y--)
1323         {
1324           p=pixels+(image->rows-y-1)*bytes_per_line;
1325           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1326           if (q == (Quantum *) NULL)
1327             break;
1328           for (x=0; x < (ssize_t) image->columns; x++)
1329           {
1330             SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
1331             SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
1332             SetPixelRed(image,ScaleCharToQuantum(*p++),q);
1333             SetPixelAlpha(image,OpaqueAlpha,q);
1334             q+=GetPixelChannels(image);
1335           }
1336           if (SyncAuthenticPixels(image,exception) == MagickFalse)
1337             break;
1338           offset=(MagickOffsetType) (image->rows-y-1);
1339           if (image->previous == (Image *) NULL)
1340             {
1341               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
1342                 (image->rows-y),image->rows);
1343               if (status == MagickFalse)
1344                 break;
1345             }
1346         }
1347         break;
1348       }
1349       case 32:
1350       {
1351         /*
1352           Convert bitfield encoded DirectColor scanline.
1353         */
1354         if ((bmp_info.compression != BI_RGB) &&
1355             (bmp_info.compression != BI_BITFIELDS))
1356           {
1357             pixel_info=RelinquishVirtualMemory(pixel_info);
1358             ThrowReaderException(CorruptImageError,
1359               "UnrecognizedImageCompression");
1360           }
1361         bytes_per_line=4*(image->columns);
1362         for (y=(ssize_t) image->rows-1; y >= 0; y--)
1363         {
1364           unsigned int
1365             alpha,
1366             pixel;
1367 
1368           p=pixels+(image->rows-y-1)*bytes_per_line;
1369           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1370           if (q == (Quantum *) NULL)
1371             break;
1372           for (x=0; x < (ssize_t) image->columns; x++)
1373           {
1374             pixel=(unsigned int) (*p++);
1375             pixel|=((unsigned int) *p++ << 8);
1376             pixel|=((unsigned int) *p++ << 16);
1377             pixel|=((unsigned int) *p++ << 24);
1378             red=((pixel & bmp_info.red_mask) << shift.red) >> 16;
1379             if (quantum_bits.red == 8)
1380               red|=(red >> 8);
1381             green=((pixel & bmp_info.green_mask) << shift.green) >> 16;
1382             if (quantum_bits.green == 8)
1383               green|=(green >> 8);
1384             blue=((pixel & bmp_info.blue_mask) << shift.blue) >> 16;
1385             if (quantum_bits.blue == 8)
1386               blue|=(blue >> 8);
1387             SetPixelRed(image,ScaleShortToQuantum((unsigned short) red),q);
1388             SetPixelGreen(image,ScaleShortToQuantum((unsigned short) green),q);
1389             SetPixelBlue(image,ScaleShortToQuantum((unsigned short) blue),q);
1390             SetPixelAlpha(image,OpaqueAlpha,q);
1391             if (image->alpha_trait != UndefinedPixelTrait)
1392               {
1393                 alpha=((pixel & bmp_info.alpha_mask) << shift.alpha) >> 16;
1394                 if (quantum_bits.alpha == 8)
1395                   alpha|=(alpha >> 8);
1396                 SetPixelAlpha(image,ScaleShortToQuantum(
1397                   (unsigned short) alpha),q);
1398               }
1399             q+=GetPixelChannels(image);
1400           }
1401           if (SyncAuthenticPixels(image,exception) == MagickFalse)
1402             break;
1403           offset=(MagickOffsetType) (image->rows-y-1);
1404           if (image->previous == (Image *) NULL)
1405             {
1406               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
1407                 (image->rows-y),image->rows);
1408               if (status == MagickFalse)
1409                 break;
1410             }
1411         }
1412         break;
1413       }
1414       default:
1415       {
1416         pixel_info=RelinquishVirtualMemory(pixel_info);
1417         ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1418       }
1419     }
1420     pixel_info=RelinquishVirtualMemory(pixel_info);
1421     if (y > 0)
1422       break;
1423     if (EOFBlob(image) != MagickFalse)
1424       {
1425         ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1426           image->filename);
1427         break;
1428       }
1429     if (bmp_info.height < 0)
1430       {
1431         Image
1432           *flipped_image;
1433 
1434         /*
1435           Correct image orientation.
1436         */
1437         flipped_image=FlipImage(image,exception);
1438         if (flipped_image != (Image *) NULL)
1439           {
1440             DuplicateBlob(flipped_image,image);
1441             ReplaceImageInList(&image, flipped_image);
1442             image=flipped_image;
1443           }
1444       }
1445     /*
1446       Read embeded ICC profile
1447     */
1448     if ((bmp_info.colorspace == 0x4D424544L) && (profile_data > 0) &&
1449         (profile_size > 0))
1450       {
1451         StringInfo
1452           *profile;
1453 
1454         unsigned char
1455           *datum;
1456 
1457         offset=start_position+14+profile_data;
1458         if ((offset < TellBlob(image)) ||
1459             (SeekBlob(image,offset,SEEK_SET) != offset) ||
1460             (GetBlobSize(image) < (MagickSizeType) (offset+profile_size)))
1461           ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1462         profile=AcquireStringInfo((size_t) profile_size);
1463         if (profile == (StringInfo *) NULL)
1464           ThrowReaderException(CorruptImageError,"MemoryAllocationFailed");
1465         datum=GetStringInfoDatum(profile);
1466         if (ReadBlob(image,(size_t) profile_size,datum) == (ssize_t) profile_size)
1467           {
1468             MagickOffsetType
1469               profile_size_orig;
1470 
1471             /*
1472              Trimming padded bytes.
1473             */
1474             profile_size_orig=(MagickOffsetType) datum[0] << 24;
1475             profile_size_orig|=(MagickOffsetType) datum[1] << 16;
1476             profile_size_orig|=(MagickOffsetType) datum[2] << 8;
1477             profile_size_orig|=(MagickOffsetType) datum[3];
1478             if (profile_size_orig < profile_size)
1479               SetStringInfoLength(profile,(size_t) profile_size_orig);
1480             if (image->debug != MagickFalse)
1481               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1482                 "Profile: ICC, %u bytes",(unsigned int) profile_size_orig);
1483             (void) SetImageProfile(image,"icc",profile,exception);
1484           }
1485         profile=DestroyStringInfo(profile);
1486       }
1487     /*
1488       Proceed to next image.
1489     */
1490     if (image_info->number_scenes != 0)
1491       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1492         break;
1493     offset=(MagickOffsetType) bmp_info.ba_offset;
1494     if (offset != 0)
1495       if ((offset < TellBlob(image)) ||
1496           (SeekBlob(image,offset,SEEK_SET) != offset))
1497         ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1498     *magick='\0';
1499     count=ReadBlob(image,2,magick);
1500     if ((count == 2) && (IsBMP(magick,2) != MagickFalse))
1501       {
1502         /*
1503           Acquire next image structure.
1504         */
1505         AcquireNextImage(image_info,image,exception);
1506         if (GetNextImageInList(image) == (Image *) NULL)
1507           {
1508             status=MagickFalse;
1509             return((Image *) NULL);
1510           }
1511         image=SyncNextImageInList(image);
1512         status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1513           GetBlobSize(image));
1514         if (status == MagickFalse)
1515           break;
1516       }
1517   } while (IsBMP(magick,2) != MagickFalse);
1518   (void) CloseBlob(image);
1519   if (status == MagickFalse)
1520     return(DestroyImageList(image));
1521   return(GetFirstImageInList(image));
1522 }
1523 
1524 /*
1525 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1526 %                                                                             %
1527 %                                                                             %
1528 %                                                                             %
1529 %   R e g i s t e r B M P I m a g e                                           %
1530 %                                                                             %
1531 %                                                                             %
1532 %                                                                             %
1533 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1534 %
1535 %  RegisterBMPImage() adds attributes for the BMP image format to
1536 %  the list of supported formats.  The attributes include the image format
1537 %  tag, a method to read and/or write the format, whether the format
1538 %  supports the saving of more than one frame to the same file or blob,
1539 %  whether the format supports native in-memory I/O, and a brief
1540 %  description of the format.
1541 %
1542 %  The format of the RegisterBMPImage method is:
1543 %
1544 %      size_t RegisterBMPImage(void)
1545 %
1546 */
RegisterBMPImage(void)1547 ModuleExport size_t RegisterBMPImage(void)
1548 {
1549   MagickInfo
1550     *entry;
1551 
1552   entry=AcquireMagickInfo("BMP","BMP","Microsoft Windows bitmap image");
1553   entry->decoder=(DecodeImageHandler *) ReadBMPImage;
1554   entry->encoder=(EncodeImageHandler *) WriteBMPImage;
1555   entry->magick=(IsImageFormatHandler *) IsBMP;
1556   entry->flags^=CoderAdjoinFlag;
1557   entry->flags|=CoderDecoderSeekableStreamFlag;
1558   (void) RegisterMagickInfo(entry);
1559   entry=AcquireMagickInfo("BMP","BMP2","Microsoft Windows bitmap image (V2)");
1560   entry->decoder=(DecodeImageHandler *) ReadBMPImage;
1561   entry->encoder=(EncodeImageHandler *) WriteBMPImage;
1562   entry->magick=(IsImageFormatHandler *) IsBMP;
1563   entry->flags^=CoderAdjoinFlag;
1564   entry->flags|=CoderDecoderSeekableStreamFlag;
1565   (void) RegisterMagickInfo(entry);
1566   entry=AcquireMagickInfo("BMP","BMP3","Microsoft Windows bitmap image (V3)");
1567   entry->decoder=(DecodeImageHandler *) ReadBMPImage;
1568   entry->encoder=(EncodeImageHandler *) WriteBMPImage;
1569   entry->magick=(IsImageFormatHandler *) IsBMP;
1570   entry->flags^=CoderAdjoinFlag;
1571   entry->flags|=CoderDecoderSeekableStreamFlag;
1572   (void) RegisterMagickInfo(entry);
1573   return(MagickImageCoderSignature);
1574 }
1575 
1576 /*
1577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1578 %                                                                             %
1579 %                                                                             %
1580 %                                                                             %
1581 %   U n r e g i s t e r B M P I m a g e                                       %
1582 %                                                                             %
1583 %                                                                             %
1584 %                                                                             %
1585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1586 %
1587 %  UnregisterBMPImage() removes format registrations made by the
1588 %  BMP module from the list of supported formats.
1589 %
1590 %  The format of the UnregisterBMPImage method is:
1591 %
1592 %      UnregisterBMPImage(void)
1593 %
1594 */
UnregisterBMPImage(void)1595 ModuleExport void UnregisterBMPImage(void)
1596 {
1597   (void) UnregisterMagickInfo("BMP");
1598   (void) UnregisterMagickInfo("BMP2");
1599   (void) UnregisterMagickInfo("BMP3");
1600 }
1601 
1602 /*
1603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1604 %                                                                             %
1605 %                                                                             %
1606 %                                                                             %
1607 %   W r i t e B M P I m a g e                                                 %
1608 %                                                                             %
1609 %                                                                             %
1610 %                                                                             %
1611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1612 %
1613 %  WriteBMPImage() writes an image in Microsoft Windows bitmap encoded
1614 %  image format, version 3 for Windows or (if the image has a matte channel)
1615 %  version 4.
1616 %
1617 %  The format of the WriteBMPImage method is:
1618 %
1619 %      MagickBooleanType WriteBMPImage(const ImageInfo *image_info,
1620 %        Image *image,ExceptionInfo *exception)
1621 %
1622 %  A description of each parameter follows.
1623 %
1624 %    o image_info: the image info.
1625 %
1626 %    o image:  The image.
1627 %
1628 %    o exception: return any errors or warnings in this structure.
1629 %
1630 */
WriteBMPImage(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)1631 static MagickBooleanType WriteBMPImage(const ImageInfo *image_info,Image *image,
1632   ExceptionInfo *exception)
1633 {
1634   BMPInfo
1635     bmp_info;
1636 
1637   BMPSubtype
1638     bmp_subtype;
1639 
1640   const char
1641     *option;
1642 
1643   const StringInfo
1644     *profile;
1645 
1646   MagickBooleanType
1647     have_color_info,
1648     status;
1649 
1650   MagickOffsetType
1651     scene;
1652 
1653   MemoryInfo
1654     *pixel_info;
1655 
1656   register const Quantum
1657     *p;
1658 
1659   register ssize_t
1660     i,
1661     x;
1662 
1663   register unsigned char
1664     *q;
1665 
1666   size_t
1667     bytes_per_line,
1668     imageListLength,
1669     type;
1670 
1671   ssize_t
1672     y;
1673 
1674   unsigned char
1675     *bmp_data,
1676     *pixels;
1677 
1678   MagickOffsetType
1679     profile_data,
1680     profile_size,
1681     profile_size_pad;
1682 
1683   /*
1684     Open output image file.
1685   */
1686   assert(image_info != (const ImageInfo *) NULL);
1687   assert(image_info->signature == MagickCoreSignature);
1688   assert(image != (Image *) NULL);
1689   assert(image->signature == MagickCoreSignature);
1690   if (image->debug != MagickFalse)
1691     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1692   assert(exception != (ExceptionInfo *) NULL);
1693   assert(exception->signature == MagickCoreSignature);
1694   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1695   if (status == MagickFalse)
1696     return(status);
1697   type=4;
1698   if (LocaleCompare(image_info->magick,"BMP2") == 0)
1699     type=2;
1700   else
1701     if (LocaleCompare(image_info->magick,"BMP3") == 0)
1702       type=3;
1703   option=GetImageOption(image_info,"bmp:format");
1704   if (option != (char *) NULL)
1705     {
1706       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1707           "  Format=%s",option);
1708       if (LocaleCompare(option,"bmp2") == 0)
1709         type=2;
1710       if (LocaleCompare(option,"bmp3") == 0)
1711         type=3;
1712       if (LocaleCompare(option,"bmp4") == 0)
1713         type=4;
1714     }
1715   scene=0;
1716   imageListLength=GetImageListLength(image);
1717   do
1718   {
1719     /*
1720       Initialize BMP raster file header.
1721     */
1722     if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1723       (void) TransformImageColorspace(image,sRGBColorspace,exception);
1724     (void) memset(&bmp_info,0,sizeof(bmp_info));
1725     bmp_info.file_size=14+12;
1726     if (type > 2)
1727       bmp_info.file_size+=28;
1728     bmp_info.offset_bits=bmp_info.file_size;
1729     bmp_info.compression=BI_RGB;
1730     bmp_info.red_mask=0x00ff0000U;
1731     bmp_info.green_mask=0x0000ff00U;
1732     bmp_info.blue_mask=0x000000ffU;
1733     bmp_info.alpha_mask=0xff000000U;
1734     bmp_subtype=UndefinedSubtype;
1735     if ((image->storage_class == PseudoClass) && (image->colors > 256))
1736       (void) SetImageStorageClass(image,DirectClass,exception);
1737     if (image->storage_class != DirectClass)
1738       {
1739         /*
1740           Colormapped BMP raster.
1741         */
1742         bmp_info.bits_per_pixel=8;
1743         if (image->colors <= 2)
1744           bmp_info.bits_per_pixel=1;
1745         else
1746           if (image->colors <= 16)
1747             bmp_info.bits_per_pixel=4;
1748           else
1749             if (image->colors <= 256)
1750               bmp_info.bits_per_pixel=8;
1751         if (image_info->compression == RLECompression)
1752           bmp_info.bits_per_pixel=8;
1753         bmp_info.number_colors=1U << bmp_info.bits_per_pixel;
1754         if (image->alpha_trait != UndefinedPixelTrait)
1755           (void) SetImageStorageClass(image,DirectClass,exception);
1756         else
1757           if ((size_t) bmp_info.number_colors < image->colors)
1758             (void) SetImageStorageClass(image,DirectClass,exception);
1759           else
1760             {
1761               bmp_info.file_size+=3*(1UL << bmp_info.bits_per_pixel);
1762               bmp_info.offset_bits+=3*(1UL << bmp_info.bits_per_pixel);
1763               if (type > 2)
1764                 {
1765                   bmp_info.file_size+=(1UL << bmp_info.bits_per_pixel);
1766                   bmp_info.offset_bits+=(1UL << bmp_info.bits_per_pixel);
1767                 }
1768             }
1769       }
1770     if (image->storage_class == DirectClass)
1771       {
1772         /*
1773           Full color BMP raster.
1774         */
1775         bmp_info.number_colors=0;
1776         option=GetImageOption(image_info,"bmp:subtype");
1777         if (option != (const char *) NULL)
1778         {
1779           if (image->alpha_trait != UndefinedPixelTrait)
1780             {
1781               if (LocaleNCompare(option,"ARGB4444",8) == 0)
1782                 {
1783                   bmp_subtype=ARGB4444;
1784                   bmp_info.red_mask=0x00000f00U;
1785                   bmp_info.green_mask=0x000000f0U;
1786                   bmp_info.blue_mask=0x0000000fU;
1787                   bmp_info.alpha_mask=0x0000f000U;
1788                 }
1789               else if (LocaleNCompare(option,"ARGB1555",8) == 0)
1790                 {
1791                   bmp_subtype=ARGB1555;
1792                   bmp_info.red_mask=0x00007c00U;
1793                   bmp_info.green_mask=0x000003e0U;
1794                   bmp_info.blue_mask=0x0000001fU;
1795                   bmp_info.alpha_mask=0x00008000U;
1796                 }
1797             }
1798           else
1799           {
1800             if (LocaleNCompare(option,"RGB555",6) == 0)
1801               {
1802                 bmp_subtype=RGB555;
1803                 bmp_info.red_mask=0x00007c00U;
1804                 bmp_info.green_mask=0x000003e0U;
1805                 bmp_info.blue_mask=0x0000001fU;
1806                 bmp_info.alpha_mask=0U;
1807               }
1808             else if (LocaleNCompare(option,"RGB565",6) == 0)
1809               {
1810                 bmp_subtype=RGB565;
1811                 bmp_info.red_mask=0x0000f800U;
1812                 bmp_info.green_mask=0x000007e0U;
1813                 bmp_info.blue_mask=0x0000001fU;
1814                 bmp_info.alpha_mask=0U;
1815               }
1816           }
1817         }
1818         if (bmp_subtype != UndefinedSubtype)
1819           {
1820             bmp_info.bits_per_pixel=16;
1821             bmp_info.compression=BI_BITFIELDS;
1822           }
1823         else
1824           {
1825             bmp_info.bits_per_pixel=(unsigned short) ((type > 3) &&
1826                (image->alpha_trait != UndefinedPixelTrait) ? 32 : 24);
1827             bmp_info.compression=(unsigned int) ((type > 3) &&
1828               (image->alpha_trait != UndefinedPixelTrait) ? BI_BITFIELDS : BI_RGB);
1829             if ((type == 3) && (image->alpha_trait != UndefinedPixelTrait))
1830               {
1831                 option=GetImageOption(image_info,"bmp3:alpha");
1832                 if (IsStringTrue(option))
1833                   bmp_info.bits_per_pixel=32;
1834               }
1835           }
1836       }
1837     bytes_per_line=4*((image->columns*bmp_info.bits_per_pixel+31)/32);
1838     bmp_info.ba_offset=0;
1839     profile=GetImageProfile(image,"icc");
1840     have_color_info=(image->rendering_intent != UndefinedIntent) ||
1841       (profile != (StringInfo *) NULL) || (image->gamma != 0.0) ?  MagickTrue :
1842       MagickFalse;
1843     if (type == 2)
1844       bmp_info.size=12;
1845     else
1846       if ((type == 3) || ((image->alpha_trait == UndefinedPixelTrait) &&
1847           (have_color_info == MagickFalse)))
1848         {
1849           type=3;
1850           bmp_info.size=40;
1851         }
1852       else
1853         {
1854           int
1855             extra_size;
1856 
1857           bmp_info.size=108;
1858           extra_size=68;
1859           if ((image->rendering_intent != UndefinedIntent) ||
1860               (profile != (StringInfo *) NULL))
1861             {
1862               bmp_info.size=124;
1863               extra_size+=16;
1864             }
1865           bmp_info.file_size+=extra_size;
1866           bmp_info.offset_bits+=extra_size;
1867         }
1868     if (((ssize_t) image->columns != (ssize_t) ((signed int) image->columns)) ||
1869         ((ssize_t) image->rows != (ssize_t) ((signed int) image->rows)))
1870       ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
1871     bmp_info.width=(ssize_t) image->columns;
1872     bmp_info.height=(ssize_t) image->rows;
1873     bmp_info.planes=1;
1874     bmp_info.image_size=(unsigned int) (bytes_per_line*image->rows);
1875     bmp_info.file_size+=bmp_info.image_size;
1876     bmp_info.x_pixels=75*39;
1877     bmp_info.y_pixels=75*39;
1878     switch (image->units)
1879     {
1880       case UndefinedResolution:
1881       case PixelsPerInchResolution:
1882       {
1883         bmp_info.x_pixels=(unsigned int) (100.0*image->resolution.x/2.54);
1884         bmp_info.y_pixels=(unsigned int) (100.0*image->resolution.y/2.54);
1885         break;
1886       }
1887       case PixelsPerCentimeterResolution:
1888       {
1889         bmp_info.x_pixels=(unsigned int) (100.0*image->resolution.x);
1890         bmp_info.y_pixels=(unsigned int) (100.0*image->resolution.y);
1891         break;
1892       }
1893     }
1894     bmp_info.colors_important=bmp_info.number_colors;
1895     /*
1896       Convert MIFF to BMP raster pixels.
1897     */
1898     pixel_info=AcquireVirtualMemory(image->rows,MagickMax(bytes_per_line,
1899       image->columns+256UL)*sizeof(*pixels));
1900     if (pixel_info == (MemoryInfo *) NULL)
1901       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1902     pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
1903     (void) memset(pixels,0,(size_t) bmp_info.image_size);
1904     switch (bmp_info.bits_per_pixel)
1905     {
1906       case 1:
1907       {
1908         size_t
1909           bit,
1910           byte;
1911 
1912         /*
1913           Convert PseudoClass image to a BMP monochrome image.
1914         */
1915         for (y=0; y < (ssize_t) image->rows; y++)
1916         {
1917           ssize_t
1918             offset;
1919 
1920           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1921           if (p == (const Quantum *) NULL)
1922             break;
1923           q=pixels+(image->rows-y-1)*bytes_per_line;
1924           bit=0;
1925           byte=0;
1926           for (x=0; x < (ssize_t) image->columns; x++)
1927           {
1928             byte<<=1;
1929             byte|=GetPixelIndex(image,p) != 0 ? 0x01 : 0x00;
1930             bit++;
1931             if (bit == 8)
1932               {
1933                 *q++=(unsigned char) byte;
1934                 bit=0;
1935                 byte=0;
1936               }
1937              p+=GetPixelChannels(image);
1938            }
1939            if (bit != 0)
1940              {
1941                *q++=(unsigned char) (byte << (8-bit));
1942                x++;
1943              }
1944           offset=(ssize_t) (image->columns+7)/8;
1945           for (x=offset; x < (ssize_t) bytes_per_line; x++)
1946             *q++=0x00;
1947           if (image->previous == (Image *) NULL)
1948             {
1949               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1950                 image->rows);
1951               if (status == MagickFalse)
1952                 break;
1953             }
1954         }
1955         break;
1956       }
1957       case 4:
1958       {
1959         unsigned int
1960           byte,
1961           nibble;
1962 
1963         ssize_t
1964           offset;
1965 
1966         /*
1967           Convert PseudoClass image to a BMP monochrome image.
1968         */
1969         for (y=0; y < (ssize_t) image->rows; y++)
1970         {
1971           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1972           if (p == (const Quantum *) NULL)
1973             break;
1974           q=pixels+(image->rows-y-1)*bytes_per_line;
1975           nibble=0;
1976           byte=0;
1977           for (x=0; x < (ssize_t) image->columns; x++)
1978           {
1979             byte<<=4;
1980             byte|=((unsigned int) GetPixelIndex(image,p) & 0x0f);
1981             nibble++;
1982             if (nibble == 2)
1983               {
1984                 *q++=(unsigned char) byte;
1985                 nibble=0;
1986                 byte=0;
1987               }
1988             p+=GetPixelChannels(image);
1989           }
1990           if (nibble != 0)
1991             {
1992               *q++=(unsigned char) (byte << 4);
1993               x++;
1994             }
1995           offset=(ssize_t) (image->columns+1)/2;
1996           for (x=offset; x < (ssize_t) bytes_per_line; x++)
1997             *q++=0x00;
1998           if (image->previous == (Image *) NULL)
1999             {
2000               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2001                 image->rows);
2002               if (status == MagickFalse)
2003                 break;
2004             }
2005         }
2006         break;
2007       }
2008       case 8:
2009       {
2010         /*
2011           Convert PseudoClass packet to BMP pixel.
2012         */
2013         for (y=0; y < (ssize_t) image->rows; y++)
2014         {
2015           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2016           if (p == (const Quantum *) NULL)
2017             break;
2018           q=pixels+(image->rows-y-1)*bytes_per_line;
2019           for (x=0; x < (ssize_t) image->columns; x++)
2020           {
2021             *q++=(unsigned char) GetPixelIndex(image,p);
2022             p+=GetPixelChannels(image);
2023           }
2024           for ( ; x < (ssize_t) bytes_per_line; x++)
2025             *q++=0x00;
2026           if (image->previous == (Image *) NULL)
2027             {
2028               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2029                 image->rows);
2030               if (status == MagickFalse)
2031                 break;
2032             }
2033         }
2034         break;
2035       }
2036       case 16:
2037       {
2038         /*
2039           Convert DirectClass packet to BMP BGR888.
2040         */
2041         for (y=0; y < (ssize_t) image->rows; y++)
2042         {
2043           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2044           if (p == (const Quantum *) NULL)
2045             break;
2046           q=pixels+(image->rows-y-1)*bytes_per_line;
2047           for (x=0; x < (ssize_t) image->columns; x++)
2048           {
2049             unsigned short
2050               pixel;
2051 
2052             pixel=0;
2053             if (bmp_subtype == ARGB4444)
2054               {
2055                 pixel=(unsigned short) (ScaleQuantumToAny(
2056                   GetPixelAlpha(image,p),15) << 12);
2057                 pixel|=(unsigned short) (ScaleQuantumToAny(
2058                   GetPixelRed(image,p),15) << 8);
2059                 pixel|=(unsigned short) (ScaleQuantumToAny(
2060                   GetPixelGreen(image,p),15) << 4);
2061                 pixel|=(unsigned short) (ScaleQuantumToAny(
2062                   GetPixelBlue(image,p),15));
2063               }
2064             else if (bmp_subtype == RGB565)
2065               {
2066                 pixel=(unsigned short) (ScaleQuantumToAny(
2067                   GetPixelRed(image,p),31) << 11);
2068                 pixel|=(unsigned short) (ScaleQuantumToAny(
2069                   GetPixelGreen(image,p),63) << 5);
2070                 pixel|=(unsigned short) (ScaleQuantumToAny(
2071                   GetPixelBlue(image,p),31));
2072               }
2073             else
2074               {
2075                 if (bmp_subtype == ARGB1555)
2076                   pixel=(unsigned short) (ScaleQuantumToAny(
2077                     GetPixelAlpha(image,p),1) << 15);
2078                 pixel|=(unsigned short) (ScaleQuantumToAny(
2079                   GetPixelRed(image,p),31) << 10);
2080                 pixel|=(unsigned short) (ScaleQuantumToAny(
2081                   GetPixelGreen(image,p),31) << 5);
2082                 pixel|=(unsigned short) (ScaleQuantumToAny(
2083                   GetPixelBlue(image,p),31));
2084               }
2085             *((unsigned short *) q)=pixel;
2086             q+=2;
2087             p+=GetPixelChannels(image);
2088           }
2089           for (x=2L*(ssize_t) image->columns; x < (ssize_t) bytes_per_line; x++)
2090             *q++=0x00;
2091           if (image->previous == (Image *) NULL)
2092             {
2093               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2094                 image->rows);
2095               if (status == MagickFalse)
2096                 break;
2097             }
2098         }
2099         break;
2100       }
2101       case 24:
2102       {
2103         /*
2104           Convert DirectClass packet to BMP BGR888.
2105         */
2106         for (y=0; y < (ssize_t) image->rows; y++)
2107         {
2108           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2109           if (p == (const Quantum *) NULL)
2110             break;
2111           q=pixels+(image->rows-y-1)*bytes_per_line;
2112           for (x=0; x < (ssize_t) image->columns; x++)
2113           {
2114             *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
2115             *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
2116             *q++=ScaleQuantumToChar(GetPixelRed(image,p));
2117             p+=GetPixelChannels(image);
2118           }
2119           for (x=3L*(ssize_t) image->columns; x < (ssize_t) bytes_per_line; x++)
2120             *q++=0x00;
2121           if (image->previous == (Image *) NULL)
2122             {
2123               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2124                 image->rows);
2125               if (status == MagickFalse)
2126                 break;
2127             }
2128         }
2129         break;
2130       }
2131       case 32:
2132       {
2133         /*
2134           Convert DirectClass packet to ARGB8888 pixel.
2135         */
2136         for (y=0; y < (ssize_t) image->rows; y++)
2137         {
2138           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2139           if (p == (const Quantum *) NULL)
2140             break;
2141           q=pixels+(image->rows-y-1)*bytes_per_line;
2142           for (x=0; x < (ssize_t) image->columns; x++)
2143           {
2144             *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
2145             *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
2146             *q++=ScaleQuantumToChar(GetPixelRed(image,p));
2147             *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
2148             p+=GetPixelChannels(image);
2149           }
2150           if (image->previous == (Image *) NULL)
2151             {
2152               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2153                 image->rows);
2154               if (status == MagickFalse)
2155                 break;
2156             }
2157         }
2158         break;
2159       }
2160     }
2161     if ((type > 2) && (bmp_info.bits_per_pixel == 8))
2162       if (image_info->compression != NoCompression)
2163         {
2164           MemoryInfo
2165             *rle_info;
2166 
2167           /*
2168             Convert run-length encoded raster pixels.
2169           */
2170           rle_info=AcquireVirtualMemory((size_t) (2*(bytes_per_line+2)+2),
2171             (image->rows+2)*sizeof(*pixels));
2172           if (rle_info == (MemoryInfo *) NULL)
2173             {
2174               pixel_info=RelinquishVirtualMemory(pixel_info);
2175               ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2176             }
2177           bmp_data=(unsigned char *) GetVirtualMemoryBlob(rle_info);
2178           bmp_info.file_size-=bmp_info.image_size;
2179           bmp_info.image_size=(unsigned int) EncodeImage(image,bytes_per_line,
2180             pixels,bmp_data);
2181           bmp_info.file_size+=bmp_info.image_size;
2182           pixel_info=RelinquishVirtualMemory(pixel_info);
2183           pixel_info=rle_info;
2184           pixels=bmp_data;
2185           bmp_info.compression=BI_RLE8;
2186         }
2187     /*
2188       Write BMP for Windows, all versions, 14-byte header.
2189     */
2190     if (image->debug != MagickFalse)
2191       {
2192         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2193           "   Writing BMP version %.20g datastream",(double) type);
2194         if (image->storage_class == DirectClass)
2195           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2196             "   Storage class=DirectClass");
2197         else
2198           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2199             "   Storage class=PseudoClass");
2200         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2201           "   Image depth=%.20g",(double) image->depth);
2202         if (image->alpha_trait != UndefinedPixelTrait)
2203           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2204             "   Matte=True");
2205         else
2206           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2207             "   Matte=MagickFalse");
2208         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2209           "   BMP bits_per_pixel=%.20g",(double) bmp_info.bits_per_pixel);
2210         switch ((int) bmp_info.compression)
2211         {
2212            case BI_RGB:
2213            {
2214              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2215                "   Compression=BI_RGB");
2216              break;
2217            }
2218            case BI_RLE8:
2219            {
2220              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2221                "   Compression=BI_RLE8");
2222              break;
2223            }
2224            case BI_BITFIELDS:
2225            {
2226              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2227                "   Compression=BI_BITFIELDS");
2228              break;
2229            }
2230            default:
2231            {
2232              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2233                "   Compression=UNKNOWN (%u)",bmp_info.compression);
2234              break;
2235            }
2236         }
2237         if (bmp_info.number_colors == 0)
2238           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2239             "   Number_colors=unspecified");
2240         else
2241           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2242             "   Number_colors=%u",bmp_info.number_colors);
2243       }
2244     profile_data=0;
2245     profile_size=0;
2246     profile_size_pad=0;
2247     if (profile != (StringInfo *) NULL)
2248       {
2249         profile_data=(MagickOffsetType) bmp_info.file_size-14;  /* from head of BMP info header */
2250         profile_size=(MagickOffsetType) GetStringInfoLength(profile);
2251         if ((profile_size % 4) > 0)
2252           profile_size_pad=4-(profile_size%4);
2253         bmp_info.file_size+=profile_size+profile_size_pad;
2254       }
2255     (void) WriteBlob(image,2,(unsigned char *) "BM");
2256     (void) WriteBlobLSBLong(image,bmp_info.file_size);
2257     (void) WriteBlobLSBLong(image,bmp_info.ba_offset);  /* always 0 */
2258     (void) WriteBlobLSBLong(image,bmp_info.offset_bits);
2259     if (type == 2)
2260       {
2261         /*
2262           Write 12-byte version 2 bitmap header.
2263         */
2264         (void) WriteBlobLSBLong(image,bmp_info.size);
2265         (void) WriteBlobLSBSignedShort(image,(signed short) bmp_info.width);
2266         (void) WriteBlobLSBSignedShort(image,(signed short) bmp_info.height);
2267         (void) WriteBlobLSBShort(image,bmp_info.planes);
2268         (void) WriteBlobLSBShort(image,bmp_info.bits_per_pixel);
2269       }
2270     else
2271       {
2272         /*
2273           Write 40-byte version 3+ bitmap header.
2274         */
2275         (void) WriteBlobLSBLong(image,bmp_info.size);
2276         (void) WriteBlobLSBSignedLong(image,(signed int) bmp_info.width);
2277         (void) WriteBlobLSBSignedLong(image,(signed int) bmp_info.height);
2278         (void) WriteBlobLSBShort(image,bmp_info.planes);
2279         (void) WriteBlobLSBShort(image,bmp_info.bits_per_pixel);
2280         (void) WriteBlobLSBLong(image,bmp_info.compression);
2281         (void) WriteBlobLSBLong(image,bmp_info.image_size);
2282         (void) WriteBlobLSBLong(image,bmp_info.x_pixels);
2283         (void) WriteBlobLSBLong(image,bmp_info.y_pixels);
2284         (void) WriteBlobLSBLong(image,bmp_info.number_colors);
2285         (void) WriteBlobLSBLong(image,bmp_info.colors_important);
2286       }
2287     if ((type > 3) && ((image->alpha_trait != UndefinedPixelTrait) ||
2288         (have_color_info != MagickFalse)))
2289       {
2290         /*
2291           Write the rest of the 108-byte BMP Version 4 header.
2292         */
2293         (void) WriteBlobLSBLong(image,bmp_info.red_mask);
2294         (void) WriteBlobLSBLong(image,bmp_info.green_mask);
2295         (void) WriteBlobLSBLong(image,bmp_info.blue_mask);
2296         (void) WriteBlobLSBLong(image,bmp_info.alpha_mask);
2297         if (profile != (StringInfo *) NULL)
2298           (void) WriteBlobLSBLong(image,0x4D424544U);  /* PROFILE_EMBEDDED */
2299         else
2300           (void) WriteBlobLSBLong(image,0x73524742U);  /* sRGB */
2301         (void) WriteBlobLSBLong(image,(unsigned int)
2302           (image->chromaticity.red_primary.x*0x40000000));
2303         (void) WriteBlobLSBLong(image,(unsigned int)
2304           (image->chromaticity.red_primary.y*0x40000000));
2305         (void) WriteBlobLSBLong(image,(unsigned int)
2306           ((1.000f-(image->chromaticity.red_primary.x+
2307           image->chromaticity.red_primary.y))*0x40000000));
2308         (void) WriteBlobLSBLong(image,(unsigned int)
2309           (image->chromaticity.green_primary.x*0x40000000));
2310         (void) WriteBlobLSBLong(image,(unsigned int)
2311           (image->chromaticity.green_primary.y*0x40000000));
2312         (void) WriteBlobLSBLong(image,(unsigned int)
2313           ((1.000f-(image->chromaticity.green_primary.x+
2314           image->chromaticity.green_primary.y))*0x40000000));
2315         (void) WriteBlobLSBLong(image,(unsigned int)
2316           (image->chromaticity.blue_primary.x*0x40000000));
2317         (void) WriteBlobLSBLong(image,(unsigned int)
2318           (image->chromaticity.blue_primary.y*0x40000000));
2319         (void) WriteBlobLSBLong(image,(unsigned int)
2320           ((1.000f-(image->chromaticity.blue_primary.x+
2321           image->chromaticity.blue_primary.y))*0x40000000));
2322         (void) WriteBlobLSBLong(image,(unsigned int)
2323           (bmp_info.gamma_scale.x*0x10000));
2324         (void) WriteBlobLSBLong(image,(unsigned int)
2325           (bmp_info.gamma_scale.y*0x10000));
2326         (void) WriteBlobLSBLong(image,(unsigned int)
2327           (bmp_info.gamma_scale.z*0x10000));
2328         if ((image->rendering_intent != UndefinedIntent) ||
2329             (profile != (StringInfo *) NULL))
2330           {
2331             ssize_t
2332               intent;
2333 
2334             switch ((int) image->rendering_intent)
2335             {
2336               case SaturationIntent:
2337               {
2338                 intent=LCS_GM_BUSINESS;
2339                 break;
2340               }
2341               case RelativeIntent:
2342               {
2343                 intent=LCS_GM_GRAPHICS;
2344                 break;
2345               }
2346               case PerceptualIntent:
2347               {
2348                 intent=LCS_GM_IMAGES;
2349                 break;
2350               }
2351               case AbsoluteIntent:
2352               {
2353                 intent=LCS_GM_ABS_COLORIMETRIC;
2354                 break;
2355               }
2356               default:
2357               {
2358                 intent=0;
2359                 break;
2360               }
2361             }
2362             (void) WriteBlobLSBLong(image,(unsigned int) intent);
2363             (void) WriteBlobLSBLong(image,(unsigned int) profile_data);
2364             (void) WriteBlobLSBLong(image,(unsigned int)
2365               (profile_size+profile_size_pad));
2366             (void) WriteBlobLSBLong(image,0x00);  /* reserved */
2367           }
2368       }
2369     if (image->storage_class == PseudoClass)
2370       {
2371         unsigned char
2372           *bmp_colormap;
2373 
2374         /*
2375           Dump colormap to file.
2376         */
2377         if (image->debug != MagickFalse)
2378           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2379             "  Colormap: %.20g entries",(double) image->colors);
2380         bmp_colormap=(unsigned char *) AcquireQuantumMemory((size_t) (1UL <<
2381           bmp_info.bits_per_pixel),4*sizeof(*bmp_colormap));
2382         if (bmp_colormap == (unsigned char *) NULL)
2383           {
2384             pixel_info=RelinquishVirtualMemory(pixel_info);
2385             ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2386           }
2387         q=bmp_colormap;
2388         for (i=0; i < (ssize_t) MagickMin((ssize_t) image->colors,(ssize_t) bmp_info.number_colors); i++)
2389         {
2390           *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].blue));
2391           *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].green));
2392           *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].red));
2393           if (type > 2)
2394             *q++=(unsigned char) 0x0;
2395         }
2396         for ( ; i < (ssize_t) (1UL << bmp_info.bits_per_pixel); i++)
2397         {
2398           *q++=(unsigned char) 0x00;
2399           *q++=(unsigned char) 0x00;
2400           *q++=(unsigned char) 0x00;
2401           if (type > 2)
2402             *q++=(unsigned char) 0x00;
2403         }
2404         if (type <= 2)
2405           (void) WriteBlob(image,(size_t) (3*(1L << bmp_info.bits_per_pixel)),
2406             bmp_colormap);
2407         else
2408           (void) WriteBlob(image,(size_t) (4*(1L << bmp_info.bits_per_pixel)),
2409             bmp_colormap);
2410         bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);
2411       }
2412     if (image->debug != MagickFalse)
2413       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2414         "  Pixels:  %u bytes",bmp_info.image_size);
2415     (void) WriteBlob(image,(size_t) bmp_info.image_size,pixels);
2416     if (profile != (StringInfo *) NULL)
2417       {
2418         if (image->debug != MagickFalse)
2419           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2420                                 "  Profile:  %g bytes",(double) profile_size+profile_size_pad);
2421         (void) WriteBlob(image,(size_t) profile_size,GetStringInfoDatum(profile));
2422         if (profile_size_pad > 0)  /* padding for 4 bytes multiple */
2423           (void) WriteBlob(image,(size_t) profile_size_pad,"\0\0\0");
2424       }
2425     pixel_info=RelinquishVirtualMemory(pixel_info);
2426     if (GetNextImageInList(image) == (Image *) NULL)
2427       break;
2428     image=SyncNextImageInList(image);
2429     status=SetImageProgress(image,SaveImagesTag,scene++,imageListLength);
2430     if (status == MagickFalse)
2431       break;
2432   } while (image_info->adjoin != MagickFalse);
2433   (void) CloseBlob(image);
2434   return(MagickTrue);
2435 }
2436