Coverage Report

Created: 2025-08-12 07:37

/src/imagemagick/coders/bmp.c
Line
Count
Source (jump to first uncovered 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
%                                   Cristy                                    %
17
%                            Glenn Randers-Pehrson                            %
18
%                               December 2001                                 %
19
%                                                                             %
20
%                                                                             %
21
%  Copyright @ 1999 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
%    https://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 "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-private.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

71
/*
72
  Macro definitions (from Windows wingdi.h).
73
*/
74
#undef BI_JPEG
75
36.6k
#define BI_JPEG  4
76
#undef BI_PNG
77
18.7k
#define BI_PNG  5
78
#ifndef BI_ALPHABITFIELDS
79
42.8k
 #define BI_ALPHABITFIELDS 6
80
#endif
81
#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__)
82
#undef BI_RGB
83
47.5k
#define BI_RGB  0
84
#undef BI_RLE8
85
39.1k
#define BI_RLE8  1
86
#undef BI_RLE4
87
30.1k
#define BI_RLE4  2
88
#undef BI_BITFIELDS
89
58.8k
#define BI_BITFIELDS  3
90
91
#undef LCS_CALIBRATED_RBG
92
#define LCS_CALIBRATED_RBG  0
93
#undef LCS_sRGB
94
#define LCS_sRGB  1
95
#undef LCS_WINDOWS_COLOR_SPACE
96
#define LCS_WINDOWS_COLOR_SPACE  2
97
#undef PROFILE_LINKED
98
#define PROFILE_LINKED  3
99
#undef PROFILE_EMBEDDED
100
#define PROFILE_EMBEDDED  4
101
102
#undef LCS_GM_BUSINESS
103
34
#define LCS_GM_BUSINESS  1  /* Saturation */
104
#undef LCS_GM_GRAPHICS
105
12
#define LCS_GM_GRAPHICS  2  /* Relative */
106
#undef LCS_GM_IMAGES
107
472
#define LCS_GM_IMAGES  4  /* Perceptual */
108
#undef LCS_GM_ABS_COLORIMETRIC
109
23
#define LCS_GM_ABS_COLORIMETRIC  8  /* Absolute */
110
#endif
111

112
/*
113
  Enumerated declarations.
114
*/
115
typedef enum
116
{
117
  UndefinedSubtype,
118
  RGB555,
119
  RGB565,
120
  ARGB4444,
121
  ARGB1555
122
} BMPSubtype;
123
124
/*
125
  Typedef declarations.
126
*/
127
typedef struct _BMPInfo
128
{
129
  unsigned int
130
    file_size,
131
    ba_offset,
132
    offset_bits,
133
    size;
134
135
  ssize_t
136
    width,
137
    height;
138
139
  unsigned short
140
    planes,
141
    bits_per_pixel;
142
143
  unsigned int
144
    compression,
145
    image_size,
146
    x_pixels,
147
    y_pixels,
148
    number_colors,
149
    red_mask,
150
    green_mask,
151
    blue_mask,
152
    alpha_mask,
153
    colors_important;
154
155
  long
156
    colorspace;
157
158
  PrimaryInfo
159
    red_primary,
160
    green_primary,
161
    blue_primary,
162
    gamma_scale;
163
} BMPInfo;
164

165
/*
166
  Forward declarations.
167
*/
168
static MagickBooleanType
169
  WriteBMPImage(const ImageInfo *,Image *,ExceptionInfo *);
170

171
/*
172
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173
%                                                                             %
174
%                                                                             %
175
%                                                                             %
176
%   D e c o d e I m a g e                                                     %
177
%                                                                             %
178
%                                                                             %
179
%                                                                             %
180
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
181
%
182
%  DecodeImage unpacks the packed image pixels into runlength-encoded pixel
183
%  packets.
184
%
185
%  The format of the DecodeImage method is:
186
%
187
%      MagickBooleanType DecodeImage(Image *image,const size_t compression,
188
%        unsigned char *pixels,const size_t number_pixels)
189
%
190
%  A description of each parameter follows:
191
%
192
%    o image: the address of a structure of type Image.
193
%
194
%    o compression:  Zero means uncompressed.  A value of 1 means the
195
%      compressed pixels are runlength encoded for a 256-color bitmap.
196
%      A value of 2 means a 16-color bitmap.  A value of 3 means bitfields
197
%      encoding.
198
%
199
%    o pixels:  The address of a byte (8 bits) array of pixel data created by
200
%      the decoding process.
201
%
202
%    o number_pixels:  The number of pixels.
203
%
204
*/
205
static MagickBooleanType DecodeImage(Image *image,const size_t compression,
206
  unsigned char *pixels,const size_t number_pixels)
207
1.86k
{
208
1.86k
  int
209
1.86k
    byte,
210
1.86k
    count;
211
212
1.86k
  ssize_t
213
1.86k
    i,
214
1.86k
    x,
215
1.86k
    y;
216
217
1.86k
  unsigned char
218
1.86k
    *p,
219
1.86k
    *q;
220
221
1.86k
  assert(image != (Image *) NULL);
222
1.86k
  assert(image->signature == MagickCoreSignature);
223
1.86k
  assert(pixels != (unsigned char *) NULL);
224
1.86k
  if (IsEventLogging() != MagickFalse)
225
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
226
1.86k
  (void) memset(pixels,0,number_pixels*sizeof(*pixels));
227
1.86k
  byte=0;
228
1.86k
  x=0;
229
1.86k
  p=pixels;
230
1.86k
  q=pixels+number_pixels;
231
26.5k
  for (y=0; y < (ssize_t) image->rows; )
232
25.8k
  {
233
25.8k
    MagickBooleanType
234
25.8k
      status;
235
236
25.8k
    if ((p < pixels) || (p >= q))
237
538
      break;
238
25.2k
    count=ReadBlobByte(image);
239
25.2k
    if (count == EOF)
240
552
      break;
241
24.7k
    if (count > 0)
242
13.4k
      {
243
        /*
244
          Encoded mode.
245
        */
246
13.4k
        count=(int) MagickMin((ssize_t) count,(ssize_t) (q-p));
247
13.4k
        byte=ReadBlobByte(image);
248
13.4k
        if (byte == EOF)
249
41
          break;
250
13.4k
        if (compression == BI_RLE8)
251
4.81k
          {
252
545k
            for (i=0; i < (ssize_t) count; i++)
253
540k
              *p++=(unsigned char) byte;
254
4.81k
          }
255
8.60k
        else
256
8.60k
          {
257
933k
            for (i=0; i < (ssize_t) count; i++)
258
924k
              *p++=(unsigned char)
259
924k
                ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
260
8.60k
          }
261
13.4k
        x+=count;
262
13.4k
      }
263
11.2k
    else
264
11.2k
      {
265
        /*
266
          Escape mode.
267
        */
268
11.2k
        count=ReadBlobByte(image);
269
11.2k
        if (count == EOF)
270
10
          break;
271
11.2k
        if (count == 0x01)
272
16
          break;
273
11.2k
        switch (count)
274
11.2k
        {
275
5.46k
          case 0x00:
276
5.46k
          {
277
            /*
278
              End of line.
279
            */
280
5.46k
            x=0;
281
5.46k
            y++;
282
5.46k
            p=pixels+y*(ssize_t) image->columns;
283
5.46k
            break;
284
0
          }
285
1.09k
          case 0x02:
286
1.09k
          {
287
            /*
288
              Delta mode.
289
            */
290
1.09k
            byte=ReadBlobByte(image);
291
1.09k
            if (byte == EOF)
292
5
              return(MagickFalse);
293
1.09k
            x+=byte;
294
1.09k
            byte=ReadBlobByte(image);
295
1.09k
            if (byte == EOF)
296
4
              return(MagickFalse);
297
1.08k
            y+=byte;
298
1.08k
            p=pixels+y*(ssize_t) image->columns+x;
299
1.08k
            break;
300
1.09k
          }
301
4.66k
          default:
302
4.66k
          {
303
            /*
304
              Absolute mode.
305
            */
306
4.66k
            count=(int) MagickMin((ssize_t) count,(ssize_t) (q-p));
307
4.66k
            if (count < 0)
308
0
              break;
309
4.66k
            if (compression == BI_RLE8)
310
33.8k
              for (i=0; i < (ssize_t) count; i++)
311
32.2k
              {
312
32.2k
                byte=ReadBlobByte(image);
313
32.2k
                if (byte == EOF)
314
95
                  break;
315
32.1k
                *p++=(unsigned char) byte;
316
32.1k
              }
317
3.01k
            else
318
57.8k
              for (i=0; i < (ssize_t) count; i++)
319
55.0k
              {
320
55.0k
                if ((i & 0x01) == 0)
321
28.2k
                  {
322
28.2k
                    byte=ReadBlobByte(image);
323
28.2k
                    if (byte == EOF)
324
165
                      break;
325
28.2k
                  }
326
54.8k
                *p++=(unsigned char)
327
54.8k
                  ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
328
54.8k
              }
329
4.66k
            x+=count;
330
            /*
331
              Read pad byte.
332
            */
333
4.66k
            if (compression == BI_RLE8)
334
1.65k
              {
335
1.65k
                if ((count & 0x01) != 0)
336
870
                  if (ReadBlobByte(image) == EOF)
337
73
                    break;
338
1.65k
              }
339
3.01k
            else
340
3.01k
              if (((count & 0x03) == 1) || ((count & 0x03) == 2))
341
1.51k
                if (ReadBlobByte(image) == EOF)
342
107
                  break;
343
4.48k
            break;
344
4.66k
          }
345
11.2k
        }
346
11.2k
      }
347
24.6k
    status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
348
24.6k
      image->rows);
349
24.6k
    if (status == MagickFalse)
350
0
      break;
351
24.6k
  }
352
1.85k
  (void) ReadBlobByte(image);  /* end of line */
353
1.85k
  (void) ReadBlobByte(image);
354
1.85k
  return((p-pixels) < (ssize_t) number_pixels ? MagickFalse : MagickTrue);
355
1.86k
}
356

357
/*
358
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
359
%                                                                             %
360
%                                                                             %
361
%                                                                             %
362
%   E n c o d e I m a g e                                                     %
363
%                                                                             %
364
%                                                                             %
365
%                                                                             %
366
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367
%
368
%  EncodeImage compresses pixels using a runlength encoded format.
369
%
370
%  The format of the EncodeImage method is:
371
%
372
%    static MagickBooleanType EncodeImage(Image *image,
373
%      const size_t bytes_per_line,const unsigned char *pixels,
374
%      unsigned char *compressed_pixels)
375
%
376
%  A description of each parameter follows:
377
%
378
%    o image:  The image.
379
%
380
%    o bytes_per_line: the number of bytes in a scanline of compressed pixels
381
%
382
%    o pixels:  The address of a byte (8 bits) array of pixel data created by
383
%      the compression process.
384
%
385
%    o compressed_pixels:  The address of a byte (8 bits) array of compressed
386
%      pixel data.
387
%
388
*/
389
static size_t EncodeImage(Image *image,const size_t bytes_per_line,
390
  const unsigned char *pixels,unsigned char *compressed_pixels)
391
111
{
392
111
  MagickBooleanType
393
111
    status;
394
395
111
  const unsigned char
396
111
    *p;
397
398
111
  ssize_t
399
111
    i,
400
111
    x;
401
402
111
  unsigned char
403
111
    *q;
404
405
111
  ssize_t
406
111
    y;
407
408
  /*
409
    Runlength encode pixels.
410
  */
411
111
  assert(image != (Image *) NULL);
412
111
  assert(image->signature == MagickCoreSignature);
413
111
  assert(pixels != (const unsigned char *) NULL);
414
111
  assert(compressed_pixels != (unsigned char *) NULL);
415
111
  if (IsEventLogging() != MagickFalse)
416
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
417
111
  p=pixels;
418
111
  q=compressed_pixels;
419
111
  i=0;
420
56.9k
  for (y=0; y < (ssize_t) image->rows; y++)
421
56.8k
  {
422
30.7M
    for (x=0; x < (ssize_t) bytes_per_line; x+=i)
423
30.6M
    {
424
      /*
425
        Determine runlength.
426
      */
427
101M
      for (i=1; ((x+i) < (ssize_t) bytes_per_line); i++)
428
101M
        if ((i == 255) || (*(p+i) != *p))
429
30.5M
          break;
430
30.6M
      *q++=(unsigned char) i;
431
30.6M
      *q++=(*p);
432
30.6M
      p+=(ptrdiff_t) i;
433
30.6M
    }
434
    /*
435
      End of line.
436
    */
437
56.8k
    *q++=(unsigned char) 0x00;
438
56.8k
    *q++=(unsigned char) 0x00;
439
56.8k
    status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
440
56.8k
      image->rows);
441
56.8k
    if (status == MagickFalse)
442
0
      break;
443
56.8k
  }
444
  /*
445
    End of bitmap.
446
  */
447
111
  *q++=(unsigned char) 0x00;
448
111
  *q++=(unsigned char) 0x01;
449
111
  return((size_t) (q-compressed_pixels));
450
111
}
451

452
/*
453
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
454
%                                                                             %
455
%                                                                             %
456
%                                                                             %
457
%   I s B M P                                                                 %
458
%                                                                             %
459
%                                                                             %
460
%                                                                             %
461
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
462
%
463
%  IsBMP() returns MagickTrue if the image format type, identified by the
464
%  magick string, is BMP.
465
%
466
%  The format of the IsBMP method is:
467
%
468
%      MagickBooleanType IsBMP(const unsigned char *magick,const size_t length)
469
%
470
%  A description of each parameter follows:
471
%
472
%    o magick: compare image format pattern against these bytes.
473
%
474
%    o length: Specifies the length of the magick string.
475
%
476
*/
477
static MagickBooleanType IsBMP(const unsigned char *magick,const size_t length)
478
19.9k
{
479
19.9k
  if (length < 2)
480
0
    return(MagickFalse);
481
19.9k
  if ((LocaleNCompare((char *) magick,"BA",2) == 0) ||
482
19.9k
      (LocaleNCompare((char *) magick,"BM",2) == 0) ||
483
19.9k
      (LocaleNCompare((char *) magick,"IC",2) == 0) ||
484
19.9k
      (LocaleNCompare((char *) magick,"PI",2) == 0) ||
485
19.9k
      (LocaleNCompare((char *) magick,"CI",2) == 0) ||
486
19.9k
      (LocaleNCompare((char *) magick,"CP",2) == 0))
487
14.2k
    return(MagickTrue);
488
5.78k
  return(MagickFalse);
489
19.9k
}
490

