Coverage Report

Created: 2025-12-31 07:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/graphicsmagick/coders/miff.c
Line
Count
Source
1
/*
2
% Copyright (C) 2003-2025 GraphicsMagick Group
3
% Copyright (C) 2002 ImageMagick Studio
4
% Copyright 1991-1999 E. I. du Pont de Nemours and Company
5
%
6
% This program is covered by multiple licenses, which are described in
7
% Copyright.txt. You should have received a copy of Copyright.txt with this
8
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
9
%
10
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11
%                                                                             %
12
%                                                                             %
13
%                                                                             %
14
%                        M   M  IIIII  FFFFF  FFFFF                           %
15
%                        MM MM    I    F      F                               %
16
%                        M M M    I    FFF    FFF                             %
17
%                        M   M    I    F      F                               %
18
%                        M   M  IIIII  F      F                               %
19
%                                                                             %
20
%                                                                             %
21
%                      Read/Write MIFF Image Format.                          %
22
%                                                                             %
23
%                                                                             %
24
%                              Software Design                                %
25
%                                John Cristy                                  %
26
%                                 July 1992                                   %
27
%                                                                             %
28
%                                                                             %
29
%                                                                             %
30
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
31
%
32
%
33
*/
34

35
/*
36
  Include declarations.
37
*/
38
#include "magick/studio.h"
39
#include "magick/attribute.h"
40
#include "magick/blob.h"
41
#include "magick/color.h"
42
#include "magick/color_lookup.h"
43
#include "magick/colormap.h"
44
#include "magick/compress.h"
45
#include "magick/constitute.h"
46
#include "magick/enum_strings.h"
47
#include "magick/log.h"
48
#include "magick/magick.h"
49
#include "magick/monitor.h"
50
#include "magick/pixel_cache.h"
51
#include "magick/profile.h"
52
#include "magick/utility.h"
53
#include "magick/version.h"
54
#include "magick/static.h"
55
#if defined(HasZLIB)
56
#  include "zlib.h"
57
#endif
58
#if defined(HasBZLIB)
59
#  include "bzlib.h"
60
#endif
61
62
/*
63
  Forward declarations.
64
*/
65
static unsigned int
66
  WriteMIFFImage(const ImageInfo *,Image *);
67

68
/*
69
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70
%                                                                             %
71
%                                                                             %
72
%                                                                             %
73
%   I s M I F F                                                               %
74
%                                                                             %
75
%                                                                             %
76
%                                                                             %
77
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78
%
79
%  Method IsMIFF returns True if the image format type, identified by the
80
%  magick string, is MIFF.
81
%
82
%  The format of the IsMIFF method is:
83
%
84
%      unsigned int IsMIFF(const unsigned char *magick,const size_t length)
85
%
86
%  A description of each parameter follows:
87
%
88
%    o status:  Method IsMIFF returns True if the image format type is MIFF.
89
%
90
%    o magick: This string is generally the first few bytes of an image file
91
%      or blob.
92
%
93
%    o length: Specifies the length of the magick string.
94
%
95
%
96
*/
97
static unsigned int IsMIFF(const unsigned char *magick,const size_t length)
98
0
{
99
0
  if (length < 14)
100
0
    return(False);
101
0
  if (LocaleNCompare((char *) magick,"id=ImageMagick",14) == 0)
102
0
    return(True);
103
0
  return(False);
104
0
}
105

106
/*
107
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
108
%                                                                             %
109
%                                                                             %
110
%                                                                             %
111
%   R e a d M I F F I m a g e                                                 %
112
%                                                                             %
113
%                                                                             %
114
%                                                                             %
115
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
116
%
117
%  Method ReadMIFFImage reads a MIFF image file and returns it.  It
118
%  allocates the memory necessary for the new Image structure and returns a
119
%  pointer to the new image.
120
%
121
%  The format of the ReadMIFFImage method is:
122
%
123
%      Image *ReadMIFFImage(const ImageInfo *image_info,
124
%        ExceptionInfo *exception)
125
%
126
%  Decompression code contributed by Kyle Shorter.
127
%
128
%  A description of each parameter follows:
129
%
130
%    o image: Method ReadMIFFImage returns a pointer to the image after
131
%      reading.  A null image is returned if there is a memory shortage or
132
%      if the image cannot be read.
133
%
134
%    o image_info: Specifies a pointer to a ImageInfo structure.
135
%
136
%    o exception: return any errors or warnings in this structure.
137
%
138
%
139
*/
140
141
142
static MagickPassFail
143
ImportRLEPixels(Image *image,
144
                const QuantumType quantum_type,
145
                const unsigned int quantum_size,
146
                const unsigned char *source)
147
8.15k
{
148
149
8.15k
  register const unsigned char
150
8.15k
    *p;
151
152
8.15k
  register unsigned int
153
8.15k
    index,
154
8.15k
    quantum;
155
156
8.15k
  register int
157
8.15k
    length;
158
159
8.15k
  register IndexPacket
160
8.15k
    *indexes;
161
162
8.15k
  register long
163
8.15k
    x;
164
165
8.15k
  PixelPacket
166
8.15k
    pixel;
167
168
8.15k
  register PixelPacket
169
8.15k
    *q;
170
171
8.15k
  assert(image != (Image *) NULL);
172
8.15k
  assert(image->signature == MagickSignature);
173
8.15k
  assert(source != (const unsigned char *) NULL);
174
175
  /*
176
    FIXME: gray DirectClass pixels (quantum_type=GrayQuantum and
177
    GrayAlphaQuantum ) should be properly supported with RLE since
178
    modern ImageMagick supports it.  For the moment we support it by
179
    reading as PseudoClass using IndexQuantum.
180
   */
181
8.15k
  assert((quantum_size == 8) || (quantum_size == 16) || (quantum_size == 32));
182
8.15k
  if (!(((quantum_type == IndexQuantum) && (image->storage_class == PseudoClass)) ||
183
6.37k
        ((quantum_type == IndexAlphaQuantum) && (image->storage_class == PseudoClass)) ||
184
        /*  ((quantum_type == GrayQuantum) && (image->storage_class == DirectClass) && !image->matte) ||*/
185
        /*  ((quantum_type == GrayAlphaQuantum) && (image->storage_class == DirectClass) && image->matte) ||*/
186
6.37k
        ((quantum_type == CMYKAQuantum) && (image->storage_class == DirectClass) && image->matte) ||
187
6.37k
        ((quantum_type == CMYKQuantum) && (image->storage_class == DirectClass) && !image->matte) ||
188
6.37k
        ((quantum_type == RGBAQuantum) && (image->storage_class == DirectClass) && image->matte) ||
189
2.59k
        ((quantum_type == RGBQuantum) && (image->storage_class == DirectClass) && !image->matte)))
190
2
    {
191
2
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
192
2
                            "RLE decompression not supported for QuantumType=%s, ClassType=%s, Matte=%s",
193
2
                            QuantumTypeToString(quantum_type),ClassTypeToString(image->storage_class),
194
2
                            image->matte ? "True" : "False");
195
2
      ThrowBinaryException(CoderError,RLECompressionNotSupported,image->filename);
196
0
    }
197
198
8.14k
  p=source;
199
8.14k
  q=AccessMutablePixels(image);
200
8.14k
  length=0;
201
8.14k
  index=0;
202
8.14k
  indexes=AccessMutableIndexes(image);
203
204
8.14k
  pixel.red=0;
205
8.14k
  pixel.green=0;
206
8.14k
  pixel.blue=0;
207
8.14k
  pixel.opacity=TransparentOpacity;
208
209
8.14k
  switch (quantum_type)
