root/ImageMagick/trunk/coders/bmp.c

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