Coverage Report

Created: 2025-11-16 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/graphicsmagick/coders/dib.c
Line
Count
Source
1
/*
2
% Copyright (C) 2003-2025 GraphicsMagick Group
3
% Copyright (C) 2002 ImageMagick Studio
4
%
5
% This program is covered by multiple licenses, which are described in
6
% Copyright.txt. You should have received a copy of Copyright.txt with this
7
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
8
%
9
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10
%                                                                             %
11
%                                                                             %
12
%                                                                             %
13
%                            DDDD   IIIII  BBBB                               %
14
%                            D   D    I    B   B                              %
15
%                            D   D    I    BBBB                               %
16
%                            D   D    I    B   B                              %
17
%                            DDDD   IIIII  BBBB                               %
18
%                                                                             %
19
%                                                                             %
20
%                   Read/Write Windows DIB Image Format.                      %
21
%                                                                             %
22
%                                                                             %
23
%                              Software Design                                %
24
%                                John Cristy                                  %
25
%                                 July 1992                                   %
26
%                                                                             %
27
%                                                                             %
28
%                                                                             %
29
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
30
%
31
%
32
*/
33

34
/*
35
  Include declarations.
36
*/
37
#include "magick/studio.h"
38
#include "magick/analyze.h"
39
#include "magick/blob.h"
40
#include "magick/colormap.h"
41
#include "magick/log.h"
42
#include "magick/magick.h"
43
#include "magick/monitor.h"
44
#include "magick/pixel_cache.h"
45
#include "magick/render.h"
46
#include "magick/transform.h"
47
#include "magick/utility.h"
48

49
/*
50
  Macro definitions (from Windows wingdi.h).
51
*/
52
#undef BI_RLE8
53
1.22M
#define BI_RLE8  1
54

55
/*
56
  Typedef declarations.
57
*/
58
typedef struct _DIBInfo
59
{
60
  magick_uint32_t
61
    header_size;
62
63
  magick_int32_t
64
    width,
65
    height;
66
67
  magick_uint16_t
68
    planes,
69
    bits_per_pixel;
70
71
  magick_uint32_t
72
    compression, /* 0=uncompressed, 1=8bit RLE, 2=4bit RLE, 3=RGB masked */
73
    image_size,
74
    x_pixels,
75
    y_pixels,
76
    number_colors,
77
    colors_important;
78
79
  magick_uint16_t
80
    red_mask,
81
    green_mask,
82
    blue_mask,
83
    alpha_mask;
84
85
  magick_int32_t
86
    colorspace;
87
88
  PointInfo
89
    red_primary,
90
    green_primary,
91
    blue_primary,
92
    gamma_scale;
93
} DIBInfo;
94

95
/*
96
  Forward declarations.
97
*/
98
static unsigned int
99
  WriteDIBImage(const ImageInfo *,Image *);
100

101
static void LogDIBInfo(const DIBInfo *dib_info)
102
91.6k
{
103
  /*
104
    Dump 40-byte version 3+ bitmap header.
105
    BMP version 4 has same members, but is 108 bytes.
106
  */
107
91.6k
  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
108
91.6k
                        "DIB Header:\n"
109
91.6k
                        "    Header Size:          %u\n"
110
91.6k
                        "    Width:                %d\n"
111
91.6k
                        "    Height:               %d\n"
112
91.6k
                        "    Planes:               %u\n"
113
91.6k
                        "    Bits Per Pixel:       %u\n"
114
91.6k
                        "    Compression:          %u\n"
115
91.6k
                        "    Size Of Bitmap:       %u\n"
116
91.6k
                        "    Horizontal Resolution:%u\n"
117
91.6k
                        "    Vertical Resolution:  %u\n"
118
91.6k
                        "    Colors Used:          %u\n"
119
91.6k
                        "    Colors Important:     %u",
120
91.6k
                        (unsigned int) dib_info->header_size,
121
91.6k
                        (signed int) dib_info->width,
122
91.6k
                        (signed int) dib_info->height,
123
91.6k
                        (unsigned int) dib_info->planes,
124
91.6k
                        (unsigned int) dib_info->bits_per_pixel,
125
91.6k
                        (unsigned int) dib_info->compression,
126
91.6k
                        (unsigned int) dib_info->image_size,
127
91.6k
                        (unsigned int) dib_info->x_pixels,
128
91.6k
                        (unsigned int) dib_info->y_pixels,
129
91.6k
                        (unsigned int) dib_info->number_colors,
130
91.6k
                        (unsigned int) dib_info->colors_important
131
91.6k
                        );
132
91.6k
}
133
/*
134
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
135
%                                                                             %
136
%                                                                             %
137
%                                                                             %
138
%   D e c o d e I m a g e                                                     %
139
%                                                                             %
140
%                                                                             %
141
%                                                                             %
142
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
143
%
144
%  Method DecodeImage unpacks the packed image pixels into runlength-encoded
145
%  pixel packets.
146
%
147
%  The format of the DecodeImage method is:
148
%
149
%      unsigned int DecodeImage(Image *image,const unsigned long compression,
150
%        unsigned char *pixels)
151
%
152
%  A description of each parameter follows:
153
%
154
%    o status:  Method DecodeImage returns True if all the pixels are
155
%      uncompressed without error, otherwise False.
156
%
157
%    o image: The address of a structure of type Image.
158
%
159
%    o compression:  A value of 1 means the compressed pixels are runlength
160
%      encoded for a 256-color bitmap.  A value of 2 means a 16-color bitmap.
161
%
162
%    o pixels:  The address of a byte (8 bits) array of pixel data created by
163
%      the decoding process.
164
%
165
%    o pixels_size: The size of the allocated buffer array.
166
%
167
%
168
*/
169
static MagickPassFail DecodeImage(Image *image,const unsigned long compression,
170
                                  unsigned char *pixels, const size_t pixels_size)
171
9.37k
{
172
9.37k
  unsigned long
173
9.37k
    x,
174
9.37k
    y;
175
176
9.37k
  unsigned int
177
9.37k
    i;
178
179
9.37k
  int
180
9.37k
    byte,
181
9.37k
    count;
182
183
9.37k
  register unsigned char
184
9.37k
    *q;
185
186
9.37k
  unsigned char
187
9.37k
    *end;
188
189
9.37k
  assert(image != (Image *) NULL);
190
9.37k
  assert(pixels != (unsigned char *) NULL);
191
9.37k
  if (image->logging)
192
9.37k
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
193
9.37k
                          "  Decoding RLE compressed pixels to"
194
9.37k
                          " %" MAGICK_SIZE_T_F "u bytes",
195
9.37k
                          (MAGICK_SIZE_T) image->rows*(size_t)image->columns);
196
197
9.37k
  byte=0;
198
9.37k
  x=0;
199
9.37k
  q=pixels;
200
9.37k
  end=pixels + pixels_size;
201
  /*
202
    Decompress sufficient data to support the number of pixels (or
203
    rows) in the image and then return.
204
205
    Do not wait to read the final EOL and EOI markers (if not yet
206
    encountered) since we always read this marker just before we
207
    return.
208
  */
209
1.22M
  for (y=0; y < image->rows; )
210
1.21M
    {
211
1.21M
      if (q < pixels || q >= end)
212
4.06k
        {
213
4.06k
          if (image->logging)
214
4.06k
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
215
4.06k
                                  "  Decode buffer full (y=%lu, "
216
4.06k
                                  "pixels_size=%" MAGICK_SIZE_T_F "u, "
217
4.06k
                                  "pixels=%p, q=%p, end=%p)",
218
4.06k
                                  y, (MAGICK_SIZE_T) pixels_size,
219
4.06k
                                  pixels, q, end);
220
4.06k
          break;
221
4.06k
        }
222
1.21M
      count=ReadBlobByte(image);
223
1.21M
      if (count == EOF)
224
353
        return MagickFail;
225
1.21M
      if (count > 0)
