Coverage Report

Created: 2026-09-06 07:31

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.99M
#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
104k
{
104
  /*
105
    Dump 40-byte version 3+ bitmap header.
106
    BMP version 4 has same members, but is 108 bytes.
107
  */
108
104k
  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
109
104k
                        "DIB Header:\n"
110
104k
                        "    Header Size:          %u\n"
111
104k
                        "    Width:                %d\n"
112
104k
                        "    Height:               %d\n"
113
104k
                        "    Planes:               %u\n"
114
104k
                        "    Bits Per Pixel:       %u\n"
115
104k
                        "    Compression:          %u\n"
116
104k
                        "    Size Of Bitmap:       %u\n"
117
104k
                        "    Horizontal Resolution:%u\n"
118
104k
                        "    Vertical Resolution:  %u\n"
119
104k
                        "    Colors Used:          %u\n"
120
104k
                        "    Colors Important:     %u",
121
104k
                        (unsigned int) dib_info->header_size,
122
104k
                        (signed int) dib_info->width,
123
104k
                        (signed int) dib_info->height,
124
104k
                        (unsigned int) dib_info->planes,
125
104k
                        (unsigned int) dib_info->bits_per_pixel,
126
104k
                        (unsigned int) dib_info->compression,
127
104k
                        (unsigned int) dib_info->image_size,
128
104k
                        (unsigned int) dib_info->x_pixels,
129
104k
                        (unsigned int) dib_info->y_pixels,
130
104k
                        (unsigned int) dib_info->number_colors,
131
104k
                        (unsigned int) dib_info->colors_important
132
104k
                        );
133
104k
}
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.3k
{
173
11.3k
  unsigned long
174
11.3k
    x,
175
11.3k
    y;
176
177
11.3k
  unsigned int
178
11.3k
    i;
179
180
11.3k
  int
181
11.3k
    byte,
182
11.3k
    count;
183
184
11.3k
  register unsigned char
185
11.3k
    *q;
186
187
11.3k
  unsigned char
188
11.3k
    *end;
189
190
11.3k
  assert(image != (Image *) NULL);
191
11.3k
  assert(pixels != (unsigned char *) NULL);
192
11.3k
  if (image->logging)
193
11.3k
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
194
11.3k
                          "  Decoding RLE compressed pixels to"
195
11.3k
                          " %" MAGICK_SIZE_T_F "u bytes",
196
11.3k
                          (MAGICK_SIZE_T) image->rows*(size_t)image->columns);
197
198
11.3k
  byte=0;
199
11.3k
  x=0;
200
11.3k
  q=pixels;
201
11.3k
  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.98M
  for (y=0; y < image->rows; )
211
1.97M
    {
212
1.97M
      if (q < pixels || q >= end)
213
5.28k
        {
214
5.28k
          if (image->logging)
215
5.28k
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
216
5.28k
                                  "  Decode buffer full (y=%lu, "
217
5.28k
                                  "pixels_size=%" MAGICK_SIZE_T_F "u, "
218
5.28k
                                  "pixels=%p, q=%p, end=%p)",
219
5.28k
                                  y, (MAGICK_SIZE_T) pixels_size,
220
5.28k
                                  pixels, q, end);
221
5.28k
          break;
222
5.28k
        }
223
1.97M
      count=ReadBlobByte(image);
224
1.97M
      if (count == EOF)
225
399
        return MagickFail;
226
1.97M
      if (count > 0)
227
1.85M
        {
228
1.85M
          count=Min(count, end - q);
229
          /*
230
            Encoded mode.
231
          */
232
1.85M
          byte=ReadBlobByte(image);
233
1.85M
          if (byte == EOF)
234
772
            return MagickFail;
235
1.85M
          if (compression == BI_RLE8)
236
1.84M
            {
237
266M
              for ( i=count; i != 0; --i )
238
264M
                {
239
264M
                  *q++=(unsigned char) byte;
240
264M
                }
241
1.84M
            }
242
10.0k
          else
243
10.0k
            {
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
10.0k
            }
250
1.85M
          x+=count;
251
1.85M
        }
252
115k
      else
253
115k
        {
254
          /*
255
            Escape mode.
256
          */
257
115k
          count=ReadBlobByte(image);
258
115k
          if (count == EOF)
259
115
            return MagickFail;
260
115k
          if (count == 0x01)
261
434
            {
262
434
              if (image->logging)
263
434
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
264
434
                                      "  RLE Escape code encountered");
265
434
              goto rle_decode_done;
266
434
            }
267
114k
          switch (count)
268
114k
            {
269
42.6k
            case 0x00:
270
42.6k
              {
271
                /*
272
                  End of line.
273
                */
274
42.6k
                x=0;
275
42.6k
                y++;
276
42.6k
                q=pixels+(size_t) y*image->columns;
277
42.6k
                break;
278
0
              }
279
1.50k
            case 0x02:
280
1.50k
              {
281
                /*
282
                  Delta mode.
283
                */
284
1.50k
                byte=ReadBlobByte(image);
285
1.50k
                if (byte == EOF)
286
5
                  return MagickFail;
287
1.49k
                x+=byte;
288
1.49k
                byte=ReadBlobByte(image);
289
1.49k
                if (byte == EOF)
290
15
                  return MagickFail;
291
1.48k
                y+=byte;
292
1.48k
                q=pixels+y*(size_t) image->columns+x;
293
1.48k
                break;
294
1.49k
              }
295
70.6k
            default:
296
70.6k
              {
297
                /*
298
                  Absolute mode.
299
                */
300
70.6k
                count=Min(count, end - q);
301
70.6k
                if (count < 0)
302
0
                  return MagickFail;
303
70.6k
                if (compression == BI_RLE8)
304
8.18M
                  for (i=count; i != 0; --i)
305
8.12M
                    {
306
8.12M
                      byte=ReadBlobByte(image);
307
8.12M
                      if (byte == EOF)
308
206
                        return MagickFail;
309
8.11M
                      *q++=byte;
310
8.11M
                    }
311
3.41k
                else
312
62.7k
                  for (i=0; i < (unsigned int) count; i++)
313
59.4k
                    {
314
59.4k
                      if ((i & 0x01) == 0)
315
30.3k
                        {
316
30.3k
                          byte=ReadBlobByte(image);
317
30.3k
                          if (byte == EOF)
318
84
                            return MagickFail;
319
30.3k
                        }
320
59.3k
                      *q++=(unsigned char)
321
59.3k
                        ((i & 0x01) ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
322
59.3k
                    }
323
70.3k
                x+=count;
324
                /*
325
                  Read pad byte.
326
                */
327
70.3k
                if (compression == BI_RLE8)
328
67.0k
                  {
329
67.0k
                    if (count & 0x01)
330
58.4k
                      if (ReadBlobByte(image) == EOF)
331
13
                        return MagickFail;
332
67.0k
                  }
333
3.33k
                else
334
3.33k
                  if (((count & 0x03) == 1) || ((count & 0x03) == 2))
335
2.19k
                    if (ReadBlobByte(image) == EOF)
336
32
                      return MagickFail;
337
70.3k
                break;
338
70.3k
              }
339
114k
            }
340
114k
        }
