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