226
1.13M
        {
227
1.13M
          count=Min(count, end - q);
228
          /*
229
            Encoded mode.
230
          */
231
1.13M
          byte=ReadBlobByte(image);
232
1.13M
          if (byte == EOF)
233
493
            return MagickFail;
234
1.13M
          if (compression == BI_RLE8)
235
1.13M
            {
236
164M
              for ( i=count; i != 0; --i )
237
163M
                {
238
163M
                  *q++=(unsigned char) byte;
239
163M
                }
240
1.13M
            }
241
3.44k
          else
242
3.44k
            {
243
223k
              for ( i=0; i < (unsigned int) count; i++ )
244
219k
                {
245
219k
                  *q++=(unsigned char)
246
219k
                    ((i & 0x01) ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
247
219k
                }
248
3.44k
            }
249
1.13M
          x+=count;
250
1.13M
        }
251
80.0k
      else
252
80.0k
        {
253
          /*
254
            Escape mode.
255
          */
256
80.0k
          count=ReadBlobByte(image);
257
80.0k
          if (count == EOF)
258
138
            return MagickFail;
259
79.8k
          if (count == 0x01)
260
405
            {
261
405
              if (image->logging)
262
405
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
263
405
                                      "  RLE Escape code encountered");
264
405
              goto rle_decode_done;
265
405
            }
266
79.4k
          switch (count)
267
79.4k
            {
268
32.8k
            case 0x00:
269
32.8k
              {
270
                /*
271
                  End of line.
272
                */
273
32.8k
                x=0;
274
32.8k
                y++;
275
32.8k
                q=pixels+(size_t) y*image->columns;
276
32.8k
                break;
277
0
              }
278
1.44k
            case 0x02:
279
1.44k
              {
280
                /*
281
                  Delta mode.
282
                */
283
1.44k
                byte=ReadBlobByte(image);
284
1.44k
                if (byte == EOF)
285
5
                  return MagickFail;
286
1.44k
                x+=byte;
287
1.44k
                byte=ReadBlobByte(image);
288
1.44k
                if (byte == EOF)
289
16
                  return MagickFail;
290
1.42k
                y+=byte;
291
1.42k
                q=pixels+y*(size_t) image->columns+x;
292
1.42k
                break;
293
1.44k
              }
294
45.1k
            default:
295
45.1k
              {
296
                /*
297
                  Absolute mode.
298
                */
299
45.1k
                count=Min(count, end - q);
300
45.1k
                if (count < 0)
301
0
                  return MagickFail;
302
45.1k
                if (compression == BI_RLE8)
303
5.09M
                  for (i=count; i != 0; --i)
304
5.04M
                    {
305
5.04M
                      byte=ReadBlobByte(image);
306
5.04M
                      if (byte == EOF)
307
156
                        return MagickFail;
308
5.04M
                      *q++=byte;
309
5.04M
                    }
310
2.55k
                else
311
35.5k
                  for (i=0; i < (unsigned int) count; i++)
312
33.0k
                    {
313
33.0k
                      if ((i & 0x01) == 0)
314
17.1k
                        {
315
17.1k
                          byte=ReadBlobByte(image);
316
17.1k
                          if (byte == EOF)
317
66
                            return MagickFail;
318
17.1k
                        }
319
32.9k
                      *q++=(unsigned char)
320
32.9k
                        ((i & 0x01) ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
321
32.9k
                    }
322
44.9k
                x+=count;
323
                /*
324
                  Read pad byte.
325
                */
326
44.9k
                if (compression == BI_RLE8)
327
42.4k
                  {
328
42.4k
                    if (count & 0x01)
329
36.5k
                      if (ReadBlobByte(image) == EOF)
330
12
                        return MagickFail;
331
42.4k
                  }
332
2.48k
                else
333
2.48k
                  if (((count & 0x03) == 1) || ((count & 0x03) == 2))
334
1.67k
                    if (ReadBlobByte(image) == EOF)
335
34
                      return MagickFail;
336
44.9k
                break;
337
44.9k
              }
338
79.4k
            }
339
79.4k
        }
340
1.21M
      if (QuantumTick(y,image->rows))
341
115k
        if (!MagickMonitorFormatted(y,image->rows,&image->exception,
342
115k
                                    LoadImageText,image->filename,
343
115k
                                    image->columns,image->rows))
344
0
          break;
345
1.21M
    }
346
7.69k
  (void) ReadBlobByte(image);  /* end of line */
347
7.69k
  (void) ReadBlobByte(image);
348
8.10k
 rle_decode_done:
349
8.10k
  if (image->logging)
350
8.10k
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
351
8.10k
                          "  Decoded %" MAGICK_SIZE_T_F "u bytes",
352
8.10k
                          (MAGICK_SIZE_T) (q-pixels));
353
8.10k
  if ((MAGICK_SIZE_T) (q-pixels) < pixels_size)
354
405
    {
355
405
      if (image->logging)
356
405
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
357
405
                              "  RLE decoded output is truncated");
358
405
      return MagickFail;
359
405
    }
360
7.69k
  return(MagickPass);
361
8.10k
}
362

363
/*
364
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
365
%                                                                             %
366
%                                                                             %
367
%                                                                             %
368
%   E n c o d e I m a g e                                                     %
369
%                                                                             %
370
%                                                                             %
371
%                                                                             %
372
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
373
%
374
%  Method EncodeImage compresses pixels using a runlength encoded format.
375
%
376
%  The format of the EncodeImage method is:
377
%
378
%    static unsigned int EncodeImage(Image *image,
379
%      const unsigned long bytes_per_line,const unsigned char *pixels,
380
%      unsigned char *compressed_pixels)
381
%
382
%  A description of each parameter follows:
383
%
384
%    o status:  Method EncodeImage returns the number of bytes in the
385
%      runlength encoded compress_pixels array.
386
%
387
%    o image:  A pointer to an Image structure.
388
%
389
%    o bytes_per_line: The number of bytes in a scanline of compressed pixels
390
%
391
%    o pixels:  The address of a byte (8 bits) array of pixel data created by
392
%      the compression process.
393
%
394
%    o compressed_pixels:  The address of a byte (8 bits) array of compressed
395
%      pixel data.
396
%
397
%
398
*/
399
static size_t EncodeImage(Image *image,const size_t bytes_per_line,
400
  const unsigned char *pixels,unsigned char *compressed_pixels)
401
260
{
402
260
  unsigned long
403
260
    y;
404
405
260
  register const unsigned char
406
260
    *p;
407
408
260
  register unsigned long
409
260
    i,
410
260
    x;
411
412
260
  register unsigned char
413
260
    *q;
414
415
  /*
416
    Runlength encode pixels.
417
  */
418
260
  assert(image != (Image *) NULL);
419
260
  assert(pixels != (const unsigned char *) NULL);
420
260
  assert(compressed_pixels != (unsigned char *) NULL);
421
260
  p=pixels;
422
260
  q=compressed_pixels;
423
260
  i=0;
424
75.9k
  for (y=0; y < image->rows; y++)
425
75.7k
  {
426
35.4M
    for (x=0; x < bytes_per_line; x+=i)
427
35.4M
    {
428
      /*
429
        Determine runlength.
430
      */
431
103M
      for (i=1; (((size_t) x+i) < bytes_per_line); i++)
432
103M
        if ((*(p+i) != *p) || (i == 255U))
433
35.3M
          break;
434
35.4M
      *q++=(unsigned char) i;
435
35.4M
      *q++=(*p);
436
35.4M
      p+=i;
437
35.4M
    }
438
    /*
439
      End of line.
440
    */
441
75.7k
    *q++=0x00;
442
75.7k
    *q++=0x00;
443
75.7k
    if (QuantumTick(y,image->rows))
444
19.8k
      if (!MagickMonitorFormatted(y,image->rows,&image->exception,
445
19.8k
                                  SaveImageText,image->filename,
446
19.8k
                                  image->columns,image->rows))
447
0
        break;
448
75.7k
  }
449
  /*
450
    End of bitmap.
451
  */
452
260
  *q++=0;
453
260
  *q++=0x01;
454
260
  return((size_t) (q-compressed_pixels));
455
260
}
456