341
1.97M
      if (QuantumTick(y,image->rows))
342
181k
        if (!MagickMonitorFormatted(y,image->rows,&image->exception,
343
181k
                                    LoadImageText,image->filename,
344
181k
                                    image->columns,image->rows))
345
0
          break;
346
1.97M
    }
347
9.27k
  (void) ReadBlobByte(image);  /* end of line */
348
9.27k
  (void) ReadBlobByte(image);
349
9.71k
 rle_decode_done:
350
9.71k
  if (image->logging)
351
9.71k
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
352
9.71k
                          "  Decoded %" MAGICK_SIZE_T_F "u bytes",
353
9.71k
                          (MAGICK_SIZE_T) (q-pixels));
354
9.71k
  if ((MAGICK_SIZE_T) (q-pixels) < pixels_size)
355
434
    {
356
434
      if (image->logging)
357
434
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
358
434
                              "  RLE decoded output is truncated");
359
434
      return MagickFail;
360
434
    }
361
9.27k
  return(MagickPass);
362
9.71k
}
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
336
{
403
336
  unsigned long
404
336
    y;
405
406
336
  register const unsigned char
407
336
    *p;
408
409
336
  register unsigned long
410
336
    i,
411
336
    x;
412
413
336
  register unsigned char
414
336
    *q;
415
416
  /*
417
    Runlength encode pixels.
418
  */
419
336
  assert(image != (Image *) NULL);
420
336
  assert(pixels != (const unsigned char *) NULL);
421
336
  assert(compressed_pixels != (unsigned char *) NULL);
422
336
  p=pixels;
423
336
  q=compressed_pixels;
424
336
  i=0;
425
77.6k
  for (y=0; y < image->rows; y++)
426
77.3k
  {
427
39.7M
    for (x=0; x < bytes_per_line; x+=i)
428
39.6M
    {
429
      /*
430
        Determine runlength.
431
      */
432
106M
      for (i=1; (((size_t) x+i) < bytes_per_line); i++)
433
106M
        if ((*(p+i) != *p) || (i == 255U))
434
39.5M
          break;
435
39.6M
      *q++=(unsigned char) i;
436
39.6M
      *q++=(*p);
437
39.6M
      p+=i;
438
39.6M
    }
439
    /*
440
      End of line.
441
    */
442
77.3k
    *q++=0x00;
443
77.3k
    *q++=0x00;
444
77.3k
    if (QuantumTick(y,image->rows))
445
22.6k
      if (!MagickMonitorFormatted(y,image->rows,&image->exception,
446
22.6k
                                  SaveImageText,image->filename,
447
22.6k
                                  image->columns,image->rows))
448
0
        break;
449
77.3k
  }
450
  /*
451
    End of bitmap.
452
  */
453
336
  *q++=0;
454
336
  *q++=0x01;
455
336
  return((size_t) (q-compressed_pixels));
456
336
}
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
117k
{
529
117k
  DIBInfo
530
117k
    dib_info;
531
532
117k
  Image
533
117k
    *image;
534
535
117k
  IndexPacket
536
117k
    index;
537
538
117k
  long
539
117k
    bit,
540
117k
    y;
541
542
117k
  register IndexPacket
543
117k
    *indexes;
544
545
117k
  register long
546
117k
    x;
547
548
117k
  register PixelPacket
549
117k
    *q;
550
551
117k
  register long
552
117k
    i;
553
554
117k
  register unsigned char
555
117k
    *p;
556
557
117k
  TimerInfo
558
117k
    timer;
559
560
117k
  size_t
561
117k
    count,
562
117k
    length;
563
564
117k
  unsigned char
565
117k
    *pixels;
566
567
117k
  unsigned int
568
117k
    status;
569
570
117k
  size_t
571
117k
    bytes_per_line,
572
117k
    packet_size,
573
117k
    pixels_size;
574
575
117k
  magick_off_t
576
117k
    file_size;
577
578
  /*
579
    Open image file.
580
  */
581
117k
  assert(image_info != (const ImageInfo *) NULL);
582
117k
  assert(image_info->signature == MagickSignature);
583
117k
  assert(exception != (ExceptionInfo *) NULL);
584
117k
  assert(exception->signature == MagickSignature);
585
117k
  GetTimerInfo(&timer);
586
117k
  image=AllocateImage(image_info);
587
117k
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
588
117k
  if (status == False)
589
117k
    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
590
117k
  file_size=GetBlobSize(image);
591
  /*
592
    Determine if this is a DIB file.
593
  */
594
117k
  (void) memset(&dib_info,0,sizeof(DIBInfo));
595
117k
  dib_info.header_size=ReadBlobLSBLong(image);
596
117k
  if (dib_info.header_size!=40)
597
111k
    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
111k
  dib_info.width=ReadBlobLSBSignedLong(image);
611
111k
  dib_info.height=ReadBlobLSBSignedLong(image);
612
111k
  dib_info.planes=ReadBlobLSBShort(image);
613
111k
  dib_info.bits_per_pixel=ReadBlobLSBShort(image);
614
111k
  dib_info.compression=ReadBlobLSBLong(image);
615
111k
  dib_info.image_size=ReadBlobLSBLong(image);
616
111k
  dib_info.x_pixels=ReadBlobLSBLong(image);
617
111k
  dib_info.y_pixels=ReadBlobLSBLong(image);
618
111k
  dib_info.number_colors=ReadBlobLSBLong(image);
619
111k
  dib_info.colors_important=ReadBlobLSBLong(image);
620
111k
  if (EOFBlob(image))
621
104k
    ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
622
104k
  LogDIBInfo(&dib_info);
623
104k
  if (dib_info.planes != 1)
624
95.6k
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
625
95.6k
  if ((dib_info.bits_per_pixel != 1) &&
626
64.8k
      (dib_info.bits_per_pixel != 4) &&
627
56.3k
      (dib_info.bits_per_pixel != 8) &&
628
43.7k
      (dib_info.bits_per_pixel != 16) &&
629
38.5k
      (dib_info.bits_per_pixel != 24) &&
630
32.8k
      (dib_info.bits_per_pixel != 32))
631
91.9k
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
632
91.9k
  if ((dib_info.compression == 3) && ((dib_info.bits_per_pixel == 16) ||
633
1.19k
      (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
91.9k
  if (EOFBlob(image))
640
91.2k
    ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
641
91.2k
  if (dib_info.width <= 0)
642
89.8k
      ThrowReaderException(CorruptImageError,NegativeOrZeroImageSize,image);
643
89.8k
  if (dib_info.height == 0)
644
87.6k
      ThrowReaderException(CorruptImageError,NegativeOrZeroImageSize,image);
645
87.6k
  if (dib_info.height < -2147483647)
646
86.6k
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
647
86.6k
  image->matte=dib_info.bits_per_pixel == 32;
648
86.6k
  image->columns=AbsoluteValue(dib_info.width);
649
86.6k
  image->rows=AbsoluteValue(dib_info.height);
650
86.6k
  image->depth=8;
651
86.6k
  if (dib_info.number_colors > 256)
652
68.2k
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
653
68.2k
  if (dib_info.colors_important > 256)
654
56.8k
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
655
56.8k
  if ((dib_info.number_colors != 0) && (dib_info.bits_per_pixel > 8))
656
52.5k
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
657
52.5k
  if ((dib_info.image_size != 0U) && (dib_info.image_size > file_size))
658
44.7k
    ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
659
44.7k
  if ((dib_info.number_colors != 0) || (dib_info.bits_per_pixel <= 8))
660
31.9k
    {
661
31.9k
      image->storage_class=PseudoClass;
662
31.9k
      image->colors=dib_info.number_colors;
663
31.9k
      if (image->colors == 0)
664
12.8k
        image->colors=1L << dib_info.bits_per_pixel;
665
31.9k
    }
666
44.7k
  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
44.7k
   if (CheckImagePixelLimits(image, exception) != MagickPass)
685
30.4k
    ThrowReaderException(ResourceLimitError,ImagePixelLimitExceeded,image);
686
687
14.3k
  if (image->storage_class == PseudoClass)
688
12.1k
    {
689
12.1k
      unsigned char
690
12.1k
        *dib_colormap;
691
692
12.1k
      size_t
693
12.1k
        packet_size;
694
695
      /*
696
        Read DIB raster colormap.
697
      */
698
12.1k
      if (!AllocateImageColormap(image,image->colors))
699
12.1k
        ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
700
12.1k
      dib_colormap=MagickAllocateResourceLimitedArray(unsigned char *,image->colors,4);
701
12.1k
      if (dib_colormap == (unsigned char *) NULL)
702
12.1k
        ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
703
12.1k
      packet_size=4;
704
12.1k
      if ((count=ReadBlob(image,packet_size*image->colors,(char *) dib_colormap))
705
12.1k
          != packet_size*image->colors)
706
1.01k
        {
707
1.01k
          if (image->logging)
708
1.01k
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
709
1.01k
                                  "Read %" MAGICK_SIZE_T_F  "u bytes from blob"
710
1.01k
                                  " (expected %" MAGICK_SIZE_T_F  "u bytes)",
711
1.01k
                                  (MAGICK_SIZE_T) count,
712
1.01k
                                  (MAGICK_SIZE_T) packet_size*image->colors);
713
1.01k
          MagickFreeResourceLimitedMemory(unsigned char *,dib_colormap);
714
1.01k
          ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
715
0
        }
716
11.1k
      p=dib_colormap;
717
83.5k
      for (i=0; i < (long) image->colors; i++)
718
72.4k
      {
719
72.4k
        image->colormap[i].blue=ScaleCharToQuantum(*p++);
720
72.4k
        image->colormap[i].green=ScaleCharToQuantum(*p++);
721
72.4k
        image->colormap[i].red=ScaleCharToQuantum(*p++);
722
72.4k
        if (packet_size == 4)
723
72.4k
          p++;
724
72.4k
      }
725
11.1k
      MagickFreeResourceLimitedMemory(unsigned char *,dib_colormap);
726
11.1k
    }
727
  /*
728
    Read image data.
729
  */
730
13.3k
  packet_size=dib_info.bits_per_pixel;
731
13.3k
  if (dib_info.compression == 2)
732
1.65k
    packet_size<<=1;
733
734
  /*
735
     Below emulates:
736
     bytes_per_line=4*((image->columns*dib_info.packet_size+31)/32);
737
  */
738
13.3k
  bytes_per_line=MagickArraySize(image->columns,packet_size);
739
13.3k
  if ((bytes_per_line > 0) && (~((size_t) 0) - bytes_per_line) > 31)
740
13.3k
    bytes_per_line = MagickArraySize(4,(bytes_per_line+31)/32);
741
13.3k
  if (bytes_per_line == 0)
742
13.3k
    ThrowReaderException(CoderError,ArithmeticOverflow,image);
743
13.3k
  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
744
13.3k
                        "%" MAGICK_SIZE_T_F "u bytes per line",
745
13.3k
                        (MAGICK_SIZE_T) bytes_per_line);
746
  /*
747
    Validate that file data size is suitable for claimed dimensions.
748
  */
749
13.3k
  {
750
13.3k
    size_t
751
13.3k
      maximum_image_size;
752
753
13.3k
    maximum_image_size=MagickArraySize(bytes_per_line,image->rows);
754
13.3k
    if ((maximum_image_size == 0) ||
755
13.3k
        (maximum_image_size >
756
13.3k
         ((size_t) file_size * ((dib_info.compression == 1 ? 256 :
757
13.3k
                                 dib_info.compression == 2 ? 8 : 1)))))
758
13.1k
      ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
759
13.1k
  }
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.1k
  if (length == 0)
768
13.1k
    ThrowReaderException(CoderError,ArithmeticOverflow,image);
769
13.1k
  if ((image->columns+1UL) < image->columns)
770
13.1k
    ThrowReaderException(CoderError,ArithmeticOverflow,image);
771
13.1k
  pixels_size=MagickArraySize(image->rows,Max(bytes_per_line,(size_t) image->columns+1));
772
13.1k
  if (pixels_size == 0)
773
13.1k
    ThrowReaderException(CoderError,ArithmeticOverflow,image);
774
13.1k
  pixels=MagickAllocateResourceLimitedMemory(unsigned char *,pixels_size);
775
13.1k
  if (pixels == (unsigned char *) NULL)
776
13.1k
    ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
777
13.1k
  if ((dib_info.compression == 0) || (dib_info.compression == 3))
778
1.83k
    {
779
1.83k
      if ((count=ReadBlob(image,length,(char *) pixels)) != length)
780
188
        {
781
188
          if (image->logging)
782
188
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
783
188
                                  "Read %" MAGICK_SIZE_T_F  "u bytes from blob"
784
188
                                  " (expected %" MAGICK_SIZE_T_F  "u bytes)",
785
188
                                  (MAGICK_SIZE_T) count,
786
188
                                  (MAGICK_SIZE_T) length);
787
188
          MagickFreeResourceLimitedMemory(unsigned char *,pixels);
788
188
          ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
789
0
        }
790
1.83k
    }
791
11.3k
  else
792
11.3k
    {
793
      /*
794
        Convert run-length encoded raster pixels.
795
796
        DecodeImage() normally decompresses to rows*columns bytes of data.
797
      */
798
11.3k
      (void) memset(pixels,0,pixels_size);
799
11.3k
      status=DecodeImage(image,dib_info.compression,pixels,
800
11.3k
                         (size_t) image->rows*image->columns);
801
11.3k
      if (status == False)
802
2.07k
        {
803
2.07k
          MagickFreeResourceLimitedMemory(unsigned char *,pixels);
804
2.07k
          ThrowReaderException(CorruptImageError,UnableToRunlengthDecodeImage,
805
2.07k
                               image);
806
0
        }
807
11.3k
    }
808
  /*
809
    Initialize image structure.
810
  */
811
10.9k
  image->units=PixelsPerCentimeterResolution;
812
10.9k
  image->x_resolution=dib_info.x_pixels/100.0;
813
10.9k
  image->y_resolution=dib_info.y_pixels/100.0;
814
  /*
815
    Convert DIB raster image to pixel packets.
816
  */
817
10.9k
  switch (dib_info.bits_per_pixel)
818
10.9k
  {
819
908
    case 1:
820
908
    {
821
      /*
822
        Convert bitmap scanline.
823
      */
824
140k
      for (y=(long) image->rows-1; y >= 0; y--)
825
139k
      {
826
139k
        p=pixels+((size_t) image->rows-y-1)*bytes_per_line;
827
139k
        q=SetImagePixels(image,0,y,image->columns,1);
828
139k
        if (q == (PixelPacket *) NULL)
829
47
          break;
830
139k
        indexes=AccessMutableIndexes(image);
831
15.3M
        for (x=0; x < ((long) image->columns-7); x+=8)
832
15.2M
        {
833
137M
          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.2M
          p++;
841
15.2M
        }
842
139k
        if ((image->columns % 8) != 0)
843
75.2k
          {
844
237k
            for (bit=0; bit < (long) (image->columns % 8); bit++)
845
162k
            {
846
162k
              index=((*p) & (0x80 >> bit) ? 0x01 : 0x00);
847
162k
              VerifyColormapIndex(status,image,index);
848
162k
              indexes[x+bit]=index;
849
162k
              *q++=image->colormap[index];
850
162k
            }
851
75.2k
            p++;
852
75.2k
          }
853
139k
        if (!SyncImagePixels(image))
854
0
          break;
855
139k
        if (image->previous == (Image *) NULL)
856
139k
          if (QuantumTick(y,image->rows))
857
44.8k
            {
858
44.8k
              status=MagickMonitorFormatted((size_t) image->rows-y-1,image->rows,
859
44.8k
                                            exception,LoadImageText,
860
44.8k
                                            image->filename,
861
44.8k
                                            image->columns,image->rows);
862
44.8k
              if (status == False)
863
0
                break;
864
44.8k
            }
865
139k
      }
866
908
      break;
867
0
    }
868
3.73k
    case 4:
869
3.73k
    {
870
      /*
871
        Convert PseudoColor scanline.
872
      */
873
45.0k
      for (y=(long) image->rows-1; y >= 0; y--)
874
42.8k
      {
875
42.8k
        p=pixels+((size_t) image->rows-y-1)*bytes_per_line;
876
42.8k
        q=SetImagePixels(image,0,y,image->columns,1);
877
42.8k
        if (q == (PixelPacket *) NULL)
878
1.62k
          break;
879
41.2k
        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
41.2k
        if ((image->columns % 2) != 0)
893
34.4k
          {
894
34.4k
            index=(IndexPacket) ((*p >> 4) & 0xf);
895
34.4k
            VerifyColormapIndex(status,image,index);
896
34.4k
            indexes[x]=index;
897
34.4k
            *q++=image->colormap[index];
898
34.4k
            p++;
899
34.4k
          }
900
41.2k
        if (!SyncImagePixels(image))
901
0
          break;
902
41.2k
        if (image->previous == (Image *) NULL)
903
41.2k
          if (QuantumTick(y,image->rows))
904
19.0k
            {
905
19.0k
              status=MagickMonitorFormatted((size_t) image->rows-y-1,image->rows,
906
19.0k
                                            exception,LoadImageText,
907
19.0k
                                            image->filename,
908
19.0k
                                            image->columns,image->rows);
909
19.0k
              if (status == False)
910
0
                break;
911
19.0k
            }
912
41.2k
      }
913
3.73k
      break;
914
0
    }
915
4.72k
    case 8:
916
4.72k
    {
917
      /*
918
        Convert PseudoColor scanline.
919
      */
920
4.72k
      if ((dib_info.compression == 1) || (dib_info.compression == 2))
921
1.49k
        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.34k
          break;
928
32.8k
        indexes=AccessMutableIndexes(image);
929
544k
        for (x=0; x < (long) image->columns; x++)
930
511k
        {
931
511k
          index=(IndexPacket) (*p);
932
511k
          VerifyColormapIndex(status,image,index);
933
511k
          indexes[x]=index;
934
511k
          *q=image->colormap[index];
935
511k
          p++;
936
511k
          q++;
937
511k
        }
938
32.8k
        if (!SyncImagePixels(image))
939
0
          break;
940
32.8k
        if (image->previous == (Image *) NULL)
941
32.8k
          if (QuantumTick(y,image->rows))
942
16.7k
            {
943
16.7k
              status=MagickMonitorFormatted((size_t) image->rows-y-1,image->rows,
944
16.7k
                                            exception,LoadImageText,
945
16.7k
                                            image->filename,
946
16.7k
                                            image->columns,image->rows);
947
16.7k
              if (status == False)
948
0
                break;
949
16.7k
            }
950
32.8k
      }
951
4.72k
      break;
952
0
    }
953
762
    case 16:
954
762
    {
955
762
      unsigned short
956
762
        word;
957
958
      /*
959
        Convert DirectColor (555 or 565) scanline.
960
      */
961
762
      image->storage_class=DirectClass;
962
762
      if (dib_info.compression == 1)
963
258
        bytes_per_line=(size_t) 2*image->columns;
964
50.2k
      for (y=(long) image->rows-1; y >= 0; y--)
965
49.4k
      {
966
49.4k
        p=pixels+((size_t) image->rows-y-1)*bytes_per_line;
967
49.4k
        q=SetImagePixels(image,0,y,image->columns,1);
968
49.4k
        if (q == (PixelPacket *) NULL)
969
0
          break;
970
1.70M
        for (x=0; x < (long) image->columns; x++)
971
1.65M
        {
972
1.65M
          word=(*p++);
973
1.65M
          word|=(*p++ << 8);
974
1.65M
          if (dib_info.red_mask == 0)
975
1.65M
            {
976
1.65M
              q->red=ScaleCharToQuantum(ScaleColor5to8((word >> 10) & 0x1f));
977
1.65M
              q->green=ScaleCharToQuantum(ScaleColor5to8((word >> 5) & 0x1f));
978
1.65M
              q->blue=ScaleCharToQuantum(ScaleColor5to8(word & 0x1f));
979
1.65M
            }
980
582
          else
981
582
            {
982
582
              q->red=ScaleCharToQuantum(ScaleColor5to8((word >> 11) & 0x1f));
983
582
              q->green=ScaleCharToQuantum(ScaleColor6to8((word >> 5) & 0x3f));
984
582
              q->blue=ScaleCharToQuantum(ScaleColor5to8(word & 0x1f));
985
582
            }
986
1.65M
          q++;
987
1.65M
        }
988
49.4k
        if (!SyncImagePixels(image))
989
0
          break;
990
49.4k
        if (image->previous == (Image *) NULL)
991
49.4k
          if (QuantumTick(y,image->rows))
992
20.1k
            {
993
20.1k
              status=MagickMonitorFormatted((size_t) image->rows-y-1,image->rows,
994
20.1k
                                            exception,LoadImageText,
995
20.1k
                                            image->filename,
996
20.1k
                                            image->columns,image->rows);
997
20.1k
              if (status == False)
998
0
                break;
999
20.1k
            }
1000
49.4k
      }
1001
762
      break;
1002
0
    }
1003
473
    case 24:
1004
792
    case 32:
1005
792
    {
1006
      /*
1007
        Convert DirectColor scanline.
1008
      */
1009
51.8k
      for (y=(long) image->rows-1; y >= 0; y--)
1010
51.1k
      {
1011
51.1k
        p=pixels+((size_t) image->rows-y-1)*bytes_per_line;
1012
51.1k
        q=SetImagePixels(image,0,y,image->columns,1);
1013
51.1k
        if (q == (PixelPacket *) NULL)
1014
26
          break;
1015
2.93M
        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.76M
            q->opacity=ScaleCharToQuantum(*p++);
1022
2.88M
          q++;
1023
2.88M
        }
1024
51.0k
        if (!SyncImagePixels(image))
1025
0
          break;
1026
51.0k
        if (image->previous == (Image *) NULL)
1027
51.0k
          if (QuantumTick(y,image->rows))
1028
23.6k
            {
1029
23.6k
              status=MagickMonitorFormatted((size_t) image->rows-y-1,image->rows,
1030
23.6k
                                            exception,LoadImageText,
1031
23.6k
                                            image->filename,
1032
23.6k
                                            image->columns,image->rows);
1033
23.6k
              if (status == False)
1034
0
                break;
1035
23.6k
            }
1036
51.0k
      }
1037
792
      break;
1038
473
    }