491
/*
492
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
493
%                                                                             %
494
%                                                                             %
495
%                                                                             %
496
%   R e a d B M P I m a g e                                                   %
497
%                                                                             %
498
%                                                                             %
499
%                                                                             %
500
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
501
%
502
%  ReadBMPImage() reads a Microsoft Windows bitmap image file, Version
503
%  2, 3 (for Windows or NT), or 4, and  returns it.  It allocates the memory
504
%  necessary for the new Image structure and returns a pointer to the new
505
%  image.
506
%
507
%  The format of the ReadBMPImage method is:
508
%
509
%      image=ReadBMPImage(image_info)
510
%
511
%  A description of each parameter follows:
512
%
513
%    o image_info: the image info.
514
%
515
%    o exception: return any errors or warnings in this structure.
516
%
517
*/
518
519
static Image *ReadEmbedImage(const ImageInfo *image_info,Image *image,
520
  const char *magick,ExceptionInfo *exception)
521
21.9k
{
522
21.9k
  const void
523
21.9k
    *stream;
524
525
21.9k
  Image
526
21.9k
    *embed_image;
527
528
21.9k
  ImageInfo
529
21.9k
    *embed_info;
530
531
21.9k
  MemoryInfo
532
21.9k
    *pixel_info;
533
534
21.9k
  size_t
535
21.9k
    length;
536
537
21.9k
  ssize_t
538
21.9k
    count;
539
540
21.9k
  unsigned char
541
21.9k
    *pixels;
542
543
  /*
544
    Read embedded image.
545
  */
546
21.9k
  length=(size_t) ((MagickOffsetType) GetBlobSize(image)-TellBlob(image));
547
21.9k
  pixel_info=AcquireVirtualMemory(length,sizeof(*pixels));
548
21.9k
  if (pixel_info == (MemoryInfo *) NULL)
549
16
    {
550
16
      (void) ThrowMagickException(exception,GetMagickModule(),
551
16
        ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
552
16
      return((Image *) NULL);
553
16
    }
554
21.9k
  pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
555
21.9k
  stream=ReadBlobStream(image,length,pixels,&count);
556
21.9k
  if (count != (ssize_t) length)
557
0
    {
558
0
      pixel_info=RelinquishVirtualMemory(pixel_info);
559
0
      (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
560
0
        "ImproperImageHeader","`%s'",image->filename);
561
0
      return((Image *) NULL);
562
0
    }
563
21.9k
  embed_info=AcquireImageInfo();
564
21.9k
  (void) FormatLocaleString(embed_info->filename,MagickPathExtent,
565
21.9k
    "%s:%s",magick,image_info->filename);
566
21.9k
  embed_image=BlobToImage(embed_info,stream,(size_t) count,exception);
567
21.9k
  embed_info=DestroyImageInfo(embed_info);
568
21.9k
  pixel_info=RelinquishVirtualMemory(pixel_info);
569
21.9k
  if (embed_image != (Image *) NULL)
570
10.4k
    {
571
10.4k
      (void) CopyMagickString(embed_image->filename,image->filename,
572
10.4k
        MagickPathExtent);
573
10.4k
      (void) CopyMagickString(embed_image->magick_filename,
574
10.4k
        image->magick_filename,MagickPathExtent);
575
10.4k
      (void) CopyMagickString(embed_image->magick,image->magick,
576
10.4k
        MagickPathExtent);
577
10.4k
    }
578
21.9k
  return(embed_image);
579
21.9k
}
580
581
static Image *ReadBMPImage(const ImageInfo *image_info,ExceptionInfo *exception)
582
31.6k
{
583
31.6k
  BMPInfo
584
31.6k
    bmp_info;
585
586
31.6k
  Image
587
31.6k
    *image;
588
589
31.6k
  MagickBooleanType
590
31.6k
    ignore_filesize,
591
31.6k
    status;
592
593
31.6k
  MagickOffsetType
594
31.6k
    offset,
595
31.6k
    profile_data,
596
31.6k
    profile_size,
597
31.6k
    start_position;
598
599
31.6k
  MagickSizeType
600
31.6k
    blob_size;
601
602
31.6k
  MemoryInfo
603
31.6k
    *pixel_info;
604
605
31.6k
  Quantum
606
31.6k
    index,
607
31.6k
    *q;
608
609
31.6k
  size_t
610
31.6k
    bit,
611
31.6k
    bytes_per_line,
612
31.6k
    length;
613
614
31.6k
  ssize_t
615
31.6k
    count,
616
31.6k
    i,
617
31.6k
    x,
618
31.6k
    y;
619
620
31.6k
  unsigned char
621
31.6k
    magick[12],
622
31.6k
    *p,
623
31.6k
    *pixels;
624
625
31.6k
  unsigned int
626
31.6k
    blue,
627
31.6k
    green,
628
31.6k
    offset_bits,
629
31.6k
    red;
630
631
  /*
632
    Open image file.
633
  */
634
31.6k
  assert(image_info != (const ImageInfo *) NULL);
635
31.6k
  assert(image_info->signature == MagickCoreSignature);
636
31.6k
  if (IsEventLogging() != MagickFalse)
637
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
638
0
      image_info->filename);
639
31.6k
  assert(exception != (ExceptionInfo *) NULL);
640
31.6k
  assert(exception->signature == MagickCoreSignature);
641
31.6k
  image=AcquireImage(image_info,exception);
642
31.6k
  image->columns=0;
643
31.6k
  image->rows=0;
644
31.6k
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
645
31.6k
  if (status == MagickFalse)
646
0
    {
647
0
      image=DestroyImageList(image);
648
0
      return((Image *) NULL);
649
0
    }
650
  /*
651
    Determine if this a BMP file.
652
  */
653
31.6k
  (void) memset(&bmp_info,0,sizeof(bmp_info));
654
31.6k
  bmp_info.ba_offset=0;
655
31.6k
  start_position=0;
656
31.6k
  offset_bits=0;
657
31.6k
  count=ReadBlob(image,2,magick);
658
31.6k
  if (count != 2)
659
31.3k
    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
660
31.3k
  blob_size=GetBlobSize(image);
661
31.3k
  do
662
38.4k
  {
663
38.4k
    PixelInfo
664
38.4k
      quantum_bits;
665
666
38.4k
    PixelPacket
667
38.4k
      shift;
668
669
    /*
670
      Verify BMP identifier.
671
    */
672
38.4k
    start_position=TellBlob(image)-2;
673
38.4k
    bmp_info.ba_offset=0;
674
39.7k
    while (LocaleNCompare((char *) magick,"BA",2) == 0)
675
1.38k
    {
676
1.38k
      bmp_info.file_size=ReadBlobLSBLong(image);
677
1.38k
      bmp_info.ba_offset=ReadBlobLSBLong(image);
678
1.38k
      bmp_info.offset_bits=ReadBlobLSBLong(image);
679
1.38k
      count=ReadBlob(image,2,magick);
680
1.38k
      if (count != 2)
681
73
        break;
682
1.38k
    }
683
38.4k
    if (image->debug != MagickFalse)
684
0
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  Magick: %c%c",
685
0
        magick[0],magick[1]);
686
38.4k
    if ((count != 2) || ((LocaleNCompare((char *) magick,"BM",2) != 0) &&
687
38.3k
        (LocaleNCompare((char *) magick,"CI",2) != 0)))
688
38.2k
      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
689
38.2k
    bmp_info.file_size=ReadBlobLSBLong(image);
690
38.2k
    (void) ReadBlobLSBLong(image);
691
38.2k
    bmp_info.offset_bits=ReadBlobLSBLong(image);
692
38.2k
    bmp_info.size=ReadBlobLSBLong(image);
693
38.2k
    if (image->debug != MagickFalse)
694
0
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
695
0
        "  BMP header size: %u",bmp_info.size);
696
38.2k
    if (LocaleNCompare((char *) magick,"CI",2) == 0)
697
7.85k
      {
698
7.85k
        if ((bmp_info.size != 12) && (bmp_info.size != 40) &&
699
7.85k
            (bmp_info.size != 64))
700
7.59k
          ThrowReaderException(CorruptImageError,"ImproperImageHeader");
701
7.59k
      }
702
37.9k
    if (bmp_info.size > 124)
703
37.8k
      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
704
    /*
705
      Get option to bypass file size check
706
    */
707
37.8k
    ignore_filesize=IsStringTrue(GetImageOption(image_info,
708
37.8k
      "bmp:ignore-filesize"));
709
37.8k
    if ((ignore_filesize == MagickFalse) && (bmp_info.file_size != 0) &&
710
37.8k
        ((MagickSizeType) bmp_info.file_size > GetBlobSize(image)))
711
37.6k
      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
712
37.6k
    if (bmp_info.offset_bits < bmp_info.size)
713
37.6k
      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
714
37.6k
    bmp_info.offset_bits=MagickMax(14+bmp_info.size,bmp_info.offset_bits);
715
37.6k
    profile_data=0;
716
37.6k
    profile_size=0;
717
37.6k
    if (bmp_info.size == 12)
718
5.30k
      {
719
        /*
720
          OS/2 BMP image file.
721
        */
722
5.30k
        (void) CopyMagickString(image->magick,"BMP2",MagickPathExtent);
723
5.30k
        bmp_info.width=(ssize_t) ((short) ReadBlobLSBShort(image));
724
5.30k
        bmp_info.height=(ssize_t) ((short) ReadBlobLSBShort(image));
725
5.30k
        bmp_info.planes=ReadBlobLSBShort(image);
726
5.30k
        bmp_info.bits_per_pixel=ReadBlobLSBShort(image);
727
5.30k
        bmp_info.x_pixels=0;
728
5.30k
        bmp_info.y_pixels=0;
729
5.30k
        bmp_info.number_colors=0;
730
5.30k
        bmp_info.compression=BI_RGB;
731
5.30k
        bmp_info.image_size=0;
732
5.30k
        bmp_info.alpha_mask=0;
733
5.30k
        if (image->debug != MagickFalse)
734
0
          {
735
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
736
0
              "  Format: OS/2 Bitmap");
737
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
738
0
              "  Geometry: %.20gx%.20g",(double) bmp_info.width,(double)
739
0
              bmp_info.height);
740
0
          }
741
5.30k
      }
742
32.3k
    else
743
32.3k
      {
744
        /*
745
          Microsoft Windows BMP image file.
746
        */
747
32.3k
        switch (bmp_info.size)
748
32.3k
        {
749
29.2k
          case 40: case 52: case 56: case 64: case 78: case 108: case 124:
750
29.2k
          {
751
29.2k
            break;
752
27.8k
          }
753
3.10k
          default:
754
3.10k
          {
755
3.10k
            if (bmp_info.size < 64)
756
2.79k
              ThrowReaderException(CorruptImageError,"ImproperImageHeader");
757
2.79k
            break;
758
3.10k
          }
759
32.3k
        }
760
32.0k
        bmp_info.width=(ssize_t) ReadBlobLSBSignedLong(image);
761
32.0k
        bmp_info.height=(ssize_t) ReadBlobLSBSignedLong(image);
762
32.0k
        bmp_info.planes=ReadBlobLSBShort(image);
763
32.0k
        bmp_info.bits_per_pixel=ReadBlobLSBShort(image);
764
32.0k
        bmp_info.compression=ReadBlobLSBLong(image);
765
32.0k
        if (bmp_info.size > 16)
766
32.0k
          {
767
32.0k
            bmp_info.image_size=ReadBlobLSBLong(image);
768
32.0k
            bmp_info.x_pixels=ReadBlobLSBLong(image);
769
32.0k
            bmp_info.y_pixels=ReadBlobLSBLong(image);
770
32.0k
            bmp_info.number_colors=ReadBlobLSBLong(image);
771
32.0k
            bmp_info.colors_important=ReadBlobLSBLong(image);
772
32.0k
          }
773
32.0k
        if (image->debug != MagickFalse)
774
0
          {
775
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
776
0
              "  Format: MS Windows bitmap");
777
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
778
0
              "  Geometry: %.20gx%.20g",(double) bmp_info.width,(double)
779
0
              bmp_info.height);
780
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
781
0
              "  Bits per pixel: %.20g",(double) bmp_info.bits_per_pixel);
782
0
            switch (bmp_info.compression)
783
0
            {
784
0
              case BI_RGB:
785
0
              {
786
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
787
0
                  "  Compression: BI_RGB");
788
0
                break;
789
0
              }
790
0
              case BI_RLE4:
791
0
              {
792
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
793
0
                  "  Compression: BI_RLE4");
794
0
                break;
795
0
              }
796
0
              case BI_RLE8:
797
0
              {
798
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
799
0
                  "  Compression: BI_RLE8");
800
0
                break;
801
0
              }
802
0
              case BI_BITFIELDS:
803
0
              {
804
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
805
0
                  "  Compression: BI_BITFIELDS");
806
0
                break;
807
0
              }
808
0
              case BI_ALPHABITFIELDS:
809
0
              {
810
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
811
0
                  "  Compression: BI_ALPHABITFIELDS");
812
0
                break;
813
0
              }
814
0
              case BI_PNG:
815
0
              {
816
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
817
0
                  "  Compression: BI_PNG");
818
0
                break;
819
0
              }
820
0
              case BI_JPEG:
821
0
              {
822
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
823
0
                  "  Compression: BI_JPEG");
824
0
                break;
825
0
              }
826
0
              default:
827
0
              {
828
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
829
0
                  "  Compression: UNKNOWN (%u)",bmp_info.compression);
830
0
              }
831
0
            }
832
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
833
0
              "  Number of colors: %u",bmp_info.number_colors);
834
0
          }
835
32.0k
        if ((bmp_info.height < 0) &&
836
32.0k
          (bmp_info.compression != BI_RGB) && (bmp_info.compression != BI_BITFIELDS))
837
31.8k
          ThrowReaderException(CoderError,"CompressNotSupported");
838
31.8k
        if ((bmp_info.size > 40) || (bmp_info.compression == BI_BITFIELDS) ||
839
31.8k
            (bmp_info.compression == BI_ALPHABITFIELDS))
840
841
7.26k
          {
842
7.26k
            bmp_info.red_mask=ReadBlobLSBLong(image);
843
7.26k
            bmp_info.green_mask=ReadBlobLSBLong(image);
844
7.26k
            bmp_info.blue_mask=ReadBlobLSBLong(image);
845
7.26k
            if (bmp_info.compression == BI_ALPHABITFIELDS)
846
265
              bmp_info.alpha_mask=ReadBlobLSBLong(image);
847
7.26k
            if (((bmp_info.size == 40) ||
848
7.26k
                 (bmp_info.compression == BI_ALPHABITFIELDS)) &&
849
7.26k
                 (bmp_info.bits_per_pixel != 16) &&
850
7.26k
                 (bmp_info.bits_per_pixel != 32))
851
7.22k
              ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel");
852
7.22k
          }
853
31.8k
        if (bmp_info.size > 40)