210
8.14k
    {
211
1.77k
    case IndexQuantum:
212
1.77k
      {
213
        /*
214
          PseudoClass
215
        */
216
1.77k
        switch (quantum_size)
217
1.77k
          {
218
1.43k
          case 8:
219
1.43k
            {
220
31.5k
              for (x=(long) image->columns; x > 0; x--)
221
30.1k
                {
222
30.1k
                  if (length == 0)
223
1.83k
                    {
224
1.83k
                      index=((unsigned int) *p++);
225
1.83k
                      VerifyColormapIndex(image,index);
226
1.83k
                      pixel=image->colormap[index];
227
1.83k
                      length=((int) *p++)+1;
228
1.83k
                    }
229
30.1k
                  length--;
230
30.1k
                  *indexes++=index;
231
30.1k
                *q++=pixel;
232
30.1k
                }
233
1.43k
              break;
234
0
            }
235
337
          case 16:
236
337
            {
237
2.45k
              for (x=(long) image->columns; x > 0; x--)
238
2.12k
                {
239
2.12k
                  if (length == 0)
240
416
                    {
241
416
                      index =((unsigned int) *p++ << 8);
242
416
                      index|=((unsigned int) *p++);
243
416
                      VerifyColormapIndex(image,index);
244
416
                      pixel=image->colormap[index];
245
416
                      length=((int) *p++)+1;
246
416
                    }
247
2.12k
                  length--;
248
2.12k
                  *indexes++=index;
249
2.12k
                  *q++=pixel;
250
2.12k
                }
251
337
              break;
252
0
            }
253
0
          case 32:
254
0
            {
255
              /*
256
                This case should never actually be used.
257
              */
258
0
              for (x=(long) image->columns; x > 0; x--)
259
0
                {
260
0
                  if (length == 0)
261
0
                    {
262
0
                      index =((unsigned int) *p++ << 24);
263
0
                      index|=((unsigned int) *p++ << 16);
264
0
                      index|=((unsigned int) *p++ << 8);
265
0
                      index|=((unsigned int) *p++);
266
0
                      VerifyColormapIndex(image,index);
267
0
                      pixel=image->colormap[index];
268
0
                      length=((int) *p++)+1;
269
0
                    }
270
0
                  length--;
271
0
                  *indexes++=index;
272
0
                  *q++=pixel;
273
0
                }
274
0
              break;
275
0
            }
276
1.77k
          }
277
1.77k
        break;
278
1.77k
      }
279
1.77k
    case IndexAlphaQuantum:
280
0
      {
281
        /*
282
          PseudoClass plus alpha channel
283
        */
284
0
        switch (quantum_size)
285
0
          {
286
0
          case 8:
287
0
            {
288
0
              for (x=(long) image->columns; x > 0; x--)
289
0
                {
290
0
                  if (length == 0)
291
0
                    {
292
0
                      index=((unsigned int) *p++);
293
0
                      VerifyColormapIndex(image,index);
294
0
                      pixel=image->colormap[index];
295
0
                      quantum=((unsigned int) *p++);
296
0
                      pixel.opacity=MaxRGB-ScaleCharToQuantum(quantum);
297
0
                      length=((int) *p++)+1;
298
0
                    }
299
0
                  length--;
300
0
                  *indexes++=index;
301
0
                *q++=pixel;
302
0
                }
303
0
              break;
304
0
            }
305
0
          case 16:
306
0
            {
307
0
              for (x=(long) image->columns; x > 0; x--)
308
0
                {
309
0
                  if (length == 0)
310
0
                    {
311
0
                      index =((unsigned int) *p++ << 8);
312
0
                      index|=((unsigned int) *p++);
313
0
                      VerifyColormapIndex(image,index);
314
0
                      pixel=image->colormap[index];
315
0
                      quantum =((unsigned int) *p++ << 8);
316
0
                      quantum|=((unsigned int) *p++);
317
0
                      pixel.opacity=MaxRGB-ScaleShortToQuantum(quantum);
318
0
                      length=((int) *p++)+1;
319
0
                    }
320
0
                  length--;
321
0
                  *indexes++=index;
322
0
                  *q++=pixel;
323
0
                }
324
0
              break;
325
0
            }
326
0
          case 32:
327
0
            {
328
              /*
329
                This case should never actually be used.
330
              */
331
0
              for (x=(long) image->columns; x > 0; x--)
332
0
                {
333
0
                  if (length == 0)
334
0
                    {
335
0
                      index =((unsigned int) *p++ << 24);
336
0
                      index|=((unsigned int) *p++ << 16);
337
0
                      index|=((unsigned int) *p++ << 8);
338
0
                      index|=((unsigned int) *p++);
339
0
                      VerifyColormapIndex(image,index);
340
0
                      pixel=image->colormap[index];
341
0
                      quantum =((unsigned int) *p++ << 24);
342
0
                      quantum|=((unsigned int) *p++ << 16);
343
0
                      quantum|=((unsigned int) *p++ << 8);
344
0
                      quantum|=((unsigned int) *p++);
345
0
                      pixel.opacity=MaxRGB-ScaleLongToQuantum(quantum);
346
0
                      length=((int) *p++)+1;
347
0
                    }
348
0
                  length--;
349
0
                  *indexes++=index;
350
0
                  *q++=pixel;
351
0
                }
352
0
              break;
353
0
            }
354
0
          }
355
0
        break;
356
0
      }
357
0
    case CMYKAQuantum:
358
0
      {
359
        /*
360
          Directclass CMYK & matte
361
        */
362
0
        switch (quantum_size)
363
0
          {
364
0
          case 8:
365
0
            {
366
0
              for (x=(long) image->columns; x > 0; x--)
367
0
                {
368
0
                  if (length == 0)
369
0
                    {
370
0
                      pixel.red=ScaleCharToQuantum(*p++);
371
0
                      pixel.green=ScaleCharToQuantum(*p++);
372
0
                      pixel.blue=ScaleCharToQuantum(*p++);
373
0
                      pixel.opacity=ScaleCharToQuantum(*p++);
374
0
                      index=(IndexPacket) MaxRGB-ScaleCharToQuantum(*p++);
375
0
                      length=((int) *p++)+1;
376
0
                    }
377
0
                  length--;
378
0
                  *indexes++=index;
379
0
                  *q++=pixel;
380
0
                }
381
0
              break;
382
0
            }
383
0
          case 16:
384
0
            {
385
0
              for (x=(long) image->columns; x > 0; x--)
386
0
                {
387
0
                  if (length == 0)
388
0
                    {
389
0
                      quantum= ((unsigned int) *p++ << 8);
390
0
                      quantum|=((unsigned int) *p++);
391
0
                      pixel.red=ScaleShortToQuantum(quantum);
392
0
                      quantum= ((unsigned int) *p++ << 8);
393
0
                      quantum|=((unsigned int) *p++);
394
0
                      pixel.green=ScaleShortToQuantum(quantum);
395
0
                      quantum =((unsigned int) *p++ << 8);
396
0
                      quantum|=((unsigned int) *p++);
397
0
                      pixel.blue=ScaleShortToQuantum(quantum);
398
0
                      quantum =((unsigned int) *p++ << 8);
399
0
                      quantum|=((unsigned int) *p++);
400
0
                      pixel.opacity=ScaleShortToQuantum(quantum);
401
0
                      quantum =((unsigned int) *p++ << 8);
402
0
                      quantum|=((unsigned int) *p++);
403
0
                      index=(IndexPacket) MaxRGB-ScaleShortToQuantum(quantum);
404
0
                      length=((int) *p++)+1;
405
0
                    }
406
0
                  length--;
407
0
                  *indexes++=index;
408
0
                  *q++=pixel;
409
0
                }
410
0
              break;
411
0
            }
412
0
          case 32:
413
0
            {
414
0
              for (x=(long) image->columns; x > 0; x--)
415
0
                {
416
0
                  if (length == 0)
417
0
                    {
418
0
                      quantum =((unsigned int) *p++ << 24);
419
0
                      quantum|=((unsigned int) *p++ << 16);
420
0
                      quantum|=((unsigned int) *p++ << 8);
421
0
                      quantum|=((unsigned int) *p++);
422
0
                      pixel.red=ScaleLongToQuantum(quantum);
423
0
                      quantum =((unsigned int) *p++ << 24);
424
0
                      quantum|=((unsigned int) *p++ << 16);
425
0
                      quantum|=((unsigned int) *p++ << 8);
426
0
                      quantum|=((unsigned int) *p++);
427
0
                      pixel.green=ScaleLongToQuantum(quantum);
428
0
                      quantum =((unsigned int) *p++ << 24);
429
0
                      quantum|=((unsigned int) *p++ << 16);
430
0
                      quantum|=((unsigned int) *p++ << 8);
431
0
                      quantum|=((unsigned int) *p++);
432
0
                      pixel.blue=ScaleLongToQuantum(quantum);
433
0
                      quantum =((unsigned int) *p++ << 24);
434
0
                      quantum|=((unsigned int) *p++ << 16);
435
0
                      quantum|=((unsigned int) *p++ << 8);
436
0
                      quantum|=((unsigned int) *p++);
437
0
                      pixel.opacity=ScaleLongToQuantum(quantum);
438
0
                      quantum =((unsigned int) *p++ << 24);
439
0
                      quantum|=((unsigned int) *p++ << 16);
440
0
                      quantum|=((unsigned int) *p++ << 8);
441
0
                      quantum|=((unsigned int) *p++);
442
0
                      index=(IndexPacket) MaxRGB-ScaleLongToQuantum(quantum);
443
0
                      length=((int) *p++)+1;
444
0
                    }
445
0
                  length--;
446
0
                  *indexes++=index;
447
0
                  *q++=pixel;
448
0
                }
449
0
              break;
450
0
            }
451
0
          }
452
0
        break;
453
0
      }
454
0
    case CMYKQuantum:
455
0
      {
456
        /*
457
          Directclass CMYK without matte
458
        */
459
0
        switch (quantum_size)
460
0
          {
461
0
          case 8:
462
0
            {
463
0
              for (x=(long) image->columns; x > 0; x--)
464
0
                {
465
0
                  if (length == 0)
466
0
                    {
467
0
                      pixel.red=ScaleCharToQuantum(*p++);
468
0
                      pixel.green=ScaleCharToQuantum(*p++);
469
0
                      pixel.blue=ScaleCharToQuantum(*p++);
470
0
                      pixel.opacity=ScaleCharToQuantum(*p++);
471
0
                      length=((int) *p++)+1;
472
0
                    }
473
0
                  length--;
474
0
                  *q++=pixel;
475
0
                }
476
0
              break;
477
0
            }
478
0
          case 16:
479
0
            {
480
0
              for (x=(long) image->columns; x > 0; x--)
481
0
                {
482
0
                  if (length == 0)
483
0
                    {
484
0
                      quantum =((unsigned int) *p++ << 8);
485
0
                      quantum|=((unsigned int) *p++);
486
0
                      pixel.red=ScaleShortToQuantum(quantum);
487
0
                      quantum =((unsigned int) *p++ << 8);
488
0
                      quantum|=((unsigned int) *p++);
489
0
                      pixel.green=ScaleShortToQuantum(quantum);
490
0
                      quantum =((unsigned int) *p++ << 8);
491
0
                      quantum|=((unsigned int) *p++);
492
0
                      pixel.blue=ScaleShortToQuantum(quantum);
493
0
                      quantum =((unsigned int) *p++ << 8);
494
0
                      quantum|=((unsigned int) *p++);
495
0
                      pixel.opacity=ScaleShortToQuantum(quantum);
496
0
                      length=((int) *p++)+1;
497
0
                    }
498
0
                  length--;
499
0
                  *q++=pixel;
500
0
                }
501
0
              break;
502
0
            }
503
0
          case 32:
504
0
            {
505
0
              for (x=(long) image->columns; x > 0; x--)
506
0
                {
507
0
                  if (length == 0)
508
0
                    {
509
0
                      quantum =((unsigned int) *p++ << 24);
510
0
                      quantum|=((unsigned int) *p++ << 16);
511
0
                      quantum|=((unsigned int) *p++ << 8);
512
0
                      quantum|=((unsigned int) *p++);
513
0
                      pixel.red=ScaleLongToQuantum(quantum);
514
0
                      quantum =((unsigned int) *p++ << 24);
515
0
                      quantum|=((unsigned int) *p++ << 16);
516
0
                      quantum|=((unsigned int) *p++ << 8);
517
0
                      quantum|=((unsigned int) *p++);
518
0
                      pixel.green=ScaleLongToQuantum(quantum);
519
0
                      quantum =((unsigned int) *p++ << 24);
520
0
                      quantum|=((unsigned int) *p++ << 16);
521
0
                      quantum|=((unsigned int) *p++ << 8);
522
0
                      quantum|=((unsigned int) *p++);
523
0
                      pixel.blue=ScaleLongToQuantum(quantum);
524
0
                      quantum =((unsigned int) *p++ << 24);
525
0
                      quantum|=((unsigned int) *p++ << 16);
526
0
                      quantum|=((unsigned int) *p++ << 8);
527
0
                      quantum|=((unsigned int) *p++);
528
0
                      pixel.opacity=ScaleLongToQuantum(quantum);
529
0
                      length=((int) *p++)+1;
530
0
                    }
531
0
                  length--;
532
0
                  *q++=pixel;
533
0
                }
534
0
              break;
535
0
            }
536
0
          }
537
0
        break;
538
0
      }
539
3.78k
    case RGBAQuantum:
540
3.78k
      {
541
        /*
542
          Directclass RGB with matte
543
        */
544
3.78k
        switch (quantum_size)
545
3.78k
          {
546
1.39k
          case 8:
547
1.39k
            {
548
415k
              for (x=(long) image->columns; x > 0; x--)
549
414k
                {
550
414k
                  if (length == 0)
551
7.41k
                    {
552
7.41k
                      pixel.red=ScaleCharToQuantum(*p++);
553
7.41k
                      pixel.green=ScaleCharToQuantum(*p++);
554
7.41k
                      pixel.blue=ScaleCharToQuantum(*p++);
555
7.41k
                      pixel.opacity=MaxRGB-ScaleCharToQuantum(*p++);
556
7.41k
                      length=((int) *p++)+1;
557
7.41k
                    }
558
414k
                  length--;
559
414k
                  *q++=pixel;
560
414k
                }
561
1.39k
              break;
562
0
            }
563
876
          case 16:
564
876
            {
565
32.8k
              for (x=(long) image->columns; x > 0; x--)
566
32.0k
                {
567
32.0k
                  if (length == 0)
568
1.28k
                    {
569
1.28k
                      quantum =((unsigned int) *p++ << 8);
570
1.28k
                      quantum|=((unsigned int) *p++);
571
1.28k
                      pixel.red=ScaleShortToQuantum(quantum);
572
1.28k
                      quantum =((unsigned int) *p++ << 8);
573
1.28k
                      quantum|=((unsigned int) *p++);
574
1.28k
                      pixel.green=ScaleShortToQuantum(quantum);
575
1.28k
                      quantum =((unsigned int) *p++ << 8);
576
1.28k
                      quantum|=((unsigned int) *p++);
577
1.28k
                      pixel.blue=ScaleShortToQuantum(quantum);
578
1.28k
                      quantum =((unsigned int) *p++ << 8);
579
1.28k
                      quantum|=((unsigned int) *p++);
580
1.28k
                      pixel.opacity=MaxRGB-ScaleShortToQuantum(quantum);
581
1.28k
                      length=((int) *p++)+1;
582
1.28k
                    }
583
32.0k
                  length--;
584
32.0k
                  *q++=pixel;
585
32.0k
                }
586
876
              break;
587
0
            }
588
1.51k
          case 32:
589
1.51k
            {
590
52.1k
              for (x=(long) image->columns; x > 0; x--)
591
50.6k
                {
592
50.6k
                  if (length == 0)
593
1.70k
                    {
594
1.70k
                      quantum =((unsigned int) *p++ << 24);
595
1.70k
                      quantum|=((unsigned int) *p++ << 16);
596
1.70k
                      quantum|=((unsigned int) *p++ << 8);
597
1.70k
                      quantum|=((unsigned int) *p++);
598
1.70k
                      pixel.red=ScaleLongToQuantum(quantum);
599
1.70k
                      quantum =((unsigned int) *p++ << 24);
600
1.70k
                      quantum|=((unsigned int) *p++ << 16);
601
1.70k
                      quantum|=((unsigned int) *p++ << 8);
602
1.70k
                      quantum|=((unsigned int) *p++);
603
1.70k
                      pixel.green=ScaleLongToQuantum(quantum);
604
1.70k
                      quantum =((unsigned int) *p++ << 24);
605
1.70k
                      quantum|=((unsigned int) *p++ << 16);
606
1.70k
                      quantum|=((unsigned int) *p++ << 8);
607
1.70k
                      quantum|=((unsigned int) *p++);
608
1.70k
                      pixel.blue=ScaleLongToQuantum(quantum);
609
1.70k
                      quantum =((unsigned int) *p++ << 24);
610
1.70k
                      quantum|=((unsigned int) *p++ << 16);
611
1.70k
                      quantum|=((unsigned int) *p++ << 8);
612
1.70k
                      quantum|=((unsigned int) *p++);
613
1.70k
                      pixel.opacity=MaxRGB-ScaleLongToQuantum(quantum);
614
1.70k
                      length=((int) *p++)+1;
615
1.70k
                    }
616
50.6k
                  length--;
617
50.6k
                  *q++=pixel;
618
50.6k
                }
619
1.51k
              break;
620
0
            }
621
3.78k
          }
622
3.78k
        break;
623
3.78k
      }
624
3.78k
    case RGBQuantum:
625
2.58k
      {
626
        /*
627
          Directclass RGB without matte
628
        */
629
2.58k
        switch (quantum_size)
630
2.58k
          {
631
546
          case 8:
632
546
            {
633
18.2k
              for (x=(long) image->columns; x > 0; x--)
634
17.6k
                {
635
17.6k
                  if (length == 0)
636
1.07k
                    {
637
1.07k
                      pixel.red=ScaleCharToQuantum(*p++);
638
1.07k
                      pixel.green=ScaleCharToQuantum(*p++);
639
1.07k
                      pixel.blue=ScaleCharToQuantum(*p++);
640
1.07k
                      length=((int) *p++)+1;
641
1.07k
                    }
642
17.6k
                  length--;
643
17.6k
                  *q++=pixel;
644
17.6k
                }
645
546
              break;
646
0
            }
647
389
          case 16:
648
389
            {
649
4.12k
              for (x=(long) image->columns; x > 0; x--)
650
3.73k
                {
651
3.73k
                  if (length == 0)
652
497
                    {
653
497
                      quantum =((unsigned int) *p++ << 8);
654
497
                      quantum|=((unsigned int) *p++);
655
497
                      pixel.red=ScaleShortToQuantum(quantum);
656
497
                      quantum =((unsigned int) *p++ << 8);
657
497
                      quantum|=((unsigned int) *p++);
658
497
                      pixel.green=ScaleShortToQuantum(quantum);
659
497
                      quantum =((unsigned int) *p++ << 8);
660
497
                      quantum|=((unsigned int) *p++);
661
497
                      pixel.blue=ScaleShortToQuantum(quantum);
662
497
                      length=((int) *p++)+1;
663
497
                    }
664
3.73k
                  length--;
665
3.73k
                  *q++=pixel;
666
3.73k
                }
667
389
              break;
668
0
            }
669
1.65k
          case 32:
670
1.65k
            {
671
585k
              for (x=(long) image->columns; x > 0; x--)
672
583k
                {
673
583k
                  if (length == 0)
674
7.87k
                    {
675
7.87k
                      quantum =((unsigned int) *p++ << 24);
676
7.87k
                      quantum|=((unsigned int) *p++ << 16);
677
7.87k
                      quantum|=((unsigned int) *p++ << 8);
678
7.87k
                      quantum|=((unsigned int) *p++);
679
7.87k
                      pixel.red=ScaleLongToQuantum(quantum);
680
7.87k
                      quantum =((unsigned int) *p++ << 24);
681
7.87k
                      quantum|=((unsigned int) *p++ << 16);
682
7.87k
                      quantum|=((unsigned int) *p++ << 8);
683
7.87k
                      quantum|=((unsigned int) *p++);
684
7.87k
                      pixel.green=ScaleLongToQuantum(quantum);
685
7.87k
                      quantum =((unsigned int) *p++ << 24);
686
7.87k
                      quantum|=((unsigned int) *p++ << 16);
687
7.87k
                      quantum|=((unsigned int) *p++ << 8);
688
7.87k
                      quantum|=((unsigned int) *p++);
689
7.87k
                      pixel.blue=ScaleLongToQuantum(quantum);
690
7.87k
                      length=((int) *p++)+1;
691
7.87k
                    }
692
583k
                  length--;
693
583k
                  *q++=pixel;
694
583k
                }
695
1.65k
            }
696
1.65k
            break;
697
2.58k
          }
698
2.58k
        break;
699
2.58k
      }
700
2.58k
    default:
701
0
      {
702
0
      }
703
8.14k
    }
704
8.14k
  return(MagickPass);
705
8.14k
}
706
707
#if 0
708
static void *BZLIBAllocFunc(void *opaque, int items, int size)
709
{
710
  ARG_NOT_USED(opaque);
711
  return MagickMallocCleared((size_t) items*size);
712
}
713
static void BZLIBFreeFunc(void *opaque, void *address)
714
{
715
  ARG_NOT_USED(opaque);
716
  MagickFree(address);
717
}
718
#endif
719
720
#if defined(HasZLIB)
721
static voidpf ZLIBAllocFunc(voidpf opaque, uInt items, uInt size) MAGICK_FUNC_MALLOC;
722
static voidpf ZLIBAllocFunc(voidpf opaque, uInt items, uInt size)
723
10.4k
{
724
10.4k
  ARG_NOT_USED(opaque);
725
10.4k
  return MagickMallocCleared(MagickArraySize(items,size));
726
10.4k
}
727
static void ZLIBFreeFunc(voidpf opaque, voidpf address)
728
10.4k
{
729
10.4k
  ARG_NOT_USED(opaque);
730
10.4k
  MagickFree(address);
731
10.4k
}
732
#endif /* defined(HasZLIB) */
733
734
#define ThrowMIFFReaderException(code_,reason_,image_)                  \
735
94.4k
  do {                                                                  \
736
94.4k
    MagickFreeResourceLimitedMemory(char *,comment);                    \
737
94.4k
    MagickFreeResourceLimitedMemory(char *,values);                     \
738
94.4k
    if (number_of_profiles > 0)                                         \
739
94.4k
      {                                                                 \
740
14.7k
        unsigned long _index;                                           \
741
46.9k
        for (_index=0; _index < number_of_profiles; _index++)           \
742
32.1k
          {                                                             \
743
32.1k
            MagickFreeMemory(profiles[_index].name);                    \
744
32.1k
            MagickFreeResourceLimitedMemory(unsigned char *,profiles[_index].info); \
745
32.1k
          }                                                             \
746
14.7k
        MagickFreeResourceLimitedMemory(ProfileInfo *,profiles);        \
747
14.7k
        number_of_profiles=0;                                           \
748
14.7k
      }                                                                 \
749
94.4k
    MagickFreeResourceLimitedMemory(unsigned char *,pixels);            \
750
94.4k
    MagickFreeResourceLimitedMemory(unsigned char *,compress_pixels);   \
751
94.4k
    ThrowReaderException(code_,reason_,image_);                         \
752
0
  } while (0);
753
754
568k
#define ReadMIFFMaxKeyWordCount 256 /* Arbitrary limit on keywords in one MIFF frame */
755
756
/*
757
  Ignore attempts to set the same attribute multiple times.
758
*/
759
static MagickPassFail
760
SetNewImageAttribute(Image *image,const char *key,const char *value)
761
259k
{
762
259k
  MagickPassFail
763
259k
    status;
764
765
259k
  status = SetImageAttribute(image,key,value);
766
767
259k
  if (GetImageAttribute(image,key) == (const ImageAttribute *) NULL)
768
0
    status = SetImageAttribute(image,key,value);
769
259k
  else
770
259k
    status = MagickFail;
771
772
259k
  return status;
773
259k
};
774
775
static Image *ReadMIFFImage(const ImageInfo *image_info,
776
  ExceptionInfo *exception)