457
/*
458
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
459
%                                                                             %
460
%                                                                             %
461
%                                                                             %
462
%   I s D I B                                                                 %
463
%                                                                             %
464
%                                                                             %
465
%                                                                             %
466
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
467
%
468
%  Method IsDIB returns True if the image format type, identified by the
469
%  magick string, is DIB.
470
%
471
%  The format of the IsDIB method is:
472
%
473
%      unsigned int IsDIB(const unsigned char *magick,const size_t length)
474
%
475
%  A description of each parameter follows:
476
%
477
%    o status:  Method IsDIB returns True if the image format type is DIB.
478
%
479
%    o magick: This string is generally the first few bytes of an image file
480
%      or blob.
481
%
482
%    o length: Specifies the length of the magick string.
483
%
484
%
485
*/
486
static unsigned int IsDIB(const unsigned char *magick,const size_t length)
487
0
{
488
0
  if (length < 2)
489
0
    return(False);
490
0
  if( (*magick == 40) && (*(magick+1)==0))
491
0
    return(True);
492
0
  return(False);
493
0
}
494

495
/*
496
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
497
%                                                                             %
498
%                                                                             %
499
%                                                                             %
500
%   R e a d D I B I m a g e                                                   %
501
%                                                                             %
502
%                                                                             %
503
%                                                                             %
504
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
505
%
506
%  Method ReadDIBImage reads a Microsoft Windows bitmap image file and
507
%  returns it.  It allocates the memory necessary for the new Image structure
508
%  and returns a pointer to the new image.
509
%
510
%  The format of the ReadDIBImage method is:
511
%
512
%      image=ReadDIBImage(image_info)
513
%
514
%  A description of each parameter follows:
515
%
516
%    o image:  Method ReadDIBImage returns a pointer to the image after
517
%      reading.  A null image is returned if there is a memory shortage or
518
%      if the image cannot be read.
519
%
520
%    o image_info: Specifies a pointer to a ImageInfo structure.
521
%
522
%    o exception: return any errors or warnings in this structure.
523
%
524
%
525
*/
526
static Image *ReadDIBImage(const ImageInfo *image_info,ExceptionInfo *exception)
527
102k
{
528
102k
  DIBInfo
529
102k
    dib_info;
530
531
102k
  Image
532
102k
    *image;
533
534
102k
  IndexPacket
535
102k
    index;
536
537
102k
  long
538
102k
    bit,
539
102k
    y;
540
541
102k
  register IndexPacket
542
102k
    *indexes;
543
544
102k
  register long
545
102k
    x;
546
547
102k
  register PixelPacket
548
102k
    *q;
549
550
102k
  register long
551
102k
    i;
552
553
102k
  register unsigned char
554
102k
    *p;
555
556
102k
  TimerInfo
557
102k
    timer;
558
559
102k
  size_t
560
102k
    count,
561
102k
    length;
562
563
102k
  unsigned char
564
102k
    *pixels;
565
566
102k
  unsigned int
567
102k
    status;
568
569
102k
  size_t
570
102k
    bytes_per_line,
571
102k
    packet_size,
572
102k
    pixels_size;
573
574
102k
  magick_off_t
575
102k
    file_size;
576
577
  /*
578
    Open image file.
579
  */
580
102k
  assert(image_info != (const ImageInfo *) NULL);
581
102k
  assert(image_info->signature == MagickSignature);
582
102k
  assert(exception != (ExceptionInfo *) NULL);
583
102k
  assert(exception->signature == MagickSignature);
584
102k
  GetTimerInfo(&timer);
585
102k
  image=AllocateImage(image_info);
586
102k
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
587
102k
  if (status == False)
588
102k
    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
589
102k
  file_size=GetBlobSize(image);
590
  /*
591
    Determine if this is a DIB file.
592
  */
593
102k
  (void) memset(&dib_info,0,sizeof(DIBInfo));
594
102k
  dib_info.header_size=ReadBlobLSBLong(image);
595
102k
  if (dib_info.header_size!=40)
596
97.6k
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
597
  /*
598
    Microsoft Windows 3.X DIB image file.
599
  */
600
601
  /*
602
    BMP v3 defines width and height as signed LONG (32 bit) values.  If
603
    height is a positive number, then the image is a "bottom-up"
604
    bitmap with origin in the lower-left corner.  If height is a
605
    negative number, then the image is a "top-down" bitmap with the
606
    origin in the upper-left corner.  The meaning of negative values
607
    is not defined for width.
608
  */
609
97.6k
  dib_info.width=ReadBlobLSBSignedLong(image);
610
97.6k
  dib_info.height=ReadBlobLSBSignedLong(image);
611
97.6k
  dib_info.planes=ReadBlobLSBShort(image);
612
97.6k
  dib_info.bits_per_pixel=ReadBlobLSBShort(image);
613
97.6k
  dib_info.compression=ReadBlobLSBLong(image);
614
97.6k
  dib_info.image_size=ReadBlobLSBLong(image);
615
97.6k
  dib_info.x_pixels=ReadBlobLSBLong(image);
616
97.6k
  dib_info.y_pixels=ReadBlobLSBLong(image);
617
97.6k
  dib_info.number_colors=ReadBlobLSBLong(image);
618
97.6k
  dib_info.colors_important=ReadBlobLSBLong(image);
619
97.6k
  if (EOFBlob(image))
620
91.6k
    ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
621
91.6k
  LogDIBInfo(&dib_info);
622
91.6k
  if (dib_info.planes != 1)
623
83.3k
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
624
83.3k
  if ((dib_info.bits_per_pixel != 1) &&
625
58.9k
      (dib_info.bits_per_pixel != 4) &&
626
51.2k
      (dib_info.bits_per_pixel != 8) &&
627
40.3k
      (dib_info.bits_per_pixel != 16) &&
628
35.9k
      (dib_info.bits_per_pixel != 24) &&
629
30.7k
      (dib_info.bits_per_pixel != 32))
630
80.4k
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
631
80.4k
  if ((dib_info.compression == 3) && ((dib_info.bits_per_pixel == 16) ||
632
1.06k
      (dib_info.bits_per_pixel == 32)))
633
1.84k
    {
634
1.84k
      dib_info.red_mask=ReadBlobLSBShort(image);
635
1.84k
      dib_info.green_mask=ReadBlobLSBShort(image);
636
1.84k
      dib_info.blue_mask=ReadBlobLSBShort(image);
637
1.84k
    }
638
80.4k
  if (EOFBlob(image))
639
79.7k
    ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
640
79.7k
  if (dib_info.width <= 0)
641
78.0k
      ThrowReaderException(CorruptImageError,NegativeOrZeroImageSize,image);
642
78.0k
  if (dib_info.height == 0)
643
74.9k
      ThrowReaderException(CorruptImageError,NegativeOrZeroImageSize,image);
644
74.9k
  if (dib_info.height < -2147483647)
645
74.3k
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
646
74.3k
  image->matte=dib_info.bits_per_pixel == 32;
647
74.3k
  image->columns=AbsoluteValue(dib_info.width);
648
74.3k
  image->rows=AbsoluteValue(dib_info.height);
649
74.3k
  image->depth=8;
650
74.3k
  if (dib_info.number_colors > 256)
651
58.5k
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
652
58.5k
  if (dib_info.colors_important > 256)
653
47.9k
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
654
47.9k
  if ((dib_info.number_colors != 0) && (dib_info.bits_per_pixel > 8))
655
43.0k
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
656
43.0k
  if ((dib_info.image_size != 0U) && (dib_info.image_size > file_size))
657
34.9k
    ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
658
34.9k
  if ((dib_info.number_colors != 0) || (dib_info.bits_per_pixel <= 8))
659
24.4k
    {
660
24.4k
      image->storage_class=PseudoClass;
661
24.4k
      image->colors=dib_info.number_colors;
662
24.4k
      if (image->colors == 0)
663
9.02k
        image->colors=1L << dib_info.bits_per_pixel;
664
24.4k
    }
665
34.9k
  if (image_info->size)
666
1.35k
    {
667
1.35k
      int
668
1.35k
        flags;
669
670
1.35k
      RectangleInfo
671
1.35k
        geometry;
672
673
1.35k
      flags=GetGeometry(image_info->size,&geometry.x,&geometry.y,
674
1.35k
        &geometry.width,&geometry.height);
675
1.35k
      if ((flags & WidthValue) && (geometry.width != 0)
676
1.35k
          && (geometry.width < image->columns))
677
1.00k
        image->columns=geometry.width;
678
1.35k
      if ((flags & HeightValue) && (geometry.height != 0)
679
1.35k
          && (geometry.height < image->rows))
680
1.26k
        image->rows=geometry.height;
681
1.35k
    }
682
683
34.9k
   if (CheckImagePixelLimits(image, exception) != MagickPass)
684
22.8k
    ThrowReaderException(ResourceLimitError,ImagePixelLimitExceeded,image);
685
686
12.0k
  if (image->storage_class == PseudoClass)
687
10.6k
    {
688
10.6k
      unsigned char
689
10.6k
        *dib_colormap;
690
691
10.6k
      size_t
692
10.6k
        packet_size;
693
694
      /*
695
        Read DIB raster colormap.
696
      */
697
10.6k
      if (!AllocateImageColormap(image,image->colors))
698
10.6k
        ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
699
10.6k
      dib_colormap=MagickAllocateResourceLimitedArray(unsigned char *,image->colors,4);
700
10.6k
      if (dib_colormap == (unsigned char *) NULL)
701
10.6k
        ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
702
10.6k
      packet_size=4;
703
10.6k
      if ((count=ReadBlob(image,packet_size*image->colors,(char *) dib_colormap))
704
10.6k
          != packet_size*image->colors)
705
993
        {
706
993
          if (image->logging)
707
993
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
708
993
                                  "Read %" MAGICK_SIZE_T_F  "u bytes from blob"
709
993
                                  " (expected %" MAGICK_SIZE_T_F  "u bytes)",
710
993
                                  (MAGICK_SIZE_T) count,
711
993
                                  (MAGICK_SIZE_T) packet_size*image->colors);
712
993
          MagickFreeResourceLimitedMemory(dib_colormap);
713
993
          ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
714
0
        }
715
9.67k
      p=dib_colormap;
716
59.1k
      for (i=0; i < (long) image->colors; i++)
717
49.4k
      {
718
49.4k
        image->colormap[i].blue=ScaleCharToQuantum(*p++);
719
49.4k
        image->colormap[i].green=ScaleCharToQuantum(*p++);
720
49.4k
        image->colormap[i].red=ScaleCharToQuantum(*p++);
721
49.4k
        if (packet_size == 4)
722
49.4k
          p++;
723
49.4k
      }
724
9.67k
      MagickFreeResourceLimitedMemory(dib_colormap);
725
9.67k
    }