854
6.16k
          {
855
6.16k
            double
856
6.16k
              gamma;
857
858
            /*
859
              Read color management information.
860
            */
861
6.16k
            bmp_info.alpha_mask=ReadBlobLSBLong(image);
862
6.16k
            bmp_info.colorspace=ReadBlobLSBSignedLong(image);
863
            /*
864
              Decode 2^30 fixed point formatted CIE primaries.
865
            */
866
55.5k
#           define BMP_DENOM ((double) 0x40000000)
867
6.16k
            bmp_info.red_primary.x=(double) ReadBlobLSBLong(image)/BMP_DENOM;
868
6.16k
            bmp_info.red_primary.y=(double) ReadBlobLSBLong(image)/BMP_DENOM;
869
6.16k
            bmp_info.red_primary.z=(double) ReadBlobLSBLong(image)/BMP_DENOM;
870
6.16k
            bmp_info.green_primary.x=(double) ReadBlobLSBLong(image)/BMP_DENOM;
871
6.16k
            bmp_info.green_primary.y=(double) ReadBlobLSBLong(image)/BMP_DENOM;
872
6.16k
            bmp_info.green_primary.z=(double) ReadBlobLSBLong(image)/BMP_DENOM;
873
6.16k
            bmp_info.blue_primary.x=(double) ReadBlobLSBLong(image)/BMP_DENOM;
874
6.16k
            bmp_info.blue_primary.y=(double) ReadBlobLSBLong(image)/BMP_DENOM;
875
6.16k
            bmp_info.blue_primary.z=(double) ReadBlobLSBLong(image)/BMP_DENOM;
876
877
6.16k
            gamma=bmp_info.red_primary.x+bmp_info.red_primary.y+
878
6.16k
              bmp_info.red_primary.z;
879
6.16k
            gamma=MagickSafeReciprocal(gamma);
880
6.16k
            bmp_info.red_primary.x*=gamma;
881
6.16k
            bmp_info.red_primary.y*=gamma;
882
883
6.16k
            gamma=bmp_info.green_primary.x+bmp_info.green_primary.y+
884
6.16k
              bmp_info.green_primary.z;
885
6.16k
            gamma=MagickSafeReciprocal(gamma);
886
6.16k
            bmp_info.green_primary.x*=gamma;
887
6.16k
            bmp_info.green_primary.y*=gamma;
888
889
6.16k
            gamma=bmp_info.blue_primary.x+bmp_info.blue_primary.y+
890
6.16k
              bmp_info.blue_primary.z;
891
6.16k
            gamma=MagickSafeReciprocal(gamma);
892
6.16k
            bmp_info.blue_primary.x*=gamma;
893
6.16k
            bmp_info.blue_primary.y*=gamma;
894
895
            /*
896
              Decode 16^16 fixed point formatted gamma_scales.
897
            */
898
6.16k
            bmp_info.gamma_scale.x=(double) ReadBlobLSBLong(image)/0x10000;
899
6.16k
            bmp_info.gamma_scale.y=(double) ReadBlobLSBLong(image)/0x10000;
900
6.16k
            bmp_info.gamma_scale.z=(double) ReadBlobLSBLong(image)/0x10000;
901
902
6.16k
            if (bmp_info.colorspace == 0)
903
1.26k
              {
904
1.26k
                image->chromaticity.red_primary.x=bmp_info.red_primary.x;
905
1.26k
                image->chromaticity.red_primary.y=bmp_info.red_primary.y;
906
1.26k
                image->chromaticity.green_primary.x=bmp_info.green_primary.x;
907
1.26k
                image->chromaticity.green_primary.y=bmp_info.green_primary.y;
908
1.26k
                image->chromaticity.blue_primary.x=bmp_info.blue_primary.x;
909
1.26k
                image->chromaticity.blue_primary.y=bmp_info.blue_primary.y;
910
                /*
911
                  Compute a single gamma from the BMP 3-channel gamma.
912
                */
913
1.26k
                image->gamma=(bmp_info.gamma_scale.x+bmp_info.gamma_scale.y+
914
1.26k
                  bmp_info.gamma_scale.z)/3.0;
915
1.26k
              }
916
6.16k
          }
917
25.6k
        else
918
25.6k
          (void) CopyMagickString(image->magick,"BMP3",MagickPathExtent);
919
31.8k
        if (bmp_info.size > 108)
920
3.51k
          {
921
3.51k
            size_t
922
3.51k
              intent;
923
924
            /*
925
              Read BMP Version 5 color management information.
926
            */
927
3.51k
            intent=ReadBlobLSBLong(image);
928
3.51k
            switch ((int) intent)
929
3.51k
            {
930
33
              case LCS_GM_BUSINESS:
931
33
              {
932
33
                image->rendering_intent=SaturationIntent;
933
33
                break;
934
0
              }
935
11
              case LCS_GM_GRAPHICS:
936
11
              {
937
11
                image->rendering_intent=RelativeIntent;
938
11
                break;
939
0
              }
940
54
              case LCS_GM_IMAGES:
941
54
              {
942
54
                image->rendering_intent=PerceptualIntent;
943
54
                break;
944
0
              }
945
21
              case LCS_GM_ABS_COLORIMETRIC:
946
21
              {
947
21
                image->rendering_intent=AbsoluteIntent;
948
21
                break;
949
0
              }
950
3.51k
            }
951
3.51k
            profile_data=(MagickOffsetType) ReadBlobLSBLong(image);
952
3.51k
            profile_size=(MagickOffsetType) ReadBlobLSBLong(image);
953
3.51k
            (void) ReadBlobLSBLong(image);  /* Reserved byte */
954
3.51k
          }
955
31.8k
      }
956
37.1k
    if ((ignore_filesize == MagickFalse) &&
957
37.1k
        (MagickSizeType) bmp_info.file_size != blob_size)
958
34.9k
      (void) ThrowMagickException(exception,GetMagickModule(),
959
34.9k
        CorruptImageError,"LengthAndFilesizeDoNotMatch","`%s'",
960
34.9k
        image->filename);
961
37.1k
    if (bmp_info.width <= 0)
962
36.7k
      ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
963
36.7k
    if (bmp_info.height == 0)
964
36.6k
      ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
965
36.6k
    if (bmp_info.compression == BI_JPEG)
966
17.8k
      {
967
        /*
968
          Read embedded JPEG image.
969
        */
970
17.8k
        Image *embed_image = ReadEmbedImage(image_info,image,"jpeg",exception);
971
17.8k
        (void) CloseBlob(image);
972
17.8k
        image=DestroyImageList(image);
973
17.8k
        return(embed_image);
974
17.8k
      }
975
18.7k
    if (bmp_info.compression == BI_PNG)
976
4.07k
      {
977
        /*
978
          Read embedded PNG image.
979
        */
980
4.07k
        Image *embed_image = ReadEmbedImage(image_info,image,"png",exception);
981
4.07k
        (void) CloseBlob(image);
982
4.07k
        image=DestroyImageList(image);
983
4.07k
        return(embed_image);
984
4.07k
      }
985
14.6k
    if (bmp_info.planes != 1)
986
14.2k
      ThrowReaderException(CorruptImageError,"StaticPlanesValueNotEqualToOne");
987
14.2k
    switch (bmp_info.bits_per_pixel)
988
14.2k
    {
989
14.1k
      case 1: case 4: case 8: case 16: case 24: case 32: case 64:
990
14.1k
      {
991
14.1k
        break;
992
13.8k
      }
993
26
      default:
994
26
        ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel");
995
14.2k
    }
996
14.1k
    if ((bmp_info.bits_per_pixel < 16) &&
997
14.1k
        (bmp_info.number_colors > (1U << bmp_info.bits_per_pixel)))
998
14.0k
      ThrowReaderException(CorruptImageError,"UnrecognizedNumberOfColors");
999
14.0k
    if ((MagickSizeType) bmp_info.number_colors > blob_size)
1000
14.0k
      ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
1001
14.0k
    if ((bmp_info.compression == BI_RLE8) && (bmp_info.bits_per_pixel != 8))
1002
14.0k
      ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel");
1003
14.0k
    if ((bmp_info.compression == BI_RLE4) && (bmp_info.bits_per_pixel != 4))
1004
14.0k
      ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel");
1005
14.0k
    if ((bmp_info.compression == BI_BITFIELDS) &&
1006
14.0k
        (bmp_info.bits_per_pixel < 16))
1007
14.0k
      ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel");
1008
14.0k
    switch (bmp_info.compression)
1009
14.0k
    {
1010
7.86k
      case BI_RGB:
1011
7.86k
        image->compression=NoCompression;
1012
7.86k
        break;
1013
815
      case BI_RLE8:
1014
1.99k
      case BI_RLE4:
1015
1.99k
        image->compression=RLECompression;
1016
1.99k
        break;
1017
3.73k
      case BI_BITFIELDS:
1018
3.73k
        break;
1019
243
      case BI_ALPHABITFIELDS:
1020
243
        break;
1021
0
      case BI_JPEG:
1022
0
        ThrowReaderException(CoderError,"JPEGCompressNotSupported");
1023
0
      case BI_PNG:
1024
0
        ThrowReaderException(CoderError,"PNGCompressNotSupported");
1025
181
      default:
1026
181
        ThrowReaderException(CorruptImageError,"UnrecognizedImageCompression");
1027
14.0k
    }
1028
13.8k
    image->columns=(size_t) MagickAbsoluteValue(bmp_info.width);
1029
13.8k
    image->rows=(size_t) MagickAbsoluteValue(bmp_info.height);
1030
13.8k
    image->depth=bmp_info.bits_per_pixel <= 8 ? bmp_info.bits_per_pixel : 8;
1031
13.8k
    image->alpha_trait=((bmp_info.alpha_mask != 0) &&
1032
13.8k
      ((bmp_info.compression == BI_BITFIELDS) || 
1033
5.31k
       (bmp_info.compression == BI_ALPHABITFIELDS))) ? BlendPixelTrait :
1034
13.8k
       UndefinedPixelTrait;
1035
13.8k
    if (bmp_info.bits_per_pixel < 16)
1036
6.51k
      {
1037
6.51k
        size_t
1038
6.51k
          one;
1039
1040
6.51k
        image->storage_class=PseudoClass;
1041
6.51k
        image->colors=bmp_info.number_colors;
1042
6.51k
        one=1;
1043
6.51k
        if (image->colors == 0)
1044
3.62k
          image->colors=one << bmp_info.bits_per_pixel;
1045
6.51k
      }
1046
13.8k
    image->resolution.x=(double) bmp_info.x_pixels/100.0;
1047
13.8k
    image->resolution.y=(double) bmp_info.y_pixels/100.0;
1048
13.8k
    image->units=PixelsPerCentimeterResolution;
1049
13.8k
    if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
1050
0
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1051
0
        break;
1052
13.8k
    status=SetImageExtent(image,image->columns,image->rows,exception);
1053
13.8k
    if (status == MagickFalse)
1054
403
      return(DestroyImageList(image));
1055
13.4k
    if (image->storage_class == PseudoClass)
1056
6.32k
      {
1057
6.32k
        unsigned char
1058
6.32k
          *bmp_colormap;
1059
1060
6.32k
        size_t
1061
6.32k
          packet_size;
1062
1063
        /*
1064
          Read BMP raster colormap.
1065
        */
1066
6.32k
        if (image->debug != MagickFalse)
1067
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1068
0
            "  Reading colormap of %.20g colors",(double) image->colors);
1069
6.32k
        if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
1070
6.32k
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1071
6.32k
        bmp_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
1072
6.32k
          image->colors,4*sizeof(*bmp_colormap));
1073
6.32k
        if (bmp_colormap == (unsigned char *) NULL)
1074
6.32k
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1075
6.32k
        if ((bmp_info.size == 12) || (bmp_info.size == 64))
1076
2.92k
          packet_size=3;
1077
3.40k
        else
1078
3.40k
          packet_size=4;
1079
6.32k
        offset=SeekBlob(image,start_position+14+bmp_info.size,SEEK_SET);
1080
6.32k
        if (offset < 0)
1081
0
          {
1082
0
            bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);
1083
0
            ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1084
0
          }
1085
6.32k
        count=ReadBlob(image,packet_size*image->colors,bmp_colormap);
1086
6.32k
        if (count != (ssize_t) (packet_size*image->colors))
1087
208
          {
1088
208
            bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);
1089
208
            ThrowReaderException(CorruptImageError,
1090
208
              "InsufficientImageDataInFile");
1091
0
          }
1092
6.11k
        p=bmp_colormap;
1093
50.4k
        for (i=0; i < (ssize_t) image->colors; i++)
1094
44.3k
        {
1095
44.3k
          image->colormap[i].blue=(MagickRealType) ScaleCharToQuantum(*p++);
1096
44.3k
          image->colormap[i].green=(MagickRealType) ScaleCharToQuantum(*p++);
1097
44.3k
          image->colormap[i].red=(MagickRealType) ScaleCharToQuantum(*p++);
1098
44.3k
          if (packet_size == 4)
1099
16.5k
            p++;
1100
44.3k
        }
1101
6.11k
        bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);
1102
6.11k
      }
1103
    /*
1104
      Read image data.
1105
    */
1106
13.2k
    if (bmp_info.offset_bits == offset_bits)
1107
13.1k
      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1108
13.1k
    offset_bits=bmp_info.offset_bits;
1109
13.1k
    offset=SeekBlob(image,start_position+bmp_info.offset_bits,SEEK_SET);
1110
13.1k
    if (offset < 0)
1111
13.1k
      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1112
13.1k
    if (bmp_info.compression == BI_RLE4)
1113
1.13k
      bmp_info.bits_per_pixel<<=1;
1114
13.1k
    bytes_per_line=4*((image->columns*bmp_info.bits_per_pixel+31)/32);
1115
13.1k
    length=(size_t) bytes_per_line*image->rows;
1116
13.1k
    if ((MagickSizeType) (length/256) > blob_size)
1117
13.0k
      ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
1118
13.0k
    pixel_info=AcquireVirtualMemory(image->rows,
1119
13.0k
      MagickMax(bytes_per_line,image->columns+1UL)*sizeof(*pixels));
1120
13.0k
    if (pixel_info == (MemoryInfo *) NULL)
1121
13.0k
      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1122
13.0k
    pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
1123
13.0k
    if ((bmp_info.compression == BI_RGB) ||
1124
13.0k
        (bmp_info.compression == BI_BITFIELDS) ||
1125
13.0k
        (bmp_info.compression == BI_ALPHABITFIELDS))
1126
11.2k
      {
1127
11.2k
        if (image->debug != MagickFalse)
1128
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1129
0
            "  Reading pixels (%.20g bytes)",(double) length);
1130
11.2k
        count=ReadBlob(image,length,pixels);
1131
11.2k
        if (count != (ssize_t) length)