1039
0
    default:
1040
0
      {
1041
0
        MagickFreeResourceLimitedMemory(unsigned char *,pixels);
1042
0
        ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
1043
0
      }
1044
10.9k
  }
1045
10.9k
  MagickFreeResourceLimitedMemory(unsigned char *,pixels);
1046
10.9k
  if (EOFBlob(image))
1047
1.18k
    ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
1048
10.9k
                   image->filename);
1049
10.9k
  if (strcmp(image_info->magick,"ICODIB") == 0)
1050
943
    {
1051
      /*
1052
        Handle ICO mask.
1053
      */
1054
943
      char
1055
943
        byte;
1056
1057
943
      image->matte=MagickFalse;
1058
7.12k
      for (y=(long) image->rows-1; y >= 0; y--)
1059
7.07k
        {
1060
7.07k
          if (image->logging)
1061
7.07k
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1062
7.07k
                                  "y=%ld", y);
1063
7.07k
          q=GetImagePixels(image,0,y,image->columns,1);
1064
7.07k
          if (q == (PixelPacket *) NULL)
1065
0
            break;
1066
30.7k
          for (x=0; x < ((long) image->columns-7); x+=8)
1067
24.0k
            {
1068
24.0k
              byte=0;
1069
24.0k
              if (ReadBlob(image,sizeof(byte),&byte) != sizeof(byte))
1070
340
                break;
1071
213k
              for (bit=0; bit < 8; bit++)
1072
189k
                {
1073
189k
                  q[x+bit].opacity=(Quantum)
1074
189k
                    (byte & (0x80 >> bit) ? TransparentOpacity : OpaqueOpacity);
1075
189k
                  if (q[x+bit].opacity != OpaqueOpacity)
1076
67.8k
                    image->matte=MagickTrue;
1077
189k
                }
1078
23.6k
            }
1079
          /* Detect early loop termination above due to EOF */
1080
7.07k
          if (x < ((long) image->columns-7))
1081
340
            break;
1082
6.73k
          if ((image->columns % 8) != 0)
1083
4.74k
            {
1084
4.74k
              byte=0;
1085
4.74k
              if (ReadBlob(image,sizeof(byte),&byte) != sizeof(byte))
1086
553
                break;
1087
15.7k
              for (bit=0; bit < (long) (image->columns % 8); bit++)
1088
11.5k
                {
1089
11.5k
                  q[x+bit].opacity=(Quantum)
1090
11.5k
                    (byte & (0x80 >> bit) ? TransparentOpacity : OpaqueOpacity);
1091
11.5k
                  if (q[x+bit].opacity != OpaqueOpacity)
1092
4.08k
                    image->matte=MagickTrue;
1093
11.5k
                }
1094
4.19k
            }
1095
6.17k
          if (image->columns % 32)
1096
17.9k
            for (x=0; x < (long) ((32-(image->columns % 32))/8); x++)
1097
12.7k
              {
1098
12.7k
                byte=0;
1099
12.7k
                if (ReadBlob(image,sizeof(byte),&byte) != sizeof(byte))
1100
163
                  break;
1101
12.7k
              }
1102
6.17k
          if (!SyncImagePixels(image))
1103
0
            break;
1104
6.17k
          if (image->previous == (Image *) NULL)
1105
6.17k
            if (QuantumTick(y,image->rows))
1106
4.54k
              if (!MagickMonitorFormatted((size_t) image->rows-y-1,image->rows,&image->exception,
1107
4.54k
                                          LoadImageText,image->filename,
1108
4.54k
                                          image->columns,image->rows))
1109
0
                break;
1110
6.17k
        }
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
943
      if ((image->storage_class == PseudoClass) && (image->matte == MagickTrue))
