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