777
97.6k
{
778
97.6k
#if defined(HasBZLIB)
779
97.6k
  bz_stream
780
97.6k
    bzip_info;
781
97.6k
#endif
782
783
97.6k
  char
784
97.6k
    id[MaxTextExtent],
785
97.6k
    keyword[MaxTextExtent];
786
787
97.6k
  double
788
97.6k
    version;
789
790
97.6k
  Image
791
97.6k
    *image;
792
793
97.6k
  int
794
97.6k
    c;
795
796
97.6k
  size_t
797
97.6k
    compressed_length,
798
97.6k
    length,
799
97.6k
    pixels_size;
800
801
97.6k
  long
802
97.6k
    y;
803
804
97.6k
  QuantumType
805
97.6k
    quantum_type;
806
807
97.6k
  register unsigned long
808
97.6k
    i;
809
810
97.6k
  register PixelPacket
811
97.6k
    *q;
812
813
97.6k
  register unsigned char
814
97.6k
    *p;
815
816
97.6k
  unsigned char
817
97.6k
    *compress_pixels = (unsigned char *) NULL,
818
97.6k
    *pixels = (unsigned char *) NULL;
819
820
97.6k
  void
821
97.6k
    *pixels_p;
822
823
97.6k
  MagickPassFail
824
97.6k
    status;
825
826
97.6k
  unsigned int
827
97.6k
    colors,
828
97.6k
    comment_count,
829
97.6k
    depth,
830
97.6k
    keyword_count,
831
97.6k
    packet_size,
832
97.6k
    quantum_size;
833
834
97.6k
  ProfileInfo
835
97.6k
    *profiles=0;
836
837
97.6k
  unsigned long
838
97.6k
    number_of_profiles=0;
839
840
97.6k
  char
841
97.6k
    *comment = NULL,
842
97.6k
    *values = NULL;
843
844
97.6k
#if defined(HasZLIB)
845
97.6k
  z_stream
846
97.6k
    zip_info;
847
97.6k
#endif
848
849
  /*
850
    Open image file.
851
  */
852
97.6k
  assert(image_info != (const ImageInfo *) NULL);
853
97.6k
  assert(image_info->signature == MagickSignature);
854
97.6k
  assert(exception != (ExceptionInfo *) NULL);
855
97.6k
  assert(exception->signature == MagickSignature);
856
97.6k
  image=AllocateImage(image_info);
857
97.6k
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
858
97.6k
  if (status == MagickFail)
859
97.6k
    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
860
  /*
861
    Decode image header;  header terminates one character beyond a ':'.
862
  */
863
97.6k
  c=ReadBlobByte(image);
864
97.6k
  if (c == EOF)
865
0
    {
866
0
      DestroyImage(image);
867
0
      return((Image *) NULL);
868
0
    }
869
97.6k
  *id='\0';
870
97.6k
  version=0.0;
871
97.6k
  do
872
97.6k
  {
873
    /*
874
      Decode image header;  header terminates one character beyond a ':'.
875
    */
876
97.6k
    colors=0;
877
97.6k
    image->depth=8;
878
97.6k
    image->compression=NoCompression;
879
97.6k
    image->storage_class=DirectClass;
880
97.6k
    comment_count=0;
881
97.6k
    keyword_count=0;
882
842k
    while (isgraph(c) && (c != ':'))
883
784k
    {
884
784k
      register char
885
784k
        *p;
886
887
784k
      if (c == '{')
888
14.8k
        {
889
14.8k
          size_t
890
14.8k
            comment_length;
891
892
          /*
893
            Insist that format is identified prior to any comments.
894
          */
895
14.8k
          if (id[0] == '\0')
896
3.14k
            {
897
3.14k
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
898
3.14k
                                    "Comment precedes format identifier (id=ImageMagick)");
899
3.14k
              ThrowMIFFReaderException(CorruptImageError,ImproperImageHeader,image);
900
0
            }
901
902
          /*
903
            Insist that only one comment is provided
904
          */
905
11.7k
          if (comment_count > 0)
906
3.53k
            {
907
3.53k
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
908
3.53k
                                    "Too many comments!");
909
3.53k
              ThrowMIFFReaderException(CorruptImageError,ImproperImageHeader,image);
910
0
            }
911
912
          /*
913
            Read comment-- any text between { }.
914
          */
915
8.20k
          comment_length=MaxTextExtent;
916
8.20k
          comment=MagickAllocateResourceLimitedMemory(char *,comment_length);
917
8.20k
          if (comment == (char *) NULL)
918
0
            ThrowMIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
919
8.20k
              image);
920
8.20k
          p=comment;
921
3.03M
          for ( ; comment != (char *) NULL; p++)
922
3.03M
          {
923
3.03M
            c=ReadBlobByte(image);
924
3.03M
            if ((c == EOF) || (c == '}'))
925
8.20k
              break;
926
3.02M
            if ((size_t) (p-comment+1) >= comment_length)
927
1.13k
              {
928
1.13k
                char
929
1.13k
                  *new_comment;
930
931
1.13k
                *p='\0';
932
1.13k
                comment_length += MaxTextExtent;
933
1.13k
                new_comment=MagickReallocateResourceLimitedMemory(char *,comment,comment_length);
934
1.13k
                if (new_comment == (char *) NULL)
935
0
                  {
936
0
                    MagickFreeResourceLimitedMemory(char *,comment);
937
0
                    break;
938
0
                  }
939
1.13k
                comment=new_comment;
940
1.13k
                p=comment+strlen(comment);
941
1.13k
              }
942
3.02M
            *p=c;
943
3.02M
          }
944
8.20k
          if (comment == (char *) NULL)
945
0
            ThrowMIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
946
8.20k
              image);
947
8.20k
          *p='\0';
948
8.20k
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Comment: \"%s\"", comment);
949
8.20k
          (void) SetNewImageAttribute(image,"comment",comment);
950
8.20k
          comment_count++;
951
8.20k
          MagickFreeResourceLimitedMemory(char *,comment);
952
8.20k
          c=ReadBlobByte(image);
953
8.20k
        }
954
769k
      else
955
769k
        if (isalnum(c))
956
597k
          {
957
597k
            size_t
958
597k
              values_length;
959
960
597k
            MagickBool
961
597k
              in_brace=MagickFalse;
962
963
            /*
964
              Get keyword.
965
            */
966
597k
            keyword[0]='\0';
967
597k
            p=keyword;
968
597k
            do
969
34.9M
            {
970
34.9M
              if ((p-keyword) < (MaxTextExtent-1))
971
10.6M
                *p++=c;
972
34.9M
              c=ReadBlobByte(image);
973
34.9M
            } while ((c != '=') && (c != EOF));
974
597k
            *p='\0';
975
597k
            if (c == EOF)
976
573k
              ThrowMIFFReaderException(CorruptImageError,ImproperImageHeader,image);
977
978
            /*
979
              Insist that the first keyword must be 'id' (id=ImageMagick)
980
            */
981
573k
            if ((keyword_count == 0) && (LocaleCompare(keyword,"id") != 0))
982
14
              {
983
14
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
984
14
                                      "First keyword must be 'id' (have '%s')",
985
14
                                      keyword);
986
14
                ThrowMIFFReaderException(CorruptImageError,ImproperImageHeader,image);
987
0
              }
988
            /*
989
              Get values.
990
991
              Values not containing spaces are terminated by the first
992
              white-space (or new-line) encountered.  Values containing
993
              spaces and/or new-lines must be surrounded by braces.
994
            */
995
573k
            values_length=MaxTextExtent;
996
573k
            values=MagickAllocateResourceLimitedMemory(char *,values_length);
997
573k
            if (values == (char *) NULL)
998
573k
              ThrowMIFFReaderException(ResourceLimitError,MemoryAllocationFailed,image);
999
573k
            values[0]='\0';
1000
573k
            c=ReadBlobByte(image);
1001
573k
            in_brace=(c == '{');
1002
573k
            if (in_brace)
1003
57.7k
              c=ReadBlobByte(image);
1004
573k
            p=values;
1005
51.7M
            while ((((!in_brace) && (c != '\n')) ||
1006
8.93M
                     ((in_brace) && (c != '}'))) &&
1007
51.7M
                   (c != EOF))
1008
51.6M
              {
1009
51.6M
                if ((size_t) (p-values+1) >= values_length)
1010
19.1k
                  {
1011
19.1k
                    char
1012
19.1k
                      *new_values;
1013
1014
19.1k
                    *p='\0';
1015
19.1k
                    values_length += MaxTextExtent;
1016
19.1k
                    new_values=MagickReallocateResourceLimitedMemory(char *,values,values_length);
1017
19.1k
                    if (new_values == (char *) NULL)
1018
0
                      {
1019
0
                        MagickFreeResourceLimitedMemory(char *,values);
1020
0
                        break;
1021
0
                      }
1022
19.1k
                    values=new_values;
1023
19.1k
                    p=values+strlen(values);
1024
19.1k
                  }
1025
51.6M
                if (values == (char *) NULL)
1026
51.6M
                  ThrowMIFFReaderException(ResourceLimitError,MemoryAllocationFailed,image);
1027
51.6M
                *p++=c;
1028
51.6M
                c=ReadBlobByte(image);
1029
51.6M
                if (!in_brace)
1030
42.8M
                  if (isspace(c))
1031
468k
                    break;
1032
51.6M
              }
1033
573k
            *p='\0';
1034
573k
            keyword_count++;
1035
573k
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1036
573k
                                  "keyword[%u]=\"%s\" values=\"%s\"",keyword_count,keyword,values);
1037
            /*
1038
              Insist that the first keyword value must be 'ImageMagick' (id=ImageMagick)
1039
            */
1040
573k
            if ((keyword_count == 1) && (LocaleCompare(values,"ImageMagick") != 0))
1041
4.80k
              {
1042
4.80k
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1043
4.80k
                                      "First keyword/value must be 'id=ImageMagick'");
1044
4.80k
                ThrowMIFFReaderException(CorruptImageError,ImproperImageHeader,image);
1045
0
              }
1046
            /*
1047
              Arbitrarily limit the number of header keywords to avoid DOS attempts.
1048
            */
1049
568k
            if (keyword_count > ReadMIFFMaxKeyWordCount)
1050
59
              {
1051
59
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1052
59
                                      "Excessive key word count %u"
1053
59
                                      " (Denial of service attempt?)",keyword_count);
1054
59
                ThrowMIFFReaderException(CorruptImageError,ImproperImageHeader,image);
1055
0
              }
1056
            /*
1057
              Assign a value to the specified keyword.
1058
            */
1059
568k
            switch (*keyword)