1117
82
        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
943
    }
1130
10.9k
  if (dib_info.height < 0)
1131
9.06k
    {
1132
9.06k
      Image
1133
9.06k
        *flipped_image;
1134
      /*
1135
        Correct image orientation.
1136
      */
1137
9.06k
      flipped_image=FlipImage(image,exception);
1138
9.06k
      if (flipped_image == (Image *) NULL)
1139
0
        {
1140
0
          DestroyImageList(image);
1141
0
          return((Image *) NULL);
1142
0
        }
1143
9.06k
      DestroyBlob(flipped_image);
1144
9.06k
      flipped_image->blob=ReferenceBlob(image->blob);
1145
9.06k
      DestroyImage(image);
1146
9.06k
      image=flipped_image;
1147
9.06k
    }
1148
10.9k
  CloseBlob(image);
1149
10.9k
  StopTimer(&timer);
1150
10.9k
  image->timer=timer;
1151
10.9k
  return(image);
1152
10.9k
}
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
593
{
1264
593
  DIBInfo
1265
593
    dib_info;
1266
1267
593
  unsigned long
1268
593
    y;
1269
1270
593
  register const PixelPacket
1271
593
    *p;
1272
1273
593
  register const IndexPacket
1274
593
    *indexes;
1275
1276
593
  register unsigned long
1277
593
    i,
1278
593
    x;
1279
1280
593
  register unsigned char
1281
593
    *q;
1282
1283
593
  unsigned char
1284
593
    *dib_data,
1285
593
    *pixels;
1286
1287
593
  unsigned int
1288
593
    status;
1289
1290
593
  size_t
1291
593
    bytes_per_line,
1292
593
    image_size;
1293
1294
593
  ImageCharacteristics
1295
593
    characteristics;
1296
1297
  /*
1298
    Open output image file.
1299
  */
1300
593
  assert(image_info != (const ImageInfo *) NULL);
1301
593
  assert(image_info->signature == MagickSignature);
1302
593
  assert(image != (Image *) NULL);
1303
593
  assert(image->signature == MagickSignature);
1304
593
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1305
593
  if (status == False)
1306
593
    ThrowWriterException(FileOpenError,UnableToOpenFile,image);
1307
  /*
1308
    Ensure that image is in an RGB space.
1309
  */
1310
593
  if (TransformColorspace(image,RGBColorspace) == MagickFail)
1311
593
      ThrowWriterException(CoderError,UnableToTransformColorspace,image);
1312
  /*
1313
    Analyze image to be written.
1314
  */
1315
593
  if (!GetImageCharacteristics(image,&characteristics,
1316
593
                               (OptimizeType == image_info->type),
1317
593
                               &image->exception))
1318
0
    {
1319
0
      CloseBlob(image);
1320
0
      return MagickFail;
1321
0
    }
1322
  /*
1323
    Initialize DIB raster file header.
1324
  */
1325
593
  if (image->storage_class == DirectClass)
1326
164
    {
1327
      /*
1328
        Full color DIB raster.
1329
      */
1330
164
      dib_info.number_colors=0;
1331
164
      dib_info.bits_per_pixel=image->matte ? 32 : 24;
1332
164
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1333
164
                            "Writing full color DIB raster with %u bits per pixel...",
1334
164
                            dib_info.bits_per_pixel);
1335
164
    }