1132
324
          {
1133
324
            pixel_info=RelinquishVirtualMemory(pixel_info);
1134
324
            ThrowReaderException(CorruptImageError,
1135
324
              "InsufficientImageDataInFile");
1136
0
          }
1137
11.2k
      }
1138
1.86k
    else
1139
1.86k
      {
1140
        /*
1141
          Convert run-length encoded raster pixels.
1142
        */
1143
1.86k
        status=DecodeImage(image,bmp_info.compression,pixels,
1144
1.86k
          image->columns*image->rows);
1145
1.86k
        if (status == MagickFalse)
1146
628
          {
1147
628
            pixel_info=RelinquishVirtualMemory(pixel_info);
1148
628
            ThrowReaderException(CorruptImageError,
1149
628
              "UnableToRunlengthDecodeImage");
1150
0
          }
1151
1.86k
      }
1152
    /*
1153
      Convert BMP raster image to pixel packets.
1154
    */
1155
12.1k
    if (bmp_info.compression == BI_RGB)
1156
7.02k
      {
1157
        /*
1158
          We should ignore the alpha value in BMP3 files but there have been
1159
          reports about 32 bit files with alpha. We do a quick check to see if
1160
          the alpha channel contains a value that is not zero (default value).
1161
          If we find a non zero value we assume the program that wrote the file
1162
          wants to use the alpha channel.
1163
        */
1164
7.02k
        if (((image->alpha_trait & BlendPixelTrait) == 0) &&
1165
7.02k
            (bmp_info.size == 40) && (bmp_info.bits_per_pixel == 32))
1166
406
          {
1167
406
            bytes_per_line=4*(image->columns);
1168
1.65k
            for (y=(ssize_t) image->rows-1; y >= 0; y--)
1169
1.25k
            {
1170
1.25k
              p=pixels+((ssize_t) image->rows-y-1)*(ssize_t) bytes_per_line;
1171
2.78k
              for (x=0; x < (ssize_t) image->columns; x++)
1172
1.90k
              {
1173
1.90k
                if (*(p+3) != 0)
1174
373
                  {
1175
373
                    image->alpha_trait=BlendPixelTrait;
1176
373
                    y=-1;
1177
373
                    break;
1178
373
                  }
1179
1.53k
                p+=(ptrdiff_t) 4;
1180
1.53k
              }
1181
1.25k
            }
1182
406
          }
1183
7.02k
        bmp_info.alpha_mask=image->alpha_trait != UndefinedPixelTrait ?
1184
6.64k
          0xff000000U : 0U;
1185
7.02k
        bmp_info.red_mask=0x00ff0000U;
1186
7.02k
        bmp_info.green_mask=0x0000ff00U;
1187
7.02k
        bmp_info.blue_mask=0x000000ffU;
1188
7.02k
        if (bmp_info.bits_per_pixel == 16)
1189
1.08k
          {
1190
            /*
1191
              RGB555.
1192
            */
1193
1.08k
            bmp_info.red_mask=0x00007c00U;
1194
1.08k
            bmp_info.green_mask=0x000003e0U;
1195
1.08k
            bmp_info.blue_mask=0x0000001fU;
1196
1.08k
          }
1197
7.02k
      }
1198
12.1k
    (void) memset(&shift,0,sizeof(shift));
1199
12.1k
    (void) memset(&quantum_bits,0,sizeof(quantum_bits));
1200
12.1k
    if ((bmp_info.bits_per_pixel == 16) || (bmp_info.bits_per_pixel == 32))
1201
5.73k
      {
1202
5.73k
        unsigned int
1203
5.73k
          sample;
1204
1205
        /*
1206
          Get shift and quantum bits info from bitfield masks.
1207
        */
1208
5.73k
        if (bmp_info.red_mask != 0)
1209
51.1k
          while (((bmp_info.red_mask << shift.red) & 0x80000000UL) == 0)
1210
45.6k
          {
1211
45.6k
            shift.red++;
1212
45.6k
            if (shift.red >= 32U)
1213
0
              break;
1214
45.6k
          }
1215
5.73k
        if (bmp_info.green_mask != 0)
1216
62.2k
          while (((bmp_info.green_mask << shift.green) & 0x80000000UL) == 0)
1217
56.8k
          {
1218
56.8k
            shift.green++;
1219
56.8k
            if (shift.green >= 32U)
1220
0
              break;
1221
56.8k
          }
1222
5.73k
        if (bmp_info.blue_mask != 0)
1223
78.7k
          while (((bmp_info.blue_mask << shift.blue) & 0x80000000UL) == 0)
1224
73.5k
          {
1225
73.5k
            shift.blue++;
1226
73.5k
            if (shift.blue >= 32U)
1227
0
              break;
1228
73.5k
          }
1229
5.73k
        if (bmp_info.alpha_mask != 0)
1230
23.2k
          while (((bmp_info.alpha_mask << shift.alpha) & 0x80000000UL) == 0)
1231
19.8k
          {
1232
19.8k
            shift.alpha++;
1233
19.8k
            if (shift.alpha >= 32U)
1234
0
              break;
1235
19.8k
          }
1236
5.73k
        sample=shift.red;
1237
45.2k
        while (((bmp_info.red_mask << sample) & 0x80000000UL) != 0)
1238
40.0k
        {
1239
40.0k
          sample++;
1240
40.0k
          if (sample >= 32U)
1241
498
            break;
1242
40.0k
        }
1243
5.73k
        quantum_bits.red=(MagickRealType) (sample-shift.red);
1244
5.73k
        sample=shift.green;
1245
33.5k
        while (((bmp_info.green_mask << sample) & 0x80000000UL) != 0)
1246
28.0k
        {
1247
28.0k
          sample++;
1248
28.0k
          if (sample >= 32U)
1249
266
            break;
1250
28.0k
        }
1251
5.73k
        quantum_bits.green=(MagickRealType) (sample-shift.green);
1252
5.73k
        sample=shift.blue;
1253
31.4k
        while (((bmp_info.blue_mask << sample) & 0x80000000UL) != 0)
1254
27.8k
        {
1255
27.8k
          sample++;
1256
27.8k
          if (sample >= 32U)
1257
2.14k
            break;
1258
27.8k
        }
1259
5.73k
        quantum_bits.blue=(MagickRealType) (sample-shift.blue);
1260
5.73k
        sample=shift.alpha;
1261
19.6k
        while (((bmp_info.alpha_mask << sample) & 0x80000000UL) != 0)
1262
14.0k
        {
1263
14.0k
          sample++;
1264
14.0k
          if (sample >= 32U)
1265
184
            break;
1266
14.0k
        }
1267
5.73k
        quantum_bits.alpha=(MagickRealType) (sample-shift.alpha);
1268
5.73k
      }
1269
12.1k
    switch (bmp_info.bits_per_pixel)