1060
568k
            {
1061
9.15k
              case 'b':
1062
15.1k
              case 'B':
1063
15.1k
              {
1064
15.1k
                if (LocaleCompare(keyword,"background-color") == 0)
1065
954
                  {
1066
954
                    (void) QueryColorDatabase(values,&image->background_color,
1067
954
                      exception);
1068
954
                    break;
1069
954
                  }
1070
14.1k
                if (LocaleCompare(keyword,"blue-primary") == 0)
1071
210
                  {
1072
210
                    (void) sscanf(values,"%lf,%lf",
1073
210
                      &image->chromaticity.blue_primary.x,
1074
210
                      &image->chromaticity.blue_primary.y);
1075
210
                    break;
1076
210
                  }
1077
13.9k
                if (LocaleCompare(keyword,"border-color") == 0)
1078
4.26k
                  {
1079
4.26k
                    (void) QueryColorDatabase(values,&image->border_color,
1080
4.26k
                      exception);
1081
4.26k
                    break;
1082
4.26k
                  }
1083
9.68k
                (void) SetNewImageAttribute(image,keyword,
1084
9.68k
                  *values == '{' ? values+1 : values);
1085
9.68k
                break;
1086
13.9k
              }
1087
74.3k
              case 'c':
1088
76.5k
              case 'C':
1089
76.5k
              {
1090
76.5k
                if (LocaleCompare(keyword,"class") == 0)
1091
491
                  {
1092
491
                    image->storage_class=UndefinedClass;
1093
491
                    if (LocaleCompare(values,"PseudoClass") == 0)
1094
0
                      image->storage_class=PseudoClass;
1095
491
                    else
1096
491
                      if (LocaleCompare(values,"DirectClass") == 0)
1097
0
                        image->storage_class=DirectClass;
1098
491
                    break;
1099
491
                  }
1100
                /* Legacy ImageMagick 4.2.9 used keyword "color-profile" for ICC profile */
1101
76.0k
                if (LocaleCompare(keyword,"color-profile") == 0)
1102
0
                  {
1103
0
                    ProfileInfo
1104
0
                      *new_profiles = (ProfileInfo *) NULL;
1105
1106
0
                    if (MagickAtoL(values) <= 0)
1107
0
                      ThrowMIFFReaderException(CorruptImageError,ImproperImageHeader,image);
1108
0
                    i=number_of_profiles;
1109
0
                    new_profiles=MagickReallocateResourceLimitedArray(ProfileInfo *,profiles,
1110
0
                                                                     (size_t)number_of_profiles+1,sizeof(ProfileInfo));
1111
0
                    if (new_profiles == (ProfileInfo *) NULL)
1112
0
                      ThrowMIFFReaderException(ResourceLimitError,MemoryAllocationFailed,image);
1113
0
                    profiles=new_profiles;
1114
0
                    profiles[i].name=AllocateString("icc");
1115
0
                    profiles[i].length=MagickAtoL(values);
1116
0
                    profiles[i].info=(unsigned char *) NULL;
1117
0
                    number_of_profiles++;
1118
0
                    break;
1119
0
                  }
1120
76.0k
                if (LocaleCompare(keyword,"colors") == 0)
1121
317
                  {
1122
317
                    colors=MagickAtoL(values);
1123
317
                    break;
1124
317
                  }
1125
75.7k
                if (LocaleCompare(keyword,"colorspace") == 0)
1126
5.41k
                  {
1127
                    /*
1128
                      ImageMagick now uses colorspace=sRGB for ordinary RGB images.
1129
                    */
1130
5.41k
                    if (LocaleCompare(values,"sRGB") == 0)
1131
222
                      image->colorspace=RGBColorspace;
1132
5.19k
                    else
1133
5.19k
                      image->colorspace=(StringToColorspaceType(values));
1134
5.41k
                    break;
1135
5.41k
                  }
1136
70.2k
                if (LocaleCompare(keyword,"compression") == 0)
1137
6.25k
                  {
1138
6.25k
                    image->compression=NoCompression;
1139
6.25k
                    if (LocaleCompare(values,"None") == 0)
1140
194
                      image->compression=NoCompression;
1141
6.05k
                    else
1142
6.05k
                      if (LocaleCompare(values,"Zip") == 0)
1143
3.00k
                        image->compression=ZipCompression;
1144
3.05k
                      else
1145
3.05k
                        if (LocaleCompare(values,"BZip") == 0)
1146
1.85k
                          image->compression=BZipCompression;
1147
1.19k
                        else
1148
1.19k
                          if ((LocaleCompare(values,"RLE") == 0) ||
1149
647
                              (LocaleCompare(values,"RunlengthEncoded") == 0))
1150
544
                            image->compression=RLECompression;
1151
6.25k
                    break;
1152
6.25k
                  }
1153
64.0k
                if (LocaleCompare(keyword,"columns") == 0)
1154
49.0k
                  {
1155
49.0k
                    image->columns= MagickAtoL(values);
1156
49.0k
                    break;
1157
49.0k
                  }
1158
15.0k
                (void) SetNewImageAttribute(image,keyword,
1159
15.0k
                  *values == '{' ? values+1 : values);
1160
15.0k
                break;
1161
64.0k
              }
1162
8.47k
              case 'd':
1163
9.99k
              case 'D':
1164
9.99k
              {
1165
9.99k
                if (LocaleCompare(keyword,"delay") == 0)
1166
347
                  {
1167
347
                    image->delay=MagickAtoL(values);
1168
347
                    break;
1169
347
                  }
1170
9.64k
                if (LocaleCompare(keyword,"depth") == 0)
1171
2.42k
                  {
1172
2.42k
                    image->depth=MagickAtoL(values);
1173
2.42k
                    break;
1174
2.42k
                  }
1175
7.22k
                if (LocaleCompare(keyword,"dispose") == 0)
1176
1.81k
                  {
1177
1.81k
                    image->dispose=(DisposeType) MagickAtoL(values);
1178
1.81k
                    if (LocaleCompare(values,"Background") == 0)
1179
202
                      image->dispose=BackgroundDispose;
1180
1.60k
                    else
1181
1.60k
                      if (LocaleCompare(values,"None") == 0)
1182
611
                        image->dispose=NoneDispose;
1183
997
                      else
1184
997
                        if (LocaleCompare(values,"Previous") == 0)
1185
0
                          image->dispose=PreviousDispose;
1186
1.81k
                    break;
1187
1.81k
                  }
1188
5.41k
                (void) SetNewImageAttribute(image,keyword,
1189
5.41k
                  *values == '{' ? values+1 : values);
1190
5.41k
                break;
1191
7.22k
              }
1192
5.91k
              case 'g':
1193
9.52k
              case 'G':
1194
9.52k
              {
1195
9.52k
                if (LocaleCompare(keyword,"gamma") == 0)
1196
201
                  {
1197
201
                    image->gamma=MagickAtoF(values);
1198
201
                    break;
1199
201
                  }
1200
9.32k
                if (LocaleCompare(keyword,"green-primary") == 0)
1201
511
                  {
1202
511
                    (void) sscanf(values,"%lf,%lf",
1203
511
                      &image->chromaticity.green_primary.x,
1204
511
                      &image->chromaticity.green_primary.y);
1205
511
                    break;
1206
511
                  }
1207
8.81k
                (void) SetNewImageAttribute(image,keyword,
1208
8.81k
                  *values == '{' ? values+1 : values);
1209
8.81k
                break;
1210
9.32k
              }
1211
68.8k
              case 'i':
1212
116k
              case 'I':
1213
116k
              {
1214
116k
                if (LocaleCompare(keyword,"id") == 0)
1215
99.4k
                  {
1216
99.4k
                    (void) strlcpy(id,values,MaxTextExtent);
1217
99.4k
                    break;
1218
99.4k
                  }
1219
17.2k
                if (LocaleCompare(keyword,"iterations") == 0)
1220
349
                  {
1221
349
                    image->iterations=MagickAtoL(values);
1222
349
                    break;
1223
349
                  }
1224
16.8k
                (void) SetNewImageAttribute(image,keyword,
1225
16.8k
                  *values == '{' ? values+1 : values);
1226
16.8k
                break;
1227
17.2k
              }
1228
25.1k
              case 'm':
1229
27.0k
              case 'M':
1230
27.0k
              {
1231
27.0k
                if (LocaleCompare(keyword,"matte") == 0)
1232
1.11k
                  {
1233
1.11k
                    image->matte=(LocaleCompare(values,"True") == 0) ||
1234
857
                      (LocaleCompare(values,"true") == 0);
1235
1.11k
                    break;
1236
1.11k
                  }
1237
25.9k
                if (LocaleCompare(keyword,"matte-color") == 0)
1238
10.2k
                  {
1239
10.2k
                    (void) QueryColorDatabase(values,&image->matte_color,
1240
10.2k
                      exception);
1241
10.2k
                    break;
1242
10.2k
                  }
1243
15.6k
                if (LocaleCompare(keyword,"montage") == 0)
1244
1.28k
                  {
1245
1.28k
                    (void) CloneString(&image->montage,values);
1246
1.28k
                    break;
1247
1.28k
                  }
1248
14.3k
                (void) SetNewImageAttribute(image,keyword,
1249
14.3k
                  *values == '{' ? values+1 : values);
1250
14.3k
                break;
1251
15.6k
              }
1252
10.2k
              case 'o':
1253
12.7k
              case 'O':
1254
12.7k
              {
1255
12.7k
                if (LocaleCompare(keyword,"opaque") == 0)
1256
213
                  {
1257
213
                    image->matte=(LocaleCompare(values,"True") == 0) ||
1258
213
                      (LocaleCompare(values,"true") == 0);
1259
213
                    break;
1260
213
                  }
1261
12.5k
                if (LocaleCompare(keyword,"orientation") == 0)
1262
2.42k
                  {
1263
2.42k
                    image->orientation=StringToOrientationType(values);
1264
2.42k
                    break;
1265
2.42k
                  }
1266
10.0k
                (void) SetNewImageAttribute(image,keyword,
1267
10.0k
                  *values == '{' ? values+1 : values);
1268
10.0k
                break;
1269
12.5k
              }
1270
13.3k
              case 'p':
1271
174k
              case 'P':
1272
174k
              {
1273
174k
                if (LocaleCompare(keyword,"page") == 0)
1274
30.3k
                  {
1275
30.3k
                    char
1276
30.3k
                      *geometry;
1277
1278
30.3k
                    geometry=GetPageGeometry(values);
1279
30.3k
                    (void) GetGeometry(geometry,&image->page.x,&image->page.y,
1280
30.3k
                      &image->page.width,&image->page.height);
1281
30.3k
                    MagickFreeMemory(geometry);
1282
30.3k
                    break;
1283
30.3k
                  }
1284
144k
                if ((LocaleNCompare(keyword,"profile-",8) == 0) ||
1285
90.4k
                    (LocaleNCompare(keyword,"profile:",8) == 0))
1286
56.3k
                  {
1287
56.3k
                    ProfileInfo
1288
56.3k
                      *new_profiles;
1289
1290
56.3k
                    if (MagickAtoL(values) <= 0)
1291
51.9k
                      ThrowMIFFReaderException(CorruptImageError,ImproperImageHeader,image);
1292
51.9k
                    i=number_of_profiles;
1293
51.9k
                    new_profiles=MagickReallocateResourceLimitedArray(ProfileInfo *,profiles,
1294
51.9k
                                                                     (size_t)number_of_profiles+1,sizeof(ProfileInfo));
1295
51.9k
                    if (new_profiles == (ProfileInfo *) NULL)
1296
51.9k
                      ThrowMIFFReaderException(ResourceLimitError,MemoryAllocationFailed,image);
1297
51.9k
                    profiles=new_profiles;
1298
51.9k
                    profiles[i].name=AllocateString(keyword+8);
1299
51.9k
                    profiles[i].length=MagickAtoL(values);
1300
51.9k
                    profiles[i].info=(unsigned char *) NULL;
1301
51.9k
                    number_of_profiles++;
1302
51.9k
                    break;
1303
51.9k
                  }
1304
88.2k
                (void) SetNewImageAttribute(image,keyword,
1305
88.2k
                  *values == '{' ? values+1 : values);
1306
88.2k
                break;
1307
144k
              }
1308
43.4k
              case 'r':
1309
68.9k
              case 'R':
1310
68.9k
              {
1311
68.9k
                if (LocaleCompare(keyword,"red-primary") == 0)
1312
221
                  {
1313
221
                    (void) sscanf(values,"%lf,%lf",
1314
221
                      &image->chromaticity.red_primary.x,
1315
221
                      &image->chromaticity.red_primary.y);
1316
221
                    break;
1317
221
                  }
1318
68.7k
                if (LocaleCompare(keyword,"rendering-intent") == 0)
1319
448
                  {
1320
448
                    image->rendering_intent=UndefinedIntent;
1321
448
                    if (LocaleCompare(values,"Saturation") == 0)
1322
0
                      image->rendering_intent=SaturationIntent;
1323
448
                    else
1324
448
                      if (LocaleCompare(values,"perceptual") == 0)
1325
0
                        image->rendering_intent=PerceptualIntent;
1326
448
                      else
1327
448
                        if (LocaleCompare(values,"absolute") == 0)
1328
0
                          image->rendering_intent=AbsoluteIntent;
1329
448
                        else
1330
448
                          if (LocaleCompare(values,"relative") == 0)
1331
0
                            image->rendering_intent=RelativeIntent;
1332
448
                    break;
1333
448
                  }
1334
68.3k
                if (LocaleCompare(keyword,"resolution") == 0)
1335
6.63k
                  {
1336
6.63k
                    (void) GetMagickDimension(values,&image->x_resolution,
1337
6.63k
                                              &image->y_resolution,NULL,NULL);
1338
6.63k
                    break;
1339
6.63k
                  }
1340
61.6k
                if (LocaleCompare(keyword,"rows") == 0)
1341
34.7k
                  {
1342
34.7k
                    image->rows= MagickAtoL(values);
1343
34.7k
                    break;
1344
34.7k
                  }
1345
26.8k
                (void) SetNewImageAttribute(image,keyword,
1346
26.8k
                  *values == '{' ? values+1 : values);
1347
26.8k
                break;
1348
61.6k
              }
1349
7.25k
              case 's':
1350
13.6k
              case 'S':
1351
13.6k
              {
1352
13.6k
                if (LocaleCompare(keyword,"scene") == 0)
1353
427
                  {
1354
427
                    image->scene=MagickAtoL(values);
1355
427
                    break;
1356
427
                  }
1357
13.1k
                (void) SetNewImageAttribute(image,keyword,
1358
13.1k
                  *values == '{' ? values+1 : values);
1359
13.1k
                break;
1360
13.6k
              }
1361
2.28k
              case 'u':
1362
3.51k
              case 'U':
1363
3.51k
              {
1364
3.51k
                if (LocaleCompare(keyword,"units") == 0)
1365
299
                  {
1366
299
                    image->units=UndefinedResolution;
1367
299
                    if (LocaleCompare(values,"pixels-per-inch") == 0)
1368
0
                      image->units=PixelsPerInchResolution;
1369
299
                    else
1370
299
                      if (LocaleCompare(values,"pixels-per-centimeter") == 0)
1371
0
                        image->units=PixelsPerCentimeterResolution;
1372
299
                    break;
1373
299
                  }
1374
3.21k
                (void) SetNewImageAttribute(image,keyword,
1375
3.21k
                  *values == '{' ? values+1 : values);
1376
3.21k
                break;
1377
3.51k
              }
1378
2.29k
              case 'v':
1379
3.45k
              case 'V':
1380
3.45k
              {
1381
3.45k
                if (LocaleCompare(keyword,"version") == 0)
1382
537
                  {
1383
537
                    version=MagickAtoF(values);
1384
537
                    break;
1385
537
                  }
1386
2.91k
                (void) SetNewImageAttribute(image,keyword,
1387
2.91k
                  *values == '{' ? values+1 : values);
1388
2.91k
                break;
1389
3.45k
              }
1390
8.59k
              case 'w':
1391
11.0k
              case 'W':
1392
11.0k
              {
1393
11.0k
                if (LocaleCompare(keyword,"white-point") == 0)
1394
0
                  {
1395
0
                    (void) sscanf(values,"%lf,%lf",
1396
0
                      &image->chromaticity.white_point.x,
1397
0
                      &image->chromaticity.white_point.y);
1398
0
                    break;
1399
0
                  }
1400
11.0k
                (void) SetNewImageAttribute(image,keyword,
1401
11.0k
                  *values == '{' ? values+1 : values);
1402
11.0k
                break;
1403
11.0k
              }
1404
25.3k
              default:
1405
25.3k
              {
1406
25.3k
                (void) SetNewImageAttribute(image,keyword,
1407
25.3k
                  *values == '{' ? values+1 : values);
1408
25.3k
                break;
1409
11.0k
              }
1410
568k
            }
1411
564k
            MagickFreeResourceLimitedMemory(char *,values);
1412
564k
          }
1413
172k
        else
1414
172k
          {
1415
172k
            c=ReadBlobByte(image);
1416
172k
          }
1417
745k
      while (isspace(c))
1418
623k
        c=ReadBlobByte(image);
1419
745k
    }
1420
57.8k
    (void) ReadBlobByte(image);
1421
1422
57.8k
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1423
57.8k
                          "id=\"%s\" version=%g class=%s colorspace=%s compression=%s matte=%s "
1424
57.8k
                          "columns=%lu rows=%lu depth=%u",
1425
57.8k
                          id,version,
1426
57.8k
                          ClassTypeToString(image->storage_class),
1427
57.8k
                          ColorspaceTypeToString(image->colorspace),
1428
57.8k
                          CompressionTypeToString(image->compression),
1429
57.8k
                          MagickBoolToString(image->matte),
1430
57.8k
                          image->columns, image->rows, image->depth);
1431
1432
    /*
1433
      Verify that required image information is defined.
1434
    */
1435
57.8k
    if ((LocaleCompare(id,"ImageMagick") != 0) ||
1436
57.2k
        (image->storage_class == UndefinedClass) ||
1437
57.2k
        (image->compression == UndefinedCompression) ||
1438
57.2k
        (image->colorspace == UndefinedColorspace) ||
1439
57.1k
        (image->columns == 0) ||
1440
33.0k
        (image->rows == 0) ||
1441
26.3k
        (image->depth == 0) || (image->depth > 32))
1442
31.6k
      {
1443
31.6k
        if (image->previous)
1444
0
          {
1445
0
            DeleteImageFromList(&image);
1446
0
            ThrowException(exception,CorruptImageWarning,ImproperImageHeader,image->filename);
1447
0
            break;
1448
0
          }
1449
31.6k
        else
1450
31.6k
          {
1451
31.6k
            ThrowMIFFReaderException(CorruptImageError,ImproperImageHeader,
1452
31.6k
              image);
1453
0
          }
1454
31.6k
      }
1455
1456
    /*
1457
      Create a normalized version of depth.
1458
    */
1459
26.2k
    if (image->depth <= 8)
1460
24.4k
      depth=8;
1461
1.82k
    else if (image->depth <= 16)
1462
195
      depth=16;
1463
1.63k
    else
1464
1.63k
      depth=32;
1465
1466
26.2k
    if (image->montage != (char *) NULL)
1467
82
      {
1468
82
        register char
1469
82
          *p;
1470
1471
82
        size_t
1472
82
          directory_length;
1473
1474
        /*
1475
          Image directory.
1476
        */
1477
82
        image->directory=MagickAllocateMemory(char *,MaxTextExtent);
1478
82
        if (image->directory == (char *) NULL)
1479
82
          ThrowMIFFReaderException(CorruptImageError,UnableToReadImageData,image);
1480
82
        p=image->directory;
1481
82
        directory_length=0;
1482
82
        do
1483
565k
        {
1484
565k
          *p='\0';
1485
565k
          if (((directory_length+1) % MaxTextExtent) == 0)
1486
271
            {
1487
              /*
1488
                Allocate more memory for the image directory.
1489
              */
1490
271
              MagickReallocMemory(char *,image->directory,
1491
271
                (directory_length+MaxTextExtent+1));
1492
271
              if (image->directory == (char *) NULL)
1493
0
                ThrowMIFFReaderException(CorruptImageError,UnableToReadImageData,
1494
271
                  image);
1495
271
              p=image->directory+directory_length;
1496
271
            }
1497
565k
          c=ReadBlobByte(image);
1498
565k
          if (c == EOF)
1499
57
            break;
1500
565k
          *p++=c;
1501
565k
          ++directory_length;
1502
565k
        } while (c != '\0');
1503
82
      }
1504
1505
    /*
1506
      Attached profiles.
1507
    */
1508
26.2k
    if (number_of_profiles > 0)
1509
14.7k
      {
1510
35.7k
        for (i=0; i < number_of_profiles; i++)
1511
24.8k
        {
1512
24.8k
          if (profiles[i].length > 0)
1513
24.8k
            {
1514
24.8k
              if ((((magick_off_t) profiles[i].length) > 0) &&
1515
24.8k
                  ((BlobIsSeekable(image)
1516
24.8k
                    && (GetBlobSize(image) - TellBlob(image)) >
1517
24.8k
                    (magick_off_t) profiles[i].length) ||
1518
3.99k
                   (profiles[i].length < 15*1024*1024)))
1519
24.5k
                {
1520
24.5k
                  profiles[i].info=MagickAllocateResourceLimitedMemory(unsigned char *,profiles[i].length);
1521
24.5k
                  if (profiles[i].info == (unsigned char *) NULL)
1522
0
                    ThrowMIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
1523
24.5k
                                             image);
1524
24.5k
                  if (ReadBlob(image,profiles[i].length,profiles[i].info)
1525
24.5k
                      != profiles[i].length)
1526
3.64k
                    ThrowMIFFReaderException(CorruptImageError,
1527
24.5k
                                             UnexpectedEndOfFile,
1528
24.5k
                                             image);
1529
20.9k
                  (void) SetImageProfile(image,profiles[i].name,profiles[i].info,profiles[i].length);
1530
20.9k
                }
1531
297
              else
1532
297
                {
1533
297
                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1534
297
                                        "Profile size %" MAGICK_SIZE_T_F "u is excessively large",
1535
297
                                        (MAGICK_SIZE_T ) profiles[i].length);
1536
297
                  ThrowMIFFReaderException(CorruptImageError,ImproperImageHeader,
1537
297
                                           image);
1538
0
                }
1539
24.8k
            }
1540
20.9k
          MagickFreeMemory(profiles[i].name);
1541
20.9k
          MagickFreeResourceLimitedMemory(unsigned char *,profiles[i].info);
1542
20.9k
        }
1543
10.8k
        MagickFreeResourceLimitedMemory(ProfileInfo *,profiles);
1544
10.8k
        number_of_profiles=0;
1545
10.8k
      }
1546
1547
22.3k
    if (image->storage_class == PseudoClass)
1548
0
      {
1549
        /*
1550
          Create image colormap.
1551
        */
1552
0
        if (!AllocateImageColormap(image,colors != 0 ? colors : 256))
1553
0
          ThrowMIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
1554
0
            image);
1555
0
        if (colors != 0)
1556
0
          {
1557
0
            unsigned char
1558
0
              *colormap;
1559
1560
0
            unsigned int
1561
0
              packet_size,
1562
0
              pixel;
1563
1564
            /*
1565
              Read image colormap from file.
1566
            */
1567
0
            packet_size=3*depth/8;
1568
0
            colormap=MagickAllocateResourceLimitedArray(unsigned char *,packet_size,image->colors);
1569
0
            if (colormap == (unsigned char *) NULL)
1570
0
              ThrowMIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
1571
0
                image);