1336
429
  else
1337
429
    {
1338
      /*
1339
        Colormapped DIB raster.
1340
      */
1341
429
      dib_info.bits_per_pixel=8;
1342
429
      if (characteristics.monochrome)
1343
93
        dib_info.bits_per_pixel=1;
1344
429
      dib_info.number_colors=1 << dib_info.bits_per_pixel;
1345
429
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1346
429
                            "Writing colormapped DIB with %u colors and %u "
1347
429
                            "bit%s per colormap index...",
1348
429
                            dib_info.number_colors, dib_info.bits_per_pixel,
1349
429
                            dib_info.bits_per_pixel ? "s" : "");
1350
429
    }
1351
  /*
1352
     Below emulates:
1353
     bytes_per_line=4*((image->columns*dib_info.bits_per_pixel+31)/32);
1354
  */
1355
593
  bytes_per_line=MagickArraySize(image->columns,dib_info.bits_per_pixel);
1356
593
  if ((bytes_per_line > 0) && (~((size_t) 0) - bytes_per_line) > 31)
1357
593
    bytes_per_line = MagickArraySize(4,(bytes_per_line+31)/32);
1358
593
  if (bytes_per_line == 0)
1359
593
    ThrowWriterException(CoderError,ArithmeticOverflow,image);
1360
593
  image_size=MagickArraySize(bytes_per_line,image->rows);