1270
12.1k
    {
1271
3.60k
      case 1:
1272
3.60k
      {
1273
        /*
1274
          Convert bitmap scanline.
1275
        */
1276
10.5k
        for (y=(ssize_t) image->rows-1; y >= 0; y--)
1277
6.96k
        {
1278
6.96k
          p=pixels+((ssize_t) image->rows-y-1)*(ssize_t) bytes_per_line;
1279
6.96k
          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1280
6.96k
          if (q == (Quantum *) NULL)
1281
0
            break;
1282
19.6k
          for (x=0; x < ((ssize_t) image->columns-7); x+=8)
1283
12.7k
          {
1284
114k
            for (bit=0; bit < 8; bit++)
1285
101k
            {
1286
101k
              index=(Quantum) (((*p) & (0x80 >> bit)) != 0 ? 0x01 : 0x00);
1287
101k
              SetPixelIndex(image,index,q);
1288
101k
              q+=(ptrdiff_t) GetPixelChannels(image);
1289
101k
            }
1290
12.7k
            p++;
1291
12.7k
          }
1292
6.96k
          if ((image->columns % 8) != 0)
1293
5.96k
            {
1294
27.7k
              for (bit=0; bit < (image->columns % 8); bit++)
1295
21.7k
              {
1296
21.7k
                index=(Quantum) (((*p) & (0x80 >> bit)) != 0 ? 0x01 : 0x00);
1297
21.7k
                SetPixelIndex(image,index,q);
1298
21.7k
                q+=(ptrdiff_t) GetPixelChannels(image);
1299
21.7k
              }
1300
5.96k
              p++;
1301
5.96k
            }
1302
6.96k
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
1303
0
            break;
1304
6.96k
          if (image->previous == (Image *) NULL)
1305
3.77k
            {
1306
3.77k
              status=SetImageProgress(image,LoadImageTag,((MagickOffsetType)
1307
3.77k
                image->rows-y),image->rows);
1308
3.77k
              if (status == MagickFalse)
1309
0
                break;
1310
3.77k
            }
1311
6.96k
        }
1312
3.60k
        (void) SyncImage(image,exception);
1313
3.60k
        break;
1314
0
      }
1315
373
      case 4:
1316
373
      {
1317
        /*
1318
          Convert PseudoColor scanline.
1319
        */
1320
5.60k
        for (y=(ssize_t) image->rows-1; y >= 0; y--)
1321
5.23k
        {
1322
5.23k
          p=pixels+((ssize_t) image->rows-y-1)*(ssize_t) bytes_per_line;
1323
5.23k
          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1324
5.23k
          if (q == (Quantum *) NULL)
1325
0
            break;
1326
10.1k
          for (x=0; x < ((ssize_t) image->columns-1); x+=2)
1327
4.95k
          {
1328
4.95k
            ValidateColormapValue(image,(ssize_t) ((*p >> 4) & 0x0f),&index,
1329
4.95k
              exception);
1330
4.95k
            SetPixelIndex(image,index,q);
1331
4.95k
            q+=(ptrdiff_t) GetPixelChannels(image);
1332
4.95k
            ValidateColormapValue(image,(ssize_t) (*p & 0x0f),&index,exception);
1333
4.95k
            SetPixelIndex(image,index,q);
1334
4.95k
            q+=(ptrdiff_t) GetPixelChannels(image);
1335
4.95k
            p++;
1336
4.95k
          }
1337
5.23k
          if ((image->columns % 2) != 0)
1338
3.78k
            {
1339
3.78k
              ValidateColormapValue(image,(ssize_t) ((*p >> 4) & 0xf),&index,
1340
3.78k
                exception);
1341
3.78k
              SetPixelIndex(image,index,q);
1342
3.78k
              q+=(ptrdiff_t) GetPixelChannels(image);
1343
3.78k
              p++;
1344
3.78k
              x++;
1345
3.78k
            }
1346
5.23k
          if (x < (ssize_t) image->columns)
1347
0
            break;
1348
5.23k
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
1349
0
            break;
1350
5.23k
          if (image->previous == (Image *) NULL)
1351
4.44k
            {
1352
4.44k
              status=SetImageProgress(image,LoadImageTag,((MagickOffsetType)
1353
4.44k
                image->rows-y),image->rows);
1354
4.44k
              if (status == MagickFalse)
1355
0
                break;
1356
4.44k
            }
1357
5.23k
        }
1358
373
        (void) SyncImage(image,exception);
1359
373
        break;
1360
0
      }
1361
1.46k
      case 8:
1362
1.46k
      {
1363
        /*
1364
          Convert PseudoColor scanline.
1365
        */
1366
1.46k
        if ((bmp_info.compression == BI_RLE8) ||
1367
1.46k
            (bmp_info.compression == BI_RLE4))
1368
1.23k
          bytes_per_line=image->columns;
1369
133k
        for (y=(ssize_t) image->rows-1; y >= 0; y--)
1370
131k
        {
1371
131k
          p=pixels+((ssize_t) image->rows-y-1)*(ssize_t) bytes_per_line;
1372
131k
          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1373
131k
          if (q == (Quantum *) NULL)
1374
0
            break;
1375
3.88M
          for (x=(ssize_t) image->columns; x != 0; --x)
1376
3.75M
          {
1377
3.75M
            ValidateColormapValue(image,(ssize_t) *p++,&index,exception);
1378
3.75M
            SetPixelIndex(image,index,q);
1379
3.75M
            q+=(ptrdiff_t) GetPixelChannels(image);
1380
3.75M
          }
1381
131k
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
1382
0
            break;
1383
131k
          offset=((MagickOffsetType) image->rows-y-1);
1384
131k
          if (image->previous == (Image *) NULL)
1385
82.0k
            {
1386
82.0k
              status=SetImageProgress(image,LoadImageTag,((MagickOffsetType)
1387
82.0k
                image->rows-y),image->rows);
1388
82.0k
              if (status == MagickFalse)
1389
0
                break;
1390
82.0k
            }
1391
131k
        }
1392
1.46k
        (void) SyncImage(image,exception);
1393
1.46k
        break;
1394
0
      }
1395
3.91k
      case 16:
1396
3.91k
      {
1397
3.91k
        unsigned int
1398
3.91k
          alpha,
1399
3.91k
          pixel;
1400
1401
        /*
1402
          Convert bitfield encoded 16-bit PseudoColor scanline.
1403
        */
1404
3.91k
        if ((bmp_info.compression != BI_RGB) &&
1405
3.91k
            (bmp_info.compression != BI_BITFIELDS))
1406
27
          {
1407
27
            pixel_info=RelinquishVirtualMemory(pixel_info);
1408
27
            ThrowReaderException(CorruptImageError,
1409
27
              "UnrecognizedImageCompression");
1410
0
          }
1411
3.88k
        bytes_per_line=2*(image->columns+image->columns % 2);
1412
3.88k
        image->storage_class=DirectClass;
1413
13.1k
        for (y=(ssize_t) image->rows-1; y >= 0; y--)
1414
9.26k
        {
1415
9.26k
          p=pixels+((ssize_t) image->rows-y-1)*(ssize_t) bytes_per_line;
1416
9.26k
          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1417
9.26k
          if (q == (Quantum *) NULL)
1418
0
            break;
1419
28.4k
          for (x=0; x < (ssize_t) image->columns; x++)
1420
19.1k
          {
1421
19.1k
            pixel=(unsigned int) (*p++);
1422
19.1k
            pixel|=(unsigned int) (*p++) << 8;
1423
19.1k
            red=((pixel & bmp_info.red_mask) << shift.red) >> 16;
1424
19.1k
            if (quantum_bits.red == 5)
1425
7.28k
              red|=((red & 0xff00) >> 5);
1426
19.1k
            if (quantum_bits.red <= 8)
1427
16.9k
              red|=((red & 0xff00) >> 8);
1428
19.1k
            green=((pixel & bmp_info.green_mask) << shift.green) >> 16;
1429
19.1k
            if (quantum_bits.green == 5)
1430
7.55k
              green|=((green & 0xff00) >> 5);
1431
19.1k
            if (quantum_bits.green == 6)
1432
723
              green|=((green & 0xff00) >> 6);
1433
19.1k
            if (quantum_bits.green <= 8)
1434
17.5k
              green|=((green & 0xff00) >> 8);
1435
19.1k
            blue=((pixel & bmp_info.blue_mask) << shift.blue) >> 16;
1436
19.1k
            if (quantum_bits.blue == 5)
1437
7.23k
              blue|=((blue & 0xff00) >> 5);
1438
19.1k
            if (quantum_bits.blue <= 8)
1439
17.1k
              blue|=((blue & 0xff00) >> 8);
1440
19.1k
            SetPixelRed(image,ScaleShortToQuantum((unsigned short) red),q);
1441
19.1k
            SetPixelGreen(image,ScaleShortToQuantum((unsigned short) green),q);
1442
19.1k
            SetPixelBlue(image,ScaleShortToQuantum((unsigned short) blue),q);
1443
19.1k
            SetPixelAlpha(image,OpaqueAlpha,q);
1444
19.1k
            if (image->alpha_trait != UndefinedPixelTrait)
1445
10.3k
              {
1446
10.3k
                alpha=((pixel & bmp_info.alpha_mask) << shift.alpha) >> 16;
1447
10.3k
                if (quantum_bits.alpha <= 8)
1448
8.85k
                  alpha|=((alpha & 0xff00) >> 8);
1449
10.3k
                SetPixelAlpha(image,ScaleShortToQuantum((unsigned short)
1450
10.3k
                  alpha),q);
1451
10.3k
              }
1452
19.1k
            q+=(ptrdiff_t) GetPixelChannels(image);
1453
19.1k
          }
1454
9.26k
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
1455
0
            break;
1456
9.26k
          offset=((MagickOffsetType) image->rows-y-1);
1457
9.26k
          if (image->previous == (Image *) NULL)
1458
6.22k
            {
1459
6.22k
              status=SetImageProgress(image,LoadImageTag,((MagickOffsetType)
1460
6.22k
                image->rows-y),image->rows);
1461
6.22k
              if (status == MagickFalse)
1462
0
                break;
1463
6.22k
            }
1464
9.26k
        }
1465
3.88k
        break;
1466
3.91k
      }
1467
727
      case 24:
1468
727
      {
1469
        /*
1470
          Convert DirectColor scanline.
1471
        */
1472
727
        bytes_per_line=4*((image->columns*24+31)/32);
1473
3.26k
        for (y=(ssize_t) image->rows-1; y >= 0; y--)
1474
2.53k
        {
1475
2.53k
          p=pixels+((ssize_t) image->rows-y-1)*(ssize_t) bytes_per_line;
1476
2.53k
          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1477
2.53k
          if (q == (Quantum *) NULL)
1478
0
            break;
1479
6.84k
          for (x=0; x < (ssize_t) image->columns; x++)
1480
4.31k
          {
1481
4.31k
            SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
1482
4.31k
            SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
1483
4.31k
            SetPixelRed(image,ScaleCharToQuantum(*p++),q);
1484
4.31k
            SetPixelAlpha(image,OpaqueAlpha,q);
1485
4.31k
            q+=(ptrdiff_t) GetPixelChannels(image);
1486
4.31k
          }
1487
2.53k
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
1488
0
            break;
1489
2.53k
          offset=((MagickOffsetType) image->rows-y-1);
1490
2.53k
          if (image->previous == (Image *) NULL)
1491
1.53k
            {
1492
1.53k
              status=SetImageProgress(image,LoadImageTag,((MagickOffsetType)
1493
1.53k
                image->rows-y),image->rows);
1494
1.53k
              if (status == MagickFalse)
1495
0
                break;
1496
1.53k
            }
1497
2.53k
        }
1498
727
        break;
1499
3.91k
      }
1500
1.82k
      case 32:
1501
1.82k
      {
1502
        /*
1503
          Convert bitfield encoded DirectColor scanline.
1504
        */
1505
1.82k
        if ((bmp_info.compression != BI_RGB) &&
1506
1.82k
            (bmp_info.compression != BI_BITFIELDS))
1507
212
          {
1508
212
            pixel_info=RelinquishVirtualMemory(pixel_info);
1509
212
            ThrowReaderException(CorruptImageError,
1510
212
              "UnrecognizedImageCompression");
1511
0
          }
1512
1.61k
        bytes_per_line=4*(image->columns);
1513
7.71k
        for (y=(ssize_t) image->rows-1; y >= 0; y--)
1514
6.10k
        {
1515
6.10k
          unsigned int
1516
6.10k
            alpha,
1517
6.10k
            pixel;
1518
1519
6.10k
          p=pixels+((ssize_t) image->rows-y-1)*(ssize_t) bytes_per_line;
1520
6.10k
          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1521
6.10k
          if (q == (Quantum *) NULL)
1522
0
            break;
1523
15.0k
          for (x=0; x < (ssize_t) image->columns; x++)
1524
8.96k
          {
1525
8.96k
            pixel=(unsigned int) (*p++);
1526
8.96k
            pixel|=((unsigned int) *p++ << 8);
1527
8.96k
            pixel|=((unsigned int) *p++ << 16);
1528
8.96k
            pixel|=((unsigned int) *p++ << 24);
1529
8.96k
            red=((pixel & bmp_info.red_mask) << shift.red) >> 16;
1530
8.96k
            if (quantum_bits.red == 8)
1531
6.32k
              red|=(red >> 8);
1532
8.96k
            green=((pixel & bmp_info.green_mask) << shift.green) >> 16;
1533
8.96k
            if (quantum_bits.green == 8)
1534
6.38k
              green|=(green >> 8);
1535
8.96k
            blue=((pixel & bmp_info.blue_mask) << shift.blue) >> 16;
1536
8.96k
            if (quantum_bits.blue == 8)
1537
6.38k
              blue|=(blue >> 8);
1538
8.96k
            SetPixelRed(image,ScaleShortToQuantum((unsigned short) red),q);
1539
8.96k
            SetPixelGreen(image,ScaleShortToQuantum((unsigned short) green),q);
1540
8.96k
            SetPixelBlue(image,ScaleShortToQuantum((unsigned short) blue),q);
1541
8.96k
            SetPixelAlpha(image,OpaqueAlpha,q);
1542
8.96k
            if (image->alpha_trait != UndefinedPixelTrait)
1543
4.33k
              {
1544
4.33k
                alpha=((pixel & bmp_info.alpha_mask) << shift.alpha) >> 16;
1545
4.33k
                if (quantum_bits.alpha == 8)
1546
2.69k
                  alpha|=(alpha >> 8);
1547
4.33k
                SetPixelAlpha(image,ScaleShortToQuantum(
1548
4.33k
                  (unsigned short) alpha),q);
1549
4.33k
              }
1550
8.96k
            q+=(ptrdiff_t) GetPixelChannels(image);
1551
8.96k
          }
1552
6.10k
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
1553
0
            break;
1554
6.10k
          offset=((MagickOffsetType) image->rows-y-1);
1555
6.10k
          if (image->previous == (Image *) NULL)
1556
4.02k
            {
1557
4.02k
              status=SetImageProgress(image,LoadImageTag,((MagickOffsetType)
1558
4.02k
                image->rows-y),image->rows);
1559
4.02k
              if (status == MagickFalse)
1560
0
                break;
1561
4.02k
            }
1562
6.10k
        }
1563
1.61k
        break;
1564
1.82k
      }
1565
241
      case 64:
1566
241
      {
1567
        /*
1568
          Convert DirectColor scanline.
1569
        */
1570
241
        bytes_per_line=4*((image->columns*64+31)/32);
1571
1.79k
        for (y=(ssize_t) image->rows-1; y >= 0; y--)
1572
1.55k
        {
1573
1.55k
          unsigned short
1574
1.55k
            *p16;
1575
1576
1.55k
          p16=(unsigned short *) (pixels+((ssize_t) image->rows-y-1)*
1577
1.55k
            (ssize_t) bytes_per_line);
1578
1.55k
          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1579
1.55k
          if (q == (Quantum *) NULL)
1580
0
            break;
1581
4.24k
          for (x=0; x < (ssize_t) image->columns; x++)
1582
2.69k
          {
1583
2.69k
            SetPixelBlue(image,ScaleShortToQuantum(*p16++),q);
1584
2.69k
            SetPixelGreen(image,ScaleShortToQuantum(*p16++),q);
1585
2.69k
            SetPixelRed(image,ScaleShortToQuantum(*p16++),q);
1586
2.69k
            SetPixelAlpha(image,ScaleShortToQuantum(*p16++),q);
1587
2.69k
            q+=(ptrdiff_t) GetPixelChannels(image);
1588
2.69k
          }
1589
1.55k
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
1590
0
            break;
1591
1.55k
          offset=((MagickOffsetType) image->rows-y-1);
1592
1.55k
          if (image->previous == (Image *) NULL)
1593
761
            {
1594
761
              status=SetImageProgress(image,LoadImageTag,((MagickOffsetType)
1595
761
                image->rows-y),image->rows);
1596
761
              if (status == MagickFalse)
1597
0
                break;
1598
761
            }
1599
1.55k
        }
1600
241
        break;
1601
1.82k
      }
1602
0
      default:
1603
0
      {
1604
0
        pixel_info=RelinquishVirtualMemory(pixel_info);
1605
0
        ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1606
0
      }
1607
12.1k
    }
1608
11.9k
    pixel_info=RelinquishVirtualMemory(pixel_info);
1609
11.9k
    if (y > 0)
1610
0
      break;
1611
11.9k
    if (EOFBlob(image) != MagickFalse)
1612
128
      {
1613
128
        ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1614
128
          image->filename);
1615
128
        break;
1616
128
      }
1617
11.7k
    if (bmp_info.height < 0)
1618
4.84k
      {
1619
4.84k
        Image
1620
4.84k
          *flipped_image;
1621
1622
        /*
1623
          Correct image orientation.
1624
        */
1625
4.84k
        flipped_image=FlipImage(image,exception);
1626
4.84k
        if (flipped_image != (Image *) NULL)
1627
4.84k
          {
1628
4.84k
            DuplicateBlob(flipped_image,image);
1629
4.84k
            ReplaceImageInList(&image, flipped_image);
1630
4.84k
            image=flipped_image;
1631
4.84k
          }
1632
4.84k
      }
1633
    /*
1634
      Read embedded ICC profile
1635
    */
1636
11.7k
    if ((bmp_info.colorspace == 0x4D424544L) && (profile_data > 0) &&
1637
11.7k
        (profile_size > 0))
1638
2.86k
      {
1639
2.86k
        StringInfo
1640
2.86k
          *profile;
1641
1642
2.86k
        unsigned char
1643
2.86k
          *datum;
1644
1645
2.86k
        offset=start_position+14+profile_data;
1646
2.86k
        if ((offset < TellBlob(image)) ||
1647
2.86k
            (SeekBlob(image,offset,SEEK_SET) != offset) ||
1648
2.86k
            (blob_size < (MagickSizeType) (offset+profile_size)))
1649
2.67k
          ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1650
2.67k
        profile=AcquireProfileStringInfo("icc",(size_t) profile_size,
1651
2.67k
          exception);
1652
2.67k
        if (profile == (StringInfo *) NULL)
1653
0
          (void) SeekBlob(image,profile_size,SEEK_CUR);
1654
2.67k
        else
1655
2.67k
          {
1656
2.67k
            datum=GetStringInfoDatum(profile);
1657
2.67k
            if (ReadBlob(image,(size_t) profile_size,datum) != (ssize_t) profile_size)
1658
0
              profile=DestroyStringInfo(profile);
1659
2.67k
            else
1660
2.67k
              {
1661
2.67k
                MagickOffsetType
1662
2.67k
                  profile_size_orig;
1663
1664
                /*
1665
                 Trimming padded bytes.
1666
                */
1667
2.67k
                profile_size_orig=(MagickOffsetType) datum[0] << 24;
1668
2.67k
                profile_size_orig|=(MagickOffsetType) datum[1] << 16;
1669
2.67k
                profile_size_orig|=(MagickOffsetType) datum[2] << 8;
1670
2.67k
                profile_size_orig|=(MagickOffsetType) datum[3];
1671
2.67k
                if (profile_size_orig < profile_size)
1672
59
                  SetStringInfoLength(profile,(size_t) profile_size_orig);
1673
2.67k
                if (image->debug != MagickFalse)
1674
0
                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1675
0
                    "Profile: ICC, %u bytes",(unsigned int) profile_size_orig);
1676
2.67k
                (void) SetImageProfilePrivate(image,profile,exception);
1677
2.67k
              }
1678
2.67k
          }
1679
2.67k
      }
1680
    /*
1681
      Proceed to next image.
1682
    */
1683
11.5k
    if (image_info->number_scenes != 0)
1684
0
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1685
0
        break;
1686
11.5k
    offset=(MagickOffsetType) bmp_info.ba_offset;
1687
11.5k
    if (offset != 0)
1688
158
      if ((offset < TellBlob(image)) ||
1689
158
          (SeekBlob(image,offset,SEEK_SET) != offset))
1690
11.5k
        ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1691
11.5k
    *magick='\0';
1692
11.5k
    count=ReadBlob(image,2,magick);
1693
11.5k
    if ((count == 2) && (IsBMP(magick,2) != MagickFalse))
1694
7.08k
      {
1695
        /*
1696
          Acquire next image structure.
1697
        */
1698
7.08k
        AcquireNextImage(image_info,image,exception);
1699
7.08k
        if (GetNextImageInList(image) == (Image *) NULL)
1700
0
          {
1701
0
            status=MagickFalse;
1702
0
            break;
1703
0
          }
1704
7.08k
        image=SyncNextImageInList(image);
1705
7.08k
        status=SetImageProgress(image,LoadImagesTag,TellBlob(image),blob_size);
1706
7.08k
        if (status == MagickFalse)
1707
0
          break;
1708
7.08k
      }
1709
11.5k
  } while (IsBMP(magick,2) != MagickFalse);
1710
4.57k
  if (CloseBlob(image) == MagickFalse)
1711
0
    status=MagickFalse;
1712
4.57k
  if (status == MagickFalse)
1713
0
    return(DestroyImageList(image));
1714
4.57k
  return(GetFirstImageInList(image));
1715
4.57k
}
1716