1572
0
            (void) ReadBlob(image, (size_t)packet_size*image->colors,colormap);
1573
0
            p=colormap;
1574
0
            switch (depth)
1575
0
              {
1576
0
              case 8:
1577
0
                {
1578
0
                  for (i=0; i < image->colors; i++)
1579
0
                    {
1580
0
                      image->colormap[i].red=ScaleCharToQuantum(*p++);
1581
0
                      image->colormap[i].green=ScaleCharToQuantum(*p++);
1582
0
                      image->colormap[i].blue=ScaleCharToQuantum(*p++);
1583
0
                    }
1584
0
                  break;
1585
0
                }
1586
0
              case 16:
1587
0
                {
1588
0
                  for (i=0; i < image->colors; i++)
1589
0
                    {
1590
0
                      pixel=((unsigned int) *p << 8) | (unsigned int) *(p+1);
1591
0
                      image->colormap[i].red=ScaleShortToQuantum(pixel);
1592
0
                      p+=2;
1593
0
                      pixel=((unsigned int) *p << 8) | (unsigned int) *(p+1);
1594
0
                      image->colormap[i].green=ScaleShortToQuantum(pixel);
1595
0
                      p+=2;
1596
0
                      pixel=((unsigned int) *p << 8) | (unsigned int) *(p+1);
1597
0
                      image->colormap[i].blue=ScaleShortToQuantum(pixel);
1598
0
                      p+=2;
1599
0
                    }
1600
0
                  break;
1601
0
                }
1602
0
              case 32:
1603
0
                {
1604
0
                  for (i=0; i < image->colors; i++)
1605
0
                    {
1606
0
                      pixel=((unsigned int) *p << 24) |
1607
0
                        ((unsigned int) *(p+1) << 16) |
1608
0
                        ((unsigned int) *(p+2) << 8) |
1609
0
                        (unsigned int) *(p+3);
1610
0
                      image->colormap[i].red=ScaleLongToQuantum(pixel);
1611
0
                      p+=4;
1612
0
                      pixel=((unsigned int) *p << 24) |
1613
0
                        ((unsigned int) *(p+1) << 16) |
1614
0
                        ((unsigned int) *(p+2) << 8) |
1615
0
                        (unsigned int) *(p+3);
1616
0
                      image->colormap[i].green=ScaleLongToQuantum(pixel);
1617
0
                      p+=4;
1618
0
                      pixel=((unsigned int) *p << 24) |
1619
0
                        ((unsigned int) *(p+1) << 16) |
1620
0
                        ((unsigned int) *(p+2) << 8) |
1621
0
                        (unsigned int) *(p+3);
1622
0
                      image->colormap[i].blue=ScaleLongToQuantum(pixel);
1623
0
                      p+=4;
1624
0
                    }
1625
0
                }
1626
0
              } /* switch (depth) */
1627
0
            MagickFreeResourceLimitedMemory(unsigned char *,colormap);
1628
0
          }
1629
0
      }
1630
22.3k
    if (image_info->ping && (image_info->subrange != 0))
1631
0
      if (image->scene >= (image_info->subimage+image_info->subrange-1))
1632
0
        break;
1633
1634
22.3k
    if (CheckImagePixelLimits(image, exception) != MagickPass)
1635
17.0k
      ThrowMIFFReaderException(ResourceLimitError,ImagePixelLimitExceeded,image);
1636
1637
    /*
1638
      Determine import properties
1639
    */
1640
5.29k
    quantum_size=0;
1641
5.29k
    if (image->storage_class == PseudoClass)
1642
0
      {
1643
0
        quantum_type=image->matte ? IndexAlphaQuantum : IndexQuantum;
1644
0
        if (image->colors <= 256)
1645
0
          quantum_size=8;
1646
0
        else if (image->colors <= 65536)
1647
0
          quantum_size=16;
1648
0
        else
1649
0
          quantum_size=32;
1650
0
      }
1651
5.29k
    else
1652
5.29k
      {
1653
5.29k
        quantum_type=RGBQuantum;
1654
5.29k
        quantum_size=depth;
1655
5.29k
        if IsGrayColorspace(image->colorspace)
1656
475
          {
1657
475
            quantum_type=GrayQuantum;
1658
475
            if (image->matte)
1659
38
              quantum_type=GrayAlphaQuantum;
1660
475
          }
1661
4.82k
        else if (image->colorspace == CMYKColorspace)
1662
0
          {
1663
0
            quantum_type=CMYKQuantum;
1664
0
            if (image->matte)
1665
0
              quantum_type=CMYKAQuantum;
1666
0
          }
1667
4.82k
        else
1668
4.82k
          {
1669
4.82k
            quantum_type=RGBQuantum;
1670
4.82k
            if (image->matte)
1671
116
              quantum_type=RGBAQuantum;
1672
4.82k
          }
1673
5.29k
      }
1674
5.29k
    if ((quantum_type == GrayQuantum) && (MaxValueGivenBits(depth) <= MaxMap))
1675
225
      {
1676
        /*
1677
          Create image colormap and read grey image as PseudoClass.
1678
        */
1679
225
        if (!AllocateImageColormap(image,MaxValueGivenBits(depth)+1))
1680
0
          ThrowMIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
1681
225
                                   image);
1682
225
        quantum_type=IndexQuantum;
1683
225
      }
1684
1685
     /*
1686
      Allocate image pixels.
1687
    */
1688
5.29k
    packet_size=quantum_size/8;
1689
5.29k
    if ((image->storage_class == DirectClass) &&
1690
5.07k
        (!IsGrayColorspace(image->colorspace)))
1691
4.82k
      packet_size=3*quantum_size/8;
1692
5.29k
    if (image->colorspace == CMYKColorspace)
1693
0
      packet_size+=quantum_size/8;
1694
5.29k
    if (image->matte)
1695
154
      packet_size+=quantum_size/8;
1696
5.29k
    if (image->compression == RLECompression)
1697
305
      packet_size++;
1698
5.29k
    pixels_size=MagickArraySize(packet_size,image->columns);
1699
5.29k
    if (pixels_size == 0)
1700
5.29k
      ThrowMIFFReaderException(CoderError,ArithmeticOverflow,image);
1701
5.29k
    pixels=MagickAllocateResourceLimitedMemory(unsigned char *,pixels_size);
1702
5.29k
    if (pixels == (unsigned char *) NULL)
1703
5.29k
      ThrowMIFFReaderException(ResourceLimitError,MemoryAllocationFailed,image);
1704
5.29k
    length=(size_t) (1.01*pixels_size);
1705
5.29k
    if (length < pixels_size)
1706
5.29k
      ThrowMIFFReaderException(CoderError,ArithmeticOverflow,image);
1707
5.29k
    if (~((size_t) 0) - length > 600)
1708
5.29k
      length += 600;
1709
0
    else
1710
5.29k
      ThrowMIFFReaderException(CoderError,ArithmeticOverflow,image);
1711
5.29k
    compressed_length = length;
1712
5.29k
    compress_pixels=MagickAllocateResourceLimitedMemory(unsigned char *,compressed_length);
1713
5.29k
    if (compress_pixels == (unsigned char *) NULL)
1714
5.29k
      ThrowMIFFReaderException(ResourceLimitError,MemoryAllocationFailed,image);
1715
    /*
1716
      Read image pixels.
1717
    */
1718
5.29k
   length=0;
1719
5.29k
    switch (image->compression)
1720
5.29k
      {
1721
0
#if defined(HasZLIB)
1722
2.27k
      case ZipCompression:
1723
2.27k
        {
1724
2.27k
          int
1725
2.27k
            code=0;
1726
1727
386k
          for (y=0; y < (long) image->rows; y++)
1728
385k
            {
1729
385k
              q=SetImagePixels(image,0,y,image->columns,1);
1730
385k
              if (q == (PixelPacket *) NULL)
1731
0
                break;
1732
385k
              if (y == 0)
1733
2.27k
                {
1734
2.27k
                  zip_info.zalloc=ZLIBAllocFunc;
1735
2.27k
                  zip_info.zfree=ZLIBFreeFunc;
1736
2.27k
                  zip_info.opaque=(voidpf) NULL;
1737
2.27k
                  code=inflateInit(&zip_info);
1738
2.27k
                  status|=code >= 0;
1739
2.27k
                  zip_info.avail_in=0;
1740
2.27k
                }
1741
385k
              zip_info.next_out=pixels;
1742
385k
              zip_info.avail_out=(uInt) (packet_size*image->columns);
1743
385k
              do
1744
396k
                {
1745
396k
                  int
1746
396k
                    zip_status;
1747
1748
396k
                  if (zip_info.avail_in == 0)
1749
14.9k
                    {
1750
14.9k
                      zip_info.next_in=compress_pixels;
1751
14.9k
                      if (version == 0)
1752
14.6k
                        {
1753
14.6k
                          length=(int) (1.01*pixels_size+12);
1754
14.6k
                          if (image->logging)
1755
14.6k
                            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1756
14.6k
                                                  "length = %" MAGICK_SIZE_T_F "u",
1757
14.6k
                                                  (MAGICK_SIZE_T) length);
1758
14.6k
                          zip_info.avail_in=(uInt) ReadBlob(image,length,zip_info.next_in);
1759
14.6k
                        }
1760
224
                      else
1761
224
                        {
1762
224
                          length=ReadBlobMSBLong(image);
1763
224
                          if (length > compressed_length)
1764
4
                            {
1765
4
                              (void) inflateEnd(&zip_info);
1766
4
                              ThrowMIFFReaderException(CorruptImageError,
1767
4
                                                       LengthAndFilesizeDoNotMatch,
1768
4
                                                       image);
1769
0
                            }
1770
220
                          zip_info.avail_in=(uInt) ReadBlob(image,length,zip_info.next_in);
1771
220
                          if ((size_t) zip_info.avail_in != length)
1772
7
                            {
1773
7
                              (void) inflateEnd(&zip_info);
1774
7
                              ThrowMIFFReaderException(CorruptImageError,
1775
7
                                                       UnexpectedEndOfFile,
1776
7
                                                       image);
1777
0
                            }
1778
220
                        }
1779
14.9k
                    }
1780
396k
                  if (zip_info.avail_in <= 0)
1781
685
                    {
1782
685
                      (void) inflateEnd(&zip_info);
1783
685
                      ThrowMIFFReaderException(CorruptImageError,UnexpectedEndOfFile,
1784
685
                                               image);
1785
0
                    }
1786
395k
                  zip_status=inflate(&zip_info,Z_NO_FLUSH);
1787
395k
                  if (zip_status == Z_STREAM_END)
1788
3
                    {
1789
3
                      if (image->logging)
1790
3
                        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1791
3
                                              "zip_status == Z_STREAM_END");
1792
3
                    break;
1793
3
                    }
1794
395k
                  else if (zip_status != Z_OK)
1795
322
                    {
1796
322
                      (void) inflateEnd(&zip_info);
1797
322
                      ThrowMIFFReaderException(CorruptImageError,UnableToUncompressImage,
1798
322
                                           image);
1799
0
                    }
1800
395k
                } while (zip_info.avail_out != 0);
1801
384k
              if (y == (long) (image->rows-1))
1802
1.25k
                {
1803
1.25k
                  if (version == 0)
1804
1.25k
                    (void) SeekBlob(image,-((ExtendedSignedIntegralType)
1805
1.25k
                                            zip_info.avail_in),SEEK_CUR);
1806
1.25k
                  code=inflateEnd(&zip_info);
1807
1.25k
                  status|=code >= 0;
1808
1.25k
                }
1809
384k
              if ((size_t) (zip_info.next_out-pixels) < pixels_size)
1810
2
                {
1811
2
                  (void) inflateEnd(&zip_info);
1812
2
                  ThrowMIFFReaderException(CorruptImageError,UnexpectedEndOfFile,
1813
2
                                           image);
1814
0
                }
1815
384k
              if (!ImportImagePixelArea(image,quantum_type,quantum_size,pixels,0,0))
1816
0
                break;
1817
384k
              if (!SyncImagePixels(image))
1818
0
                break;
1819
384k
              if (image->previous == (Image *) NULL)
1820
384k
                if (QuantumTick(y,image->rows))
1821
72.5k
                  if (!MagickMonitorFormatted(y,image->rows,exception,
1822
72.5k
                                              LoadImageText,image->filename,
1823
72.5k
                                              image->columns,image->rows))
1824
0
                    break;
1825
384k
            }
1826
1.25k
          break;
1827
2.27k
        } /* End case ZipCompression */
1828
1.25k
#endif
1829
1.25k
#if defined(HasBZLIB)
1830
1.61k
      case BZipCompression:
1831
1.61k
        {
1832
1.61k
          int
1833
1.61k
            code=0;
1834
1835
100k
          for (y=0; y < (long) image->rows; y++)
1836
99.3k
            {
1837
99.3k
              q=SetImagePixels(image,0,y,image->columns,1);
1838
99.3k
              if (q == (PixelPacket *) NULL)
1839
0
                break;
1840
99.3k
              if (y == 0)
1841
1.61k
                {
1842
1.61k
                  bzip_info.bzalloc=NULL;
1843
1.61k
                  bzip_info.bzfree=NULL;
1844
1.61k
                  bzip_info.opaque=NULL;
1845
1.61k
                  code=BZ2_bzDecompressInit(&bzip_info,image_info->verbose,False);
1846
1.61k
                  status|=code >= 0;
1847
1.61k
                  bzip_info.avail_in=0;
1848
1.61k
                }
1849
99.3k
              bzip_info.next_out=(char *) pixels;
1850
99.3k
              bzip_info.avail_out=(unsigned int) (pixels_size);
1851
99.3k
              do
1852
103k
                {
1853
103k
                  int
1854
103k
                    bz_status;
1855
1856
103k
                  if (bzip_info.avail_in == 0)
1857
6.00k
                    {
1858
6.00k
                      bzip_info.next_in=(char *) compress_pixels;
1859
6.00k
                      if (version == 0)
1860
5.96k
                        {
1861
5.96k
                          length=(int) (1.01*pixels_size+600);
1862
5.96k
                          bzip_info.avail_in=(unsigned int) ReadBlob(image,length,bzip_info.next_in);
1863
5.96k
                          if (bzip_info.avail_in == 0)
1864
357
                            {
1865
357
                              (void) BZ2_bzDecompressEnd(&bzip_info);
1866
357
                              ThrowMIFFReaderException(CorruptImageError,UnexpectedEndOfFile,
1867
357
                                                   image);
1868
0
                            }
1869
5.96k
                        }
1870
48
                      else
1871
48
                        {
1872
48
                          length=ReadBlobMSBLong(image);
1873
48
                          if (image->logging)
1874
48
                            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1875
48
                                                  "length = %" MAGICK_SIZE_T_F "u",
1876
48
                                                  (MAGICK_SIZE_T) length);
1877
48
                          if ((length == 0) || (length > compressed_length))
1878
33
                            {
1879
33
                              (void) BZ2_bzDecompressEnd(&bzip_info);
1880
33
                              ThrowMIFFReaderException(CorruptImageError,UnableToUncompressImage,
1881
33
                                                       image);
1882
0
                            }
1883
15
                          bzip_info.avail_in=(unsigned int) ReadBlob(image,length,bzip_info.next_in);
1884
15
                          if ((size_t) bzip_info.avail_in != length)
1885
10
                            {
1886
10
                              (void) BZ2_bzDecompressEnd(&bzip_info);
1887
10
                              ThrowMIFFReaderException(CorruptImageError,UnexpectedEndOfFile,
1888
10
                                                   image);
1889
0
                            }
1890
15
                        }
1891
6.00k
                    }
1892
103k
                  bz_status=BZ2_bzDecompress(&bzip_info);
1893
103k
                  if (bz_status == BZ_STREAM_END)
1894
1
                    break;
1895
103k
                  else if (bz_status != BZ_OK)
1896
308
                    {
1897
308
                      (void) BZ2_bzDecompressEnd(&bzip_info);
1898
308
                      ThrowMIFFReaderException(CorruptImageError,UnableToUncompressImage,
1899
308
                                           image);
1900
0
                    }
1901
103k
                } while (bzip_info.avail_out != 0);
1902
98.6k
              if (y == (long) (image->rows-1))
1903
903
                {
1904
903
                  if (version == 0)
1905
903
                    (void) SeekBlob(image,-((ExtendedSignedIntegralType)
1906
903
                                            bzip_info.avail_in),SEEK_CUR);
1907
903
                  code=BZ2_bzDecompressEnd(&bzip_info);
1908
903
                  status|=code >= 0;
1909
903
                }
1910
98.6k
              if ((size_t) (((magick_uint64_t) bzip_info.total_out_hi32 << 32) |
1911
98.6k
                            bzip_info.total_out_lo32) < pixels_size)
1912
1
                {
1913
1
                  (void) BZ2_bzDecompressEnd(&bzip_info);
1914
1
                  ThrowMIFFReaderException(CorruptImageError,UnexpectedEndOfFile,
1915
1
                                           image);
1916
0
                }
1917
98.6k
              if (!ImportImagePixelArea(image,quantum_type,quantum_size,pixels,0,0))
1918
0
                break;
1919
98.6k
              if (!SyncImagePixels(image))
1920
0
                break;
1921
98.6k
              if (image->previous == (Image *) NULL)
1922
98.6k
                if (QuantumTick(y,image->rows))
1923
46.1k
                  if (!MagickMonitorFormatted(y,image->rows,exception,
1924
46.1k
                                              LoadImageText,image->filename,
1925
46.1k
                                              image->columns,image->rows))
1926
0
                    break;
1927
98.6k
            }