1361
593
  if ((image_size == 0) || ((image_size & 0xffffffff) != image_size))
1362
593
    ThrowWriterException(CoderError,ArithmeticOverflow,image);
1363
593
  dib_info.header_size=40;
1364
593
  dib_info.width=(long) image->columns;
1365
593
  dib_info.height=(long) image->rows;
1366
593
  dib_info.planes=1;
1367
593
  dib_info.compression=0;
1368
593
  dib_info.image_size=(magick_uint32_t) image_size;
1369
593
  dib_info.x_pixels=75*39;
1370
593
  dib_info.y_pixels=75*39;
1371
593
  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
593
  if (image->units == PixelsPerCentimeterResolution)
1377
593
    {
1378
593
      dib_info.x_pixels=(unsigned long) (100.0*image->x_resolution);
1379
593
      dib_info.y_pixels=(unsigned long) (100.0*image->y_resolution);
1380
593
    }
1381
593
  dib_info.colors_important=dib_info.number_colors;
1382
  /*
1383
    Convert MIFF to DIB raster pixels.
1384
  */
1385
593
  pixels=MagickAllocateResourceLimitedMemory(unsigned char *,dib_info.image_size);
1386
593
  if (pixels == (unsigned char *) NULL)
1387
593
    ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
1388
593
  switch (dib_info.bits_per_pixel)