1717
/*
1718
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1719
%                                                                             %
1720
%                                                                             %
1721
%                                                                             %
1722
%   R e g i s t e r B M P I m a g e                                           %
1723
%                                                                             %
1724
%                                                                             %
1725
%                                                                             %
1726
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1727
%
1728
%  RegisterBMPImage() adds attributes for the BMP image format to
1729
%  the list of supported formats.  The attributes include the image format
1730
%  tag, a method to read and/or write the format, whether the format
1731
%  supports the saving of more than one frame to the same file or blob,
1732
%  whether the format supports native in-memory I/O, and a brief
1733
%  description of the format.
1734
%
1735
%  The format of the RegisterBMPImage method is:
1736
%
1737
%      size_t RegisterBMPImage(void)
1738
%
1739
*/
1740
ModuleExport size_t RegisterBMPImage(void)
1741
11
{
1742
11
  MagickInfo
1743
11
    *entry;
1744
1745
11
  entry=AcquireMagickInfo("BMP","BMP","Microsoft Windows bitmap image");
1746
11
  entry->decoder=(DecodeImageHandler *) ReadBMPImage;
1747
11
  entry->encoder=(EncodeImageHandler *) WriteBMPImage;
1748
11
  entry->magick=(IsImageFormatHandler *) IsBMP;
1749
11
  entry->flags^=CoderAdjoinFlag;
1750
11
  entry->flags|=CoderDecoderSeekableStreamFlag;
1751
11
  entry->mime_type=ConstantString("image/bmp");
1752
11
  (void) RegisterMagickInfo(entry);
1753
11
  entry=AcquireMagickInfo("BMP","BMP2","Microsoft Windows bitmap image (V2)");
1754
11
  entry->decoder=(DecodeImageHandler *) ReadBMPImage;
1755
11
  entry->encoder=(EncodeImageHandler *) WriteBMPImage;
1756
11
  entry->magick=(IsImageFormatHandler *) IsBMP;
1757
11
  entry->flags^=CoderAdjoinFlag;
1758
11
  entry->flags|=CoderDecoderSeekableStreamFlag;
1759
11
  entry->mime_type=ConstantString("image/bmp");
1760
11
  (void) RegisterMagickInfo(entry);
1761
11
  entry=AcquireMagickInfo("BMP","BMP3","Microsoft Windows bitmap image (V3)");
1762
11
  entry->decoder=(DecodeImageHandler *) ReadBMPImage;
1763
11
  entry->encoder=(EncodeImageHandler *) WriteBMPImage;
1764
11
  entry->magick=(IsImageFormatHandler *) IsBMP;
1765
11
  entry->flags^=CoderAdjoinFlag;
1766
11
  entry->flags|=CoderDecoderSeekableStreamFlag;
1767
11
  entry->mime_type=ConstantString("image/bmp");
1768
11
  (void) RegisterMagickInfo(entry);
1769
11
  return(MagickImageCoderSignature);
1770
11
}
1771

1772
/*
1773
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1774
%                                                                             %
1775
%                                                                             %
1776
%                                                                             %
1777
%   U n r e g i s t e r B M P I m a g e                                       %
1778
%                                                                             %
1779
%                                                                             %
1780
%                                                                             %
1781
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1782
%
1783
%  UnregisterBMPImage() removes format registrations made by the
1784
%  BMP module from the list of supported formats.
1785
%
1786
%  The format of the UnregisterBMPImage method is:
1787
%
1788
%      UnregisterBMPImage(void)
1789
%
1790
*/
1791
ModuleExport void UnregisterBMPImage(void)
1792
0
{
1793
0
  (void) UnregisterMagickInfo("BMP");
1794
0
  (void) UnregisterMagickInfo("BMP2");
1795
0
  (void) UnregisterMagickInfo("BMP3");
1796
0
}
1797

1798
/*
1799
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1800
%                                                                             %
1801
%                                                                             %
1802
%                                                                             %
1803
%   W r i t e B M P I m a g e                                                 %
1804
%                                                                             %
1805
%                                                                             %
1806
%                                                                             %
1807
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1808
%
1809
%  WriteBMPImage() writes an image in Microsoft Windows bitmap encoded
1810
%  image format, version 3 for Windows or (if the image has a matte channel)
1811
%  version 4.
1812
%
1813
%  The format of the WriteBMPImage method is:
1814
%
1815
%      MagickBooleanType WriteBMPImage(const ImageInfo *image_info,
1816
%        Image *image,ExceptionInfo *exception)
1817
%
1818
%  A description of each parameter follows.
1819
%
1820
%    o image_info: the image info.
1821
%
1822
%    o image:  The image.
1823
%
1824
%    o exception: return any errors or warnings in this structure.
1825
%
1826
*/
1827
static MagickBooleanType WriteBMPImage(const ImageInfo *image_info,Image *image,
1828
  ExceptionInfo *exception)
1829
1.08k
{
1830
1.08k
  BMPInfo
1831
1.08k
    bmp_info;
1832
1833
1.08k
  BMPSubtype
1834
1.08k
    bmp_subtype;
1835
1836
1.08k
  const char
1837
1.08k
    *option;
1838
1839
1.08k
  const Quantum
1840
1.08k
    *p;
1841
1842
1.08k
  const StringInfo
1843
1.08k
    *profile = (const StringInfo *) NULL;
1844
1845
1.08k
  MagickBooleanType
1846
1.08k
    have_color_info,
1847
1.08k
    status;
1848
1849
1.08k
  MagickOffsetType
1850
1.08k
    profile_data,
1851
1.08k
    profile_size,
1852
1.08k
    profile_size_pad,
1853
1.08k
    scene;
1854
1855
1.08k
  MemoryInfo
1856
1.08k
    *pixel_info;
1857
1858
1.08k
  size_t
1859
1.08k
    bytes_per_line,
1860
1.08k
    number_scenes,
1861
1.08k
    type;
1862
1863
1.08k
  ssize_t
1864
1.08k
    i,
1865
1.08k
    x,
1866
1.08k
    y;
1867
1868
1.08k
  unsigned char
1869
1.08k
    *bmp_data,
1870
1.08k
    *pixels,
1871
1.08k
    *q;
1872
1873
  /*
1874
    Open output image file.
1875
  */
1876
1.08k
  assert(image_info != (const ImageInfo *) NULL);
1877
1.08k
  assert(image_info->signature == MagickCoreSignature);
1878
1.08k
  assert(image != (Image *) NULL);
1879
1.08k
  assert(image->signature == MagickCoreSignature);
1880
1.08k
  assert(exception != (ExceptionInfo *) NULL);
1881
1.08k
  assert(exception->signature == MagickCoreSignature);
1882
1.08k
  if (IsEventLogging() != MagickFalse)
1883
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1884
1.08k
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1885
1.08k
  if (status == MagickFalse)
1886
0
    return(status);
1887
1.08k
  if (((image->columns << 3) != (size_t) ((int) (image->columns << 3))) ||
1888
1.08k
      ((image->rows << 3) != (size_t) ((int) (image->rows << 3))))
1889
1.08k
    ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
1890
1.08k
  type=4;
1891
1.08k
  if (LocaleCompare(image_info->magick,"BMP2") == 0)
1892
294
    type=2;
1893
790
  else
1894
790
    if (LocaleCompare(image_info->magick,"BMP3") == 0)
1895
341
      type=3;
1896
1.08k
  option=GetImageOption(image_info,"bmp:format");
1897
1.08k
  if (option != (char *) NULL)
1898
0
    {
1899
0
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1900
0
          "  Format=%s",option);
1901
0
      if (LocaleCompare(option,"bmp2") == 0)
1902
0
        type=2;
1903
0
      if (LocaleCompare(option,"bmp3") == 0)
1904
0
        type=3;
1905
0
      if (LocaleCompare(option,"bmp4") == 0)
1906
0
        type=4;
1907
0
    }
1908
1.08k
  scene=0;
1909
1.08k
  number_scenes=GetImageListLength(image);
1910
1.08k
  do
1911
1.08k
  {
1912
    /*
1913
      Initialize BMP raster file header.
1914
    */
1915
1.08k
    if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1916
0
      (void) TransformImageColorspace(image,sRGBColorspace,exception);
1917
1.08k
    (void) memset(&bmp_info,0,sizeof(bmp_info));
1918
1.08k
    bmp_info.file_size=14+12;
1919
1.08k
    if (type > 2)
1920
790
      bmp_info.file_size+=28;
1921
1.08k
    bmp_info.offset_bits=bmp_info.file_size;
1922
1.08k
    bmp_info.compression=BI_RGB;
1923
1.08k
    bmp_info.red_mask=0x00ff0000U;
1924
1.08k
    bmp_info.green_mask=0x0000ff00U;
1925
1.08k
    bmp_info.blue_mask=0x000000ffU;
1926
1.08k
    bmp_info.alpha_mask=0xff000000U;
1927
1.08k
    bmp_subtype=UndefinedSubtype;
1928
1.08k
    if ((image->storage_class == PseudoClass) && (image->colors > 256))
1929
31
      (void) SetImageStorageClass(image,DirectClass,exception);
1930
1.08k
    if (image->storage_class != DirectClass)
1931
593
      {
1932
        /*
1933
          Colormapped BMP raster.
1934
        */
1935
593
        bmp_info.bits_per_pixel=8;
1936
593
        if (image->colors <= 2)
1937
275
          bmp_info.bits_per_pixel=1;
1938
318
        else
1939
318
          if (image->colors <= 16)
1940
172
            bmp_info.bits_per_pixel=4;
1941
146
          else
1942
146
            if (image->colors <= 256)
1943
146
              bmp_info.bits_per_pixel=8;
1944
593
        if (image_info->compression == RLECompression)
1945
0
          bmp_info.bits_per_pixel=8;
1946
593
        bmp_info.number_colors=1U << bmp_info.bits_per_pixel;
1947
593
        if (image->alpha_trait != UndefinedPixelTrait)
1948
0
          (void) SetImageStorageClass(image,DirectClass,exception);
1949
593
        else
1950
593
          if ((size_t) bmp_info.number_colors < image->colors)
1951
0
            (void) SetImageStorageClass(image,DirectClass,exception);
1952
593
          else
1953
593
            {
1954
593
              bmp_info.file_size+=3*(1UL << bmp_info.bits_per_pixel);
1955
593
              bmp_info.offset_bits+=3*(1UL << bmp_info.bits_per_pixel);
1956
593
              if (type > 2)
1957
426
                {
1958
426
                  bmp_info.file_size+=(1UL << bmp_info.bits_per_pixel);
1959
426
                  bmp_info.offset_bits+=(1UL << bmp_info.bits_per_pixel);
1960
426
                }
1961
593
            }
1962
593
      }
1963
1.08k
    if (image->storage_class == DirectClass)
1964
491
      {
1965
        /*
1966
          Full color BMP raster.
1967
        */
1968
491
        bmp_info.number_colors=0;
1969
491
        option=GetImageOption(image_info,"bmp:subtype");
1970
491
        if (option != (const char *) NULL)
1971
0
        {
1972
0
          if (image->alpha_trait != UndefinedPixelTrait)
1973
0
            {
1974
0
              if (LocaleNCompare(option,"ARGB4444",8) == 0)
1975
0
                {
1976
0
                  bmp_subtype=ARGB4444;
1977
0
                  bmp_info.red_mask=0x00000f00U;
1978
0
                  bmp_info.green_mask=0x000000f0U;
1979
0
                  bmp_info.blue_mask=0x0000000fU;
1980
0
                  bmp_info.alpha_mask=0x0000f000U;
1981
0
                }
1982
0
              else if (LocaleNCompare(option,"ARGB1555",8) == 0)
1983
0
                {
1984
0
                  bmp_subtype=ARGB1555;
1985
0
                  bmp_info.red_mask=0x00007c00U;
1986
0
                  bmp_info.green_mask=0x000003e0U;
1987
0
                  bmp_info.blue_mask=0x0000001fU;
1988
0
                  bmp_info.alpha_mask=0x00008000U;
1989
0
                }
1990
0
            }
1991
0
          else
1992
0
          {
1993
0
            if (LocaleNCompare(option,"RGB555",6) == 0)
1994
0
              {
1995
0
                bmp_subtype=RGB555;
1996
0
                bmp_info.red_mask=0x00007c00U;
1997
0
                bmp_info.green_mask=0x000003e0U;
1998
0
                bmp_info.blue_mask=0x0000001fU;
1999
0
                bmp_info.alpha_mask=0U;
2000
0
              }
2001
0
            else if (LocaleNCompare(option,"RGB565",6) == 0)
2002
0
              {
2003
0
                bmp_subtype=RGB565;
2004
0
                bmp_info.red_mask=0x0000f800U;
2005
0
                bmp_info.green_mask=0x000007e0U;
2006
0
                bmp_info.blue_mask=0x0000001fU;
2007
0
                bmp_info.alpha_mask=0U;
2008
0
              }
2009
0
          }
2010
0
        }
2011
491
        if (bmp_subtype != UndefinedSubtype)
2012
0
          {
2013
0
            bmp_info.bits_per_pixel=16;
2014
0
            bmp_info.compression=BI_BITFIELDS;
2015
0
          }
2016
491
        else
2017
491
          {
2018
491
            bmp_info.bits_per_pixel=(unsigned short) ((type > 3) &&
2019
491
               (image->alpha_trait != UndefinedPixelTrait) ? 32 : 24);
2020
491
            bmp_info.compression=(unsigned int) ((type > 3) &&
2021
491
              (image->alpha_trait != UndefinedPixelTrait) ? BI_BITFIELDS : BI_RGB);
2022
491
            if ((type == 3) && (image->alpha_trait != UndefinedPixelTrait))
2023
29
              {
2024
29
                option=GetImageOption(image_info,"bmp3:alpha");
2025
29
                if (IsStringTrue(option))
2026
0
                  bmp_info.bits_per_pixel=32;
2027
29
              }
2028
491
          }
2029
491
      }
2030
1.08k
    bytes_per_line=4*((image->columns*bmp_info.bits_per_pixel+31)/32);
2031
1.08k
    bmp_info.ba_offset=0;
2032
1.08k
    if (type > 3)
2033
449
      profile=GetImageProfile(image,"icc");
2034
1.08k
    have_color_info=(image->rendering_intent != UndefinedIntent) ||
2035
1.08k
      (profile != (StringInfo *) NULL) || (image->gamma != 0.0) ?  MagickTrue :
2036
1.08k
      MagickFalse;
2037
1.08k
    if (type == 2)
2038
294
      bmp_info.size=12;
2039
790
    else
2040
790
      if ((type == 3) || (((image->alpha_trait & BlendPixelTrait) == 0) &&
2041
449
          (have_color_info == MagickFalse)))
2042
341
        {
2043
341
          type=3;
2044
341
          bmp_info.size=40;
2045
341
        }
2046
449
      else
2047
449
        {
2048
449
          int
2049
449
            extra_size;
2050
2051
449
          bmp_info.size=108;
2052
449
          extra_size=68;
2053
449
          if ((image->rendering_intent != UndefinedIntent) ||
2054
449
              (profile != (StringInfo *) NULL))
2055
422
            {
2056
422
              bmp_info.size=124;
2057
422
              extra_size+=16;
2058
422
            }
2059
449
          bmp_info.file_size+=(unsigned int) extra_size;
2060
449
          bmp_info.offset_bits+=(unsigned int) extra_size;
2061
449
        }
2062
1.08k
    if (((ssize_t) image->columns != (ssize_t) ((signed int) image->columns)) ||
2063
1.08k
        ((ssize_t) image->rows != (ssize_t) ((signed int) image->rows)))
2064
1.08k
      ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
2065
1.08k
    bmp_info.width=(ssize_t) image->columns;
2066
1.08k
    bmp_info.height=(ssize_t) image->rows;
2067
1.08k
    bmp_info.planes=1;
2068
1.08k
    bmp_info.image_size=(unsigned int) (bytes_per_line*image->rows);
2069
1.08k
    bmp_info.file_size+=bmp_info.image_size;
2070
1.08k
    bmp_info.x_pixels=75*39;
2071
1.08k
    bmp_info.y_pixels=75*39;
2072
1.08k
    switch (image->units)
2073
1.08k
    {
2074
69
      case UndefinedResolution:
2075
69
      case PixelsPerInchResolution:
2076
69
      {
2077
69
        bmp_info.x_pixels=CastDoubleToUInt(100.0*image->resolution.x/2.54);
2078
69
        bmp_info.y_pixels=CastDoubleToUInt(100.0*image->resolution.y/2.54);
2079
69
        break;
2080
69
      }
2081
1.01k
      case PixelsPerCentimeterResolution:
2082
1.01k
      {
2083
1.01k
        bmp_info.x_pixels=CastDoubleToUInt(100.0*image->resolution.x);
2084
1.01k
        bmp_info.y_pixels=CastDoubleToUInt(100.0*image->resolution.y);
2085
1.01k
        break;
2086
69
      }
2087
1.08k
    }
2088
1.08k
    bmp_info.colors_important=bmp_info.number_colors;
2089
    /*
2090
      Convert MIFF to BMP raster pixels.
2091
    */
2092
1.08k
    pixel_info=AcquireVirtualMemory(image->rows,MagickMax(bytes_per_line,
2093
1.08k
      image->columns+256UL)*sizeof(*pixels));
2094
1.08k
    if (pixel_info == (MemoryInfo *) NULL)
2095
1.08k
      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2096
1.08k
    pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
2097
1.08k
    (void) memset(pixels,0,(size_t) bmp_info.image_size);
2098
1.08k
    switch (bmp_info.bits_per_pixel)
2099
1.08k
    {
2100
275
      case 1:
2101
275
      {
2102
275
        size_t
2103
275
          bit,
2104
275
          byte;
2105
2106
        /*
2107
          Convert PseudoClass image to a BMP monochrome image.
2108
        */
2109
5.58k
        for (y=0; y < (ssize_t) image->rows; y++)
2110
5.30k
        {
2111
5.30k
          ssize_t
2112
5.30k
            offset;
2113
2114
5.30k
          p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2115
5.30k
          if (p == (const Quantum *) NULL)
2116
0
            break;
2117
5.30k
          q=pixels+((ssize_t) image->rows-y-1)*(ssize_t) bytes_per_line;
2118
5.30k
          bit=0;
2119
5.30k
          byte=0;
2120
300k
          for (x=0; x < (ssize_t) image->columns; x++)
2121
295k
          {
2122
295k
            byte<<=1;
2123
295k
            byte|=(size_t) (GetPixelIndex(image,p) != 0 ? 0x01 : 0x00);
2124
295k
            bit++;
2125
295k
            if (bit == 8)
2126
36.0k
              {
2127
36.0k
                *q++=(unsigned char) byte;
2128
36.0k
                bit=0;
2129
36.0k
                byte=0;
2130
36.0k
              }
2131
295k
             p+=(ptrdiff_t) GetPixelChannels(image);
2132
295k
           }
2133
5.30k
           if (bit != 0)
2134
4.03k
             {
2135
4.03k
               *q++=(unsigned char) (byte << (8-bit));
2136
4.03k
               x++;
2137
4.03k
             }
2138
5.30k
          offset=(ssize_t) (image->columns+7)/8;
2139
15.2k
          for (x=offset; x < (ssize_t) bytes_per_line; x++)
2140
9.90k
            *q++=0x00;
2141
5.30k
          if (image->previous == (Image *) NULL)
2142
5.30k
            {
2143
5.30k
              status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2144
5.30k
                image->rows);
2145
5.30k
              if (status == MagickFalse)
2146
0
                break;
2147
5.30k
            }
2148
5.30k
        }
2149
275
        break;
2150
0
      }
2151
172
      case 4:
2152
172
      {
2153
172
        unsigned int
2154
172
          byte,
2155
172
          nibble;
2156
2157
172
        ssize_t
2158
172
          offset;
2159
2160
        /*
2161
          Convert PseudoClass image to a BMP monochrome image.
2162
        */
2163
12.6k
        for (y=0; y < (ssize_t) image->rows; y++)
2164
12.4k
        {
2165
12.4k
          p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2166
12.4k
          if (p == (const Quantum *) NULL)
2167
0
            break;
2168
12.4k
          q=pixels+((ssize_t) image->rows-y-1)*(ssize_t) bytes_per_line;
2169
12.4k
          nibble=0;
2170
12.4k
          byte=0;
2171
651k
          for (x=0; x < (ssize_t) image->columns; x++)
2172
639k
          {
2173
639k
            byte<<=4;
2174
639k
            byte|=((unsigned int) GetPixelIndex(image,p) & 0x0f);
2175
639k
            nibble++;
2176
639k
            if (nibble == 2)
2177
315k
              {
2178
315k
                *q++=(unsigned char) byte;
2179
315k
                nibble=0;
2180
315k
                byte=0;
2181
315k
              }
2182
639k
            p+=(ptrdiff_t) GetPixelChannels(image);
2183
639k
          }
2184
12.4k
          if (nibble != 0)
2185
8.81k
            {
2186
8.81k
              *q++=(unsigned char) (byte << 4);
2187
8.81k
              x++;
2188
8.81k
            }
2189
12.4k
          offset=(ssize_t) (image->columns+1)/2;
2190
40.5k
          for (x=offset; x < (ssize_t) bytes_per_line; x++)
2191
28.0k
            *q++=0x00;
2192
12.4k
          if (image->previous == (Image *) NULL)
2193
12.4k
            {
2194
12.4k
              status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2195
12.4k
                image->rows);
2196
12.4k
              if (status == MagickFalse)
2197
0
                break;
2198
12.4k
            }
2199
12.4k
        }
2200
172
        break;
2201
0
      }