1928
902
          break;
1929
1.61k
        } /* End case BZipCompression */
1930
902
#endif
1931
902
      case RLECompression:
1932
305
        {
1933
8.45k
          for (y=0; y < (long) image->rows; y++)
1934
8.24k
            {
1935
8.24k
              q=SetImagePixels(image,0,y,image->columns,1);
1936
8.24k
              if (q == (PixelPacket *) NULL)
1937
0
                break;
1938
              /*
1939
                Collect one pixel row
1940
              */
1941
8.24k
              p=pixels;
1942
30.3k
              for (length=0; length < image->columns; )
1943
22.2k
                {
1944
22.2k
                  size_t
1945
22.2k
                    bytes_read;
1946
1947
22.2k
                  if ((bytes_read=ReadBlob(image,packet_size,p)) != packet_size)
1948
92
                    ThrowMIFFReaderException(CorruptImageError,UnexpectedEndOfFile,
1949
22.2k
                                             image);
1950
22.1k
                  p+=bytes_read;
1951
22.1k
                  length+=(size_t) *(p-1)+1;
1952
22.1k
                }
1953
1954
8.15k
              if (!ImportRLEPixels(image,quantum_type,quantum_size,pixels))
1955
2
                break;
1956
8.14k
              if (!SyncImagePixels(image))
1957
0
                break;
1958
8.14k
              if (image->previous == (Image *) NULL)
1959
8.14k
                if (QuantumTick(y,image->rows))
1960
5.89k
                  if (!MagickMonitorFormatted(y,image->rows,exception,
1961
5.89k
                                              LoadImageText,image->filename,
1962
5.89k
                                              image->columns,image->rows))
1963
0
                    break;
1964
1965
8.14k
            }
1966
213
          break;
1967
305
        } /* End case RLECompression */
1968
1.11k
      default:
1969
1.11k
        {
1970
13.2k
          for (y=0; y < (long) image->rows; y++)
1971
12.4k
            {
1972
12.4k
              q=SetImagePixels(image,0,y,image->columns,1);
1973
12.4k
              if (q == (PixelPacket *) NULL)
1974
0
                break;
1975
12.4k
              pixels_p=pixels;
1976
12.4k
              if (ReadBlobZC(image, (size_t)packet_size*image->columns,&pixels_p)
1977
12.4k
                  != (size_t) packet_size*image->columns)
1978
279
                ThrowMIFFReaderException(CorruptImageError,UnexpectedEndOfFile,
1979
12.4k
                                         image);
1980
12.1k
              if (!ImportImagePixelArea(image,quantum_type,quantum_size,
1981
12.1k
                                        (const unsigned char*) pixels_p,0,0))
1982
0
                break;
1983
12.1k
              if (!SyncImagePixels(image))
1984
0
                break;
1985
12.1k
              if (image->previous == (Image *) NULL)
1986
12.1k
                if (QuantumTick(y,image->rows))
1987
4.72k
                  if (!MagickMonitorFormatted(y,image->rows,exception,
1988
4.72k
                                              LoadImageText,image->filename,
1989
4.72k
                                              image->columns,image->rows))
1990
0
                    break;
1991
12.1k
            }
1992
831
          break;
1993
1.11k
        }
1994
5.29k
      } /* End switch (image->compression) */
1995
1996
3.19k
    MagickFreeResourceLimitedMemory(unsigned char *,pixels);
1997
3.19k
    MagickFreeResourceLimitedMemory(unsigned char *,compress_pixels);
1998
1999
3.19k
    if (EOFBlob(image))
2000
3
      {
2001
3
        ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
2002
3
          image->filename);
2003
3
        status=MagickFail;
2004
3
      }
2005
    /*
2006
      Verify that pixel transfer loops completed
2007
    */
2008
3.19k
    if (y != (long) image->rows)
2009
2
      status=MagickFail;
2010
2011
3.19k
    if (status == MagickFail)
2012
5
      {
2013
5
        GetImageException(image,exception);
2014
5
        CloseBlob(image);
2015
5
        DestroyImageList(image);
2016
5
        return((Image *) NULL);
2017
5
      }
2018
3.19k
    StopTimer(&image->timer);
2019
    /*
2020
      Proceed to next image.
2021
    */
2022
3.19k
    if (image_info->subrange != 0)
2023
3.19k
      if (image->scene >= (image_info->subimage+image_info->subrange-1))
2024
3.19k
        break;
2025
0
    do
2026
0
    {
2027
0
      c=ReadBlobByte(image);
2028
0
    } while (!isgraph(c) && (c != EOF));
2029
0
    if (c != EOF && ((c == 'i') || (c == 'I')))
2030
0
      {
2031
        /*
2032
          Allocate next image structure.
2033
        */
2034
0
        AllocateNextImage(image_info,image);
2035
0
        if (image->next == (Image *) NULL)
2036
0
          {
2037
0
            DestroyImageList(image);
2038
0
            return((Image *) NULL);
2039
0
          }
2040
0
        image=SyncNextImageInList(image);
2041
0
        status=MagickMonitorFormatted(TellBlob(image),GetBlobSize(image),
2042
0
                                      exception,LoadImagesText,
2043
0
                                      image->filename);
2044
0
        if (status == MagickFail)
2045
0
          break;
2046
0
      }
2047
0
  } while (c != EOF && ((c == 'i') || (c == 'I')));
2048
3.19k
  while (image->previous != (Image *) NULL)
2049
0
    image=image->previous;
2050
3.19k
  CloseBlob(image);
2051
3.19k
  return(image);
2052
97.6k
}
2053

2054
/*
2055
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2056
%                                                                             %
2057
%                                                                             %
2058
%                                                                             %
2059
%   R e g i s t e r M I F F I m a g e                                         %
2060
%                                                                             %
2061
%                                                                             %
2062
%                                                                             %
2063
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2064
%
2065
%  Method RegisterMIFFImage adds attributes for the MIFF image format to
2066
%  the list of supported formats.  The attributes include the image format
2067
%  tag, a method to read and/or write the format, whether the format
2068
%  supports the saving of more than one frame to the same file or blob,
2069
%  whether the format supports native in-memory I/O, and a brief
2070
%  description of the format.
2071
%
2072
%  The format of the RegisterMIFFImage method is:
2073
%
2074
%      RegisterMIFFImage(void)
2075
%
2076
*/
2077
ModuleExport void RegisterMIFFImage(void)
2078
5
{
2079
  /* GraphicsMagick 1.4, Zlib 1.2.3, BZlib */
2080
5
  static const char
2081
5
    version[]= MagickPackageName " " MagickLibVersionText
2082
5
#if defined(ZLIB_VERSION)
2083
5
    ", Zlib " ZLIB_VERSION
2084
5
#endif
2085
5
#if defined(HasBZLIB)
2086
5
    ", BZlib"
2087
5
#endif
2088
5
    ;
2089
2090
5
  MagickInfo
2091
5
    *entry;
2092
2093
5
  entry=SetMagickInfo("MIFF");
2094
5
  entry->decoder=(DecoderHandler) ReadMIFFImage;
2095
5
  entry->encoder=(EncoderHandler) WriteMIFFImage;
2096
5
  entry->magick=(MagickHandler) IsMIFF;
2097
5
  entry->description="Magick Image File Format";
2098
5
  entry->seekable_stream=MagickTrue;
2099
5
  entry->version=version;
2100
5
  entry->module="MIFF";
2101
5
  entry->coder_class=PrimaryCoderClass;
2102
5
  (void) RegisterMagickInfo(entry);
2103
5
}
2104

2105
/*
2106
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2107
%                                                                             %
2108
%                                                                             %
2109
%                                                                             %
2110
%   U n r e g i s t e r M I F F I m a g e                                     %
2111
%                                                                             %
2112
%                                                                             %
2113
%                                                                             %
2114
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2115
%
2116
%  Method UnregisterMIFFImage removes format registrations made by the
2117
%  MIFF module from the list of supported formats.
2118
%
2119
%  The format of the UnregisterMIFFImage method is:
2120
%
2121
%      UnregisterMIFFImage(void)
2122
%
2123
*/
2124
ModuleExport void UnregisterMIFFImage(void)
2125
0
{
2126
0
  (void) UnregisterMagickInfo("MIFF");
2127
0
}
2128

2129
/*
2130
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2131
%                                                                             %
2132
%                                                                             %
2133
%                                                                             %
2134
%   W r i t e M I F F I m a g e                                               %
2135
%                                                                             %
2136
%                                                                             %
2137
%                                                                             %
2138
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2139
%
2140
%  Method WriteMIFFImage writes a MIFF image to a file.
2141
%
2142
%  The format of the WriteMIFFImage method is:
2143
%
2144
%      unsigned int WriteMIFFImage(const ImageInfo *image_info,Image *image)
2145
%
2146
%  Compression code contributed by Kyle Shorter.
2147
%
2148
%  A description of each parameter follows:
2149
%
2150
%    o status: Method WriteMIFFImage return True if the image is written.
2151
%      False is returned if there is a memory shortage or if the image file
2152
%      fails to write.
2153
%
2154
%    o image_info: Specifies a pointer to a ImageInfo structure.
2155
%
2156
%    o image: A pointer to an Image structure.
2157
%
2158
%
2159
*/
2160
static void WriteRunlengthPacket(const Image *image,
2161
                                 const unsigned int quantum_size,
2162
                                 const PixelPacket *pixel,
2163
                                 const size_t length,
2164
                                 unsigned char **qp,
2165
                                 const IndexPacket index)
2166
13.0k
{
2167
13.0k
  register unsigned char
2168
13.0k
    *q;
2169
2170
13.0k
  unsigned int
2171
13.0k
    value;
2172
2173
13.0k
  assert((quantum_size == 8) || (quantum_size == 16) || (quantum_size == 32));
2174
2175
13.0k
  q = *qp;
2176
2177
13.0k
  if (image->storage_class != DirectClass)
2178
1.64k
    {
2179
1.64k
      value=index;
2180
      /*
2181
        Fall-through logic
2182
      */
2183
1.64k
      switch (quantum_size)
2184
1.64k
        {
2185
0
        case 32:
2186
0
          {
2187
0
            *q++=(unsigned char) (value >> 24);
2188
0
            *q++=(unsigned char) (value >> 16);
2189
0
            *q++=(unsigned char) (value >> 8);
2190
0
            *q++=(unsigned char) value;
2191
0
            break;
2192
0
          }
2193
208
        case 16:
2194
208
          {
2195
208
            *q++=(unsigned char) (value >> 8);
2196
208
            *q++=(unsigned char) value;
2197
208
            break;
2198
0
          }
2199
1.43k
        case 8:
2200
1.43k
          {
2201
1.43k
            *q++=(unsigned char) value;
2202
1.43k
            break;
2203
0
          }
2204
1.64k
        } /* switch (quantum_size) */
2205
1.64k
      if (image->matte)
2206
0
        {
2207
0
          value=MaxRGB-pixel->opacity;
2208
0
          switch (quantum_size)
2209
0
            {
2210
0
            case 32:
2211
0
              {
2212
0
                *q++=(unsigned char) (value >> 24);
2213
0
                *q++=(unsigned char) (value >> 16);
2214
0
                *q++=(unsigned char) (value >> 8);
2215
0
                *q++=(unsigned char) value;
2216
0
                break;
2217
0
              }
2218
0
            case 16:
2219
0
              {
2220
0
                *q++=(unsigned char) (value >> 8);
2221
0
                *q++=(unsigned char) value;
2222
0
                break;
2223
0
              }
2224
0
            case 8:
2225
0
              {
2226
0
                *q++=(unsigned char) value;
2227
0
                break;
2228
0
              }
2229
0
            } /* switch (quantum_size) */
2230
0
        }
2231
1.64k
    }
2232
11.4k
  else
2233
11.4k
    {
2234
11.4k
      switch (quantum_size)
2235
11.4k
        {
2236
5.70k
        case 8:
2237
5.70k
          {
2238
5.70k
            *q++=ScaleQuantumToChar(pixel->red);
2239
5.70k
            *q++=ScaleQuantumToChar(pixel->green);
2240
5.70k
            *q++=ScaleQuantumToChar(pixel->blue);
2241
5.70k
            if (image->colorspace == CMYKColorspace)
2242
0
              {
2243
0
                *q++=ScaleQuantumToChar(pixel->opacity);
2244
0
                if (image->matte)
2245
0
                  *q++=ScaleQuantumToChar(index);
2246
0
              }
2247
5.70k
            else
2248
5.70k
              if (image->matte)
2249
4.58k
                *q++=ScaleQuantumToChar(MaxRGB-pixel->opacity);
2250
5.70k
            break;
2251
0
          }
2252
1.65k
        case 16:
2253
1.65k
          {
2254
1.65k
            value=ScaleQuantumToShort(pixel->red);
2255
1.65k
            *q++=(unsigned char) (value >> 8);
2256
1.65k
            *q++=(unsigned char) value;
2257
1.65k
            value=ScaleQuantumToShort(pixel->green);
2258
1.65k
            *q++=(unsigned char) (value >> 8);
2259
1.65k
            *q++=(unsigned char) value;
2260
1.65k
            value=ScaleQuantumToShort(pixel->blue);
2261
1.65k
            *q++=(unsigned char) (value >> 8);
2262
1.65k
            *q++=(unsigned char) value;
2263
1.65k
            if (image->colorspace == CMYKColorspace)
2264
0
              {
2265
0
                value=ScaleQuantumToShort(pixel->opacity);
2266
0
                *q++=(unsigned char) (value >> 8);
2267
0
                *q++=(unsigned char) value;
2268
0
                if (image->matte)
2269
0
                  {
2270
0
                    value=ScaleQuantumToShort(MaxRGB-index);
2271
0
                    *q++=(unsigned char) (value >> 8);
2272
0
                    *q++=(unsigned char) value;
2273
0
                  }
2274
0
              }
2275
1.65k
            else
2276
1.65k
              if (image->matte)
2277
1.38k
                {
2278
1.38k
                  value=ScaleQuantumToShort(MaxRGB-pixel->opacity);
2279
1.38k
                  *q++=(unsigned char) (value >> 8);
2280
1.38k
                  *q++=(unsigned char) value;
2281
1.38k
                }
2282
1.65k
            break;
2283
0
          }
2284
4.07k
        case 32:
2285
4.07k
          {
2286
4.07k
            value=ScaleQuantumToLong(pixel->red);
2287
4.07k
            *q++=(unsigned char) (value >> 24);
2288
4.07k
            *q++=(unsigned char) (value >> 16);
2289
4.07k
            *q++=(unsigned char) (value >> 8);
2290
4.07k
            *q++=(unsigned char) value;
2291
4.07k
            value=ScaleQuantumToLong(pixel->green);
2292
4.07k
            *q++=(unsigned char) (value >> 24);
2293
4.07k
            *q++=(unsigned char) (value >> 16);
2294
4.07k
            *q++=(unsigned char) (value >> 8);
2295
4.07k
            *q++=(unsigned char) value;
2296
4.07k
            value=ScaleQuantumToLong(pixel->blue);
2297
4.07k
            *q++=(unsigned char) (value >> 24);
2298
4.07k
            *q++=(unsigned char) (value >> 16);
2299
4.07k
            *q++=(unsigned char) (value >> 8);
2300
4.07k
            *q++=(unsigned char) value;
2301
4.07k
            if (image->colorspace == CMYKColorspace)
2302
0
              {
2303
0
                value=ScaleQuantumToLong(pixel->opacity);
2304
0
                *q++=(unsigned char) (value >> 24);
2305
0
                *q++=(unsigned char) (value >> 16);
2306
0
                *q++=(unsigned char) (value >> 8);
2307
0
                *q++=(unsigned char) value;
2308
0
                if (image->matte)
2309
0
                  {
2310
0
                    value=ScaleQuantumToLong(MaxRGB-index);
2311
0
                    *q++=(unsigned char) (value >> 24);
2312
0
                    *q++=(unsigned char) (value >> 16);
2313
0
                    *q++=(unsigned char) (value >> 8);
2314
0
                    *q++=(unsigned char) value;
2315
0
                  }
2316
0
              }
2317
4.07k
            else
2318
4.07k
              if (image->matte)
2319
1.93k
                {
2320
1.93k
                  value=ScaleQuantumToLong(MaxRGB-pixel->opacity);
2321
1.93k
                  *q++=(unsigned char) (value >> 24);
2322
1.93k
                  *q++=(unsigned char) (value >> 16);
2323
1.93k
                  *q++=(unsigned char) (value >> 8);
2324
1.93k
                  *q++=(unsigned char) value;
2325
1.93k
                }
2326
4.07k
          }
2327
11.4k
        }  /* switch (quantum_size) */
2328
11.4k
    }
2329
13.0k
  *q++=(unsigned char) length;
2330
13.0k
  *qp=q;
2331
13.0k
}
2332
2333
#define ThrowMIFFWriterException(code_,reason_,image_)                  \
2334
0
  {                                                                     \
2335
0
    MagickFreeResourceLimitedMemory(unsigned char *,compress_pixels)    \
2336
0
      MagickFreeResourceLimitedMemory(unsigned char *,pixels);          \
2337
0
    ThrowWriterException(code_,reason_,image_);                         \
2338
0
  }
