Coverage Report

Created: 2026-09-14 07:37

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