2202
146
      case 8:
2203
146
      {
2204
        /*
2205
          Convert PseudoClass packet to BMP pixel.
2206
        */
2207
68.6k
        for (y=0; y < (ssize_t) image->rows; y++)
2208
68.4k
        {
2209
68.4k
          p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2210
68.4k
          if (p == (const Quantum *) NULL)
2211
0
            break;
2212
68.4k
          q=pixels+((ssize_t) image->rows-y-1)*(ssize_t) bytes_per_line;
2213
112M
          for (x=0; x < (ssize_t) image->columns; x++)
2214
112M
          {
2215
112M
            *q++=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
2216
112M
            p+=(ptrdiff_t) GetPixelChannels(image);
2217
112M
          }
2218
161k
          for ( ; x < (ssize_t) bytes_per_line; x++)
2219
92.7k
            *q++=0x00;
2220
68.4k
          if (image->previous == (Image *) NULL)
2221
68.4k
            {
2222
68.4k
              status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2223
68.4k
                image->rows);
2224
68.4k
              if (status == MagickFalse)
2225
0
                break;
2226
68.4k
            }
2227
68.4k
        }
2228
146
        break;
2229
0
      }
2230
0
      case 16:
2231
0
      {
2232
        /*
2233
          Convert DirectClass packet to BMP BGR888.
2234
        */
2235
0
        for (y=0; y < (ssize_t) image->rows; y++)
2236
0
        {
2237
0
          p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2238
0
          if (p == (const Quantum *) NULL)
2239
0
            break;
2240
0
          q=pixels+((ssize_t) image->rows-y-1)*(ssize_t) bytes_per_line;
2241
0
          for (x=0; x < (ssize_t) image->columns; x++)
2242
0
          {
2243
0
            unsigned short
2244
0
              pixel;
2245
2246
0
            pixel=0;
2247
0
            if (bmp_subtype == ARGB4444)
2248
0
              {
2249
0
                pixel=(unsigned short) (ScaleQuantumToAny(
2250
0
                  GetPixelAlpha(image,p),15) << 12);
2251
0
                pixel|=(unsigned short) (ScaleQuantumToAny(
2252
0
                  GetPixelRed(image,p),15) << 8);
2253
0
                pixel|=(unsigned short) (ScaleQuantumToAny(
2254
0
                  GetPixelGreen(image,p),15) << 4);
2255
0
                pixel|=(unsigned short) (ScaleQuantumToAny(
2256
0
                  GetPixelBlue(image,p),15));
2257
0
              }
2258
0
            else if (bmp_subtype == RGB565)
2259
0
              {
2260
0
                pixel=(unsigned short) (ScaleQuantumToAny(
2261
0
                  GetPixelRed(image,p),31) << 11);
2262
0
                pixel|=(unsigned short) (ScaleQuantumToAny(
2263
0
                  GetPixelGreen(image,p),63) << 5);
2264
0
                pixel|=(unsigned short) (ScaleQuantumToAny(
2265
0
                  GetPixelBlue(image,p),31));
2266
0
              }
2267
0
            else
2268
0
              {
2269
0
                if (bmp_subtype == ARGB1555)
2270
0
                  pixel=(unsigned short) (ScaleQuantumToAny(
2271
0
                    GetPixelAlpha(image,p),1) << 15);
2272
0
                pixel|=(unsigned short) (ScaleQuantumToAny(
2273
0
                  GetPixelRed(image,p),31) << 10);
2274
0
                pixel|=(unsigned short) (ScaleQuantumToAny(
2275
0
                  GetPixelGreen(image,p),31) << 5);
2276
0
                pixel|=(unsigned short) (ScaleQuantumToAny(
2277
0
                  GetPixelBlue(image,p),31));
2278
0
              }
2279
0
            *((unsigned short *) q)=pixel;
2280
0
            q+=(ptrdiff_t) 2;
2281
0
            p+=(ptrdiff_t) GetPixelChannels(image);
2282
0
          }
2283
0
          for (x=2L*(ssize_t) image->columns; x < (ssize_t) bytes_per_line; x++)
2284
0
            *q++=0x00;
2285
0
          if (image->previous == (Image *) NULL)
2286
0
            {
2287
0
              status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2288
0
                image->rows);
2289
0
              if (status == MagickFalse)
2290
0
                break;
2291
0
            }
2292
0
        }
2293
0
        break;
2294
0
      }
2295
367
      case 24:
2296
367
      {
2297
        /*
2298
          Convert DirectClass packet to BMP BGR888.
2299
        */
2300
40.4k
        for (y=0; y < (ssize_t) image->rows; y++)
2301
40.0k
        {
2302
40.0k
          p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2303
40.0k
          if (p == (const Quantum *) NULL)
2304
0
            break;
2305
40.0k
          q=pixels+((ssize_t) image->rows-y-1)*(ssize_t) bytes_per_line;
2306
37.9M
          for (x=0; x < (ssize_t) image->columns; x++)
2307
37.9M
          {
2308
37.9M
            *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
2309
37.9M
            *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
2310
37.9M
            *q++=ScaleQuantumToChar(GetPixelRed(image,p));
2311
37.9M
            p+=(ptrdiff_t) GetPixelChannels(image);
2312
37.9M
          }
2313
103k
          for (x=3L*(ssize_t) image->columns; x < (ssize_t) bytes_per_line; x++)
2314
63.0k
            *q++=0x00;
2315
40.0k
          if (image->previous == (Image *) NULL)
2316
40.0k
            {
2317
40.0k
              status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2318
40.0k
                image->rows);
2319
40.0k
              if (status == MagickFalse)
2320
0
                break;
2321
40.0k
            }
2322
40.0k
        }
2323
367
        break;
2324
0
      }
2325
124
      case 32:
2326
124
      {
2327
        /*
2328
          Convert DirectClass packet to ARGB8888 pixel.
2329
        */
2330
1.10k
        for (y=0; y < (ssize_t) image->rows; y++)
2331
984
        {
2332
984
          p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2333
984
          if (p == (const Quantum *) NULL)
2334
0
            break;
2335
984
          q=pixels+((ssize_t) image->rows-y-1)*(ssize_t) bytes_per_line;
2336
2.89k
          for (x=0; x < (ssize_t) image->columns; x++)
2337
1.90k
          {
2338
1.90k
            *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
2339
1.90k
            *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
2340
1.90k
            *q++=ScaleQuantumToChar(GetPixelRed(image,p));
2341
1.90k
            *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
2342
1.90k
            p+=(ptrdiff_t) GetPixelChannels(image);
2343
1.90k
          }
2344
984
          if (image->previous == (Image *) NULL)
2345
984
            {
2346
984
              status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2347
984
                image->rows);
2348
984
              if (status == MagickFalse)
2349
0
                break;
2350
984
            }
2351
984
        }
2352
124
        break;
2353
0
      }
2354
1.08k
    }
2355
1.08k
    if ((type > 2) && (bmp_info.bits_per_pixel == 8))
2356
111
      if (image_info->compression != NoCompression)
2357
111
        {
2358
111
          MemoryInfo
2359
111
            *rle_info;
2360
2361
          /*
2362
            Convert run-length encoded raster pixels.
2363
          */
2364
111
          rle_info=AcquireVirtualMemory((size_t) (2*(bytes_per_line+2)+2),
2365
111
            (image->rows+2)*sizeof(*pixels));
2366
111
          if (rle_info == (MemoryInfo *) NULL)
2367
0
            {
2368
0
              pixel_info=RelinquishVirtualMemory(pixel_info);
2369
0
              ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2370
0
            }
2371
111
          bmp_data=(unsigned char *) GetVirtualMemoryBlob(rle_info);
2372
111
          bmp_info.file_size-=bmp_info.image_size;
2373
111
          bmp_info.image_size=(unsigned int) EncodeImage(image,bytes_per_line,
2374
111
            pixels,bmp_data);
2375
111
          bmp_info.file_size+=bmp_info.image_size;
2376
111
          pixel_info=RelinquishVirtualMemory(pixel_info);
2377
111
          pixel_info=rle_info;
2378
111
          pixels=bmp_data;
2379
111
          bmp_info.compression=BI_RLE8;
2380
111
        }
2381
    /*
2382
      Write BMP for Windows, all versions, 14-byte header.
2383
    */
2384
1.08k
    if (image->debug != MagickFalse)
2385
0
      {
2386
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2387
0
          "   Writing BMP version %.20g datastream",(double) type);