726
  /*
727
    Read image data.
728
  */
729
11.0k
  packet_size=dib_info.bits_per_pixel;
730
11.0k
  if (dib_info.compression == 2)
731
968
    packet_size<<=1;
732
733
  /*
734
     Below emulates:
735
     bytes_per_line=4*((image->columns*dib_info.packet_size+31)/32);
736
  */
737
11.0k
  bytes_per_line=MagickArraySize(image->columns,packet_size);
738
11.0k
  if ((bytes_per_line > 0) && (~((size_t) 0) - bytes_per_line) > 31)
739
11.0k
    bytes_per_line = MagickArraySize(4,(bytes_per_line+31)/32);
740
11.0k
  if (bytes_per_line == 0)
741
11.0k
    ThrowReaderException(CoderError,ArithmeticOverflow,image);
742
11.0k
  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
743
11.0k
                        "%" MAGICK_SIZE_T_F "u bytes per line",
744
11.0k
                        (MAGICK_SIZE_T) bytes_per_line);
745
  /*
746
    Validate that file data size is suitable for claimed dimensions.
747
  */
748
11.0k
  {
749
11.0k
    size_t
750
11.0k
      maximum_image_size;
751
752
11.0k
    maximum_image_size=MagickArraySize(bytes_per_line,image->rows);
753
11.0k
    if ((maximum_image_size == 0) ||
754
11.0k
        (maximum_image_size >
755
11.0k
         ((size_t) file_size * ((dib_info.compression == 1 ? 256 :
756
11.0k
                                 dib_info.compression == 2 ? 8 : 1)))))
757
10.9k
      ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
758
10.9k
  }
759
760
  /*
761
    FIXME: Need to add support for compression=3 images.  Size
762
    calculations are wrong and there is no support for applying the
763
    masks.
764
  */
765
0
  length=MagickArraySize(bytes_per_line,image->rows);
766
10.9k
  if (length == 0)
767
10.9k
    ThrowReaderException(CoderError,ArithmeticOverflow,image);
768
10.9k
  if ((image->columns+1UL) < image->columns)
769
10.9k
    ThrowReaderException(CoderError,ArithmeticOverflow,image);
770
10.9k
  pixels_size=MagickArraySize(image->rows,Max(bytes_per_line,(size_t) image->columns+1));
771
10.9k
  if (pixels_size == 0)
772
10.9k
    ThrowReaderException(CoderError,ArithmeticOverflow,image);
773
10.9k
  pixels=MagickAllocateResourceLimitedMemory(unsigned char *,pixels_size);
774
10.9k
  if (pixels == (unsigned char *) NULL)
775
10.9k
    ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
776
10.9k
  if ((dib_info.compression == 0) || (dib_info.compression == 3))
777
1.58k
    {
778
1.58k
      if ((count=ReadBlob(image,length,(char *) pixels)) != length)
779
132
        {
780
132
          if (image->logging)
781
132
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
782
132
                                  "Read %" MAGICK_SIZE_T_F  "u bytes from blob"
783
132
                                  " (expected %" MAGICK_SIZE_T_F  "u bytes)",
784
132
                                  (MAGICK_SIZE_T) count,
785
132
                                  (MAGICK_SIZE_T) length);
786
132
          MagickFreeResourceLimitedMemory(pixels);
787
132
          ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
788
0
        }
789
1.58k
    }
790
9.37k
  else
791
9.37k
    {
792
      /*
793
        Convert run-length encoded raster pixels.
794
795
        DecodeImage() normally decompresses to rows*columns bytes of data.
796
      */
797
9.37k
      (void) memset(pixels,0,pixels_size);
798
9.37k
      status=DecodeImage(image,dib_info.compression,pixels,
799
9.37k
                         (size_t) image->rows*image->columns);
800
9.37k
      if (status == False)
801
1.67k
        {
802
1.67k
          MagickFreeResourceLimitedMemory(pixels);
803
1.67k
          ThrowReaderException(CorruptImageError,UnableToRunlengthDecodeImage,
804
1.67k
                               image);
805
0
        }
806
9.37k
    }
807
  /*
808
    Initialize image structure.
809
  */
810
9.14k
  image->units=PixelsPerCentimeterResolution;
811
9.14k
  image->x_resolution=dib_info.x_pixels/100.0;
812
9.14k
  image->y_resolution=dib_info.y_pixels/100.0;
813
  /*
814
    Convert DIB raster image to pixel packets.
815
  */
816
9.14k
  switch (dib_info.bits_per_pixel)
