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