]> 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     status;
510
511   MagickOffsetType
512     offset,
513     start_position;
514
515   Quantum
516     index;
517
518   register Quantum
519     *q;
520
521   register ssize_t
522     i,
523     x;
524
525   register unsigned char
526     *p;
527
528   size_t
529     bit,
530     blue,
531     bytes_per_line,
532     green,
533     length,
534     opacity,
535     red;
536
537   ssize_t
538     count,
539     y;
540
541   unsigned char
542     magick[12],
543     *pixels;
544
545   /*
546     Open image file.
547   */
548   assert(image_info != (const ImageInfo *) NULL);
549   assert(image_info->signature == MagickSignature);
550   if (image_info->debug != MagickFalse)
551     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
552       image_info->filename);
553   assert(exception != (ExceptionInfo *) NULL);
554   assert(exception->signature == MagickSignature);
555   image=AcquireImage(image_info,exception);
556   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
557   if (status == MagickFalse)
558     {
559       image=DestroyImageList(image);
560       return((Image *) NULL);
561     }
562   /*
563     Determine if this a BMP file.
564   */
565   (void) ResetMagickMemory(&bmp_info,0,sizeof(bmp_info));
566   bmp_info.ba_offset=0;
567   start_position=0;
568   count=ReadBlob(image,2,magick);
569   do
570   {
571     PixelInfo
572       quantum_bits;
573
574     PixelPacket
575       shift;
576
577     size_t
578       profile_data,
579       profile_size;
580
581     /*
582       Verify BMP identifier.
583     */
584     if (bmp_info.ba_offset == 0)
585       start_position=TellBlob(image)-2;
586     bmp_info.ba_offset=0;
587     while (LocaleNCompare((char *) magick,"BA",2) == 0)
588     {
589       bmp_info.file_size=ReadBlobLSBLong(image);
590       bmp_info.ba_offset=ReadBlobLSBLong(image);
591       bmp_info.offset_bits=ReadBlobLSBLong(image);
592       count=ReadBlob(image,2,magick);
593       if (count != 2)
594         break;
595     }
596     if (image->debug != MagickFalse)
597       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  Magick: %c%c",
598         magick[0],magick[1]);
599     if ((count == 0) || ((LocaleNCompare((char *) magick,"BM",2) != 0) &&
600         (LocaleNCompare((char *) magick,"CI",2) != 0)))
601       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
602     bmp_info.file_size=ReadBlobLSBLong(image);
603     (void) ReadBlobLSBLong(image);
604     bmp_info.offset_bits=ReadBlobLSBLong(image);
605     bmp_info.size=ReadBlobLSBLong(image);
606     if (image->debug != MagickFalse)
607       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  BMP size: %u",
608         bmp_info.size);
609     if (bmp_info.size == 12)
610       {
611         /*
612           OS/2 BMP image file.
613         */
614         bmp_info.width=(short) ReadBlobLSBShort(image);
615         bmp_info.height=(short) ReadBlobLSBShort(image);
616         bmp_info.planes=ReadBlobLSBShort(image);
617         bmp_info.bits_per_pixel=ReadBlobLSBShort(image);
618         bmp_info.x_pixels=0;
619         bmp_info.y_pixels=0;
620         bmp_info.number_colors=0;
621         bmp_info.compression=BI_RGB;
622         bmp_info.image_size=0;
623         bmp_info.alpha_mask=0;
624         if (image->debug != MagickFalse)
625           {
626             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
627               "  Format: OS/2 Bitmap");
628             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
629               "  Geometry: %.20gx%.20g",(double) bmp_info.width,(double)
630               bmp_info.height);
631           }
632       }
633     else
634       {
635         /*
636           Microsoft Windows BMP image file.
637         */
638         if (bmp_info.size < 40)
639           ThrowReaderException(CorruptImageError,"NonOS2HeaderSizeError");
640         bmp_info.width=(int) ReadBlobLSBLong(image);
641         bmp_info.height=(int) ReadBlobLSBLong(image);
642         bmp_info.planes=ReadBlobLSBShort(image);
643         bmp_info.bits_per_pixel=ReadBlobLSBShort(image);
644         bmp_info.compression=ReadBlobLSBLong(image);
645         bmp_info.image_size=ReadBlobLSBLong(image);
646         bmp_info.x_pixels=ReadBlobLSBLong(image);
647         bmp_info.y_pixels=ReadBlobLSBLong(image);
648         bmp_info.number_colors=ReadBlobLSBLong(image);
649         bmp_info.colors_important=ReadBlobLSBLong(image);
650         profile_data=0;
651         profile_size=0;
652         if (image->debug != MagickFalse)
653           {
654             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
655               "  Format: MS Windows bitmap");
656             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
657               "  Geometry: %.20gx%.20g",(double) bmp_info.width,(double)
658               bmp_info.height);
659             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
660               "  Bits per pixel: %.20g",(double) bmp_info.bits_per_pixel);
661             switch ((int) bmp_info.compression)
662             {
663               case BI_RGB:
664               {
665                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
666                   "  Compression: BI_RGB");
667                 break;
668               }
669               case BI_RLE4:
670               {
671                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
672                   "  Compression: BI_RLE4");
673                 break;
674               }
675               case BI_RLE8:
676               {
677                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
678                   "  Compression: BI_RLE8");
679                 break;
680               }
681               case BI_BITFIELDS:
682               {
683                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
684                   "  Compression: BI_BITFIELDS");
685                 break;
686               }
687               case BI_PNG:
688               {
689                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
690                   "  Compression: BI_PNG");
691                 break;
692               }
693               case BI_JPEG:
694               {
695                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
696                   "  Compression: BI_JPEG");
697                 break;
698               }
699               default:
700               {
701                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
702                   "  Compression: UNKNOWN (%u)",bmp_info.compression);
703               }
704             }
705             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
706               "  Number of colors: %u",bmp_info.number_colors);
707           }
708         bmp_info.red_mask=ReadBlobLSBLong(image);
709         bmp_info.green_mask=ReadBlobLSBLong(image);
710         bmp_info.blue_mask=ReadBlobLSBLong(image);
711         if (bmp_info.size > 40)
712           {
713
714             double
715               sum;
716
717             /*
718               Read color management information.
719             */
720             bmp_info.alpha_mask=ReadBlobLSBLong(image);
721             bmp_info.colorspace=(int) ReadBlobLSBLong(image);
722             /*
723               Decode 2^30 fixed point formatted CIE primaries.
724             */
725 #           define BMP_DENOM ((double) 0x40000000)
726             bmp_info.red_primary.x=(double) ReadBlobLSBLong(image)/BMP_DENOM;
727             bmp_info.red_primary.y=(double) ReadBlobLSBLong(image)/BMP_DENOM;
728             bmp_info.red_primary.z=(double) ReadBlobLSBLong(image)/BMP_DENOM;
729             bmp_info.green_primary.x=(double) ReadBlobLSBLong(image)/BMP_DENOM;
730             bmp_info.green_primary.y=(double) ReadBlobLSBLong(image)/BMP_DENOM;
731             bmp_info.green_primary.z=(double) ReadBlobLSBLong(image)/BMP_DENOM;
732             bmp_info.blue_primary.x=(double) ReadBlobLSBLong(image)/BMP_DENOM;
733             bmp_info.blue_primary.y=(double) ReadBlobLSBLong(image)/BMP_DENOM;
734             bmp_info.blue_primary.z=(double) ReadBlobLSBLong(image)/BMP_DENOM;
735
736             sum=bmp_info.red_primary.x+bmp_info.red_primary.y+
737               bmp_info.red_primary.z;
738             bmp_info.red_primary.x/=sum;
739             bmp_info.red_primary.y/=sum;
740             image->chromaticity.red_primary.x=bmp_info.red_primary.x;
741             image->chromaticity.red_primary.y=bmp_info.red_primary.y;
742
743             sum=bmp_info.green_primary.x+bmp_info.green_primary.y+
744               bmp_info.green_primary.z;
745             bmp_info.green_primary.x/=sum;
746             bmp_info.green_primary.y/=sum;
747             image->chromaticity.green_primary.x=bmp_info.green_primary.x;
748             image->chromaticity.green_primary.y=bmp_info.green_primary.y;
749
750             sum=bmp_info.blue_primary.x+bmp_info.blue_primary.y+
751               bmp_info.blue_primary.z;
752             bmp_info.blue_primary.x/=sum;
753             bmp_info.blue_primary.y/=sum;
754             image->chromaticity.blue_primary.x=bmp_info.blue_primary.x;
755             image->chromaticity.blue_primary.y=bmp_info.blue_primary.y;
756
757             /*
758               Decode 16^16 fixed point formatted gamma_scales.
759             */
760             bmp_info.gamma_scale.x=(double) ReadBlobLSBLong(image)/0x10000;
761             bmp_info.gamma_scale.y=(double) ReadBlobLSBLong(image)/0x10000;
762             bmp_info.gamma_scale.z=(double) ReadBlobLSBLong(image)/0x10000;
763             /*
764               Compute a single gamma from the BMP 3-channel gamma.
765             */
766             image->gamma=(bmp_info.gamma_scale.x+bmp_info.gamma_scale.y+
767               bmp_info.gamma_scale.z)/3.0;
768           }
769
770         if (bmp_info.size > 108)
771           {
772             size_t
773               intent;
774
775             /*
776               Read BMP Version 5 color management information.
777             */
778             intent=ReadBlobLSBLong(image);
779             switch ((int) intent)
780             {
781               case LCS_GM_BUSINESS:
782               {
783                 image->rendering_intent=SaturationIntent;
784                 break;
785               }
786               case LCS_GM_GRAPHICS:
787               {
788                 image->rendering_intent=RelativeIntent;
789                 break;
790               }
791               case LCS_GM_IMAGES:
792               {
793                 image->rendering_intent=PerceptualIntent;
794                 break;
795               }
796               case LCS_GM_ABS_COLORIMETRIC:
797               {
798                 image->rendering_intent=AbsoluteIntent;
799                 break;
800               }
801             }
802             profile_data=ReadBlobLSBLong(image);
803             profile_size=ReadBlobLSBLong(image);
804             (void) profile_data;
805             (void) profile_size;
806             (void) ReadBlobLSBLong(image);  /* Reserved byte */
807           }
808       }
809     if ((MagickSizeType) bmp_info.file_size > GetBlobSize(image))
810       (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
811         "LengthAndFilesizeDoNotMatch","`%s'",image->filename);
812     else
813       if ((MagickSizeType) bmp_info.file_size < GetBlobSize(image))
814         (void) ThrowMagickException(exception,GetMagickModule(),
815           CorruptImageWarning,"LengthAndFilesizeDoNotMatch","`%s'",
816           image->filename);
817     if (bmp_info.width <= 0)
818       ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
819     if (bmp_info.height == 0)
820       ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
821     if (bmp_info.planes != 1)
822       ThrowReaderException(CorruptImageError,"StaticPlanesValueNotEqualToOne");
823     if ((bmp_info.bits_per_pixel != 1) && (bmp_info.bits_per_pixel != 4) &&
824         (bmp_info.bits_per_pixel != 8) && (bmp_info.bits_per_pixel != 16) &&
825         (bmp_info.bits_per_pixel != 24) && (bmp_info.bits_per_pixel != 32))
826       ThrowReaderException(CorruptImageError,"UnrecognizedBitsPerPixel");
827     if (bmp_info.bits_per_pixel < 16 &&
828         bmp_info.number_colors > (1U << bmp_info.bits_per_pixel))
829       {
830         ThrowReaderException(CorruptImageError,
831             "UnrecognizedNumberOfColors");
832       }
833     if ((bmp_info.compression == 1) && (bmp_info.bits_per_pixel != 8))
834       ThrowReaderException(CorruptImageError,"UnrecognizedBitsPerPixel");
835     if ((bmp_info.compression == 2) && (bmp_info.bits_per_pixel != 4))
836       ThrowReaderException(CorruptImageError,"UnrecognizedBitsPerPixel");
837     if ((bmp_info.compression == 3) && (bmp_info.bits_per_pixel < 16))
838       ThrowReaderException(CorruptImageError,"UnrecognizedBitsPerPixel");
839     switch (bmp_info.compression)
840     {
841       case BI_RGB:
842       case BI_RLE8:
843       case BI_RLE4:
844       case BI_BITFIELDS:
845         break;
846       case BI_JPEG:
847         ThrowReaderException(CoderError,"JPEGCompressNotSupported");
848       case BI_PNG:
849         ThrowReaderException(CoderError,"PNGCompressNotSupported");
850       default:
851         ThrowReaderException(CorruptImageError,"UnrecognizedImageCompression");
852     }
853     image->columns=(size_t) MagickAbsoluteValue(bmp_info.width);
854     image->rows=(size_t) MagickAbsoluteValue(bmp_info.height);
855     image->depth=bmp_info.bits_per_pixel <= 8 ? bmp_info.bits_per_pixel : 8;
856     image->alpha_trait=(bmp_info.alpha_mask != 0) &&
857       (bmp_info.compression == BI_BITFIELDS) ? BlendPixelTrait :
858       UndefinedPixelTrait;
859     if (bmp_info.bits_per_pixel < 16)
860       {
861         size_t
862           one;
863
864         image->storage_class=PseudoClass;
865         image->colors=bmp_info.number_colors;
866         one=1;
867         if (image->colors == 0)
868           image->colors=one << bmp_info.bits_per_pixel;
869       }
870     if (image->storage_class == PseudoClass)
871       {
872         unsigned char
873           *bmp_colormap;
874
875         size_t
876           packet_size;
877
878         /*
879           Read BMP raster colormap.
880         */
881         if (image->debug != MagickFalse)
882           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
883             "  Reading colormap of %.20g colors",(double) image->colors);
884         if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
885           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
886         bmp_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
887           image->colors,4*sizeof(*bmp_colormap));
888         if (bmp_colormap == (unsigned char *) NULL)
889           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
890         if ((bmp_info.size == 12) || (bmp_info.size == 64))
891           packet_size=3;
892         else
893           packet_size=4;
894         offset=SeekBlob(image,start_position+14+bmp_info.size,SEEK_SET);
895         if (offset < 0)
896           ThrowReaderException(CorruptImageError,"ImproperImageHeader");
897         count=ReadBlob(image,packet_size*image->colors,bmp_colormap);
898         if (count != (ssize_t) (packet_size*image->colors))
899           ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
900         p=bmp_colormap;
901         for (i=0; i < (ssize_t) image->colors; i++)
902         {
903           image->colormap[i].blue=ScaleCharToQuantum(*p++);
904           image->colormap[i].green=ScaleCharToQuantum(*p++);
905           image->colormap[i].red=ScaleCharToQuantum(*p++);
906           if (packet_size == 4)
907             p++;
908         }
909         bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);
910       }
911     image->resolution.x=(double) bmp_info.x_pixels/100.0;
912     image->resolution.y=(double) bmp_info.y_pixels/100.0;
913     image->units=PixelsPerCentimeterResolution;
914     if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
915       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
916         break;
917     /*
918       Read image data.
919     */
920     offset=SeekBlob(image,start_position+bmp_info.offset_bits,SEEK_SET);
921     if (offset < 0)
922       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
923     if (bmp_info.compression == BI_RLE4)
924       bmp_info.bits_per_pixel<<=1;
925     bytes_per_line=4*((image->columns*bmp_info.bits_per_pixel+31)/32);
926     length=(size_t) bytes_per_line*image->rows;
927     pixels=(unsigned char *) AcquireQuantumMemory((size_t) image->rows,
928       MagickMax(bytes_per_line,image->columns+256UL)*sizeof(*pixels));
929     if (pixels == (unsigned char *) NULL)
930       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
931     if ((bmp_info.compression == BI_RGB) ||
932         (bmp_info.compression == BI_BITFIELDS))
933       {
934         if (image->debug != MagickFalse)
935           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
936             "  Reading pixels (%.20g bytes)",(double) length);
937         count=ReadBlob(image,length,pixels);
938         if (count != (ssize_t) length)
939           {
940             pixels=(unsigned char *) RelinquishMagickMemory(pixels);
941             ThrowReaderException(CorruptImageError,
942               "InsufficientImageDataInFile");
943           }
944       }
945     else
946       {
947         /*
948           Convert run-length encoded raster pixels.
949         */
950         status=DecodeImage(image,bmp_info.compression,pixels);
951         if (status == MagickFalse)
952           {
953             pixels=(unsigned char *) RelinquishMagickMemory(pixels);
954             ThrowReaderException(CorruptImageError,
955               "UnableToRunlengthDecodeImage");
956           }
957       }
958     /*
959       Convert BMP raster image to pixel packets.
960     */
961     if (bmp_info.compression == BI_RGB)
962       {
963         bmp_info.alpha_mask=image->alpha_trait == BlendPixelTrait ?
964           0xff000000L : 0L;
965         bmp_info.red_mask=0x00ff0000U;
966         bmp_info.green_mask=0x0000ff00U;
967         bmp_info.blue_mask=0x000000ffU;
968         if (bmp_info.bits_per_pixel == 16)
969           {
970             /*
971               RGB555.
972             */
973             bmp_info.red_mask=0x00007c00U;
974             bmp_info.green_mask=0x000003e0U;
975             bmp_info.blue_mask=0x0000001fU;
976           }
977       }
978     if ((bmp_info.bits_per_pixel == 16) || (bmp_info.bits_per_pixel == 32))
979       {
980         register size_t
981           sample;
982
983         /*
984           Get shift and quantum bits info from bitfield masks.
985         */
986         (void) ResetMagickMemory(&shift,0,sizeof(shift));
987         (void) ResetMagickMemory(&quantum_bits,0,sizeof(quantum_bits));
988         if (bmp_info.red_mask != 0)
989           while (((bmp_info.red_mask << shift.red) & 0x80000000UL) == 0)
990             shift.red++;
991         if (bmp_info.green_mask != 0)
992           while (((bmp_info.green_mask << shift.green) & 0x80000000UL) == 0)
993             shift.green++;
994         if (bmp_info.blue_mask != 0)
995           while (((bmp_info.blue_mask << shift.blue) & 0x80000000UL) == 0)
996             shift.blue++;
997         if (bmp_info.alpha_mask != 0)
998           while (((bmp_info.alpha_mask << shift.alpha) & 0x80000000UL) == 0)
999             shift.alpha++;
1000         sample=shift.red;
1001         while (((bmp_info.red_mask << sample) & 0x80000000UL) != 0)
1002           sample++;
1003         quantum_bits.red=(Quantum) (sample-shift.red);
1004         sample=shift.green;
1005         while (((bmp_info.green_mask << sample) & 0x80000000UL) != 0)
1006           sample++;
1007         quantum_bits.green=(Quantum) (sample-shift.green);
1008         sample=shift.blue;
1009         while (((bmp_info.blue_mask << sample) & 0x80000000UL) != 0)
1010           sample++;
1011         quantum_bits.blue=(Quantum) (sample-shift.blue);
1012         sample=shift.alpha;
1013         while (((bmp_info.alpha_mask << sample) & 0x80000000UL) != 0)
1014           sample++;
1015         quantum_bits.alpha=(Quantum) (sample-shift.alpha);
1016       }
1017     switch (bmp_info.bits_per_pixel)
1018     {
1019       case 1:
1020       {
1021         /*
1022           Convert bitmap scanline.
1023         */
1024         for (y=(ssize_t) image->rows-1; y >= 0; y--)
1025         {
1026           p=pixels+(image->rows-y-1)*bytes_per_line;
1027           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1028           if (q == (Quantum *) NULL)
1029             break;
1030           for (x=0; x < ((ssize_t) image->columns-7); x+=8)
1031           {
1032             for (bit=0; bit < 8; bit++)
1033             {
1034               index=(Quantum) (((*p) & (0x80 >> bit)) != 0 ? 0x01 : 0x00);
1035               SetPixelIndex(image,index,q);
1036               q+=GetPixelChannels(image);
1037             }
1038             p++;
1039           }
1040           if ((image->columns % 8) != 0)
1041             {
1042               for (bit=0; bit < (image->columns % 8); bit++)
1043               {
1044                 index=(Quantum) (((*p) & (0x80 >> bit)) != 0 ? 0x01 : 0x00);
1045                 SetPixelIndex(image,index,q);
1046                 q+=GetPixelChannels(image);
1047               }
1048               p++;
1049             }
1050           if (SyncAuthenticPixels(image,exception) == MagickFalse)
1051             break;
1052           if (image->previous == (Image *) NULL)
1053             {
1054               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
1055                 image->rows);
1056               if (status == MagickFalse)
1057                 break;
1058             }
1059         }
1060         (void) SyncImage(image,exception);
1061         break;
1062       }
1063       case 4:
1064       {
1065         /*
1066           Convert PseudoColor scanline.
1067         */
1068         for (y=(ssize_t) image->rows-1; y >= 0; y--)
1069         {
1070           p=pixels+(image->rows-y-1)*bytes_per_line;
1071           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1072           if (q == (Quantum *) NULL)
1073             break;
1074           for (x=0; x < ((ssize_t) image->columns-1); x+=2)
1075           {
1076             index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f,exception);
1077             SetPixelIndex(image,index,q);
1078             q+=GetPixelChannels(image);
1079             index=ConstrainColormapIndex(image,*p & 0x0f,exception);
1080             SetPixelIndex(image,index,q);
1081             q+=GetPixelChannels(image);
1082             p++;
1083           }
1084           if ((image->columns % 2) != 0)
1085             {
1086               index=ConstrainColormapIndex(image,(*p >> 4) & 0xf,exception);
1087               SetPixelIndex(image,index,q);
1088               q+=GetPixelChannels(image);
1089               p++;
1090             }
1091           if (SyncAuthenticPixels(image,exception) == MagickFalse)
1092             break;
1093           if (image->previous == (Image *) NULL)
1094             {
1095               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
1096                 image->rows);
1097               if (status == MagickFalse)
1098                 break;
1099             }
1100         }
1101         (void) SyncImage(image,exception);
1102         break;
1103       }
1104       case 8:
1105       {
1106         /*
1107           Convert PseudoColor scanline.
1108         */
1109         if ((bmp_info.compression == BI_RLE8) ||
1110             (bmp_info.compression == BI_RLE4))
1111           bytes_per_line=image->columns;
1112         for (y=(ssize_t) image->rows-1; y >= 0; y--)
1113         {
1114           p=pixels+(image->rows-y-1)*bytes_per_line;
1115           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1116           if (q == (Quantum *) NULL)
1117             break;
1118           for (x=(ssize_t) image->columns; x != 0; --x)
1119           {
1120             index=ConstrainColormapIndex(image,*p++,exception);
1121             SetPixelIndex(image,index,q);
1122             q+=GetPixelChannels(image);
1123           }
1124           if (SyncAuthenticPixels(image,exception) == MagickFalse)
1125             break;
1126           offset=(MagickOffsetType) (image->rows-y-1);
1127           if (image->previous == (Image *) NULL)
1128             {
1129               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
1130                 image->rows);
1131               if (status == MagickFalse)
1132                 break;
1133             }
1134         }
1135         (void) SyncImage(image,exception);
1136         break;
1137       }
1138       case 16:
1139       {
1140         size_t
1141           pixel;
1142
1143         /*
1144           Convert bitfield encoded 16-bit PseudoColor scanline.
1145         */
1146         if (bmp_info.compression != BI_RGB &&
1147             bmp_info.compression != BI_BITFIELDS)
1148           {
1149             pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1150             ThrowReaderException(CorruptImageError,
1151               "UnrecognizedImageCompression");
1152           }
1153         bytes_per_line=2*(image->columns+image->columns % 2);
1154         image->storage_class=DirectClass;
1155         for (y=(ssize_t) image->rows-1; y >= 0; y--)
1156         {
1157           p=pixels+(image->rows-y-1)*bytes_per_line;
1158           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1159           if (q == (Quantum *) NULL)
1160             break;
1161           for (x=0; x < (ssize_t) image->columns; x++)
1162           {
1163             pixel=(size_t) (*p++);
1164             pixel|=(*p++) << 8;
1165             red=((pixel & bmp_info.red_mask) << shift.red) >> 16;
1166             if (quantum_bits.red == 5)
1167               red|=((red & 0xe000) >> 5);
1168             if (quantum_bits.red <= 8)
1169               red|=((red & 0xff00) >> 8);
1170             green=((pixel & bmp_info.green_mask) << shift.green) >> 16;
1171             if (quantum_bits.green == 5)
1172               green|=((green & 0xe000) >> 5);
1173             if (quantum_bits.green == 6)
1174               green|=((green & 0xc000) >> 6);
1175             if (quantum_bits.green <= 8)
1176               green|=((green & 0xff00) >> 8);
1177             blue=((pixel & bmp_info.blue_mask) << shift.blue) >> 16;
1178             if (quantum_bits.blue == 5)
1179               blue|=((blue & 0xe000) >> 5);
1180             if (quantum_bits.blue <= 8)
1181               blue|=((blue & 0xff00) >> 8);
1182             opacity=((pixel & bmp_info.alpha_mask) << shift.alpha) >> 16;
1183             if (quantum_bits.alpha <= 8)
1184               opacity|=((opacity & 0xff00) >> 8);
1185             SetPixelRed(image,ScaleShortToQuantum((unsigned short) red),q);
1186             SetPixelGreen(image,ScaleShortToQuantum((unsigned short) green),q);
1187             SetPixelBlue(image,ScaleShortToQuantum((unsigned short) blue),q);
1188             SetPixelAlpha(image,OpaqueAlpha,q);
1189             if (image->alpha_trait == BlendPixelTrait)
1190               SetPixelAlpha(image,
1191                 ScaleShortToQuantum((unsigned short) opacity),q);
1192             q+=GetPixelChannels(image);
1193           }
1194           if (SyncAuthenticPixels(image,exception) == MagickFalse)
1195             break;
1196           offset=(MagickOffsetType) (image->rows-y-1);
1197           if (image->previous == (Image *) NULL)
1198             {
1199               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
1200                 image->rows);
1201               if (status == MagickFalse)
1202                 break;
1203             }
1204         }
1205         break;
1206       }
1207       case 24:
1208       {
1209         /*
1210           Convert DirectColor scanline.
1211         */
1212         bytes_per_line=4*((image->columns*24+31)/32);
1213         for (y=(ssize_t) image->rows-1; y >= 0; y--)
1214         {
1215           p=pixels+(image->rows-y-1)*bytes_per_line;
1216           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1217           if (q == (Quantum *) NULL)
1218             break;
1219           for (x=0; x < (ssize_t) image->columns; x++)
1220           {
1221             SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
1222             SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
1223             SetPixelRed(image,ScaleCharToQuantum(*p++),q);
1224             SetPixelAlpha(image,OpaqueAlpha,q);
1225             q+=GetPixelChannels(image);
1226           }
1227           if (SyncAuthenticPixels(image,exception) == MagickFalse)
1228             break;
1229           offset=(MagickOffsetType) (image->rows-y-1);
1230           if (image->previous == (Image *) NULL)
1231             {
1232               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
1233                 image->rows);
1234               if (status == MagickFalse)
1235                 break;
1236             }
1237         }
1238         break;
1239       }
1240       case 32:
1241       {
1242         /*
1243           Convert bitfield encoded DirectColor scanline.
1244         */
1245         if ((bmp_info.compression != BI_RGB) &&
1246             (bmp_info.compression != BI_BITFIELDS))
1247           {
1248             pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1249             ThrowReaderException(CorruptImageError,
1250               "UnrecognizedImageCompression");
1251           }
1252         bytes_per_line=4*(image->columns);
1253         for (y=(ssize_t) image->rows-1; y >= 0; y--)
1254         {
1255           size_t
1256             pixel;
1257
1258           p=pixels+(image->rows-y-1)*bytes_per_line;
1259           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1260           if (q == (Quantum *) NULL)
1261             break;
1262           for (x=0; x < (ssize_t) image->columns; x++)
1263           {
1264             pixel=(size_t) (*p++);
1265             pixel|=(*p++ << 8);
1266             pixel|=(*p++ << 16);
1267             pixel|=(*p++ << 24);
1268             red=((pixel & bmp_info.red_mask) << shift.red) >> 16;
1269             if (quantum_bits.red == 8)
1270               red|=(red >> 8);
1271             green=((pixel & bmp_info.green_mask) << shift.green) >> 16;
1272             if (quantum_bits.green == 8)
1273               green|=(green >> 8);
1274             blue=((pixel & bmp_info.blue_mask) << shift.blue) >> 16;
1275             if (quantum_bits.blue == 8)
1276               blue|=(blue >> 8);
1277             opacity=((pixel & bmp_info.alpha_mask) << shift.alpha) >> 16;
1278             if (quantum_bits.alpha == 8)
1279               opacity|=(opacity >> 8);
1280             SetPixelRed(image,ScaleShortToQuantum((unsigned short) red),q);
1281             SetPixelGreen(image,ScaleShortToQuantum((unsigned short) green),q);
1282             SetPixelBlue(image,ScaleShortToQuantum((unsigned short) blue),q);
1283             SetPixelAlpha(image,OpaqueAlpha,q);
1284             if (image->alpha_trait == BlendPixelTrait)
1285               SetPixelAlpha(image,
1286                 ScaleShortToQuantum((unsigned short) opacity),q);
1287             q+=GetPixelChannels(image);
1288           }
1289           if (SyncAuthenticPixels(image,exception) == MagickFalse)
1290             break;
1291           offset=(MagickOffsetType) (image->rows-y-1);
1292           if (image->previous == (Image *) NULL)
1293             {
1294               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
1295                 image->rows);
1296               if (status == MagickFalse)
1297                 break;
1298             }
1299         }
1300         break;
1301       }
1302       default:
1303       {
1304         pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1305         ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1306       }
1307     }
1308     pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1309     if (EOFBlob(image) != MagickFalse)
1310       {
1311         ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1312           image->filename);
1313         break;
1314       }
1315     if (bmp_info.height < 0)
1316       {
1317         Image
1318           *flipped_image;
1319
1320         /*
1321           Correct image orientation.
1322         */
1323         flipped_image=FlipImage(image,exception);
1324         if (flipped_image != (Image *) NULL)
1325           {
1326             DuplicateBlob(flipped_image,image);
1327             image=DestroyImage(image);
1328             image=flipped_image;
1329           }
1330       }
1331     /*
1332       Proceed to next image.
1333     */
1334     if (image_info->number_scenes != 0)
1335       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1336         break;
1337     *magick='\0';
1338     if (bmp_info.ba_offset != 0)
1339       {
1340         offset=SeekBlob(image,(MagickOffsetType) bmp_info.ba_offset,SEEK_SET);
1341         if (offset < 0)
1342           ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1343       }
1344     count=ReadBlob(image,2,magick);
1345     if ((count == 2) && (IsBMP(magick,2) != MagickFalse))
1346       {
1347         /*
1348           Acquire next image structure.
1349         */
1350         AcquireNextImage(image_info,image,exception);
1351         if (GetNextImageInList(image) == (Image *) NULL)
1352           {
1353             image=DestroyImageList(image);
1354             return((Image *) NULL);
1355           }
1356         image=SyncNextImageInList(image);
1357         status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1358           GetBlobSize(image));
1359         if (status == MagickFalse)
1360           break;
1361       }
1362   } while (IsBMP(magick,2) != MagickFalse);
1363   (void) CloseBlob(image);
1364   return(GetFirstImageInList(image));
1365 }
1366 \f
1367 /*
1368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1369 %                                                                             %
1370 %                                                                             %
1371 %                                                                             %
1372 %   R e g i s t e r B M P I m a g e                                           %
1373 %                                                                             %
1374 %                                                                             %
1375 %                                                                             %
1376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1377 %
1378 %  RegisterBMPImage() adds attributes for the BMP image format to
1379 %  the list of supported formats.  The attributes include the image format
1380 %  tag, a method to read and/or write the format, whether the format
1381 %  supports the saving of more than one frame to the same file or blob,
1382 %  whether the format supports native in-memory I/O, and a brief
1383 %  description of the format.
1384 %
1385 %  The format of the RegisterBMPImage method is:
1386 %
1387 %      size_t RegisterBMPImage(void)
1388 %
1389 */
1390 ModuleExport size_t RegisterBMPImage(void)
1391 {
1392   MagickInfo
1393     *entry;
1394
1395   entry=SetMagickInfo("BMP");
1396   entry->decoder=(DecodeImageHandler *) ReadBMPImage;
1397   entry->encoder=(EncodeImageHandler *) WriteBMPImage;
1398   entry->magick=(IsImageFormatHandler *) IsBMP;
1399   entry->description=ConstantString("Microsoft Windows bitmap image");
1400   entry->module=ConstantString("BMP");
1401   entry->adjoin=MagickFalse;
1402   entry->seekable_stream=MagickTrue;
1403   (void) RegisterMagickInfo(entry);
1404   entry=SetMagickInfo("BMP2");
1405   entry->encoder=(EncodeImageHandler *) WriteBMPImage;
1406   entry->magick=(IsImageFormatHandler *) IsBMP;
1407   entry->description=ConstantString("Microsoft Windows bitmap image (V2)");
1408   entry->module=ConstantString("BMP");
1409   entry->adjoin=MagickFalse;
1410   entry->seekable_stream=MagickTrue;
1411   (void) RegisterMagickInfo(entry);
1412   entry=SetMagickInfo("BMP3");
1413   entry->encoder=(EncodeImageHandler *) WriteBMPImage;
1414   entry->magick=(IsImageFormatHandler *) IsBMP;
1415   entry->description=ConstantString("Microsoft Windows bitmap image (V3)");
1416   entry->module=ConstantString("BMP");
1417   entry->adjoin=MagickFalse;
1418   entry->seekable_stream=MagickTrue;
1419   (void) RegisterMagickInfo(entry);
1420   return(MagickImageCoderSignature);
1421 }
1422 \f
1423 /*
1424 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1425 %                                                                             %
1426 %                                                                             %
1427 %                                                                             %
1428 %   U n r e g i s t e r B M P I m a g e                                       %
1429 %                                                                             %
1430 %                                                                             %
1431 %                                                                             %
1432 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1433 %
1434 %  UnregisterBMPImage() removes format registrations made by the
1435 %  BMP module from the list of supported formats.
1436 %
1437 %  The format of the UnregisterBMPImage method is:
1438 %
1439 %      UnregisterBMPImage(void)
1440 %
1441 */
1442 ModuleExport void UnregisterBMPImage(void)
1443 {
1444   (void) UnregisterMagickInfo("BMP");
1445   (void) UnregisterMagickInfo("BMP2");
1446   (void) UnregisterMagickInfo("BMP3");
1447 }
1448 \f
1449 /*
1450 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1451 %                                                                             %
1452 %                                                                             %
1453 %                                                                             %
1454 %   W r i t e B M P I m a g e                                                 %
1455 %                                                                             %
1456 %                                                                             %
1457 %                                                                             %
1458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1459 %
1460 %  WriteBMPImage() writes an image in Microsoft Windows bitmap encoded
1461 %  image format, version 3 for Windows or (if the image has a matte channel)
1462 %  version 4.
1463 %
1464 %  The format of the WriteBMPImage method is:
1465 %
1466 %      MagickBooleanType WriteBMPImage(const ImageInfo *image_info,
1467 %        Image *image,ExceptionInfo *exception)
1468 %
1469 %  A description of each parameter follows.
1470 %
1471 %    o image_info: the image info.
1472 %
1473 %    o image:  The image.
1474 %
1475 %    o exception: return any errors or warnings in this structure.
1476 %
1477 */
1478 static MagickBooleanType WriteBMPImage(const ImageInfo *image_info,Image *image,
1479   ExceptionInfo *exception)
1480 {
1481   BMPInfo
1482     bmp_info;
1483
1484   const StringInfo
1485     *profile;
1486
1487   MagickBooleanType
1488     have_color_info,
1489     status;
1490
1491   MagickOffsetType
1492     scene;
1493
1494   register const Quantum
1495     *p;
1496
1497   register ssize_t
1498     i,
1499     x;
1500
1501   register unsigned char
1502     *q;
1503
1504   size_t
1505     bytes_per_line,
1506     type;
1507
1508   ssize_t
1509     y;
1510
1511   unsigned char
1512     *bmp_data,
1513     *pixels;
1514
1515   /*
1516     Open output image file.
1517   */
1518   assert(image_info != (const ImageInfo *) NULL);
1519   assert(image_info->signature == MagickSignature);
1520   assert(image != (Image *) NULL);
1521   assert(image->signature == MagickSignature);
1522   if (image->debug != MagickFalse)
1523     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1524   assert(exception != (ExceptionInfo *) NULL);
1525   assert(exception->signature == MagickSignature);
1526   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1527   if (status == MagickFalse)
1528     return(status);
1529   type=4;
1530   if (LocaleCompare(image_info->magick,"BMP2") == 0)
1531     type=2;
1532   else
1533     if (LocaleCompare(image_info->magick,"BMP3") == 0)
1534       type=3;
1535   scene=0;
1536   do
1537   {
1538     /*
1539       Initialize BMP raster file header.
1540     */
1541     if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1542       (void) TransformImageColorspace(image,sRGBColorspace,exception);
1543     (void) ResetMagickMemory(&bmp_info,0,sizeof(bmp_info));
1544     bmp_info.file_size=14+12;
1545     if (type > 2)
1546       bmp_info.file_size+=28;
1547     bmp_info.offset_bits=bmp_info.file_size;
1548     bmp_info.compression=BI_RGB;
1549     if ((image->storage_class == PseudoClass) && (image->colors > 256))
1550       (void) SetImageStorageClass(image,DirectClass,exception);
1551     if (image->storage_class != DirectClass)
1552       {
1553         /*
1554           Colormapped BMP raster.
1555         */
1556         bmp_info.bits_per_pixel=8;
1557         if (image->colors <= 2)
1558           bmp_info.bits_per_pixel=1;
1559         else
1560           if (image->colors <= 16)
1561             bmp_info.bits_per_pixel=4;
1562           else
1563             if (image->colors <= 256)
1564               bmp_info.bits_per_pixel=8;
1565         if (image_info->compression == RLECompression)
1566           bmp_info.bits_per_pixel=8;
1567         bmp_info.number_colors=1U << bmp_info.bits_per_pixel;
1568         if (image->alpha_trait == BlendPixelTrait)
1569           (void) SetImageStorageClass(image,DirectClass,exception);
1570         else
1571           if ((size_t) bmp_info.number_colors < image->colors)
1572             (void) SetImageStorageClass(image,DirectClass,exception);
1573           else
1574             {
1575               bmp_info.file_size+=3*(1UL << bmp_info.bits_per_pixel);
1576               bmp_info.offset_bits+=3*(1UL << bmp_info.bits_per_pixel);
1577               if (type > 2)
1578                 {
1579                   bmp_info.file_size+=(1UL << bmp_info.bits_per_pixel);
1580                   bmp_info.offset_bits+=(1UL << bmp_info.bits_per_pixel);
1581                 }
1582             }
1583       }
1584     if (image->storage_class == DirectClass)
1585       {
1586         /*
1587           Full color BMP raster.
1588         */
1589         bmp_info.number_colors=0;
1590         bmp_info.bits_per_pixel=(unsigned short)
1591           ((type > 3) && (image->alpha_trait == BlendPixelTrait) ? 32 : 24);
1592         bmp_info.compression=(unsigned int) ((type > 3) &&
1593           (image->alpha_trait == BlendPixelTrait) ?  BI_BITFIELDS : BI_RGB);
1594       }
1595     bytes_per_line=4*((image->columns*bmp_info.bits_per_pixel+31)/32);
1596     bmp_info.ba_offset=0;
1597     profile=GetImageProfile(image,"icc");
1598     have_color_info=(image->rendering_intent != UndefinedIntent) ||
1599       (profile != (StringInfo *) NULL) || (image->gamma != 0.0) ?  MagickTrue :
1600       MagickFalse;
1601     if (type == 2)
1602       bmp_info.size=12;
1603     else
1604       if ((type == 3) || ((image->alpha_trait != BlendPixelTrait) &&
1605           (have_color_info == MagickFalse)))
1606         {
1607           type=3;
1608           bmp_info.size=40;
1609         }
1610       else
1611         {
1612           int
1613             extra_size;
1614
1615           bmp_info.size=108;
1616           extra_size=68;
1617           if ((image->rendering_intent != UndefinedIntent) ||
1618               (profile != (StringInfo *) NULL))
1619             {
1620               bmp_info.size=124;
1621               extra_size+=16;
1622             }
1623           bmp_info.file_size+=extra_size;
1624           bmp_info.offset_bits+=extra_size;
1625         }
1626     bmp_info.width=(ssize_t) image->columns;
1627     bmp_info.height=(ssize_t) image->rows;
1628     bmp_info.planes=1;
1629     bmp_info.image_size=(unsigned int) (bytes_per_line*image->rows);
1630     bmp_info.file_size+=bmp_info.image_size;
1631     bmp_info.x_pixels=75*39;
1632     bmp_info.y_pixels=75*39;
1633     switch (image->units)
1634     {
1635       case UndefinedResolution:
1636       case PixelsPerInchResolution:
1637       {
1638         bmp_info.x_pixels=(unsigned int) (100.0*image->resolution.x/2.54);
1639         bmp_info.y_pixels=(unsigned int) (100.0*image->resolution.y/2.54);
1640         break;
1641       }
1642       case PixelsPerCentimeterResolution:
1643       {
1644         bmp_info.x_pixels=(unsigned int) (100.0*image->resolution.x);
1645         bmp_info.y_pixels=(unsigned int) (100.0*image->resolution.y);
1646         break;
1647       }
1648     }
1649     bmp_info.colors_important=bmp_info.number_colors;
1650     /*
1651       Convert MIFF to BMP raster pixels.
1652     */
1653     pixels=(unsigned char *) AcquireQuantumMemory((size_t) bmp_info.image_size,
1654       sizeof(*pixels));
1655     if (pixels == (unsigned char *) NULL)
1656       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1657     (void) ResetMagickMemory(pixels,0,(size_t) bmp_info.image_size);
1658     switch (bmp_info.bits_per_pixel)
1659     {
1660       case 1:
1661       {
1662         size_t
1663           bit,
1664           byte;
1665
1666         /*
1667           Convert PseudoClass image to a BMP monochrome image.
1668         */
1669         for (y=0; y < (ssize_t) image->rows; y++)
1670         {
1671           ssize_t
1672             offset;
1673
1674           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1675           if (p == (const Quantum *) NULL)
1676             break;
1677           q=pixels+(image->rows-y-1)*bytes_per_line;
1678           bit=0;
1679           byte=0;
1680           for (x=0; x < (ssize_t) image->columns; x++)
1681           {
1682             byte<<=1;
1683             byte|=GetPixelIndex(image,p) != 0 ? 0x01 : 0x00;
1684             bit++;
1685             if (bit == 8)
1686               {
1687                 *q++=(unsigned char) byte;
1688                 bit=0;
1689                 byte=0;
1690               }
1691              p+=GetPixelChannels(image);
1692            }
1693            if (bit != 0)
1694              {
1695                *q++=(unsigned char) (byte << (8-bit));
1696                x++;
1697              }
1698           offset=(ssize_t) (image->columns+7)/8;
1699           for (x=offset; x < (ssize_t) bytes_per_line; x++)
1700             *q++=0x00;
1701           if (image->previous == (Image *) NULL)
1702             {
1703               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1704                 image->rows);
1705               if (status == MagickFalse)
1706                 break;
1707             }
1708         }
1709         break;
1710       }
1711       case 4:
1712       {
1713         size_t
1714           byte,
1715           nibble,
1716           offset;
1717
1718         /*
1719           Convert PseudoClass image to a BMP monochrome image.
1720         */
1721         for (y=0; y < (ssize_t) image->rows; y++)
1722         {
1723           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1724           if (p == (const Quantum *) NULL)
1725             break;
1726           q=pixels+(image->rows-y-1)*bytes_per_line;
1727           nibble=0;
1728           byte=0;
1729           for (x=0; x < (ssize_t) image->columns; x++)
1730           {
1731             byte<<=4;
1732             byte|=((size_t) GetPixelIndex(image,p) & 0x0f);
1733             nibble++;
1734             if (nibble == 2)
1735               {
1736                 *q++=(unsigned char) byte;
1737                 nibble=0;
1738                 byte=0;
1739               }
1740             p+=GetPixelChannels(image);
1741           }
1742           if (nibble != 0)
1743             {
1744               *q++=(unsigned char) (byte << 4);
1745               x++;
1746             }
1747           offset=(ssize_t) (image->columns+1)/2;
1748           for (x=offset; x < (ssize_t) bytes_per_line; x++)
1749             *q++=0x00;
1750           if (image->previous == (Image *) NULL)
1751             {
1752               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1753                 image->rows);
1754               if (status == MagickFalse)
1755                 break;
1756             }
1757         }
1758         break;
1759       }
1760       case 8:
1761       {
1762         /*
1763           Convert PseudoClass packet to BMP pixel.
1764         */
1765         for (y=0; y < (ssize_t) image->rows; y++)
1766         {
1767           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1768           if (p == (const Quantum *) NULL)
1769             break;
1770           q=pixels+(image->rows-y-1)*bytes_per_line;
1771           for (x=0; x < (ssize_t) image->columns; x++)
1772           {
1773             *q++=(unsigned char) GetPixelIndex(image,p);
1774             p+=GetPixelChannels(image);
1775           }
1776           for ( ; x < (ssize_t) bytes_per_line; x++)
1777             *q++=0x00;
1778           if (image->previous == (Image *) NULL)
1779             {
1780               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1781                 image->rows);
1782               if (status == MagickFalse)
1783                 break;
1784             }
1785         }
1786         break;
1787       }
1788       case 24:
1789       {
1790         /*
1791           Convert DirectClass packet to BMP BGR888.
1792         */
1793         for (y=0; y < (ssize_t) image->rows; y++)
1794         {
1795           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1796           if (p == (const Quantum *) NULL)
1797             break;
1798           q=pixels+(image->rows-y-1)*bytes_per_line;
1799           for (x=0; x < (ssize_t) image->columns; x++)
1800           {
1801             *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
1802             *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
1803             *q++=ScaleQuantumToChar(GetPixelRed(image,p));
1804             p+=GetPixelChannels(image);
1805           }
1806           for (x=3L*(ssize_t) image->columns; x < (ssize_t) bytes_per_line; x++)
1807             *q++=0x00;
1808           if (image->previous == (Image *) NULL)
1809             {
1810               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1811                 image->rows);
1812               if (status == MagickFalse)
1813                 break;
1814             }
1815         }
1816         break;
1817       }
1818       case 32:
1819       {
1820         /*
1821           Convert DirectClass packet to ARGB8888 pixel.
1822         */
1823         for (y=0; y < (ssize_t) image->rows; y++)
1824         {
1825           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1826           if (p == (const Quantum *) NULL)
1827             break;
1828           q=pixels+(image->rows-y-1)*bytes_per_line;
1829           for (x=0; x < (ssize_t) image->columns; x++)
1830           {
1831             *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
1832             *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
1833             *q++=ScaleQuantumToChar(GetPixelRed(image,p));
1834             *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
1835             p+=GetPixelChannels(image);
1836           }
1837           if (image->previous == (Image *) NULL)
1838             {
1839               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1840                 image->rows);
1841               if (status == MagickFalse)
1842                 break;
1843             }
1844         }
1845         break;
1846       }
1847     }
1848     if ((type > 2) && (bmp_info.bits_per_pixel == 8))
1849       if (image_info->compression != NoCompression)
1850         {
1851           size_t
1852             length;
1853
1854           /*
1855             Convert run-length encoded raster pixels.
1856           */
1857           length=(size_t) (2*(bytes_per_line+2)*(image->rows+2)+2);
1858           bmp_data=(unsigned char *) NULL;
1859           if (~length >= bytes_per_line)
1860             bmp_data=(unsigned char *) AcquireQuantumMemory(length+
1861               bytes_per_line,sizeof(*bmp_data));
1862           if (bmp_data == (unsigned char *) NULL)
1863             {
1864               pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1865               ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1866             }
1867           bmp_info.file_size-=bmp_info.image_size;
1868           bmp_info.image_size=(unsigned int) EncodeImage(image,bytes_per_line,
1869             pixels,bmp_data);
1870           bmp_info.file_size+=bmp_info.image_size;
1871           pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1872           pixels=bmp_data;
1873           bmp_info.compression=BI_RLE8;
1874         }
1875     /*
1876       Write BMP for Windows, all versions, 14-byte header.
1877     */
1878     if (image->debug != MagickFalse)
1879       {
1880         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1881           "   Writing BMP version %.20g datastream",(double) type);
1882         if (image->storage_class == DirectClass)
1883           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1884             "   Storage class=DirectClass");
1885         else
1886           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1887             "   Storage class=PseudoClass");
1888         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1889           "   Image depth=%.20g",(double) image->depth);
1890         if (image->alpha_trait == BlendPixelTrait)
1891           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1892             "   Matte=True");
1893         else
1894           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1895             "   Matte=MagickFalse");
1896         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1897           "   BMP bits_per_pixel=%.20g",(double) bmp_info.bits_per_pixel);
1898         switch ((int) bmp_info.compression)
1899         {
1900            case BI_RGB:
1901            {
1902              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1903                "   Compression=BI_RGB");
1904              break;
1905            }
1906            case BI_RLE8:
1907            {
1908              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1909                "   Compression=BI_RLE8");
1910              break;
1911            }
1912            case BI_BITFIELDS:
1913            {
1914              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1915                "   Compression=BI_BITFIELDS");
1916              break;
1917            }
1918            default:
1919            {
1920              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1921                "   Compression=UNKNOWN (%u)",bmp_info.compression);
1922              break;
1923            }
1924         }
1925         if (bmp_info.number_colors == 0)
1926           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1927             "   Number_colors=unspecified");
1928         else
1929           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1930             "   Number_colors=%u",bmp_info.number_colors);
1931       }
1932     (void) WriteBlob(image,2,(unsigned char *) "BM");
1933     (void) WriteBlobLSBLong(image,bmp_info.file_size);
1934     (void) WriteBlobLSBLong(image,bmp_info.ba_offset);  /* always 0 */
1935     (void) WriteBlobLSBLong(image,bmp_info.offset_bits);
1936     if (type == 2)
1937       {
1938         /*
1939           Write 12-byte version 2 bitmap header.
1940         */
1941         (void) WriteBlobLSBLong(image,bmp_info.size);
1942         (void) WriteBlobLSBShort(image,(unsigned short) bmp_info.width);
1943         (void) WriteBlobLSBShort(image,(unsigned short) bmp_info.height);
1944         (void) WriteBlobLSBShort(image,bmp_info.planes);
1945         (void) WriteBlobLSBShort(image,bmp_info.bits_per_pixel);
1946       }
1947     else
1948       {
1949         /*
1950           Write 40-byte version 3+ bitmap header.
1951         */
1952         (void) WriteBlobLSBLong(image,bmp_info.size);
1953         (void) WriteBlobLSBLong(image,(unsigned int) bmp_info.width);
1954         (void) WriteBlobLSBLong(image,(unsigned int) bmp_info.height);
1955         (void) WriteBlobLSBShort(image,bmp_info.planes);
1956         (void) WriteBlobLSBShort(image,bmp_info.bits_per_pixel);
1957         (void) WriteBlobLSBLong(image,bmp_info.compression);
1958         (void) WriteBlobLSBLong(image,bmp_info.image_size);
1959         (void) WriteBlobLSBLong(image,bmp_info.x_pixels);
1960         (void) WriteBlobLSBLong(image,bmp_info.y_pixels);
1961         (void) WriteBlobLSBLong(image,bmp_info.number_colors);
1962         (void) WriteBlobLSBLong(image,bmp_info.colors_important);
1963       }
1964     if ((type > 3) && ((image->alpha_trait == BlendPixelTrait) ||
1965         (have_color_info != MagickFalse)))
1966       {
1967         /*
1968           Write the rest of the 108-byte BMP Version 4 header.
1969         */
1970         (void) WriteBlobLSBLong(image,0x00ff0000U);  /* Red mask */
1971         (void) WriteBlobLSBLong(image,0x0000ff00U);  /* Green mask */
1972         (void) WriteBlobLSBLong(image,0x000000ffU);  /* Blue mask */
1973         (void) WriteBlobLSBLong(image,0xff000000U);  /* Alpha mask */
1974         (void) WriteBlobLSBLong(image,0x73524742U);  /* sRGB */
1975         (void) WriteBlobLSBLong(image,(unsigned int)
1976           (image->chromaticity.red_primary.x*0x40000000));
1977         (void) WriteBlobLSBLong(image,(unsigned int)
1978           (image->chromaticity.red_primary.y*0x40000000));
1979         (void) WriteBlobLSBLong(image,(unsigned int)
1980           ((1.000f-(image->chromaticity.red_primary.x+
1981           image->chromaticity.red_primary.y))*0x40000000));
1982         (void) WriteBlobLSBLong(image,(unsigned int)
1983           (image->chromaticity.green_primary.x*0x40000000));
1984         (void) WriteBlobLSBLong(image,(unsigned int)
1985           (image->chromaticity.green_primary.y*0x40000000));
1986         (void) WriteBlobLSBLong(image,(unsigned int)
1987           ((1.000f-(image->chromaticity.green_primary.x+
1988           image->chromaticity.green_primary.y))*0x40000000));
1989         (void) WriteBlobLSBLong(image,(unsigned int)
1990           (image->chromaticity.blue_primary.x*0x40000000));
1991         (void) WriteBlobLSBLong(image,(unsigned int)
1992           (image->chromaticity.blue_primary.y*0x40000000));
1993         (void) WriteBlobLSBLong(image,(unsigned int)
1994           ((1.000f-(image->chromaticity.blue_primary.x+
1995           image->chromaticity.blue_primary.y))*0x40000000));
1996         (void) WriteBlobLSBLong(image,(unsigned int)
1997           (bmp_info.gamma_scale.x*0x10000));
1998         (void) WriteBlobLSBLong(image,(unsigned int)
1999           (bmp_info.gamma_scale.y*0x10000));
2000         (void) WriteBlobLSBLong(image,(unsigned int)
2001           (bmp_info.gamma_scale.z*0x10000));
2002         if ((image->rendering_intent != UndefinedIntent) ||
2003             (profile != (StringInfo *) NULL))
2004           {
2005             ssize_t
2006               intent;
2007
2008             switch ((int) image->rendering_intent)
2009             {
2010               case SaturationIntent:
2011               {
2012                 intent=LCS_GM_BUSINESS;
2013                 break;
2014               }
2015               case RelativeIntent:
2016               {
2017                 intent=LCS_GM_GRAPHICS;
2018                 break;
2019               }
2020               case PerceptualIntent:
2021               {
2022                 intent=LCS_GM_IMAGES;
2023                 break;
2024               }
2025               case AbsoluteIntent:
2026               {
2027                 intent=LCS_GM_ABS_COLORIMETRIC;
2028                 break;
2029               }
2030               default:
2031               {
2032                 intent=0;
2033                 break;
2034               }
2035             }
2036             (void) WriteBlobLSBLong(image,(unsigned int) intent);
2037             (void) WriteBlobLSBLong(image,0x00);  /* dummy profile data */
2038             (void) WriteBlobLSBLong(image,0x00);  /* dummy profile length */
2039             (void) WriteBlobLSBLong(image,0x00);  /* reserved */
2040           }
2041       }
2042     if (image->storage_class == PseudoClass)
2043       {
2044         unsigned char
2045           *bmp_colormap;
2046
2047         /*
2048           Dump colormap to file.
2049         */
2050         if (image->debug != MagickFalse)
2051           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2052             "  Colormap: %.20g entries",(double) image->colors);
2053         bmp_colormap=(unsigned char *) AcquireQuantumMemory((size_t) (1UL <<
2054           bmp_info.bits_per_pixel),4*sizeof(*bmp_colormap));
2055         if (bmp_colormap == (unsigned char *) NULL)
2056           ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2057         q=bmp_colormap;
2058         for (i=0; i < (ssize_t) MagickMin((ssize_t) image->colors,(ssize_t) bmp_info.number_colors); i++)
2059         {
2060           *q++=ScaleQuantumToChar(image->colormap[i].blue);
2061           *q++=ScaleQuantumToChar(image->colormap[i].green);
2062           *q++=ScaleQuantumToChar(image->colormap[i].red);
2063           if (type > 2)
2064             *q++=(unsigned char) 0x0;
2065         }
2066         for ( ; i < (ssize_t) (1UL << bmp_info.bits_per_pixel); i++)
2067         {
2068           *q++=(unsigned char) 0x00;
2069           *q++=(unsigned char) 0x00;
2070           *q++=(unsigned char) 0x00;
2071           if (type > 2)
2072             *q++=(unsigned char) 0x00;
2073         }
2074         if (type <= 2)
2075           (void) WriteBlob(image,(size_t) (3*(1L << bmp_info.bits_per_pixel)),
2076             bmp_colormap);
2077         else
2078           (void) WriteBlob(image,(size_t) (4*(1L << bmp_info.bits_per_pixel)),
2079             bmp_colormap);
2080         bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);
2081       }
2082     if (image->debug != MagickFalse)
2083       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2084         "  Pixels:  %u bytes",bmp_info.image_size);
2085     (void) WriteBlob(image,(size_t) bmp_info.image_size,pixels);
2086     pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2087     if (GetNextImageInList(image) == (Image *) NULL)
2088       break;
2089     image=SyncNextImageInList(image);
2090     status=SetImageProgress(image,SaveImagesTag,scene++,
2091       GetImageListLength(image));
2092     if (status == MagickFalse)
2093       break;
2094   } while (image_info->adjoin != MagickFalse);
2095   (void) CloseBlob(image);
2096   return(MagickTrue);
2097 }