817
9.14k
  {
818
655
    case 1:
819
655
    {
820
      /*
821
        Convert bitmap scanline.
822
      */
823
101k
      for (y=(long) image->rows-1; y >= 0; y--)
824
101k
      {
825
101k
        p=pixels+((size_t) image->rows-y-1)*bytes_per_line;
826
101k
        q=SetImagePixels(image,0,y,image->columns,1);
827
101k
        if (q == (PixelPacket *) NULL)
828
0
          break;
829
101k
        indexes=AccessMutableIndexes(image);
830
13.1M
        for (x=0; x < ((long) image->columns-7); x+=8)
831
13.0M
        {
832
117M
          for (bit=0; bit < 8; bit++)
833
104M
          {
834
104M
            index=((*p) & (0x80 >> bit) ? 0x01 : 0x00);
835
104M
            VerifyColormapIndex(image,index);
836
104M
            indexes[x+bit]=index;
837
104M
            *q++=image->colormap[index];
838
104M
          }
839
13.0M
          p++;
840
13.0M
        }
841
101k
        if ((image->columns % 8) != 0)
842
54.7k
          {
843
179k
            for (bit=0; bit < (long) (image->columns % 8); bit++)
844
124k
            {
845
124k
              index=((*p) & (0x80 >> bit) ? 0x01 : 0x00);
846
124k
              VerifyColormapIndex(image,index);
847
124k
              indexes[x+bit]=index;
848
124k
              *q++=image->colormap[index];
849
124k
            }
850
54.7k
            p++;
851
54.7k
          }
852
101k
        if (!SyncImagePixels(image))
853
0
          break;
854
101k
        if (image->previous == (Image *) NULL)
855
101k
          if (QuantumTick(y,image->rows))
856
32.2k
            {
857
32.2k
              status=MagickMonitorFormatted((size_t) image->rows-y-1,image->rows,
858
32.2k
                                            exception,LoadImageText,
859
32.2k
                                            image->filename,
860
32.2k
                                            image->columns,image->rows);
861
32.2k
              if (status == False)
862
0
                break;
863
32.2k
            }
864
101k
      }
865
655
      break;
866
0
    }
867
3.38k
    case 4:
868
3.38k
    {
869
      /*
870
        Convert PseudoColor scanline.
871
      */
872
33.4k
      for (y=(long) image->rows-1; y >= 0; y--)
873
30.0k
      {
874
30.0k
        p=pixels+((size_t) image->rows-y-1)*bytes_per_line;
875
30.0k
        q=SetImagePixels(image,0,y,image->columns,1);
876
30.0k
        if (q == (PixelPacket *) NULL)
877
0
          break;
878
30.0k
        indexes=AccessMutableIndexes(image);
879
7.09M
        for (x=0; x < ((long) image->columns-1); x+=2)
880
7.06M
        {
881
7.06M
          index=(IndexPacket) ((*p >> 4) & 0xf);
882
7.06M
          VerifyColormapIndex(image,index);
883
7.06M
          indexes[x]=index;
884
7.06M
          *q++=image->colormap[index];
885
7.06M
          index=(IndexPacket) (*p & 0xf);
886
7.06M
          VerifyColormapIndex(image,index);
887
7.06M
          indexes[x+1]=index;
888
7.06M
          *q++=image->colormap[index];
889
7.06M
          p++;
890
7.06M
        }
891
30.0k
        if ((image->columns % 2) != 0)
892
25.8k
          {
893
25.8k
            index=(IndexPacket) ((*p >> 4) & 0xf);
894
25.8k
            VerifyColormapIndex(image,index);
895
25.8k
            indexes[x]=index;
896
25.8k
            *q++=image->colormap[index];
897
25.8k
            p++;
898
25.8k
          }
899
30.0k
        if (!SyncImagePixels(image))
900
0
          break;
901
30.0k
        if (image->previous == (Image *) NULL)
902
30.0k
          if (QuantumTick(y,image->rows))
903
14.2k
            {
904
14.2k
              status=MagickMonitorFormatted((size_t) image->rows-y-1,image->rows,
905
14.2k
                                            exception,LoadImageText,
906
14.2k
                                            image->filename,
907
14.2k
                                            image->columns,image->rows);
908
14.2k
              if (status == False)
909
0
                break;
910
14.2k
            }
911
30.0k
      }
912
3.38k
      break;
913
0
    }
914
4.32k
    case 8:
915
4.32k
    {
916
      /*
917
        Convert PseudoColor scanline.
918
      */
919
4.32k
      if ((dib_info.compression == 1) || (dib_info.compression == 2))
920
1.07k
        bytes_per_line=image->columns;
921
37.4k
      for (y=(long) image->rows-1; y >= 0; y--)
922
33.1k
      {
923
33.1k
        p=pixels+((size_t) image->rows-y-1)*bytes_per_line;
924
33.1k
        q=SetImagePixels(image,0,y,image->columns,1);
925
33.1k
        if (q == (PixelPacket *) NULL)
926
0
          break;
927
33.1k
        indexes=AccessMutableIndexes(image);
928
425k
        for (x=0; x < (long) image->columns; x++)
929
392k
        {
930
392k
          index=(IndexPacket) (*p);
931
392k
          VerifyColormapIndex(image,index);
932
392k
          indexes[x]=index;
933
392k
          *q=image->colormap[index];
934
392k
          p++;
935
392k
          q++;
936
392k
        }
937
33.1k
        if (!SyncImagePixels(image))
938
0
          break;
939
33.1k
        if (image->previous == (Image *) NULL)
940
33.1k
          if (QuantumTick(y,image->rows))
941
16.4k
            {
942
16.4k
              status=MagickMonitorFormatted((size_t) image->rows-y-1,image->rows,
943
16.4k
                                            exception,LoadImageText,
944
16.4k
                                            image->filename,
945
16.4k
                                            image->columns,image->rows);
946
16.4k
              if (status == False)
947
0
                break;
948
16.4k
            }
949
33.1k
      }
950
4.32k
      break;
951
0
    }
952
408
    case 16:
953
408
    {
954
408
      unsigned short
955
408
        word;
956
957
      /*
958
        Convert DirectColor (555 or 565) scanline.
959
      */
960
408
      image->storage_class=DirectClass;
961
408
      if (dib_info.compression == 1)
962
200
        bytes_per_line=(size_t) 2*image->columns;
963
40.1k
      for (y=(long) image->rows-1; y >= 0; y--)
964
39.7k
      {
965
39.7k
        p=pixels+((size_t) image->rows-y-1)*bytes_per_line;
966
39.7k
        q=SetImagePixels(image,0,y,image->columns,1);
967
39.7k
        if (q == (PixelPacket *) NULL)
968
0
          break;
969
1.05M
        for (x=0; x < (long) image->columns; x++)
970
1.01M
        {
971
1.01M
          word=(*p++);
972
1.01M
          word|=(*p++ << 8);
973
1.01M
          if (dib_info.red_mask == 0)
974
1.01M
            {
975
1.01M
              q->red=ScaleCharToQuantum(ScaleColor5to8((word >> 10) & 0x1f));
976
1.01M
              q->green=ScaleCharToQuantum(ScaleColor5to8((word >> 5) & 0x1f));
977
1.01M
              q->blue=ScaleCharToQuantum(ScaleColor5to8(word & 0x1f));
978
1.01M
            }
979
599
          else
980
599
            {
981
599
              q->red=ScaleCharToQuantum(ScaleColor5to8((word >> 11) & 0x1f));
982
599
              q->green=ScaleCharToQuantum(ScaleColor6to8((word >> 5) & 0x3f));
983
599
              q->blue=ScaleCharToQuantum(ScaleColor5to8(word & 0x1f));
984
599
            }
985
1.01M
          q++;
986
1.01M
        }
987
39.7k
        if (!SyncImagePixels(image))
988
0
          break;
989
39.7k
        if (image->previous == (Image *) NULL)
990
39.7k
          if (QuantumTick(y,image->rows))
991
15.6k
            {
992
15.6k
              status=MagickMonitorFormatted((size_t) image->rows-y-1,image->rows,
993
15.6k
                                            exception,LoadImageText,
994
15.6k
                                            image->filename,
995
15.6k
                                            image->columns,image->rows);
996
15.6k
              if (status == False)
997
0
                break;
998
15.6k
            }
999
39.7k
      }
1000
408
      break;
1001
0
    }
1002
197
    case 24:
1003
371
    case 32:
1004
371
    {
1005
      /*
1006
        Convert DirectColor scanline.
1007
      */
1008
39.2k
      for (y=(long) image->rows-1; y >= 0; y--)
1009
38.8k
      {
1010
38.8k
        p=pixels+((size_t) image->rows-y-1)*bytes_per_line;
1011
38.8k
        q=SetImagePixels(image,0,y,image->columns,1);
1012
38.8k
        if (q == (PixelPacket *) NULL)
1013
0
          break;
1014
2.89M
        for (x=0; x < (long) image->columns; x++)
1015
2.85M
        {
1016
2.85M
          q->blue=ScaleCharToQuantum(*p++);
1017
2.85M
          q->green=ScaleCharToQuantum(*p++);
1018
2.85M
          q->red=ScaleCharToQuantum(*p++);
1019
2.85M
          if (image->matte)
1020
2.76M
            q->opacity=ScaleCharToQuantum(*p++);
1021
2.85M
          q++;
1022
2.85M
        }
1023
38.8k
        if (!SyncImagePixels(image))
1024
0
          break;
1025
38.8k
        if (image->previous == (Image *) NULL)
1026
38.8k
          if (QuantumTick(y,image->rows))
1027
15.5k
            {
1028
15.5k
              status=MagickMonitorFormatted((size_t) image->rows-y-1,image->rows,
1029
15.5k
                                            exception,LoadImageText,
1030
15.5k
                                            image->filename,
1031
15.5k
                                            image->columns,image->rows);
1032
15.5k
              if (status == False)
1033
0
                break;
1034
15.5k
            }
1035
38.8k
      }
1036
371
      break;
1037
197
    }
1038
0
    default:
1039
0
      {
1040
0
        MagickFreeResourceLimitedMemory(pixels);
1041
0
        ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
1042
0
      }
1043
9.14k
  }
