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