2388
0
        if (image->storage_class == DirectClass)
2389
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2390
0
            "   Storage class=DirectClass");
2391
0
        else
2392
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2393
0
            "   Storage class=PseudoClass");
2394
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2395
0
          "   Image depth=%.20g",(double) image->depth);
2396
0
        if (image->alpha_trait != UndefinedPixelTrait)
2397
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2398
0
            "   Matte=True");
2399
0
        else
2400
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2401
0
            "   Matte=MagickFalse");
2402
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2403
0
          "   BMP bits_per_pixel=%.20g",(double) bmp_info.bits_per_pixel);
2404
0
        switch ((int) bmp_info.compression)
2405
0
        {
2406
0
           case BI_RGB:
2407
0
           {
2408
0
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2409
0
               "   Compression=BI_RGB");
2410
0
             break;
2411
0
           }
2412
0
           case BI_RLE8:
2413
0
           {
2414
0
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2415
0
               "   Compression=BI_RLE8");
2416
0
             break;
2417
0
           }
2418
0
           case BI_BITFIELDS:
2419
0
           {
2420
0
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2421
0
               "   Compression=BI_BITFIELDS");
2422
0
             break;
2423
0
           }
2424
0
           case BI_ALPHABITFIELDS:
2425
0
           {
2426
0
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2427
0
               "   Compression=BI_BITFIELDS");
2428
0
             break;
2429
0
           }
2430
0
           default:
2431
0
           {
2432
0
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2433
0
               "   Compression=UNKNOWN (%u)",bmp_info.compression);
2434
0
             break;
2435
0
           }
2436
0
        }
2437
0
        if (bmp_info.number_colors == 0)
2438
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2439
0
            "   Number_colors=unspecified");
2440
0
        else
2441
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2442
0
            "   Number_colors=%u",bmp_info.number_colors);
2443
0
      }
2444
1.08k
    profile_data=0;
2445
1.08k
    profile_size=0;
2446
1.08k
    profile_size_pad=0;
2447
1.08k
    if (profile != (StringInfo *) NULL)
2448
22
      {
2449
22
        profile_data=(MagickOffsetType) bmp_info.file_size-14;  /* from head of BMP info header */
2450
22
        profile_size=(MagickOffsetType) GetStringInfoLength(profile);
2451
22
        if ((profile_size % 4) > 0)
2452
3
          profile_size_pad=4-(profile_size%4);
2453
22
        bmp_info.file_size+=(unsigned int) (profile_size+profile_size_pad);
2454
22
      }
2455
1.08k
    (void) WriteBlob(image,2,(unsigned char *) "BM");
2456
1.08k
    (void) WriteBlobLSBLong(image,bmp_info.file_size);
2457
1.08k
    (void) WriteBlobLSBLong(image,bmp_info.ba_offset);  /* always 0 */
2458
1.08k
    (void) WriteBlobLSBLong(image,bmp_info.offset_bits);
2459
1.08k
    if (type == 2)
2460
294
      {
2461
        /*
2462
          Write 12-byte version 2 bitmap header.
2463
        */
2464
294
        (void) WriteBlobLSBLong(image,bmp_info.size);
2465
294
        (void) WriteBlobLSBSignedShort(image,(signed short) bmp_info.width);
2466
294
        (void) WriteBlobLSBSignedShort(image,(signed short) bmp_info.height);
2467
294
        (void) WriteBlobLSBShort(image,bmp_info.planes);
2468
294
        (void) WriteBlobLSBShort(image,bmp_info.bits_per_pixel);
2469
294
      }
2470
790
    else
2471
790
      {
2472
        /*
2473
          Write 40-byte version 3+ bitmap header.
2474
        */
2475
790
        (void) WriteBlobLSBLong(image,bmp_info.size);
2476
790
        (void) WriteBlobLSBSignedLong(image,(signed int) bmp_info.width);
2477
790
        (void) WriteBlobLSBSignedLong(image,(signed int) bmp_info.height);
2478
790
        (void) WriteBlobLSBShort(image,bmp_info.planes);
2479
790
        (void) WriteBlobLSBShort(image,bmp_info.bits_per_pixel);
2480
790
        (void) WriteBlobLSBLong(image,bmp_info.compression);
2481
790
        (void) WriteBlobLSBLong(image,bmp_info.image_size);
2482
790
        (void) WriteBlobLSBLong(image,bmp_info.x_pixels);
2483
790
        (void) WriteBlobLSBLong(image,bmp_info.y_pixels);
2484
790
        (void) WriteBlobLSBLong(image,bmp_info.number_colors);
2485
790
        (void) WriteBlobLSBLong(image,bmp_info.colors_important);
2486
790
      }
2487
1.08k
    if ((type > 3) && ((image->alpha_trait != UndefinedPixelTrait) ||
2488
449
        (have_color_info != MagickFalse)))
2489
449
      {
2490
        /*
2491
          Write the rest of the 108-byte BMP Version 4 header.
2492
        */
2493
449
        (void) WriteBlobLSBLong(image,bmp_info.red_mask);
2494
449
        (void) WriteBlobLSBLong(image,bmp_info.green_mask);
2495
449
        (void) WriteBlobLSBLong(image,bmp_info.blue_mask);
2496
449
        (void) WriteBlobLSBLong(image,bmp_info.alpha_mask);
2497
449
        if (profile != (StringInfo *) NULL)
2498
22
          (void) WriteBlobLSBLong(image,0x4D424544U);  /* PROFILE_EMBEDDED */
2499
427
        else
2500
427
          (void) WriteBlobLSBLong(image,0x73524742U);  /* sRGB */
2501
2502
        /* bounds check, assign .0 if invalid value */
2503
449
        if (isgreater(image->chromaticity.red_primary.x, 1.0) ||
2504
449
            !isgreater(image->chromaticity.red_primary.x, 0.0))
2505
45
          image->chromaticity.red_primary.x = 0.0;
2506
449
        if (isgreater(image->chromaticity.red_primary.y, 1.0) ||
2507
449
            !isgreater(image->chromaticity.red_primary.y, 0.0))
2508
45
          image->chromaticity.red_primary.y = 0.0;
2509
449
        if (isgreater(image->chromaticity.green_primary.x, 1.0) ||
2510
449
            !isgreater(image->chromaticity.green_primary.x, 0.0))
2511
45
          image->chromaticity.green_primary.x = 0.0;
2512
449
        if (isgreater(image->chromaticity.green_primary.y, 1.0) ||
2513
449
            !isgreater(image->chromaticity.green_primary.y, 0.0))
2514
47
          image->chromaticity.green_primary.y = 0.0;
2515
449
        if (isgreater(image->chromaticity.blue_primary.x, 1.0) ||
2516
449
            !isgreater(image->chromaticity.blue_primary.x, 0.0))
2517
46
          image->chromaticity.blue_primary.x = 0.0;
2518
449
        if (isgreater(image->chromaticity.blue_primary.y, 1.0) ||
2519
449
            !isgreater(image->chromaticity.blue_primary.y, 0.0))
2520
46
          image->chromaticity.blue_primary.y = 0.0;
2521
449
        if (isgreater(bmp_info.gamma_scale.x, 1.0) ||
2522
449
            !isgreater(bmp_info.gamma_scale.x, 0.0))
2523
449
          bmp_info.gamma_scale.x = 0.0;
2524
449
        if (isgreater(bmp_info.gamma_scale.y, 1.0) ||
2525
449
            !isgreater(bmp_info.gamma_scale.y, 0.0))
2526
449
          bmp_info.gamma_scale.y = 0.0;
2527
449
        if (isgreater(bmp_info.gamma_scale.z, 1.0) ||
2528
449
            !isgreater(bmp_info.gamma_scale.z, 0.0))
2529
449
          bmp_info.gamma_scale.z = 0.0;
2530
2531
449
        (void) WriteBlobLSBLong(image,(unsigned int)
2532
449
          (image->chromaticity.red_primary.x*0x40000000));
2533
449
        (void) WriteBlobLSBLong(image,(unsigned int)
2534
449
          (image->chromaticity.red_primary.y*0x40000000));
2535
449
        (void) WriteBlobLSBLong(image,(unsigned int)
2536
449
          ((1.000-(image->chromaticity.red_primary.x+
2537
449
          image->chromaticity.red_primary.y))*0x40000000));
2538
449
        (void) WriteBlobLSBLong(image,(unsigned int)
2539
449
          (image->chromaticity.green_primary.x*0x40000000));
2540
449
        (void) WriteBlobLSBLong(image,(unsigned int)
2541
449
          (image->chromaticity.green_primary.y*0x40000000));
2542
449
        (void) WriteBlobLSBLong(image,(unsigned int)
2543
449
          ((1.000-(image->chromaticity.green_primary.x+
2544
449
          image->chromaticity.green_primary.y))*0x40000000));
2545
449
        (void) WriteBlobLSBLong(image,(unsigned int)
2546
449
          (image->chromaticity.blue_primary.x*0x40000000));
2547
449
        (void) WriteBlobLSBLong(image,(unsigned int)
2548
449
          (image->chromaticity.blue_primary.y*0x40000000));
2549
449
        (void) WriteBlobLSBLong(image,(unsigned int)
2550
449
          ((1.000-(image->chromaticity.blue_primary.x+
2551
449
          image->chromaticity.blue_primary.y))*0x40000000));
2552
449
        (void) WriteBlobLSBLong(image,(unsigned int)
2553
449
          (bmp_info.gamma_scale.x*0x10000));
2554
449
        (void) WriteBlobLSBLong(image,(unsigned int)
2555
449
          (bmp_info.gamma_scale.y*0x10000));
2556
449
        (void) WriteBlobLSBLong(image,(unsigned int)
2557
449
          (bmp_info.gamma_scale.z*0x10000));
2558
449
        if ((image->rendering_intent != UndefinedIntent) ||
2559
449
            (profile != (StringInfo *) NULL))
2560
422
          {
2561
422
            ssize_t
2562
422
              intent;
2563
2564
422
            switch ((int) image->rendering_intent)
2565
422
            {
2566
1
              case SaturationIntent:
2567
1
              {
2568
1
                intent=LCS_GM_BUSINESS;
2569
1
                break;
2570
0
              }
2571
1
              case RelativeIntent:
2572
1
              {
2573
1
                intent=LCS_GM_GRAPHICS;
2574
1
                break;
2575
0
              }
2576
418
              case PerceptualIntent:
2577
418
              {
2578
418
                intent=LCS_GM_IMAGES;
2579
418
                break;
2580
0
              }
2581
2
              case AbsoluteIntent:
2582
2
              {
2583
2
                intent=LCS_GM_ABS_COLORIMETRIC;
2584
2
                break;
2585
0
              }
2586
0
              default:
2587
0
              {
2588
0
                intent=0;
2589
0
                break;
2590
0
              }
2591
422
            }
2592
422
            (void) WriteBlobLSBLong(image,(unsigned int) intent);
2593
422
            (void) WriteBlobLSBLong(image,(unsigned int) profile_data);
2594
422
            (void) WriteBlobLSBLong(image,(unsigned int)
2595
422
              (profile_size+profile_size_pad));
2596
422
            (void) WriteBlobLSBLong(image,0x00);  /* reserved */
2597
422
          }
2598
449
      }
2599
1.08k
    if (image->storage_class == PseudoClass)
2600
593
      {
2601
593
        unsigned char
2602
593
          *bmp_colormap;
2603
2604
        /*
2605
          Dump colormap to file.
2606
        */
2607
593
        if (image->debug != MagickFalse)
2608
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2609
0
            "  Colormap: %.20g entries",(double) image->colors);
2610
593
        bmp_colormap=(unsigned char *) AcquireQuantumMemory((size_t) 1UL <<
2611
593
          bmp_info.bits_per_pixel,4*sizeof(*bmp_colormap));
2612
593
        if (bmp_colormap == (unsigned char *) NULL)
2613
0
          {
2614
0
            pixel_info=RelinquishVirtualMemory(pixel_info);
2615
0
            ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2616
0
          }
2617
593
        q=bmp_colormap;
2618
16.2k
        for (i=0; i < MagickMin((ssize_t) image->colors,(ssize_t) bmp_info.number_colors); i++)
2619
15.6k
        {
2620
15.6k
          *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].blue));
2621
15.6k
          *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].green));
2622
15.6k
          *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].red));
2623
15.6k
          if (type > 2)
2624
12.2k
            *q++=(unsigned char) 0x0;
2625
15.6k
        }
2626
25.5k
        for ( ; i < (ssize_t) 1UL << bmp_info.bits_per_pixel; i++)
2627
24.9k
        {
2628
24.9k
          *q++=(unsigned char) 0x00;
2629
24.9k
          *q++=(unsigned char) 0x00;
2630
24.9k
          *q++=(unsigned char) 0x00;
2631
24.9k
          if (type > 2)
2632
18.4k
            *q++=(unsigned char) 0x00;
2633
24.9k
        }
2634
593
        if (type <= 2)
2635
167
          (void) WriteBlob(image,(size_t) (3*(1L << bmp_info.bits_per_pixel)),
2636
167
            bmp_colormap);
2637
426
        else
2638
426
          (void) WriteBlob(image,(size_t) (4*(1L << bmp_info.bits_per_pixel)),
2639
426
            bmp_colormap);
2640
593
        bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);
2641
593
      }
2642
1.08k
    if (image->debug != MagickFalse)
2643
0
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2644
0
        "  Pixels:  %u bytes",bmp_info.image_size);
2645
1.08k
    (void) WriteBlob(image,(size_t) bmp_info.image_size,pixels);
2646
1.08k
    if (profile != (StringInfo *) NULL)
2647
22
      {
2648
22
        if (image->debug != MagickFalse)
2649
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2650
0
            "  Profile:  %g bytes",(double) profile_size+profile_size_pad);
2651
22
        (void) WriteBlob(image,(size_t) profile_size,
2652
22
          GetStringInfoDatum(profile));
2653
22
        if (profile_size_pad > 0)  /* padding for 4 bytes multiple */
2654
3
          (void) WriteBlob(image,(size_t) profile_size_pad,"\0\0\0");
2655
22
      }
2656
1.08k
    pixel_info=RelinquishVirtualMemory(pixel_info);
2657
1.08k
    if (GetNextImageInList(image) == (Image *) NULL)
2658
1.08k
      break;
2659
0
    image=SyncNextImageInList(image);
2660
0
    status=SetImageProgress(image,SaveImagesTag,scene++,number_scenes);
2661
0
    if (status == MagickFalse)
2662
0
      break;
2663
0
  } while (image_info->adjoin != MagickFalse);
2664
1.08k
  if (CloseBlob(image) == MagickFalse)
2665
0
    status=MagickFalse;
2666
1.08k
  return(status);
2667
1.08k
}