1044
9.14k
  MagickFreeResourceLimitedMemory(pixels);
1045
9.14k
  if (EOFBlob(image))
1046
958
    ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
1047
9.14k
                   image->filename);
1048
9.14k
  if (strcmp(image_info->magick,"ICODIB") == 0)
1049
842
    {
1050
      /*
1051
        Handle ICO mask.
1052
      */
1053
842
      char
1054
842
        byte;
1055
1056
842
      image->matte=MagickFalse;
1057
7.07k
      for (y=(long) image->rows-1; y >= 0; y--)
1058
7.02k
        {
1059
7.02k
          if (image->logging)
1060
7.02k
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1061
7.02k
                                  "y=%ld", y);
1062
7.02k
          q=GetImagePixels(image,0,y,image->columns,1);
1063
7.02k
          if (q == (PixelPacket *) NULL)
1064
0
            break;
1065
21.2k
          for (x=0; x < ((long) image->columns-7); x+=8)
1066
14.5k
            {
1067
14.5k
              byte=0;
1068
14.5k
              if (ReadBlob(image,sizeof(byte),&byte) != sizeof(byte))
1069
316
                break;
1070
128k
              for (bit=0; bit < 8; bit++)
1071
113k
                {
1072
113k
                  q[x+bit].opacity=(Quantum)
1073
113k
                    (byte & (0x80 >> bit) ? TransparentOpacity : OpaqueOpacity);
1074
113k
                  if (q[x+bit].opacity != OpaqueOpacity)
1075
70.1k
                    image->matte=MagickTrue;
1076
113k
                }
1077
14.2k
            }
1078
          /* Detect early loop termination above due to EOF */
1079
7.02k
          if (x < ((long) image->columns-7))
1080
316
            break;
1081
6.70k
          if ((image->columns % 8) != 0)
1082
5.56k
            {
1083
5.56k
              byte=0;
1084
5.56k
              if (ReadBlob(image,sizeof(byte),&byte) != sizeof(byte))
1085
481
                break;
1086
18.1k
              for (bit=0; bit < (long) (image->columns % 8); bit++)
1087
13.1k
                {
1088
13.1k
                  q[x+bit].opacity=(Quantum)
1089
13.1k
                    (byte & (0x80 >> bit) ? TransparentOpacity : OpaqueOpacity);
1090
13.1k
                  if (q[x+bit].opacity != OpaqueOpacity)
1091
4.20k
                    image->matte=MagickTrue;
1092
13.1k
                }
1093
5.08k
            }
1094
6.22k
          if (image->columns % 32)
1095
20.4k
            for (x=0; x < (long) ((32-(image->columns % 32))/8); x++)
1096
14.7k
              {
1097
14.7k
                byte=0;
1098
14.7k
                if (ReadBlob(image,sizeof(byte),&byte) != sizeof(byte))
1099
143
                  break;
1100
14.7k
              }
1101
6.22k
          if (!SyncImagePixels(image))
1102
0
            break;
1103
6.22k
          if (image->previous == (Image *) NULL)
1104
6.22k
            if (QuantumTick(y,image->rows))
1105
4.25k
              if (!MagickMonitorFormatted((size_t) image->rows-y-1,image->rows,&image->exception,
1106
4.25k
                                          LoadImageText,image->filename,
1107
4.25k
                                          image->columns,image->rows))
1108
0
                break;
1109
6.22k
        }
1110
      /*
1111
        If a PseudoClass image has a non-opaque opacity channel, then
1112
        we must mark it as DirectClass since there is no standard way
1113
        to store PseudoClass with an opacity channel.
1114
      */
1115
842
      if ((image->storage_class == PseudoClass) && (image->matte == MagickTrue))
1116
65
        image->storage_class=DirectClass;
1117
#if 0
1118
      /*
1119
        FIXME: SourceForge bug 557 provides an icon for which magick
1120
        is set to "ICODIB" by the 'icon' coder but there is no data
1121
        for the ICO mask.  Intentionally ignore EOF at this point
1122
        until this issue gets figured out.
1123
       */
1124
      if (EOFBlob(image))
1125
        ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
1126
                       image->filename);
1127
#endif
1128
842
    }
1129
9.14k
  if (dib_info.height < 0)
1130
8.12k
    {
1131
8.12k
      Image
1132
8.12k
        *flipped_image;
1133
      /*
1134
        Correct image orientation.
1135
      */
1136
8.12k
      flipped_image=FlipImage(image,exception);
1137
8.12k
      if (flipped_image == (Image *) NULL)
1138
0
        {
1139
0
          DestroyImageList(image);
1140
0
          return((Image *) NULL);
1141
0
        }
1142
8.12k
      DestroyBlob(flipped_image);
1143
8.12k
      flipped_image->blob=ReferenceBlob(image->blob);
1144
8.12k
      DestroyImage(image);
1145
8.12k
      image=flipped_image;
1146
8.12k
    }
1147
9.14k
  CloseBlob(image);
1148
9.14k
  StopTimer(&timer);
1149
9.14k
  image->timer=timer;
1150
9.14k
  return(image);
1151
9.14k
}
1152

1153
/*
1154
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1155
%                                                                             %
1156
%                                                                             %
1157
%                                                                             %
1158
%   R e g i s t e r D I B I m a g e                                           %
1159
%                                                                             %
1160
%                                                                             %
1161
%                                                                             %
1162
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1163
%
1164
%  Method RegisterDIBImage adds attributes for the DIB image format to
1165
%  the list of supported formats.  The attributes include the image format
1166
%  tag, a method to read and/or write the format, whether the format
1167
%  supports the saving of more than one frame to the same file or blob,
1168
%  whether the format supports native in-memory I/O, and a brief
1169
%  description of the format.
1170
%
1171
%  The format of the RegisterDIBImage method is:
1172
%
1173
%      RegisterDIBImage(void)
1174
%
1175
*/
1176
ModuleExport void RegisterDIBImage(void)
1177
8
{
1178
8
  MagickInfo
1179
8
    *entry;
1180
1181
8
  entry=SetMagickInfo("DIB");
1182
8
  entry->decoder=(DecoderHandler) ReadDIBImage;
1183
8
  entry->encoder=(EncoderHandler) WriteDIBImage;
1184
8
  entry->magick=(MagickHandler) IsDIB;
1185
8
  entry->adjoin=False;
1186
#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
1187
  entry->stealth=True; /* Don't list in '-list format' output */
1188
#endif /* if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) */
1189
8
  entry->description="Microsoft Windows 3.X Packed Device-Independent Bitmap";
1190
8
  entry->module="DIB";
1191
8
  (void) RegisterMagickInfo(entry);
1192
1193
8
  entry=SetMagickInfo("ICODIB");
1194
8
  entry->decoder=(DecoderHandler) ReadDIBImage;
1195
  /* entry->encoder=(EncoderHandler) WriteDIBImage; */
1196
8
  entry->magick=(MagickHandler) IsDIB;
1197
8
  entry->adjoin=False;
1198
8
  entry->stealth=True; /* Don't list in '-list format' output */
1199
8
  entry->raw=True; /* Requires size to work correctly. */
1200
8
  entry->description="Microsoft Windows 3.X Packed Device-Independent Bitmap + Mask";
1201
8
  entry->module="DIB";
1202
8
  (void) RegisterMagickInfo(entry);
1203
1204
8
}
1205

