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