]> granicus.if.org Git - imagemagick/blob - coders/bmp.c
13a4c2e00c919e231cf1f52c703dfcb1c29ef4fe
[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-2010 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             SetOpacityPixelComponent(q,OpaqueOpacity);
1147             if (image->matte != MagickFalse)
1148               q->opacity=ScaleShortToQuantum((unsigned short) (65535-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             SetOpacityPixelComponent(q,OpaqueOpacity);
1235             if (image->matte != MagickFalse)
1236               q->opacity=ScaleShortToQuantum((unsigned short) (65535-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             DuplicateBlob(flipped_image,image);
1273             image=DestroyImage(image);
1274             image=flipped_image;
1275           }
1276       }
1277     /*
1278       Proceed to next image.
1279     */
1280     if (image_info->number_scenes != 0)
1281       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1282         break;
1283     *magick='\0';
1284     if (bmp_info.ba_offset != 0)
1285       {
1286         offset=SeekBlob(image,(MagickOffsetType) bmp_info.ba_offset,SEEK_SET);
1287         if (offset < 0)
1288           ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1289       }
1290     count=ReadBlob(image,2,magick);
1291     if ((count == 2) && (IsBMP(magick,2) != MagickFalse))
1292       {
1293         /*
1294           Acquire next image structure.
1295         */
1296         AcquireNextImage(image_info,image);
1297         if (GetNextImageInList(image) == (Image *) NULL)
1298           {
1299             image=DestroyImageList(image);
1300             return((Image *) NULL);
1301           }
1302         image=SyncNextImageInList(image);
1303         status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1304           GetBlobSize(image));
1305         if (status == MagickFalse)
1306           break;
1307       }
1308   } while (IsBMP(magick,2) != MagickFalse);
1309   (void) CloseBlob(image);
1310   return(GetFirstImageInList(image));
1311 }
1312 \f
1313 /*
1314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1315 %                                                                             %
1316 %                                                                             %
1317 %                                                                             %
1318 %   R e g i s t e r B M P I m a g e                                           %
1319 %                                                                             %
1320 %                                                                             %
1321 %                                                                             %
1322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1323 %
1324 %  RegisterBMPImage() adds attributes for the BMP image format to
1325 %  the list of supported formats.  The attributes include the image format
1326 %  tag, a method to read and/or write the format, whether the format
1327 %  supports the saving of more than one frame to the same file or blob,
1328 %  whether the format supports native in-memory I/O, and a brief
1329 %  description of the format.
1330 %
1331 %  The format of the RegisterBMPImage method is:
1332 %
1333 %      unsigned long RegisterBMPImage(void)
1334 %
1335 */
1336 ModuleExport unsigned long RegisterBMPImage(void)
1337 {
1338   MagickInfo
1339     *entry;
1340
1341   entry=SetMagickInfo("BMP");
1342   entry->decoder=(DecodeImageHandler *) ReadBMPImage;
1343   entry->encoder=(EncodeImageHandler *) WriteBMPImage;
1344   entry->magick=(IsImageFormatHandler *) IsBMP;
1345   entry->description=ConstantString("Microsoft Windows bitmap image");
1346   entry->module=ConstantString("BMP");
1347   entry->adjoin=MagickFalse;
1348   entry->seekable_stream=MagickTrue;
1349   (void) RegisterMagickInfo(entry);
1350   entry=SetMagickInfo("BMP2");
1351   entry->encoder=(EncodeImageHandler *) WriteBMPImage;
1352   entry->magick=(IsImageFormatHandler *) IsBMP;
1353   entry->description=ConstantString("Microsoft Windows bitmap image (V2)");
1354   entry->module=ConstantString("BMP");
1355   entry->adjoin=MagickFalse;
1356   entry->seekable_stream=MagickTrue;
1357   (void) RegisterMagickInfo(entry);
1358   entry=SetMagickInfo("BMP3");
1359   entry->encoder=(EncodeImageHandler *) WriteBMPImage;
1360   entry->magick=(IsImageFormatHandler *) IsBMP;
1361   entry->description=ConstantString("Microsoft Windows bitmap image (V3)");
1362   entry->module=ConstantString("BMP");
1363   entry->adjoin=MagickFalse;
1364   entry->seekable_stream=MagickTrue;
1365   (void) RegisterMagickInfo(entry);
1366   return(MagickImageCoderSignature);
1367 }
1368 \f
1369 /*
1370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1371 %                                                                             %
1372 %                                                                             %
1373 %                                                                             %
1374 %   U n r e g i s t e r B M P I m a g e                                       %
1375 %                                                                             %
1376 %                                                                             %
1377 %                                                                             %
1378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1379 %
1380 %  UnregisterBMPImage() removes format registrations made by the
1381 %  BMP module from the list of supported formats.
1382 %
1383 %  The format of the UnregisterBMPImage method is:
1384 %
1385 %      UnregisterBMPImage(void)
1386 %
1387 */
1388 ModuleExport void UnregisterBMPImage(void)
1389 {
1390   (void) UnregisterMagickInfo("BMP");
1391   (void) UnregisterMagickInfo("BMP2");
1392   (void) UnregisterMagickInfo("BMP3");
1393 }
1394 \f
1395 /*
1396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1397 %                                                                             %
1398 %                                                                             %
1399 %                                                                             %
1400 %   W r i t e B M P I m a g e                                                 %
1401 %                                                                             %
1402 %                                                                             %
1403 %                                                                             %
1404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1405 %
1406 %  WriteBMPImage() writes an image in Microsoft Windows bitmap encoded
1407 %  image format, version 3 for Windows or (if the image has a matte channel)
1408 %  version 4.
1409 %
1410 %  The format of the WriteBMPImage method is:
1411 %
1412 %      MagickBooleanType WriteBMPImage(const ImageInfo *image_info,Image *image)
1413 %
1414 %  A description of each parameter follows.
1415 %
1416 %    o image_info: the image info.
1417 %
1418 %    o image:  The image.
1419 %
1420 */
1421 static MagickBooleanType WriteBMPImage(const ImageInfo *image_info,Image *image)
1422 {
1423   BMPInfo
1424     bmp_info;
1425
1426   const StringInfo
1427     *profile;
1428
1429   long
1430     y;
1431
1432   MagickBooleanType
1433     have_color_info,
1434     status;
1435
1436   MagickOffsetType
1437     scene;
1438
1439   register const IndexPacket
1440     *indexes;
1441
1442   register const PixelPacket
1443     *p;
1444
1445   register long
1446     i,
1447     x;
1448
1449   register unsigned char
1450     *q;
1451
1452   unsigned char
1453     *bmp_data,
1454     *pixels;
1455
1456   unsigned long
1457     bytes_per_line,
1458     type;
1459
1460   /*
1461     Open output image file.
1462   */
1463   assert(image_info != (const ImageInfo *) NULL);
1464   assert(image_info->signature == MagickSignature);
1465   assert(image != (Image *) NULL);
1466   assert(image->signature == MagickSignature);
1467   if (image->debug != MagickFalse)
1468     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1469   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1470   if (status == MagickFalse)
1471     return(status);
1472   type=4;
1473   if (LocaleCompare(image_info->magick,"BMP2") == 0)
1474     type=2;
1475   else
1476     if (LocaleCompare(image_info->magick,"BMP3") == 0)
1477       type=3;
1478   scene=0;
1479   do
1480   {
1481     /*
1482       Initialize BMP raster file header.
1483     */
1484     if (image->colorspace != RGBColorspace)
1485       (void) TransformImageColorspace(image,RGBColorspace);
1486     (void) ResetMagickMemory(&bmp_info,0,sizeof(bmp_info));
1487     bmp_info.file_size=14+12;
1488     if (type > 2)
1489       bmp_info.file_size+=28;
1490     bmp_info.offset_bits=bmp_info.file_size;
1491     bmp_info.compression=BI_RGB;
1492     if ((image->storage_class == PseudoClass) && (image->colors > 256))
1493       (void) SetImageStorageClass(image,DirectClass);
1494     if (image->storage_class != DirectClass)
1495       {
1496         /*
1497           Colormapped BMP raster.
1498         */
1499         bmp_info.bits_per_pixel=8;
1500         if (image->colors <= 2)
1501           bmp_info.bits_per_pixel=1;
1502         else
1503           if (image->colors <= 16)
1504             bmp_info.bits_per_pixel=4;
1505           else
1506             if (image->colors <= 256)
1507               bmp_info.bits_per_pixel=8;
1508         if (image_info->compression == RLECompression)
1509           bmp_info.bits_per_pixel=8;
1510         bmp_info.number_colors=1U << bmp_info.bits_per_pixel;
1511         if (image->matte != MagickFalse)
1512           (void) SetImageStorageClass(image,DirectClass);
1513         else
1514           if ((unsigned long) bmp_info.number_colors < image->colors)
1515             (void) SetImageStorageClass(image,DirectClass);
1516           else
1517             {
1518               bmp_info.file_size+=3*(1UL << bmp_info.bits_per_pixel);
1519               bmp_info.offset_bits+=3*(1UL << bmp_info.bits_per_pixel);
1520               if (type > 2)
1521                 {
1522                   bmp_info.file_size+=(1UL << bmp_info.bits_per_pixel);
1523                   bmp_info.offset_bits+=(1UL << bmp_info.bits_per_pixel);
1524                 }
1525             }
1526       }
1527     if (image->storage_class == DirectClass)
1528       {
1529         /*
1530           Full color BMP raster.
1531         */
1532         bmp_info.number_colors=0;
1533         bmp_info.bits_per_pixel=(unsigned short)
1534           ((type > 3) && (image->matte != MagickFalse) ? 32 : 24);
1535         bmp_info.compression=(unsigned int) ((type > 3) &&
1536           (image->matte != MagickFalse) ?  BI_BITFIELDS : BI_RGB);
1537       }
1538     bytes_per_line=4*((image->columns*bmp_info.bits_per_pixel+31)/32);
1539     bmp_info.ba_offset=0;
1540     profile=GetImageProfile(image,"icc");
1541     have_color_info=(image->rendering_intent != UndefinedIntent) ||
1542       (profile != (StringInfo *) NULL) || (image->gamma != 0.0) ?  MagickTrue :
1543       MagickFalse;
1544     if (type == 2)
1545       bmp_info.size=12;
1546     else
1547       if ((type == 3) || ((image->matte == MagickFalse) &&
1548           (have_color_info == MagickFalse)))
1549         {
1550           type=3;
1551           bmp_info.size=40;
1552         }
1553       else
1554         {
1555           int
1556             extra_size;
1557
1558           bmp_info.size=108;
1559           extra_size=68;
1560           if ((image->rendering_intent != UndefinedIntent) ||
1561               (profile != (StringInfo *) NULL))
1562             {
1563               bmp_info.size=124;
1564               extra_size+=16;
1565             }
1566           bmp_info.file_size+=extra_size;
1567           bmp_info.offset_bits+=extra_size;
1568         }
1569     bmp_info.width=(long) image->columns;
1570     bmp_info.height=(long) image->rows;
1571     bmp_info.planes=1;
1572     bmp_info.image_size=(unsigned int) (bytes_per_line*image->rows);
1573     bmp_info.file_size+=bmp_info.image_size;
1574     bmp_info.x_pixels=75*39;
1575     bmp_info.y_pixels=75*39;
1576     switch (image->units)
1577     {
1578       case UndefinedResolution:
1579       case PixelsPerInchResolution:
1580       {
1581         bmp_info.x_pixels=(unsigned int) (100.0*image->x_resolution/2.54);
1582         bmp_info.y_pixels=(unsigned int) (100.0*image->y_resolution/2.54);
1583         break;
1584       }
1585       case PixelsPerCentimeterResolution:
1586       {
1587         bmp_info.x_pixels=(unsigned int) (100.0*image->x_resolution);
1588         bmp_info.y_pixels=(unsigned int) (100.0*image->y_resolution);
1589         break;
1590       }
1591     }
1592     bmp_info.colors_important=bmp_info.number_colors;
1593     /*
1594       Convert MIFF to BMP raster pixels.
1595     */
1596     pixels=(unsigned char *) AcquireQuantumMemory((size_t) bmp_info.image_size,
1597       sizeof(*pixels));
1598     if (pixels == (unsigned char *) NULL)
1599       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1600     (void) ResetMagickMemory(pixels,0,(size_t) bmp_info.image_size);
1601     switch (bmp_info.bits_per_pixel)
1602     {
1603       case 1:
1604       {
1605         unsigned long
1606           bit,
1607           byte;
1608
1609         /*
1610           Convert PseudoClass image to a BMP monochrome image.
1611         */
1612         for (y=0; y < (long) image->rows; y++)
1613         {
1614           p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1615           if (p == (const PixelPacket *) NULL)
1616             break;
1617           indexes=GetVirtualIndexQueue(image);
1618           q=pixels+(image->rows-y-1)*bytes_per_line;
1619           bit=0;
1620           byte=0;
1621           for (x=0; x < (long) image->columns; x++)
1622           {
1623             byte<<=1;
1624             byte|=indexes[x] != 0 ? 0x01 : 0x00;
1625             bit++;
1626             if (bit == 8)
1627               {
1628                 *q++=(unsigned char) byte;
1629                 bit=0;
1630                 byte=0;
1631               }
1632            }
1633            if (bit != 0)
1634              {
1635                *q++=(unsigned char) (byte << (8-bit));
1636                x++;
1637              }
1638           for (x=(long) (image->columns+7)/8; x < (long) bytes_per_line; x++)
1639             *q++=0x00;
1640           if (image->previous == (Image *) NULL)
1641             {
1642               status=SetImageProgress(image,SaveImageTag,y,image->rows);
1643               if (status == MagickFalse)
1644                 break;
1645             }
1646         }
1647         break;
1648       }
1649       case 4:
1650       {
1651         unsigned long
1652           nibble,
1653           byte;
1654
1655         /*
1656           Convert PseudoClass image to a BMP monochrome image.
1657         */
1658         for (y=0; y < (long) image->rows; y++)
1659         {
1660           p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1661           if (p == (const PixelPacket *) NULL)
1662             break;
1663           indexes=GetVirtualIndexQueue(image);
1664           q=pixels+(image->rows-y-1)*bytes_per_line;
1665           nibble=0;
1666           byte=0;
1667           for (x=0; x < (long) image->columns; x++)
1668           {
1669             byte<<=4;
1670             byte|=((unsigned long) indexes[x] & 0x0f);
1671             nibble++;
1672             if (nibble == 2)
1673               {
1674                 *q++=(unsigned char) byte;
1675                 nibble=0;
1676                 byte=0;
1677               }
1678            }
1679          if (nibble != 0)
1680            {
1681              *q++=(unsigned char) (byte << 4);
1682              x++;
1683            }
1684           for (x=(long) (image->columns+1)/2; x < (long) bytes_per_line; x++)
1685             *q++=0x00;
1686           if (image->previous == (Image *) NULL)
1687             {
1688               status=SetImageProgress(image,SaveImageTag,y,image->rows);
1689               if (status == MagickFalse)
1690                 break;
1691             }
1692         }
1693         break;
1694       }
1695       case 8:
1696       {
1697         /*
1698           Convert PseudoClass packet to BMP pixel.
1699         */
1700         for (y=0; y < (long) image->rows; y++)
1701         {
1702           p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1703           if (p == (const PixelPacket *) NULL)
1704             break;
1705           indexes=GetVirtualIndexQueue(image);
1706           q=pixels+(image->rows-y-1)*bytes_per_line;
1707           for (x=0; x < (long) image->columns; x++)
1708             *q++=(unsigned char) indexes[x];
1709           for ( ; x < (long) bytes_per_line; x++)
1710             *q++=0x00;
1711           if (image->previous == (Image *) NULL)
1712             {
1713               status=SetImageProgress(image,SaveImageTag,y,image->rows);
1714               if (status == MagickFalse)
1715                 break;
1716             }
1717         }
1718         break;
1719       }
1720       case 24:
1721       {
1722         /*
1723           Convert DirectClass packet to BMP BGR888.
1724         */
1725         for (y=0; y < (long) image->rows; y++)
1726         {
1727           p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1728           if (p == (const PixelPacket *) NULL)
1729             break;
1730           q=pixels+(image->rows-y-1)*bytes_per_line;
1731           for (x=0; x < (long) image->columns; x++)
1732           {
1733             *q++=ScaleQuantumToChar(GetBluePixelComponent(p));
1734             *q++=ScaleQuantumToChar(GetGreenPixelComponent(p));
1735             *q++=ScaleQuantumToChar(GetRedPixelComponent(p));
1736             p++;
1737           }
1738           for (x=3L*(long) image->columns; x < (long) bytes_per_line; x++)
1739             *q++=0x00;
1740           if (image->previous == (Image *) NULL)
1741             {
1742               status=SetImageProgress(image,SaveImageTag,y,image->rows);
1743               if (status == MagickFalse)
1744                 break;
1745             }
1746         }
1747         break;
1748       }
1749       case 32:
1750       {
1751         /*
1752           Convert DirectClass packet to ARGB8888 pixel.
1753         */
1754         for (y=0; y < (long) image->rows; y++)
1755         {
1756           p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1757           if (p == (const PixelPacket *) NULL)
1758             break;
1759           q=pixels+(image->rows-y-1)*bytes_per_line;
1760           for (x=0; x < (long) image->columns; x++)
1761           {
1762             *q++=ScaleQuantumToChar(GetBluePixelComponent(p));
1763             *q++=ScaleQuantumToChar(GetGreenPixelComponent(p));
1764             *q++=ScaleQuantumToChar(GetRedPixelComponent(p));
1765             *q++=ScaleQuantumToChar(QuantumRange-GetOpacityPixelComponent(p));
1766             p++;
1767           }
1768           if (image->previous == (Image *) NULL)
1769             {
1770               status=SetImageProgress(image,SaveImageTag,y,image->rows);
1771               if (status == MagickFalse)
1772                 break;
1773             }
1774         }
1775         break;
1776       }
1777     }
1778     if ((type > 2) && (bmp_info.bits_per_pixel == 8))
1779       if (image_info->compression != NoCompression)
1780         {
1781           size_t
1782             length;
1783
1784           /*
1785             Convert run-length encoded raster pixels.
1786           */
1787           length=(size_t) (2*(bytes_per_line+2)*(image->rows+2)+2);
1788           bmp_data=(unsigned char *) NULL;
1789           if (~length >= bytes_per_line)
1790             bmp_data=(unsigned char *) AcquireQuantumMemory(length+
1791               bytes_per_line,sizeof(*bmp_data));
1792           if (bmp_data == (unsigned char *) NULL)
1793             {
1794               pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1795               ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1796             }
1797           bmp_info.file_size-=bmp_info.image_size;
1798           bmp_info.image_size=(unsigned int) EncodeImage(image,bytes_per_line,
1799             pixels,bmp_data);
1800           bmp_info.file_size+=bmp_info.image_size;
1801           pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1802           pixels=bmp_data;
1803           bmp_info.compression=BI_RLE8;
1804         }
1805     /*
1806       Write BMP for Windows, all versions, 14-byte header.
1807     */
1808     if (image->debug != MagickFalse)
1809       {
1810         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1811           "   Writing BMP version %ld datastream",type);
1812         if (image->storage_class == DirectClass)
1813           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1814             "   Storage class=DirectClass");
1815         else
1816           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1817             "   Storage class=PseudoClass");
1818         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1819           "   Image depth=%lu",image->depth);
1820         if (image->matte != MagickFalse)
1821           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1822             "   Matte=True");
1823         else
1824           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1825             "   Matte=MagickFalse");
1826         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1827           "   BMP bits_per_pixel=%d",bmp_info.bits_per_pixel);
1828         switch ((int) bmp_info.compression)
1829         {
1830            case BI_RGB:
1831            {
1832              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1833                "   Compression=BI_RGB");
1834              break;
1835            }
1836            case BI_RLE8:
1837            {
1838              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1839                "   Compression=BI_RLE8");
1840              break;
1841            }
1842            case BI_BITFIELDS:
1843            {
1844              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1845                "   Compression=BI_BITFIELDS");
1846              break;
1847            }
1848            default:
1849            {
1850              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1851                "   Compression=UNKNOWN (%u)",bmp_info.compression);
1852              break;
1853            }
1854         }
1855         if (bmp_info.number_colors == 0)
1856           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1857             "   Number_colors=unspecified");
1858         else
1859           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1860             "   Number_colors=%u",bmp_info.number_colors);
1861       }
1862     (void) WriteBlob(image,2,(unsigned char *) "BM");
1863     (void) WriteBlobLSBLong(image,bmp_info.file_size);
1864     (void) WriteBlobLSBLong(image,bmp_info.ba_offset);  /* always 0 */
1865     (void) WriteBlobLSBLong(image,bmp_info.offset_bits);
1866     if (type == 2)
1867       {
1868         /*
1869           Write 12-byte version 2 bitmap header.
1870         */
1871         (void) WriteBlobLSBLong(image,bmp_info.size);
1872         (void) WriteBlobLSBShort(image,(unsigned short) bmp_info.width);
1873         (void) WriteBlobLSBShort(image,(unsigned short) bmp_info.height);
1874         (void) WriteBlobLSBShort(image,bmp_info.planes);
1875         (void) WriteBlobLSBShort(image,bmp_info.bits_per_pixel);
1876       }
1877     else
1878       {
1879         /*
1880           Write 40-byte version 3+ bitmap header.
1881         */
1882         (void) WriteBlobLSBLong(image,bmp_info.size);
1883         (void) WriteBlobLSBLong(image,(unsigned int) bmp_info.width);
1884         (void) WriteBlobLSBLong(image,(unsigned int) bmp_info.height);
1885         (void) WriteBlobLSBShort(image,bmp_info.planes);
1886         (void) WriteBlobLSBShort(image,bmp_info.bits_per_pixel);
1887         (void) WriteBlobLSBLong(image,bmp_info.compression);
1888         (void) WriteBlobLSBLong(image,bmp_info.image_size);
1889         (void) WriteBlobLSBLong(image,bmp_info.x_pixels);
1890         (void) WriteBlobLSBLong(image,bmp_info.y_pixels);
1891         (void) WriteBlobLSBLong(image,bmp_info.number_colors);
1892         (void) WriteBlobLSBLong(image,bmp_info.colors_important);
1893       }
1894     if ((type > 3) && ((image->matte != MagickFalse) ||
1895         (have_color_info != MagickFalse)))
1896       {
1897         /*
1898           Write the rest of the 108-byte BMP Version 4 header.
1899         */
1900         (void) WriteBlobLSBLong(image,0x00ff0000U);  /* Red mask */
1901         (void) WriteBlobLSBLong(image,0x0000ff00U);  /* Green mask */
1902         (void) WriteBlobLSBLong(image,0x000000ffU);  /* Blue mask */
1903         (void) WriteBlobLSBLong(image,0xff000000U);  /* Alpha mask */
1904         (void) WriteBlobLSBLong(image,0x00000001U);  /* CSType==Calib. RGB */
1905         (void) WriteBlobLSBLong(image,(unsigned int)
1906           image->chromaticity.red_primary.x*0x3ffffff);
1907         (void) WriteBlobLSBLong(image,(unsigned int)
1908           image->chromaticity.red_primary.y*0x3ffffff);
1909         (void) WriteBlobLSBLong(image,(unsigned int)
1910           (1.000f-(image->chromaticity.red_primary.x+
1911           image->chromaticity.red_primary.y)*0x3ffffff));
1912         (void) WriteBlobLSBLong(image,(unsigned int)
1913           image->chromaticity.green_primary.x*0x3ffffff);
1914         (void) WriteBlobLSBLong(image,(unsigned int)
1915           image->chromaticity.green_primary.y*0x3ffffff);
1916         (void) WriteBlobLSBLong(image,(unsigned int)
1917           (1.000f-(image->chromaticity.green_primary.x+
1918           image->chromaticity.green_primary.y)*0x3ffffff));
1919         (void) WriteBlobLSBLong(image,(unsigned int)
1920           image->chromaticity.blue_primary.x*0x3ffffff);
1921         (void) WriteBlobLSBLong(image,(unsigned int)
1922           image->chromaticity.blue_primary.y*0x3ffffff);
1923         (void) WriteBlobLSBLong(image,(unsigned int)
1924           (1.000f-(image->chromaticity.blue_primary.x+
1925           image->chromaticity.blue_primary.y)*0x3ffffff));
1926         (void) WriteBlobLSBLong(image,(unsigned int)
1927           bmp_info.gamma_scale.x*0xffff);
1928         (void) WriteBlobLSBLong(image,(unsigned int)
1929           bmp_info.gamma_scale.y*0xffff);
1930         (void) WriteBlobLSBLong(image,(unsigned int)
1931           bmp_info.gamma_scale.z*0xffff);
1932         if ((image->rendering_intent != UndefinedIntent) ||
1933             (profile != (StringInfo *) NULL))
1934           {
1935             long
1936               intent;
1937
1938             switch ((int) image->rendering_intent)
1939             {
1940               case SaturationIntent:
1941               {
1942                 intent=LCS_GM_BUSINESS;
1943                 break;
1944               }
1945               case RelativeIntent:
1946               {
1947                 intent=LCS_GM_GRAPHICS;
1948                 break;
1949               }
1950               case PerceptualIntent:
1951               {
1952                 intent=LCS_GM_IMAGES;
1953                 break;
1954               }
1955               case AbsoluteIntent:
1956               {
1957                 intent=LCS_GM_ABS_COLORIMETRIC;
1958                 break;
1959               }
1960               default:
1961               {
1962                 intent=0;
1963                 break;
1964               }
1965             }
1966             (void) WriteBlobLSBLong(image,(unsigned int) intent);
1967             (void) WriteBlobLSBLong(image,0x00);  /* dummy profile data */
1968             (void) WriteBlobLSBLong(image,0x00);  /* dummy profile length */
1969             (void) WriteBlobLSBLong(image,0x00);  /* reserved */
1970           }
1971       }
1972     if (image->storage_class == PseudoClass)
1973       {
1974         unsigned char
1975           *bmp_colormap;
1976
1977         /*
1978           Dump colormap to file.
1979         */
1980         if (image->debug != MagickFalse)
1981           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1982             "  Colormap: %ld entries",image->colors);
1983         bmp_colormap=(unsigned char *) AcquireQuantumMemory((size_t) (1UL <<
1984           bmp_info.bits_per_pixel),4*sizeof(*bmp_colormap));
1985         if (bmp_colormap == (unsigned char *) NULL)
1986           ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1987         q=bmp_colormap;
1988         for (i=0; i < (long) MagickMin((long) image->colors,(long) bmp_info.number_colors); i++)
1989         {
1990           *q++=ScaleQuantumToChar(image->colormap[i].blue);
1991           *q++=ScaleQuantumToChar(image->colormap[i].green);
1992           *q++=ScaleQuantumToChar(image->colormap[i].red);
1993           if (type > 2)
1994             *q++=(unsigned char) 0x0;
1995         }
1996         for ( ; i < (long) (1UL << bmp_info.bits_per_pixel); i++)
1997         {
1998           *q++=(unsigned char) 0x00;
1999           *q++=(unsigned char) 0x00;
2000           *q++=(unsigned char) 0x00;
2001           if (type > 2)
2002             *q++=(unsigned char) 0x00;
2003         }
2004         if (type <= 2)
2005           (void) WriteBlob(image,(size_t) (3*(1L << bmp_info.bits_per_pixel)),
2006             bmp_colormap);
2007         else
2008           (void) WriteBlob(image,(size_t) (4*(1L << bmp_info.bits_per_pixel)),
2009             bmp_colormap);
2010         bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);
2011       }
2012     if (image->debug != MagickFalse)
2013       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2014         "  Pixels:  %u bytes",bmp_info.image_size);
2015     (void) WriteBlob(image,(size_t) bmp_info.image_size,pixels);
2016     pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2017     if (GetNextImageInList(image) == (Image *) NULL)
2018       break;
2019     image=SyncNextImageInList(image);
2020     status=SetImageProgress(image,SaveImagesTag,scene++,
2021       GetImageListLength(image));
2022     if (status == MagickFalse)
2023       break;
2024   } while (image_info->adjoin != MagickFalse);
2025   (void) CloseBlob(image);
2026   return(MagickTrue);
2027 }