1206
/*
1207
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1208
%                                                                             %
1209
%                                                                             %
1210
%                                                                             %
1211
%   U n r e g i s t e r D I B I m a g e                                       %
1212
%                                                                             %
1213
%                                                                             %
1214
%                                                                             %
1215
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1216
%
1217
%  Method UnregisterDIBImage removes format registrations made by the
1218
%  DIB module from the list of supported formats.
1219
%
1220
%  The format of the UnregisterDIBImage method is:
1221
%
1222
%      UnregisterDIBImage(void)
1223
%
1224
*/
1225
ModuleExport void UnregisterDIBImage(void)
1226
0
{
1227
0
  (void) UnregisterMagickInfo("ICODIB");
1228
0
  (void) UnregisterMagickInfo("DIB");
1229
0
}
1230

1231
/*
1232
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1233
%                                                                             %
1234
%                                                                             %
1235
%                                                                             %
1236
%   W r i t e D I B I m a g e                                                 %
1237
%                                                                             %
1238
%                                                                             %
1239
%                                                                             %
1240
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1241
%
1242
%  Method WriteDIBImage writes an image in Microsoft Windows bitmap encoded
1243
%  image format.
1244
%
1245
%  The format of the WriteDIBImage method is:
1246
%
1247
%      unsigned int WriteDIBImage(const ImageInfo *image_info,Image *image)
1248
%
1249
%  A description of each parameter follows.
1250
%
1251
%    o status: Method WriteDIBImage return True if the image is written.
1252
%      False is returned is there is a memory shortage or if the image file
1253
%      fails to write.
1254
%
1255
%    o image_info: Specifies a pointer to a ImageInfo structure.
1256
%
1257
%    o image:  A pointer to an Image structure.
1258
%
1259
%
1260
*/
1261
static unsigned int WriteDIBImage(const ImageInfo *image_info,Image *image)
1262
411
{
1263
411
  DIBInfo
1264
411
    dib_info;
1265
1266
411
  unsigned long
1267
411
    y;
1268
1269
411
  register const PixelPacket
1270
411
    *p;
1271
1272
411
  register const IndexPacket
1273
411
    *indexes;
1274
1275
411
  register unsigned long
1276
411
    i,
1277
411
    x;
1278
1279
411
  register unsigned char
1280
411
    *q;
1281
1282
411
  unsigned char
1283
411
    *dib_data,
1284
411
    *pixels;
1285
1286
411
  unsigned int
1287
411
    status;
1288
1289
411
  size_t
1290
411
    bytes_per_line,
1291
411
    image_size;
1292
1293
411
  ImageCharacteristics
1294
411
    characteristics;
1295
1296
  /*
1297
    Open output image file.
1298
  */
1299
411
  assert(image_info != (const ImageInfo *) NULL);
1300
411
  assert(image_info->signature == MagickSignature);
1301
411
  assert(image != (Image *) NULL);
1302
411
  assert(image->signature == MagickSignature);
1303
411
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1304
411
  if (status == False)
1305
411
    ThrowWriterException(FileOpenError,UnableToOpenFile,image);
1306
  /*
1307
    Ensure that image is in an RGB space.
1308
  */
1309
411
  (void) TransformColorspace(image,RGBColorspace);
1310
  /*
1311
    Analyze image to be written.
1312
  */
1313
411
  if (!GetImageCharacteristics(image,&characteristics,
1314
411
                               (OptimizeType == image_info->type),
1315
411
                               &image->exception))
1316
0
    {
1317
0
      CloseBlob(image);
1318
0
      return MagickFail;
1319
0
    }
1320
  /*
1321
    Initialize DIB raster file header.
1322
  */
1323
411
  if (image->storage_class == DirectClass)
1324
86
    {
1325
      /*
1326
        Full color DIB raster.
1327
      */
1328
86
      dib_info.number_colors=0;
1329
86
      dib_info.bits_per_pixel=image->matte ? 32 : 24;
1330
86
    }
1331
325
  else
1332
325
    {
1333
      /*
1334
        Colormapped DIB raster.
1335
      */
1336
325
      dib_info.bits_per_pixel=8;
1337
325
      if (characteristics.monochrome)
1338
65
        dib_info.bits_per_pixel=1;
1339
325
      dib_info.number_colors=1 << dib_info.bits_per_pixel;
1340
325
    }
1341
  /*
1342
     Below emulates:
1343
     bytes_per_line=4*((image->columns*dib_info.bits_per_pixel+31)/32);
1344
  */
1345
411
  bytes_per_line=MagickArraySize(image->columns,dib_info.bits_per_pixel);
1346
411
  if ((bytes_per_line > 0) && (~((size_t) 0) - bytes_per_line) > 31)
1347
411
    bytes_per_line = MagickArraySize(4,(bytes_per_line+31)/32);
1348
411
  if (bytes_per_line == 0)
1349
411
    ThrowWriterException(CoderError,ArithmeticOverflow,image);
1350
411
  image_size=MagickArraySize(bytes_per_line,image->rows);
1351
411
  if ((image_size == 0) || ((image_size & 0xffffffff) != image_size))
1352
411
    ThrowWriterException(CoderError,ArithmeticOverflow,image);
1353
411
  dib_info.header_size=40;
1354
411
  dib_info.width=(long) image->columns;
1355
411
  dib_info.height=(long) image->rows;
1356
411
  dib_info.planes=1;
1357
411
  dib_info.compression=0;
1358
411
  dib_info.image_size=(magick_uint32_t) image_size;
1359
411
  dib_info.x_pixels=75*39;
1360
411
  dib_info.y_pixels=75*39;
1361
411
  if (image->units == PixelsPerInchResolution)
1362
0
    {
1363
0
      dib_info.x_pixels=(unsigned long) (100.0*image->x_resolution/2.54);
1364
0
      dib_info.y_pixels=(unsigned long) (100.0*image->y_resolution/2.54);
1365
0
    }
1366
411
  if (image->units == PixelsPerCentimeterResolution)
1367
411
    {
1368
411
      dib_info.x_pixels=(unsigned long) (100.0*image->x_resolution);
1369
411
      dib_info.y_pixels=(unsigned long) (100.0*image->y_resolution);
1370
411
    }
1371
411
  dib_info.colors_important=dib_info.number_colors;
1372
  /*
1373
    Convert MIFF to DIB raster pixels.
1374
  */
1375
411
  pixels=MagickAllocateResourceLimitedMemory(unsigned char *,dib_info.image_size);
1376
411
  if (pixels == (unsigned char *) NULL)
1377
411
    ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
1378
411
  switch (dib_info.bits_per_pixel)
1379
411
  {
1380
65
    case 1:
1381
65
    {
1382
65
      register unsigned char
1383
65
        bit,
1384
65
        byte;
1385
1386
      /*
1387
        Convert PseudoClass image to a DIB monochrome image.
1388
      */
1389
16.9k
      for (y=0; y < image->rows; y++)
1390
16.9k
      {
1391
16.9k
        p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
1392
16.9k
        if (p == (const PixelPacket *) NULL)
1393
0
          break;
1394
16.9k
        indexes=AccessImmutableIndexes(image);
1395
16.9k
        q=pixels+(image->rows-y-1)*bytes_per_line;
1396
16.9k
        bit=0;
1397
16.9k
        byte=0;
1398
8.35M
        for (x=0; x < image->columns; x++)
1399
8.33M
        {
1400
8.33M
          byte<<=1;
1401
8.33M
          byte|=indexes[x] ? 0x01 : 0x00;
1402
8.33M
          bit++;
1403
8.33M
          if (bit == 8)
1404
1.03M
            {
1405
1.03M
              *q++=byte;
1406
1.03M
              bit=0;
1407
1.03M
              byte=0;
1408
1.03M
            }
1409
8.33M
           p++;
1410
8.33M
         }
1411
16.9k
       if (bit != 0)
1412
15.7k
         *q++=byte << (8-bit);
1413
       /* initialize padding bytes */
1414
55.3k
       for (x=(image->columns+7)/8; x < bytes_per_line; x++)
1415
38.3k
         *q++=0x00;
1416
16.9k
       if (image->previous == (Image *) NULL)
1417
16.9k
         if (QuantumTick(y,image->rows))
1418
4.18k
           if (!MagickMonitorFormatted(y,image->rows,&image->exception,
1419
4.18k
                                       SaveImageText,image->filename,
1420
4.18k
                                       image->columns,image->rows))
1421
0
             break;
1422
16.9k
      }
1423
65
      break;
1424
0
    }
1425
260
    case 8:
1426
260
    {
1427
      /*
1428
        Convert PseudoClass packet to DIB pixel.
1429
      */
1430
75.9k
      for (y=0; y < image->rows; y++)
1431
75.7k
      {
1432
75.7k
        p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
1433
75.7k
        if (p == (const PixelPacket *) NULL)
1434
0
          break;
1435
75.7k
        indexes=AccessImmutableIndexes(image);
1436
75.7k
        q=pixels+(image->rows-y-1)*bytes_per_line;
1437
103M
        for (x=0; x < image->columns; x++)
1438
103M
        {
1439
103M
          *q++=indexes[x];
1440
103M
          p++;
1441
103M
        }
1442
       /* initialize padding bytes */
1443
157k
       for (; x < bytes_per_line; x++)
1444
82.2k
         *q++=0x00;
1445
75.7k
        if (image->previous == (Image *) NULL)
1446
75.7k
          if (QuantumTick(y,image->rows))
1447
19.8k
            if (!MagickMonitorFormatted(y,image->rows,&image->exception,
1448
19.8k
                                        SaveImageText,image->filename,
1449
19.8k
                                        image->columns,image->rows))
1450
0
              break;
1451
75.7k
      }
1452
260
      break;
1453
0
    }
1454
66
    case 24:
1455
86
    case 32:
1456
86
    {
1457
      /*
1458
        Convert DirectClass packet to DIB RGB pixel.
1459
      */
1460
22.5k
      for (y=0; y < image->rows; y++)
1461
22.4k
      {
1462
22.4k
        p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
1463
22.4k
        if (p == (const PixelPacket *) NULL)
1464
0
          break;
1465
22.4k
        q=pixels+(image->rows-y-1)*bytes_per_line;
1466
3.50M
        for (x=0; x < image->columns; x++)
1467
3.48M
        {
1468
3.48M
          *q++=ScaleQuantumToChar(p->blue);
1469
3.48M
          *q++=ScaleQuantumToChar(p->green);
1470
3.48M
          *q++=ScaleQuantumToChar(p->red);
1471
3.48M
          if (image->matte)
1472
2.63M
            *q++=ScaleQuantumToChar(p->opacity);
1473
3.48M
          p++;
1474
3.48M
        }
1475
        /* initialize padding bytes */
1476
22.4k
        if (dib_info.bits_per_pixel == 24)
1477
19.7k
          {
1478
            /* initialize padding bytes */
1479
40.3k
            for (x=3*image->columns; x < bytes_per_line; x++)
1480
20.5k
              *q++=0x00;
1481
19.7k
          }
1482
22.4k
        if (image->previous == (Image *) NULL)
1483
22.4k
          if (QuantumTick(y,image->rows))
1484
4.67k
            if (!MagickMonitorFormatted(y,image->rows,&image->exception,
1485
4.67k
                                        SaveImageText,image->filename,
1486
4.67k
                                        image->columns,image->rows))
1487
0
               break;
1488
22.4k
      }
1489
86
      break;
1490
66
    }
1491
411
  }
1492
411
  if (dib_info.bits_per_pixel == 8)
1493
260
    if (image_info->compression != NoCompression)
1494
260
      {
1495
260
        size_t
1496
260
          length;
1497
1498
        /*
1499
          Convert run-length encoded raster pixels.
1500
        */
1501
260
        length=2*((size_t) bytes_per_line+2)*((size_t) image->rows+2)+2;
1502
260
        dib_data=MagickAllocateResourceLimitedMemory(unsigned char *,length);
1503
260
        if (dib_data == (unsigned char *) NULL)
1504
0
          {
1505
0
            MagickFreeResourceLimitedMemory(pixels);
1506
0
            ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,
1507
0
                                 image);
1508
0
          }
1509
260
        dib_info.image_size=(unsigned long)
1510
260
          EncodeImage(image,bytes_per_line,pixels,dib_data);
1511
260
        MagickFreeResourceLimitedMemory(pixels);
1512
260
        pixels=dib_data;
1513
260
        dib_info.compression=1;
1514
260
      }