2339
2340
static unsigned int WriteMIFFImage(const ImageInfo *image_info,Image *image)
2341
3.13k
{
2342
2343
3.13k
#if defined(HasBZLIB)
2344
3.13k
  bz_stream
2345
3.13k
    bzip_info;
2346
3.13k
#endif
2347
2348
3.13k
  char
2349
3.13k
    buffer[MaxTextExtent];
2350
2351
3.13k
  CompressionType
2352
3.13k
    compression;
2353
2354
3.13k
  const ImageAttribute
2355
3.13k
    *attribute;
2356
2357
3.13k
  IndexPacket
2358
3.13k
    index;
2359
2360
3.13k
  long
2361
3.13k
    y;
2362
2363
3.13k
  PixelPacket
2364
3.13k
    pixel;
2365
2366
3.13k
  QuantumType
2367
3.13k
    quantum_type;
2368
2369
3.13k
  register const PixelPacket
2370
3.13k
    *p;
2371
2372
3.13k
  register const IndexPacket
2373
3.13k
    *indexes;
2374
2375
3.13k
  register unsigned long
2376
3.13k
    i;
2377
2378
3.13k
  register long
2379
3.13k
    x;
2380
2381
3.13k
  unsigned char
2382
3.13k
    *q;
2383
2384
3.13k
  size_t
2385
3.13k
    length;
2386
2387
3.13k
  unsigned char
2388
3.13k
    *compress_pixels = (unsigned char *) NULL,
2389
3.13k
    *pixels = (unsigned char *) NULL;
2390
2391
3.13k
  unsigned int
2392
3.13k
    depth,
2393
3.13k
    status,
2394
3.13k
    quantum_size;
2395
2396
3.13k
  unsigned long
2397
3.13k
    packet_size,
2398
3.13k
    scene;
2399
2400
3.13k
  ImageProfileIterator
2401
3.13k
    profile_iterator;
2402
2403
3.13k
  const char
2404
3.13k
    *profile_name;
2405
2406
3.13k
  const unsigned char
2407
3.13k
    *profile_info;
2408
2409
3.13k
  size_t
2410
3.13k
    profile_length;
2411
2412
3.13k
#if defined(HasZLIB)
2413
3.13k
  z_stream
2414
3.13k
    zip_info;
2415
3.13k
#endif
2416
2417
3.13k
  size_t
2418
3.13k
    image_list_length;
2419
2420
  /*
2421
    Open output image file.
2422
  */
2423
3.13k
  assert(image_info != (const ImageInfo *) NULL);
2424
3.13k
  assert(image_info->signature == MagickSignature);
2425
3.13k
  assert(image != (Image *) NULL);
2426
3.13k
  assert(image->signature == MagickSignature);
2427
3.13k
  image_list_length=GetImageListLength(image);
2428
3.13k
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
2429
3.13k
  if (status == False)
2430
3.13k
    ThrowWriterException(FileOpenError,UnableToOpenFile,image);
2431
3.13k
  compression=image->compression;
2432
3.13k
  if (image_info->compression != UndefinedCompression)
2433
0
    compression=image_info->compression;
2434
3.13k
  scene=0;
2435
3.13k
  do
2436
3.13k
  {
2437
    /*
2438
      Transform colorspace if necessary.
2439
    */
2440
3.13k
    if (((image_info->colorspace != UndefinedColorspace) ||
2441
3.13k
         (image->colorspace != CMYKColorspace)) &&
2442
3.13k
         (image_info->colorspace != CMYKColorspace))
2443
3.13k
      (void) TransformColorspace(image,RGBColorspace);
2444
0
    else
2445
0
      (void) TransformColorspace(image,CMYKColorspace);
2446
    /*
2447
      Valid depths are 8/16/32
2448
    */
2449
3.13k
    if (image->depth > 16)
2450
1.38k
      depth=32;
2451
1.75k
    else if (image->depth > 8)
2452
124
      depth=16;
2453
1.63k
    else
2454
1.63k
      depth=8;
2455
3.13k
    if (image->storage_class != DirectClass)
2456
104
      {
2457
104
        if (image->colors > 65536)
2458
0
          quantum_size=32;
2459
104
        else if (image->colors > 256)
2460
35
          quantum_size=16;
2461
69
        else
2462
69
          quantum_size=8;
2463
104
      }
2464
3.03k
    else
2465
3.03k
      {
2466
3.03k
        quantum_size=depth;
2467
3.03k
      }
2468
    /*
2469
      Allocate image pixels.
2470
    */
2471
3.13k
    packet_size=quantum_size/8;
2472
3.13k
    if (image->storage_class == DirectClass)
2473
3.03k
      packet_size=3*quantum_size/8;
2474
3.13k
    if (image->colorspace == CMYKColorspace)
2475
0
      packet_size+=quantum_size/8;
2476
3.13k
    if (image->matte)
2477
85
      packet_size+=quantum_size/8;
2478
3.13k
    if (compression == RLECompression)
2479
211
      packet_size+=quantum_size/8;
2480
3.13k
    length= (size_t)packet_size*image->columns;
2481
3.13k
    pixels=MagickAllocateResourceLimitedMemory(unsigned char *,length);
2482
3.13k
    length=(size_t) (1.01*packet_size*image->columns+600);
2483
3.13k
    if ((compression == BZipCompression) || (compression == ZipCompression))
2484
2.14k
      if (length != (unsigned int) length)
2485
0
        compression=NoCompression;
2486
3.13k
    compress_pixels=MagickAllocateResourceLimitedMemory(unsigned char *,length);
2487
3.13k
    if ((pixels == (unsigned char *) NULL) ||
2488
3.13k
        (compress_pixels == (unsigned char *) NULL))
2489
3.13k
      ThrowMIFFWriterException(ResourceLimitError,MemoryAllocationFailed,image);
2490
    /*
2491
      Write MIFF header.
2492
    */
2493
3.13k
    (void) WriteBlobString(image,"id=ImageMagick  version=1.0\n");
2494
3.13k
    if (image->storage_class == PseudoClass)
2495
104
      FormatString(buffer,"class=PseudoClass  colors=%u  matte=%.1024s\n",
2496
104
                   image->colors,MagickBoolToString(image->matte));
2497
3.03k
    else
2498
3.03k
      if (image->colorspace == CMYKColorspace)
2499
0
        FormatString(buffer,
2500
0
                     "class=DirectClass  colorspace=CMYK  matte=%.1024s\n",
2501
0
                     MagickBoolToString(image->matte));
2502
3.03k
      else
2503
3.03k
        FormatString(buffer,"class=DirectClass  matte=%.1024s\n",
2504
3.03k
                     MagickBoolToString(image->matte));
2505
3.13k
    (void) WriteBlobString(image,buffer);
2506
3.13k
    *buffer='\0';
2507
3.13k
    switch(compression)
2508
3.13k
      {
2509
778
      case NoCompression:
2510
778
      default:
2511
778
        compression=NoCompression;
2512
778
        break;
2513
211
      case RLECompression:
2514
211
        FormatString(buffer,"compression=RLE\n");
2515
211
        break;
2516
0
#if defined(HasBZLIB)
2517
900
      case BZipCompression:
2518
900
        FormatString(buffer,"compression=BZip\n");
2519
900
        break;
2520
0
#endif /* defined(HasBZLIB) */
2521
0
#if defined(HasZLIB)
2522
1.24k
      case ZipCompression:
2523
1.24k
        FormatString(buffer,"compression=Zip\n");
2524
1.24k
        break;
2525
3.13k
#endif /* defined(HasZLIB) */
2526
3.13k
      }
2527
3.13k
    if (*buffer != '\0')
2528
2.35k
      (void) WriteBlobString(image,buffer);
2529
3.13k
    FormatString(buffer,"columns=%lu  rows=%lu  depth=%u\n",image->columns,
2530
3.13k
      image->rows,depth);
2531
3.13k
    (void) WriteBlobString(image,buffer);
2532
3.13k
    if ((image->x_resolution != 0) && (image->y_resolution != 0))
2533
22
      {
2534
22
        char
2535
22
          units[MaxTextExtent];
2536
2537
        /*
2538
          Set image resolution.
2539
        */
2540
22
        (void) strlcpy(units,"undefined",sizeof(units));
2541
22
        if (image->units == PixelsPerInchResolution)
2542
0
          (void) strlcpy(units,"pixels-per-inch",sizeof(units));
2543
22
        if (image->units == PixelsPerCentimeterResolution)
2544
0
          (void) strlcpy(units,"pixels-per-centimeter",sizeof(units));
2545
22
        FormatString(buffer,"Resolution=%gx%g  units=%.1024s\n",
2546
22
          image->x_resolution,image->y_resolution,units);
2547
22
        (void) WriteBlobString(image,buffer);
2548
22
      }
2549
3.13k
    if ((image->page.width != 0) && (image->page.height != 0))
2550
3.13k
      {
2551
3.13k
        FormatString(buffer,"page=%lux%lu%+ld%+ld\n",image->page.width,
2552
3.13k
          image->page.height,image->page.x,image->page.y);
2553
3.13k
        (void) WriteBlobString(image,buffer);
2554
3.13k
      }
2555
3.13k
    if ((image->next != (Image *) NULL) || (image->previous != (Image *) NULL))
2556
0
      {
2557
0
        if (image->scene == 0)
2558
0
          FormatString(buffer,"iterations=%lu  delay=%lu\n",image->iterations,
2559
0
            image->delay);
2560
0
        else
2561
0
          FormatString(buffer,"scene=%lu  iterations=%lu  delay=%lu\n",
2562
0
            image->scene,image->iterations,image->delay);
2563
0
        (void) WriteBlobString(image,buffer);
2564
0
      }
2565
3.13k
    else
2566
3.13k
      {
2567
3.13k
        if (image->scene != 0)
2568
143
          {
2569
143
            FormatString(buffer,"scene=%lu\n",image->scene);
2570
143
            (void) WriteBlobString(image,buffer);
2571
143
          }
2572
3.13k
        if (image->iterations != 0)
2573
75
          {
2574
75
            FormatString(buffer,"iterations=%lu\n",image->iterations);
2575
75
            (void) WriteBlobString(image,buffer);
2576
75
          }
2577
3.13k
        if (image->delay != 0)
2578
96
          {
2579
96
            FormatString(buffer,"delay=%lu\n",image->delay);
2580
96
            (void) WriteBlobString(image,buffer);
2581
96
          }
2582
3.13k
      }
2583
3.13k
    if (image->dispose != UndefinedDispose)
2584
52
      {
2585
52
        if (image->dispose == BackgroundDispose)
2586
1
          (void) strlcpy(buffer,"dispose=background\n",sizeof(buffer));
2587
51
        else
2588
51
          if (image->dispose == NoneDispose)
2589
1
            (void) strlcpy(buffer,"dispose=none\n",sizeof(buffer));
2590
50
          else
2591
50
            (void) strlcpy(buffer,"dispose=previous\n",sizeof(buffer));
2592
52
        (void) WriteBlobString(image,buffer);
2593
52
      }
2594
3.13k
    if (image->rendering_intent != UndefinedIntent)
2595
0
      {
2596
0
        if (image->rendering_intent == SaturationIntent)
2597
0
          (void) strlcpy(buffer,"rendering-intent=saturation\n",sizeof(buffer));
2598
0
        else
2599
0
          if (image->rendering_intent == PerceptualIntent)
2600
0
            (void) strlcpy(buffer,"rendering-intent=perceptual\n",sizeof(buffer));
2601
0
          else
2602
0
            if (image->rendering_intent == AbsoluteIntent)
2603
0
              (void) strlcpy(buffer,"rendering-intent=absolute\n",sizeof(buffer));
2604
0
            else
2605
0
              (void) strlcpy(buffer,"rendering-intent=relative\n",sizeof(buffer));
2606
0
        (void) WriteBlobString(image,buffer);
2607
0
      }
2608
3.13k
    if (image->gamma != 0.0)
2609
1
      {
2610
1
        FormatString(buffer,"gamma=%g\n",image->gamma);
2611
1
        (void) WriteBlobString(image,buffer);
2612
1
      }
2613
3.13k
    if (image->chromaticity.white_point.x != 0.0)
2614
0
      {
2615
        /*
2616
          Note chomaticity points.
2617
        */
2618
0
        FormatString(buffer,
2619
0
          "red-primary=%g,%g  green-primary=%g,%g  blue-primary=%g,%g\n",
2620
0
          image->chromaticity.red_primary.x,image->chromaticity.red_primary.y,
2621
0
          image->chromaticity.green_primary.x,
2622
0
          image->chromaticity.green_primary.y,
2623
0
          image->chromaticity.blue_primary.x,
2624
0
          image->chromaticity.blue_primary.y);
2625
0
        (void) WriteBlobString(image,buffer);
2626
0
        FormatString(buffer,"white-point=%g,%g\n",
2627
0
          image->chromaticity.white_point.x,image->chromaticity.white_point.y);
2628
0
        (void) WriteBlobString(image,buffer);
2629
0
      }
2630
3.13k
    if (image->orientation != UndefinedOrientation)
2631
1
      {
2632
1
        FormatString(buffer,"orientation=%s\n",
2633
1
                     OrientationTypeToString(image->orientation));
2634
1
        (void) WriteBlobString(image,buffer);
2635
1
      }
2636
    /*
2637
      Old MIFF readers (including GM 1.1) expect the ICC profile,
2638
      followed by the IPTC profile, followed by any remaining
2639
      profiles.
2640
    */
2641
3.13k
    if ((GetImageProfile(image,"ICM",&profile_length)))
2642
3
      {
2643
3
        FormatString(buffer,"profile-icc=%lu\n",(unsigned long)
2644
3
                     profile_length);
2645
3
        (void) WriteBlobString(image,buffer);
2646
3
      }
2647
3.13k
    if ((GetImageProfile(image,"IPTC",&profile_length)))
2648
0
      {
2649
0
        FormatString(buffer,"profile-iptc=%lu\n",(unsigned long)
2650
0
                     profile_length);
2651
0
        (void) WriteBlobString(image,buffer);
2652
0
      }
2653
2654
    /*
2655
      Generic profiles.
2656
    */
2657
3.13k
    profile_iterator=AllocateImageProfileIterator(image);
2658
3.13k
    if (profile_iterator)
2659
60
      {
2660
309
        while(NextImageProfile(profile_iterator,&profile_name,&profile_info,
2661
309
                               &profile_length) != MagickFail)
2662
249
          {
2663
249
            if ((LocaleCompare(profile_name,"ICC") == 0) ||
2664
248
                (LocaleCompare(profile_name,"ICM") == 0) ||
2665
246
                (LocaleCompare(profile_name,"IPTC") == 0) ||
2666
246
                (LocaleCompare(profile_name,"8BIM") == 0))
2667
3
              continue;
2668
246
            FormatString(buffer,"profile-%.1024s=%lu\n",
2669
246
                         profile_name,(unsigned long) profile_length);
2670
246
            (void) WriteBlobString(image,buffer);
2671
246
          }
2672
60
        DeallocateImageProfileIterator(profile_iterator);
2673
60
      }
2674
2675
3.13k
    if (image->montage != (char *) NULL)
2676
2
      {
2677
2
        FormatString(buffer,"montage=%.1024s\n",image->montage);
2678
2
        (void) WriteBlobString(image,buffer);
2679
2
      }
2680
3.13k
    attribute=GetImageAttribute(image,(char *) NULL);
2681
8.37k
    for ( ; attribute != (ImageAttribute *) NULL; attribute=attribute->next)
2682
5.24k
    {
2683
5.24k
      size_t attribute_length;
2684
5.24k
      if (*attribute->key == '[')
2685
0
        continue;
2686
5.24k
      FormatString(buffer,"%.1024s=",attribute->key);
2687
5.24k
      (void) WriteBlobString(image,buffer);
2688
5.24k
      attribute_length=strlen(attribute->value);
2689
4.06M
      for (i=0; i < attribute_length; i++)
2690
4.05M
        if (isspace((int) attribute->value[i]))
2691
166
          break;
2692
5.24k
      if (i < attribute_length)
2693
166
        (void) WriteBlobByte(image,'{');
2694
5.24k
      (void) WriteBlob(image,attribute_length,attribute->value);
2695
5.24k
      if (i < attribute_length)
2696
166
        (void) WriteBlobByte(image,'}');
2697
5.24k
      (void) WriteBlobByte(image,'\n');
2698
5.24k
    }
2699
3.13k
    (void) WriteBlobString(image,"\f\n:\032");
2700
3.13k
    if (image->montage != (char *) NULL)
2701
2
      {
2702
        /*
2703
          Write montage tile directory.
2704
        */
2705
2
        if (image->directory != (char *) NULL)
2706
2
          (void) WriteBlob(image,strlen(image->directory),image->directory);
2707
2
        (void) WriteBlobByte(image,'\0');
2708
2
      }
2709
    /*
2710
      Color profile.
2711
    */
2712
3.13k
    if ((profile_info=GetImageProfile(image,"ICM",&profile_length)))
2713
3
      (void) WriteBlob(image,profile_length, (const char *) profile_info);
2714
    /*
2715
      IPTC profile.
2716
    */
2717
3.13k
    if ((profile_info=GetImageProfile(image,"IPTC",&profile_length)))
2718
0
      (void) WriteBlob(image,profile_length,(const char *) profile_info);
2719
    /*
2720
      Generic profiles.
2721
    */
2722
3.13k
    profile_iterator=AllocateImageProfileIterator(image);
2723
3.38k
    while(NextImageProfile(profile_iterator,&profile_name,&profile_info,
2724
3.38k
                           &profile_length) != MagickFail)
2725
249
      {
2726
249
        if ((LocaleCompare(profile_name,"ICC") == 0) ||
2727
248
            (LocaleCompare(profile_name,"ICM") == 0) ||
2728
246
            (LocaleCompare(profile_name,"IPTC") == 0) ||
2729
246
            (LocaleCompare(profile_name,"8BIM") == 0))
2730
3
          continue;
2731
2732
246
        (void) WriteBlob(image,profile_length,(const char *) profile_info);
2733
246
      }
2734
3.13k
    DeallocateImageProfileIterator(profile_iterator);
2735
2736
3.13k
    if (image->storage_class == PseudoClass)
2737
104
      {
2738
104
        unsigned char
2739
104
          *colormap;
2740
2741
104
        unsigned int
2742
104
          packet_size;
2743
2744
        /*
2745
          Allocate colormap.
2746
        */
2747
104
        packet_size=3*depth/8;
2748
104
        colormap=MagickAllocateResourceLimitedArray(unsigned char *,packet_size,image->colors);
2749
104
        if (colormap == (unsigned char *) NULL)
2750
0
          ThrowMIFFWriterException(ResourceLimitError,MemoryAllocationFailed,
2751
104
                                   image);
2752
        /*
2753
          Write colormap to file.
2754
        */
2755
104
        q=colormap;
2756
104
        switch (depth)
2757
104
          {
2758
69
          case 8:
2759
69
            {
2760
17.7k
              for (i=0; i < image->colors; i++)
2761
17.6k
                {
2762
17.6k
                  *q++=ScaleQuantumToChar(image->colormap[i].red);
2763
17.6k
                  *q++=ScaleQuantumToChar(image->colormap[i].green);
2764
17.6k
                  *q++=ScaleQuantumToChar(image->colormap[i].blue);
2765
17.6k
                }
2766
69
              break;
2767
0
            }
2768
0
#if QuantumDepth > 8
2769
35
          case 16:
2770
35
            {
2771
2.29M
              for (i=0; i < image->colors; i++)
2772
2.29M
                {
2773
2.29M
                  *q++=ScaleQuantumToShort(image->colormap[i].red) >> 8;
2774
2.29M
                  *q++=ScaleQuantumToShort(image->colormap[i].red);
2775
2.29M
                  *q++=ScaleQuantumToShort(image->colormap[i].green) >> 8;
2776
2.29M
                  *q++=ScaleQuantumToShort(image->colormap[i].green);
2777
2.29M
                  *q++=ScaleQuantumToShort(image->colormap[i].blue) >> 8;
2778
2.29M
                  *q++=ScaleQuantumToShort(image->colormap[i].blue);
2779
2.29M
                }
2780
35
              break;
2781
0
            }
2782
104
#endif /* QuantumDepth > 8 */
2783
#if QuantumDepth > 16
2784
          case 32:
2785
            {
2786
              for (i=0; i < image->colors; i++)
2787
                {
2788
                  *q++=image->colormap[i].red >> 24;
2789
                  *q++=image->colormap[i].red >> 16;
2790
                  *q++=image->colormap[i].red >> 8;
2791
                  *q++=image->colormap[i].red;
2792
                  *q++=image->colormap[i].green >> 24;
2793
                  *q++=image->colormap[i].green >> 16;
2794
                  *q++=image->colormap[i].green >> 8;
2795
                  *q++=image->colormap[i].green;
2796
                  *q++=image->colormap[i].blue >> 24;
2797
                  *q++=image->colormap[i].blue >> 16;
2798
                  *q++=image->colormap[i].blue >> 8;
2799
                  *q++=image->colormap[i].blue;
2800
                }
2801
              break;
2802
            }
2803
#endif /* QuantumDepth > 16 */
2804
104
          } /* switch (depth) */
2805
104
        (void) WriteBlob(image, (size_t)packet_size*image->colors,colormap);
2806
104
        MagickFreeResourceLimitedMemory(unsigned char *,colormap);
2807
104
      }
2808
    /*
2809
      Write image pixels to file.
2810
    */
2811
3.13k
    quantum_type=RGBQuantum;
2812
3.13k
    if (image->storage_class == PseudoClass)
2813
104
      {
2814
104
        quantum_type=IndexAlphaQuantum;
2815
104
        if (!image->matte)
2816
104
          quantum_type=IndexQuantum;
2817
104
      }
2818
3.03k
    else
2819
3.03k
      if (image->colorspace == CMYKColorspace)
2820
0
        {
2821
0
          quantum_type=CMYKAQuantum;
2822
0
          if (!image->matte)
2823
0
            quantum_type=CMYKQuantum;
2824
0
        }
2825
3.03k
      else
2826
3.03k
        {
2827
3.03k
          quantum_type=RGBAQuantum;
2828
3.03k
          if (!image->matte)
2829
2.94k
            quantum_type=RGBQuantum;
2830
3.03k
        }
2831
3.13k
    status=True;
2832
3.13k
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2833
3.13k
                          "Using QuantumType %s, depth %u",
2834
3.13k
                          QuantumTypeToString(quantum_type),quantum_size);
2835
423k
    for (y=0; y < (long) image->rows; y++)
2836
420k
    {
2837
420k
      p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
2838
420k
      if (p == (const PixelPacket *) NULL)
2839
0
        break;
2840
420k
      indexes=AccessImmutableIndexes(image);
2841
420k
      q=pixels;
2842
420k
      switch (compression)
2843
420k
      {
2844
0
#if defined(HasZLIB)
2845
323k
        case ZipCompression:
2846
323k
        {
2847
323k
          int
2848
323k
            code;
2849
2850
323k
          if (y == 0)
2851
1.24k
            {
2852
1.24k
              zip_info.zalloc=ZLIBAllocFunc;
2853
1.24k
              zip_info.zfree=ZLIBFreeFunc;
2854
1.24k
              zip_info.opaque=(voidpf) NULL;
2855
1.24k
              code=deflateInit(&zip_info,(int) Min(image_info->quality/10,9));
2856
1.24k
              status|=code >= 0;
2857
1.24k
            }
2858
323k
          zip_info.next_in=pixels;
2859
323k
          zip_info.avail_in=(uInt) (packet_size*image->columns);
2860
323k
          (void) ExportImagePixelArea(image,quantum_type,quantum_size,pixels,0,0);
2861
323k
          do
2862
367k
          {
2863
367k
            zip_info.next_out=compress_pixels;
2864
367k
            zip_info.avail_out=(uInt) (1.01*packet_size*image->columns+12);
2865
367k
            code=deflate(&zip_info,Z_NO_FLUSH);
2866
367k
            status|=code >= 0;
2867
367k
            length=zip_info.next_out-compress_pixels;
2868
367k
            if (length != 0)
2869
61.7k
              {
2870
61.7k
                (void) WriteBlobMSBLong(image,(magick_uint32_t) length);
2871
61.7k
                (void) WriteBlob(image,length,compress_pixels);
2872
61.7k
              }
2873
367k
          } while (zip_info.avail_in != 0);
2874
323k
          if (y == (long) (image->rows-1))
2875
1.24k
            {
2876
1.24k
              for ( ; ; )
2877
11.1k
              {
2878
11.1k
                zip_info.next_out=compress_pixels;
2879
11.1k
                zip_info.avail_out=(uInt) (1.01*packet_size*image->columns+12);
2880
11.1k
                code=deflate(&zip_info,Z_FINISH);
2881
11.1k
                status|=code >= 0;
2882
11.1k
                length=zip_info.next_out-compress_pixels;
2883
11.1k
                if (length == 0)
2884
1.24k
                  break;
2885
9.89k
                (void) WriteBlobMSBLong(image,(magick_uint32_t) length);
2886
9.89k
                (void) WriteBlob(image,length,compress_pixels);
2887
9.89k
              }
2888
1.24k
              status=!deflateEnd(&zip_info);
2889
1.24k
            }
2890
323k
          break;
2891
0
        }
2892
0
#endif
2893
0
#if defined(HasBZLIB)
2894
87.2k
        case BZipCompression:
2895
87.2k
        {
2896
87.2k
          int
2897
87.2k
            code;
2898
2899
87.2k
          if (y == 0)
2900
900
            {
2901
900
              bzip_info.bzalloc=NULL;
2902
900
              bzip_info.bzfree=NULL;
2903
900
              bzip_info.opaque=NULL;
2904
900
              code=BZ2_bzCompressInit(&bzip_info,
2905
900
                (int) Min(image_info->quality/10,9),image_info->verbose,0);
2906
900
              status|=code >= 0;
2907
900
            }
2908
87.2k
          bzip_info.next_in=(char *) pixels;
2909
87.2k
          bzip_info.avail_in=(unsigned int) (packet_size*image->columns);
2910
87.2k
          (void) ExportImagePixelArea(image,quantum_type,quantum_size,pixels,0,0);
2911
87.2k
          do
2912
87.2k
          {
2913
87.2k
            bzip_info.next_out=(char *) compress_pixels;
2914
87.2k
            bzip_info.avail_out=(unsigned int)
2915
87.2k
              (1.01*packet_size*image->columns+600);
2916
87.2k
            code=BZ2_bzCompress(&bzip_info,BZ_FLUSH);
2917
87.2k
            status|=code >= 0;
2918
87.2k
            length=bzip_info.next_out-(char *) compress_pixels;
2919
87.2k
            if (length != 0)
2920
87.2k
              {
2921
87.2k
                (void) WriteBlobMSBLong(image,(magick_uint32_t) length);
2922
87.2k
                (void) WriteBlob(image,length,compress_pixels);
2923
87.2k
              }
2924
87.2k
          } while (bzip_info.avail_in != 0);
2925
87.2k
          if (y == (long) (image->rows-1))
2926
900
            {
2927
900
              for ( ; ; )
2928
1.80k
              {
2929
1.80k
                bzip_info.next_out=(char *) compress_pixels;
2930
1.80k
                bzip_info.avail_out=(unsigned int)
2931
1.80k
                  (1.01*packet_size*image->columns+600);
2932
1.80k
                code=BZ2_bzCompress(&bzip_info,BZ_FINISH);
2933
1.80k
                status|=code >= 0;
2934
1.80k
                length=bzip_info.next_out-(char *) compress_pixels;
2935
1.80k
                if (length == 0)
2936
900
                  break;
2937
900
                (void) WriteBlobMSBLong(image,(magick_uint32_t) length);
2938
900
                (void) WriteBlob(image,length,compress_pixels);
2939
900
              }
2940
900
              status=!BZ2_bzCompressEnd(&bzip_info);
2941
900
            }
2942
87.2k
          break;
2943
0
        }
2944
0
#endif
2945
4.74k
        case RLECompression:
2946
4.74k
        {
2947
4.74k
          pixel=(*p);
2948
4.74k
          index=0;
2949
4.74k
          if (image->storage_class == PseudoClass)
2950
719
            index=(*indexes);
2951
4.74k
          length=255;
2952
566k
          for (x=0; x < (long) image->columns; x++)
2953
561k
          {
2954
561k
            if ((length < 255) && (x < (long) (image->columns-1)) &&
2955
551k
                ColorMatch(p,(&pixel)) &&
2956
548k
                ((image->matte == False) || (p->opacity == pixel.opacity)))
2957
548k
              length++;
2958
13.0k
            else
2959
13.0k
              {
2960
13.0k
                if (x > 0)
2961
8.33k
                  WriteRunlengthPacket(image,quantum_size,&pixel,length,&q,index);
2962
13.0k
                length=0;
2963
13.0k
              }
2964
561k
            if (image->storage_class == PseudoClass)
2965
28.9k
              index=indexes[x];
2966
561k
            pixel=(*p);
2967
561k
            p++;
2968
561k
          }
2969
4.74k
          WriteRunlengthPacket(image,quantum_size,&pixel,length,&q,index);
2970
4.74k
          (void) WriteBlob(image,q-pixels,pixels);
2971
4.74k
          break;
2972
0
        }
2973
5.30k
        default:
2974
5.30k
        {
2975
5.30k
          (void) ExportImagePixelArea(image,quantum_type,quantum_size,pixels,0,0);
2976
5.30k
          (void) WriteBlob(image, (size_t)packet_size*image->columns,pixels);
2977
5.30k
          break;
2978
0
        }
2979
420k
      }
2980
420k
      if (image->previous == (Image *) NULL)
2981
420k
        if (QuantumTick(y,image->rows))
2982
108k
          if (!MagickMonitorFormatted(y,image->rows,&image->exception,
2983
108k
                                      SaveImageText,image->filename,
2984
108k
                                      image->columns,image->rows))
2985
0
            break;
2986
420k
    }
2987
3.13k
    MagickFreeResourceLimitedMemory(unsigned char *,pixels);
2988
3.13k
    MagickFreeResourceLimitedMemory(unsigned char *,compress_pixels);
2989
3.13k
    if (image->next == (Image *) NULL)
2990
3.13k
      break;
2991
0
    image=SyncNextImageInList(image);
2992
0
    if (status != MagickFail)
2993
0
      status=MagickMonitorFormatted(scene++,image_list_length,
2994
0
                                    &image->exception,SaveImagesText,
2995
0
                                    image->filename);
2996
0
    if (status == False)
2997
0
      break;
2998
0
  } while (image_info->adjoin);
2999
3.13k
  if (image_info->adjoin)
3000
3.13k
    while (image->previous != (Image *) NULL)
3001
0
      image=image->previous;
3002
3.13k
  status &= CloseBlob(image);
3003
3.13k
  return(status);
3004
3.13k
}