1389
593
  {
1390
93
    case 1:
1391
93
    {
1392
93
      register unsigned char
1393
93
        bit,
1394
93
        byte;
1395
1396
      /*
1397
        Convert PseudoClass image to a DIB monochrome image.
1398
      */
1399
23.9k
      for (y=0; y < image->rows; y++)
1400
23.8k
      {
1401
23.8k
        p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
1402
23.8k
        if (p == (const PixelPacket *) NULL)
1403
0
          break;
1404
23.8k
        indexes=AccessImmutableIndexes(image);
1405
23.8k
        q=pixels+(image->rows-y-1)*bytes_per_line;
1406
23.8k
        bit=0;
1407
23.8k
        byte=0;
1408
4.97M
        for (x=0; x < image->columns; x++)
1409
4.95M
        {
1410
4.95M
          byte<<=1;
1411
4.95M
          byte|=indexes[x] ? 0x01 : 0x00;
1412
4.95M
          bit++;
1413
4.95M
          if (bit == 8)
1414
615k
            {
1415
615k
              *q++=byte;
1416
615k
              bit=0;
1417
615k
              byte=0;
1418
615k
            }
1419
4.95M
           p++;
1420
4.95M
         }
1421
23.8k
       if (bit != 0)
1422
19.2k
         *q++=byte << (8-bit);
1423
       /* initialize padding bytes */
1424
79.4k
       for (x=(image->columns+7)/8; x < bytes_per_line; x++)
1425
55.5k
         *q++=0x00;
1426
23.8k
       if (image->previous == (Image *) NULL)
1427
23.8k
         if (QuantumTick(y,image->rows))
1428
5.62k
           if (!MagickMonitorFormatted(y,image->rows,&image->exception,
1429
5.62k
                                       SaveImageText,image->filename,
1430
5.62k
                                       image->columns,image->rows))
1431
0
             break;
1432
23.8k
      }
1433
93
      break;
1434
0
    }
1435
336
    case 8:
1436
336
    {
1437
      /*
1438
        Convert PseudoClass packet to DIB pixel.
1439
      */
1440
77.6k
      for (y=0; y < image->rows; y++)
1441
77.3k
      {
1442
77.3k
        p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
1443
77.3k
        if (p == (const PixelPacket *) NULL)
1444
0
          break;
1445
77.3k
        indexes=AccessImmutableIndexes(image);
1446
77.3k
        q=pixels+(image->rows-y-1)*bytes_per_line;
1447
106M
        for (x=0; x < image->columns; x++)
1448
106M
        {
1449
106M
          *q++=indexes[x];
1450
106M
          p++;
1451
106M
        }
1452
       /* initialize padding bytes */
1453
140k
       for (; x < bytes_per_line; x++)
1454
63.0k
         *q++=0x00;
1455
77.3k
        if (image->previous == (Image *) NULL)
1456
77.3k
          if (QuantumTick(y,image->rows))
1457
22.6k
            if (!MagickMonitorFormatted(y,image->rows,&image->exception,
1458
22.6k
                                        SaveImageText,image->filename,
1459
22.6k
                                        image->columns,image->rows))
1460
0
              break;
1461
77.3k
      }
1462
336
      break;
1463
0
    }
1464
95
    case 24:
1465
164
    case 32:
1466
164
    {
1467
      /*
1468
        Convert DirectClass packet to DIB RGB pixel.
1469
      */
1470
25.2k
      for (y=0; y < image->rows; y++)
1471
25.0k
      {
1472
25.0k
        p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
1473
25.0k
        if (p == (const PixelPacket *) NULL)
1474
0
          break;
1475
25.0k
        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
25.0k
        if (dib_info.bits_per_pixel == 24)
1487
20.2k
          {
1488
            /* initialize padding bytes */
1489
41.1k
            for (x=3*image->columns; x < bytes_per_line; x++)
1490
20.8k
              *q++=0x00;
1491
20.2k
          }
1492
25.0k
        if (image->previous == (Image *) NULL)
1493
25.0k
          if (QuantumTick(y,image->rows))
1494
7.05k
            if (!MagickMonitorFormatted(y,image->rows,&image->exception,
1495
7.05k
                                        SaveImageText,image->filename,
1496
7.05k
                                        image->columns,image->rows))
1497
0
               break;
1498
25.0k
      }
1499
164
      break;
1500
95
    }
1501
593
  }