1515
  /*
1516
    Write DIB header.
1517
  */
1518
411
  (void) WriteBlobLSBLong(image,dib_info.header_size);
1519
411
  (void) WriteBlobLSBLong(image,dib_info.width);
1520
411
  (void) WriteBlobLSBLong(image,dib_info.height);
1521
411
  (void) WriteBlobLSBShort(image,dib_info.planes);
1522
411
  (void) WriteBlobLSBShort(image,dib_info.bits_per_pixel);
1523
411
  (void) WriteBlobLSBLong(image,dib_info.compression);
1524
411
  (void) WriteBlobLSBLong(image,dib_info.image_size);
1525
411
  (void) WriteBlobLSBLong(image,dib_info.x_pixels);
1526
411
  (void) WriteBlobLSBLong(image,dib_info.y_pixels);
1527
411
  (void) WriteBlobLSBLong(image,dib_info.number_colors);
1528
411
  (void) WriteBlobLSBLong(image,dib_info.colors_important);
1529
411
  if (image->storage_class == PseudoClass)
1530
325
    {
1531
325
      unsigned char
1532
325
        *dib_colormap;
1533
1534
      /*
1535
        Dump colormap to file.
1536
      */
1537
325
      dib_colormap=MagickAllocateResourceLimitedArray(unsigned char *,
1538
325
                                                      (((size_t) 1U) << dib_info.bits_per_pixel),4);
1539
325
      if (dib_colormap == (unsigned char *) NULL)
1540
0
        {
1541
0
          MagickFreeResourceLimitedMemory(pixels);
1542
0
          ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
1543
0
        }
1544
325
      q=dib_colormap;
1545
5.78k
      for (i=0; i < Min(image->colors,dib_info.number_colors); i++)
1546
5.45k
      {
1547
5.45k
        *q++=ScaleQuantumToChar(image->colormap[i].blue);
1548
5.45k
        *q++=ScaleQuantumToChar(image->colormap[i].green);
1549
5.45k
        *q++=ScaleQuantumToChar(image->colormap[i].red);
1550
5.45k
        *q++=(Quantum) 0x0;
1551
5.45k
      }
1552
61.5k
      for ( ; i < (1U << dib_info.bits_per_pixel); i++)
1553
61.2k
      {
1554
61.2k
        *q++=(Quantum) 0x0;
1555
61.2k
        *q++=(Quantum) 0x0;
1556
61.2k
        *q++=(Quantum) 0x0;
1557
61.2k
        *q++=(Quantum) 0x0;
1558
61.2k
      }
1559
325
      (void) WriteBlob(image, 4*(((size_t) 1U) << dib_info.bits_per_pixel),
1560
325
        (char *) dib_colormap);
1561
325
      MagickFreeResourceLimitedMemory(dib_colormap);
1562
325
    }
1563
411
  (void) WriteBlob(image,dib_info.image_size,(char *) pixels);
1564
411
  MagickFreeResourceLimitedMemory(pixels);
1565
411
  status &= CloseBlob(image);
1566
411
  return(status);
1567
411
}