1502
593
  if (dib_info.bits_per_pixel == 8)
1503
336
    if (image_info->compression != NoCompression)
1504
336
      {
1505
336
        size_t
1506
336
          length;
1507
1508
        /*
1509
          Convert run-length encoded raster pixels.
1510
        */
1511
336
        length=2*((size_t) bytes_per_line+2)*((size_t) image->rows+2)+2;
1512
336
        dib_data=MagickAllocateResourceLimitedMemory(unsigned char *,length);
1513
336
        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
336
        dib_info.image_size=(unsigned long)
1520
336
          EncodeImage(image,bytes_per_line,pixels,dib_data);
1521
336
        MagickFreeResourceLimitedMemory(unsigned char *,pixels);
1522
336
        pixels=dib_data;
1523
336
        dib_info.compression=1;
1524
336
      }
1525
  /*
1526
    Write DIB header.
1527
  */
1528
593
  (void) WriteBlobLSBLong(image,dib_info.header_size);
1529
593
  (void) WriteBlobLSBLong(image,dib_info.width);
1530
593
  (void) WriteBlobLSBLong(image,dib_info.height);
1531
593
  (void) WriteBlobLSBShort(image,dib_info.planes);
1532
593
  (void) WriteBlobLSBShort(image,dib_info.bits_per_pixel);
1533
593
  (void) WriteBlobLSBLong(image,dib_info.compression);
1534
593
  (void) WriteBlobLSBLong(image,dib_info.image_size);
1535
593
  (void) WriteBlobLSBLong(image,dib_info.x_pixels);
1536
593
  (void) WriteBlobLSBLong(image,dib_info.y_pixels);
1537
593
  (void) WriteBlobLSBLong(image,dib_info.number_colors);
1538
593
  (void) WriteBlobLSBLong(image,dib_info.colors_important);
1539
593
  if (image->storage_class == PseudoClass)
1540
429
    {
1541
429
      unsigned char
1542
429
        *dib_colormap;
1543
1544
      /*
1545
        Dump colormap to file.
1546
      */
1547
429
      dib_colormap=MagickAllocateResourceLimitedArray(unsigned char *,
1548
429
                                                      (((size_t) 1U) << dib_info.bits_per_pixel),4);
1549
429
      if (dib_colormap == (unsigned char *) NULL)
1550
0
        {
1551
0
          MagickFreeResourceLimitedMemory(unsigned char *,pixels);
1552
0
          ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
1553
0
        }
1554
429
      q=dib_colormap;
1555
6.46k
      for (i=0; i < Min(image->colors,dib_info.number_colors); i++)
1556
6.03k
      {
1557
6.03k
        *q++=ScaleQuantumToChar(image->colormap[i].blue);
1558
6.03k
        *q++=ScaleQuantumToChar(image->colormap[i].green);
1559
6.03k
        *q++=ScaleQuantumToChar(image->colormap[i].red);
1560
6.03k
        *q++=(Quantum) 0x0;
1561
6.03k
      }
1562
80.5k
      for ( ; i < (1U << dib_info.bits_per_pixel); i++)
1563
80.1k
      {
1564
80.1k
        *q++=(Quantum) 0x0;
1565
80.1k
        *q++=(Quantum) 0x0;
1566
80.1k
        *q++=(Quantum) 0x0;
1567
80.1k
        *q++=(Quantum) 0x0;
1568
80.1k
      }
1569
429
      (void) WriteBlob(image, 4*(((size_t) 1U) << dib_info.bits_per_pixel),
1570
429
        (char *) dib_colormap);
1571
429
      MagickFreeResourceLimitedMemory(unsigned char *,dib_colormap);
1572
429
    }
1573
593
  (void) WriteBlob(image,dib_info.image_size,(char *) pixels);
1574
593
  MagickFreeResourceLimitedMemory(unsigned char *,pixels);
1575
593
  status &= CloseBlob(image);
1576
593
  return(status);
1577
593
}