1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                        M   M  IIIII  FFFFF  FFFFF                           %
7 %                        MM MM    I    F      F                               %
8 %                        M M M    I    FFF    FFF                             %
9 %                        M   M    I    F      F                               %
10 %                        M   M  IIIII  F      F                               %
11 %                                                                             %
12 %                                                                             %
13 %                      Read/Write MIFF Image Format                           %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                   Cristy                                    %
17 %                                 July 1992                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    https://imagemagick.org/script/license.php                               %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 
39 /*
40   Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/attribute.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/blob-private.h"
46 #include "MagickCore/cache.h"
47 #include "MagickCore/color.h"
48 #include "MagickCore/color-private.h"
49 #include "MagickCore/colormap.h"
50 #include "MagickCore/colormap-private.h"
51 #include "MagickCore/colorspace.h"
52 #include "MagickCore/colorspace-private.h"
53 #include "MagickCore/constitute.h"
54 #include "MagickCore/exception.h"
55 #include "MagickCore/exception-private.h"
56 #include "MagickCore/geometry.h"
57 #include "MagickCore/image.h"
58 #include "MagickCore/image-private.h"
59 #include "MagickCore/linked-list.h"
60 #include "MagickCore/list.h"
61 #include "MagickCore/magick.h"
62 #include "MagickCore/memory_.h"
63 #include "MagickCore/memory-private.h"
64 #include "MagickCore/module.h"
65 #include "MagickCore/monitor.h"
66 #include "MagickCore/monitor-private.h"
67 #include "MagickCore/option.h"
68 #include "MagickCore/pixel.h"
69 #include "MagickCore/pixel-accessor.h"
70 #include "MagickCore/profile.h"
71 #include "MagickCore/property.h"
72 #include "MagickCore/quantum-private.h"
73 #include "MagickCore/static.h"
74 #include "MagickCore/statistic.h"
75 #include "MagickCore/string_.h"
76 #include "MagickCore/string-private.h"
77 #if defined(MAGICKCORE_BZLIB_DELEGATE)
78 #include "bzlib.h"
79 #endif
80 #if defined(MAGICKCORE_LZMA_DELEGATE)
81 #include "lzma.h"
82 #endif
83 #if defined(MAGICKCORE_ZLIB_DELEGATE)
84 #include "zlib.h"
85 #endif
86 
87 /*
88   Define declarations.
89 */
90 #if !defined(LZMA_OK)
91 #define LZMA_OK  0
92 #endif
93 
94 /*
95   Forward declarations.
96 */
97 static MagickBooleanType
98   WriteMIFFImage(const ImageInfo *,Image *,ExceptionInfo *);
99 
100 /*
101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102 %                                                                             %
103 %                                                                             %
104 %                                                                             %
105 %   I s M I F F                                                               %
106 %                                                                             %
107 %                                                                             %
108 %                                                                             %
109 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110 %
111 %  IsMIFF() returns MagickTrue if the image format type, identified by the
112 %  magick string, is MIFF.
113 %
114 %  The format of the IsMIFF method is:
115 %
116 %      MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length)
117 %
118 %  A description of each parameter follows:
119 %
120 %    o magick: compare image format pattern against these bytes.
121 %
122 %    o length: Specifies the length of the magick string.
123 %
124 */
IsMIFF(const unsigned char * magick,const size_t length)125 static MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length)
126 {
127   if (length < 14)
128     return(MagickFalse);
129   if (LocaleNCompare((const char *) magick,"id=ImageMagick",14) == 0)
130     return(MagickTrue);
131   return(MagickFalse);
132 }
133 
134 /*
135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136 %                                                                             %
137 %                                                                             %
138 %                                                                             %
139 %   R e a d M I F F I m a g e                                                 %
140 %                                                                             %
141 %                                                                             %
142 %                                                                             %
143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
144 %
145 %  ReadMIFFImage() reads a MIFF image file and returns it.  It allocates the
146 %  memory necessary for the new Image structure and returns a pointer to the
147 %  new image.
148 %
149 %  The format of the ReadMIFFImage method is:
150 %
151 %      Image *ReadMIFFImage(const ImageInfo *image_info,
152 %        ExceptionInfo *exception)
153 %
154 %  Decompression code contributed by Kyle Shorter.
155 %
156 %  A description of each parameter follows:
157 %
158 %    o image_info: the image info.
159 %
160 %    o exception: return any errors or warnings in this structure.
161 %
162 */
163 
164 #if defined(MAGICKCORE_BZLIB_DELEGATE) || defined(MAGICKCORE_LZMA_DELEGATE) || defined(MAGICKCORE_ZLIB_DELEGATE)
AcquireCompressionMemory(void * context,const size_t items,const size_t size)165 static void *AcquireCompressionMemory(void *context,const size_t items,
166   const size_t size)
167 {
168   size_t
169     extent;
170 
171   (void) context;
172   if (HeapOverflowSanityCheckGetSize(items,size,&extent) != MagickFalse)
173     return((void *) NULL);
174   if (extent > GetMaxMemoryRequest())
175     return((void *) NULL);
176   return(AcquireMagickMemory(extent));
177 }
178 #endif
179 
180 #if defined(MAGICKCORE_BZLIB_DELEGATE)
181 static void *AcquireBZIPMemory(void *,int,int) magick_attribute((__malloc__));
182 
AcquireBZIPMemory(void * context,int items,int size)183 static void *AcquireBZIPMemory(void *context,int items,int size)
184 {
185   return(AcquireCompressionMemory(context,(size_t) items,(size_t) size));
186 }
187 #endif
188 
189 #if defined(MAGICKCORE_LZMA_DELEGATE)
190 static void *AcquireLZMAMemory(void *,size_t,size_t)
191   magick_attribute((__malloc__));
192 
AcquireLZMAMemory(void * context,size_t items,size_t size)193 static void *AcquireLZMAMemory(void *context,size_t items,size_t size)
194 {
195   return(AcquireCompressionMemory(context,items,size));
196 }
197 #endif
198 
199 #if defined(MAGICKCORE_ZLIB_DELEGATE)
200 static voidpf AcquireZIPMemory(voidpf,unsigned int,unsigned int)
201    magick_attribute((__malloc__));
202 
AcquireZIPMemory(voidpf context,unsigned int items,unsigned int size)203 static voidpf AcquireZIPMemory(voidpf context,unsigned int items,
204   unsigned int size)
205 {
206   return((voidpf) AcquireCompressionMemory(context,(size_t) items,
207     (size_t) size));
208 }
209 #endif
210 
PushRunlengthPacket(Image * image,const unsigned char * pixels,size_t * length,PixelInfo * pixel,ExceptionInfo * exception)211 static void PushRunlengthPacket(Image *image,const unsigned char *pixels,
212   size_t *length,PixelInfo *pixel,ExceptionInfo *exception)
213 {
214   const unsigned char
215     *p;
216 
217   p=pixels;
218   if (image->storage_class == PseudoClass)
219     {
220       pixel->index=0.0;
221       switch (image->depth)
222       {
223         case 32:
224         default:
225         {
226           pixel->index=(MagickRealType) ConstrainColormapIndex(image,(ssize_t)
227             (((size_t) *p << 24) | ((size_t) *(p+1) << 16) |
228             ((size_t) *(p+2) << 8) | (size_t) *(p+3)),exception);
229           p+=4;
230           break;
231         }
232         case 16:
233         {
234           pixel->index=(MagickRealType) ConstrainColormapIndex(image,(ssize_t)
235             (((size_t) *p << 8) | (size_t) *(p+1)),exception);
236           p+=2;
237           break;
238         }
239         case 8:
240         {
241           pixel->index=(MagickRealType) ConstrainColormapIndex(image,
242             (ssize_t) *p,exception);
243           p++;
244           break;
245         }
246       }
247       switch (image->depth)
248       {
249         case 8:
250         {
251           unsigned char
252             quantum;
253 
254           if (image->alpha_trait != UndefinedPixelTrait)
255             {
256               p=PushCharPixel(p,&quantum);
257               pixel->alpha=(MagickRealType) ScaleCharToQuantum(quantum);
258             }
259           break;
260         }
261         case 16:
262         {
263           unsigned short
264             quantum;
265 
266           if (image->alpha_trait != UndefinedPixelTrait)
267             {
268               p=PushShortPixel(MSBEndian,p,&quantum);
269               pixel->alpha=(MagickRealType) ((size_t) quantum >> (image->depth-
270                 MAGICKCORE_QUANTUM_DEPTH));
271             }
272           break;
273         }
274         case 32:
275         default:
276         {
277           unsigned int
278             quantum;
279 
280           if (image->alpha_trait != UndefinedPixelTrait)
281             {
282               p=PushLongPixel(MSBEndian,p,&quantum);
283               pixel->alpha=(MagickRealType) ((size_t) quantum >> (image->depth-
284                 MAGICKCORE_QUANTUM_DEPTH));
285             }
286           break;
287         }
288       }
289       *length=((size_t) *p++)+1;
290       return;
291     }
292   switch (image->depth)
293   {
294     case 8:
295     {
296       unsigned char
297         quantum;
298 
299       p=PushCharPixel(p,&quantum);
300       pixel->red=(MagickRealType) ScaleCharToQuantum(quantum);
301       pixel->green=pixel->red;
302       pixel->blue=pixel->red;
303       if (IsGrayColorspace(image->colorspace) == MagickFalse)
304         {
305           p=PushCharPixel(p,&quantum);
306           pixel->green=(MagickRealType) ScaleCharToQuantum(quantum);
307           p=PushCharPixel(p,&quantum);
308           pixel->blue=(MagickRealType) ScaleCharToQuantum(quantum);
309         }
310       if (image->colorspace == CMYKColorspace)
311         {
312           p=PushCharPixel(p,&quantum);
313           pixel->black=(MagickRealType) ScaleCharToQuantum(quantum);
314         }
315       if (image->alpha_trait != UndefinedPixelTrait)
316         {
317           p=PushCharPixel(p,&quantum);
318           pixel->alpha=(MagickRealType) ScaleCharToQuantum(quantum);
319         }
320       break;
321     }
322     case 16:
323     {
324       unsigned short
325         quantum;
326 
327       p=PushShortPixel(MSBEndian,p,&quantum);
328       pixel->red=(MagickRealType) ((size_t) quantum >> (image->depth-
329         MAGICKCORE_QUANTUM_DEPTH));
330       pixel->green=pixel->red;
331       pixel->blue=pixel->red;
332       if (IsGrayColorspace(image->colorspace) == MagickFalse)
333         {
334           p=PushShortPixel(MSBEndian,p,&quantum);
335           pixel->green=(MagickRealType) ((size_t) quantum >> (image->depth-
336             MAGICKCORE_QUANTUM_DEPTH));
337           p=PushShortPixel(MSBEndian,p,&quantum);
338           pixel->blue=(MagickRealType) ((size_t) quantum >> (image->depth-
339             MAGICKCORE_QUANTUM_DEPTH));
340         }
341       if (image->colorspace == CMYKColorspace)
342         {
343           p=PushShortPixel(MSBEndian,p,&quantum);
344           pixel->black=(MagickRealType) ((size_t) quantum >> (image->depth-
345             MAGICKCORE_QUANTUM_DEPTH));
346         }
347       if (image->alpha_trait != UndefinedPixelTrait)
348         {
349           p=PushShortPixel(MSBEndian,p,&quantum);
350           pixel->alpha=(MagickRealType) ((size_t) quantum >> (image->depth-
351             MAGICKCORE_QUANTUM_DEPTH));
352         }
353       break;
354     }
355     case 32:
356     default:
357     {
358       unsigned int
359         quantum;
360 
361       p=PushLongPixel(MSBEndian,p,&quantum);
362       pixel->red=(MagickRealType) ((size_t) quantum >> (image->depth-
363         MAGICKCORE_QUANTUM_DEPTH));
364       pixel->green=pixel->red;
365       pixel->blue=pixel->red;
366       if (IsGrayColorspace(image->colorspace) == MagickFalse)
367         {
368           p=PushLongPixel(MSBEndian,p,&quantum);
369           pixel->green=(MagickRealType) ((size_t) quantum >> (image->depth-
370             MAGICKCORE_QUANTUM_DEPTH));
371           p=PushLongPixel(MSBEndian,p,&quantum);
372           pixel->blue=(MagickRealType) ((size_t) quantum >> (image->depth-
373             MAGICKCORE_QUANTUM_DEPTH));
374         }
375       if (image->colorspace == CMYKColorspace)
376         {
377           p=PushLongPixel(MSBEndian,p,&quantum);
378           pixel->black=(MagickRealType) ((size_t) quantum >> (image->depth-
379             MAGICKCORE_QUANTUM_DEPTH));
380         }
381       if (image->alpha_trait != UndefinedPixelTrait)
382         {
383           p=PushLongPixel(MSBEndian,p,&quantum);
384           pixel->alpha=(MagickRealType) ((size_t) quantum >> (image->depth-
385             MAGICKCORE_QUANTUM_DEPTH));
386         }
387       break;
388     }
389   }
390   *length=(size_t) (*p++)+1;
391 }
392 
393 #if defined(MAGICKCORE_BZLIB_DELEGATE)
RelinquishBZIPMemory(void * context,void * memory)394 static void RelinquishBZIPMemory(void *context,void *memory)
395 {
396   (void) context;
397   memory=RelinquishMagickMemory(memory);
398 }
399 #endif
400 
401 #if defined(MAGICKCORE_LZMA_DELEGATE)
RelinquishLZMAMemory(void * context,void * memory)402 static void RelinquishLZMAMemory(void *context,void *memory)
403 {
404   (void) context;
405   memory=RelinquishMagickMemory(memory);
406 }
407 #endif
408 
409 #if defined(MAGICKCORE_ZLIB_DELEGATE)
RelinquishZIPMemory(voidpf context,voidpf memory)410 static void RelinquishZIPMemory(voidpf context,voidpf memory)
411 {
412   (void) context;
413   memory=RelinquishMagickMemory(memory);
414 }
415 #endif
416 
ReadMIFFImage(const ImageInfo * image_info,ExceptionInfo * exception)417 static Image *ReadMIFFImage(const ImageInfo *image_info,
418   ExceptionInfo *exception)
419 {
420 #define BZipMaxExtent(x)  ((x)+((x)/100)+600)
421 #define LZMAMaxExtent(x)  ((x)+((x)/3)+128)
422 #define ThrowMIFFException(exception,message) \
423 { \
424   if (quantum_info != (QuantumInfo *) NULL) \
425     quantum_info=DestroyQuantumInfo(quantum_info); \
426   if (compress_pixels != (unsigned char *) NULL) \
427     compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels); \
428   ThrowReaderException((exception),(message)); \
429 }
430 #define ZipMaxExtent(x)  ((x)+(((x)+7) >> 3)+(((x)+63) >> 6)+11)
431 
432 #if defined(MAGICKCORE_BZLIB_DELEGATE)
433   bz_stream
434     bzip_info;
435 #endif
436 
437   char
438     id[MagickPathExtent],
439     keyword[MagickPathExtent],
440     *options;
441 
442   double
443     version;
444 
445   GeometryInfo
446     geometry_info;
447 
448   Image
449     *image;
450 
451   int
452     c;
453 
454   LinkedListInfo
455     *profiles;
456 
457 #if defined(MAGICKCORE_LZMA_DELEGATE)
458   lzma_stream
459     initialize_lzma = LZMA_STREAM_INIT,
460     lzma_info = LZMA_STREAM_INIT;
461 
462   lzma_allocator
463     allocator;
464 #endif
465 
466   MagickBooleanType
467     status;
468 
469   PixelInfo
470     pixel;
471 
472   MagickStatusType
473     flags;
474 
475   QuantumFormatType
476     quantum_format;
477 
478   QuantumInfo
479     *quantum_info;
480 
481   QuantumType
482     quantum_type;
483 
484   ssize_t
485     i;
486 
487   size_t
488     compress_extent,
489     extent,
490     length,
491     packet_size;
492 
493   ssize_t
494     count;
495 
496   unsigned char
497     *compress_pixels,
498     *pixels;
499 
500   size_t
501     colors;
502 
503   ssize_t
504     y;
505 
506 #if defined(MAGICKCORE_ZLIB_DELEGATE)
507   z_stream
508     zip_info;
509 #endif
510 
511   /*
512     Open image file.
513   */
514   assert(image_info != (const ImageInfo *) NULL);
515   assert(image_info->signature == MagickCoreSignature);
516   if (image_info->debug != MagickFalse)
517     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
518       image_info->filename);
519   assert(exception != (ExceptionInfo *) NULL);
520   assert(exception->signature == MagickCoreSignature);
521   image=AcquireImage(image_info,exception);
522   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
523   if (status == MagickFalse)
524     {
525       image=DestroyImageList(image);
526       return((Image *) NULL);
527     }
528   /*
529     Decode image header;  header terminates one character beyond a ':'.
530   */
531   c=ReadBlobByte(image);
532   if (c == EOF)
533     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
534   *id='\0';
535   compress_pixels=(unsigned char *) NULL;
536   quantum_info=(QuantumInfo *) NULL;
537   (void) memset(keyword,0,sizeof(keyword));
538   version=0.0;
539   (void) version;
540   do
541   {
542     /*
543       Decode image header;  header terminates one character beyond a ':'.
544     */
545     SetGeometryInfo(&geometry_info);
546     length=MagickPathExtent;
547     options=AcquireString((char *) NULL);
548     quantum_format=UndefinedQuantumFormat;
549     profiles=(LinkedListInfo *) NULL;
550     colors=0;
551     image->depth=8UL;
552     image->compression=NoCompression;
553     while ((isgraph((int) ((unsigned char) c)) != 0) && (c != (int) ':'))
554     {
555       char
556         *p;
557 
558       if (c == (int) '{')
559         {
560           char
561             *comment;
562 
563           /*
564             Read comment-- any text between { }.
565           */
566           length=MagickPathExtent;
567           comment=AcquireString((char *) NULL);
568           for (p=comment; comment != (char *) NULL; p++)
569           {
570             c=ReadBlobByte(image);
571             if (c == (int) '\\')
572               c=ReadBlobByte(image);
573             else
574               if ((c == EOF) || (c == (int) '}'))
575                 break;
576             if ((size_t) (p-comment+1) >= length)
577               {
578                 *p='\0';
579                 length<<=1;
580                 comment=(char *) ResizeQuantumMemory(comment,
581                   OverAllocateMemory(length+MagickPathExtent),sizeof(*comment));
582                 if (comment == (char *) NULL)
583                   break;
584                 p=comment+strlen(comment);
585               }
586             *p=(char) c;
587           }
588           if (comment == (char *) NULL)
589             {
590               options=DestroyString(options);
591               ThrowMIFFException(ResourceLimitError,"MemoryAllocationFailed");
592             }
593           *p='\0';
594           (void) SetImageProperty(image,"comment",comment,exception);
595           comment=DestroyString(comment);
596           c=ReadBlobByte(image);
597         }
598       else
599         if (isalnum((int) ((unsigned char) c)) != MagickFalse)
600           {
601             /*
602               Get the keyword.
603             */
604             length=MagickPathExtent-1;
605             p=keyword;
606             do
607             {
608               if (c == (int) '=')
609                 break;
610               if ((size_t) (p-keyword) < (MagickPathExtent-1))
611                 *p++=(char) c;
612               c=ReadBlobByte(image);
613             } while (c != EOF);
614             *p='\0';
615             p=options;
616             while ((isspace((int) ((unsigned char) c)) != 0) && (c != EOF))
617               c=ReadBlobByte(image);
618             if (c == (int) '=')
619               {
620                 /*
621                   Get the keyword value.
622                 */
623                 c=ReadBlobByte(image);
624                 while ((c != (int) '}') && (c != EOF))
625                 {
626                   if ((size_t) (p-options+1) >= length)
627                     {
628                       *p='\0';
629                       length<<=1;
630                       options=(char *) ResizeQuantumMemory(options,length+
631                         MagickPathExtent,sizeof(*options));
632                       if (options == (char *) NULL)
633                         break;
634                       p=options+strlen(options);
635                     }
636                   *p++=(char) c;
637                   c=ReadBlobByte(image);
638                   if (c == '\\')
639                     {
640                       c=ReadBlobByte(image);
641                       if (c == (int) '}')
642                         {
643                           *p++=(char) c;
644                           c=ReadBlobByte(image);
645                         }
646                     }
647                   if (*options != '{')
648                     if (isspace((int) ((unsigned char) c)) != 0)
649                       break;
650                 }
651                 if (options == (char *) NULL)
652                   ThrowMIFFException(ResourceLimitError,
653                     "MemoryAllocationFailed");
654               }
655             *p='\0';
656             if (*options == '{')
657               (void) CopyMagickString(options,options+1,strlen(options));
658             /*
659               Assign a value to the specified keyword.
660             */
661             switch (*keyword)
662             {
663               case 'a':
664               case 'A':
665               {
666                 if (LocaleCompare(keyword,"alpha-trait") == 0)
667                   {
668                     ssize_t
669                       alpha_trait;
670 
671                     alpha_trait=ParseCommandOption(MagickPixelTraitOptions,
672                       MagickFalse,options);
673                     if (alpha_trait < 0)
674                       break;
675                     image->alpha_trait=(PixelTrait) alpha_trait;
676                     break;
677                   }
678                 (void) SetImageProperty(image,keyword,options,exception);
679                 break;
680               }
681               case 'b':
682               case 'B':
683               {
684                 if (LocaleCompare(keyword,"background-color") == 0)
685                   {
686                     (void) QueryColorCompliance(options,AllCompliance,
687                       &image->background_color,exception);
688                     break;
689                   }
690                 if (LocaleCompare(keyword,"blue-primary") == 0)
691                   {
692                     flags=ParseGeometry(options,&geometry_info);
693                     image->chromaticity.blue_primary.x=geometry_info.rho;
694                     image->chromaticity.blue_primary.y=geometry_info.sigma;
695                     if ((flags & SigmaValue) == 0)
696                       image->chromaticity.blue_primary.y=
697                         image->chromaticity.blue_primary.x;
698                     break;
699                   }
700                 if (LocaleCompare(keyword,"border-color") == 0)
701                   {
702                     (void) QueryColorCompliance(options,AllCompliance,
703                       &image->border_color,exception);
704                     break;
705                   }
706                 (void) SetImageProperty(image,keyword,options,exception);
707                 break;
708               }
709               case 'c':
710               case 'C':
711               {
712                 if (LocaleCompare(keyword,"class") == 0)
713                   {
714                     ssize_t
715                       storage_class;
716 
717                     storage_class=ParseCommandOption(MagickClassOptions,
718                       MagickFalse,options);
719                     if (storage_class < 0)
720                       break;
721                     image->storage_class=(ClassType) storage_class;
722                     break;
723                   }
724                 if (LocaleCompare(keyword,"colors") == 0)
725                   {
726                     colors=StringToUnsignedLong(options);
727                     break;
728                   }
729                 if (LocaleCompare(keyword,"colorspace") == 0)
730                   {
731                     ssize_t
732                       colorspace;
733 
734                     colorspace=ParseCommandOption(MagickColorspaceOptions,
735                       MagickFalse,options);
736                     if (colorspace < 0)
737                       break;
738                     image->colorspace=(ColorspaceType) colorspace;
739                     break;
740                   }
741                 if (LocaleCompare(keyword,"compression") == 0)
742                   {
743                     ssize_t
744                       compression;
745 
746                     compression=ParseCommandOption(MagickCompressOptions,
747                       MagickFalse,options);
748                     if (compression < 0)
749                       break;
750                     image->compression=(CompressionType) compression;
751                     break;
752                   }
753                 if (LocaleCompare(keyword,"columns") == 0)
754                   {
755                     image->columns=StringToUnsignedLong(options);
756                     break;
757                   }
758                 (void) SetImageProperty(image,keyword,options,exception);
759                 break;
760               }
761               case 'd':
762               case 'D':
763               {
764                 if (LocaleCompare(keyword,"delay") == 0)
765                   {
766                     image->delay=StringToUnsignedLong(options);
767                     break;
768                   }
769                 if (LocaleCompare(keyword,"depth") == 0)
770                   {
771                     image->depth=StringToUnsignedLong(options);
772                     break;
773                   }
774                 if (LocaleCompare(keyword,"dispose") == 0)
775                   {
776                     ssize_t
777                       dispose;
778 
779                     dispose=ParseCommandOption(MagickDisposeOptions,MagickFalse,
780                       options);
781                     if (dispose < 0)
782                       break;
783                     image->dispose=(DisposeType) dispose;
784                     break;
785                   }
786                 (void) SetImageProperty(image,keyword,options,exception);
787                 break;
788               }
789               case 'e':
790               case 'E':
791               {
792                 if (LocaleCompare(keyword,"endian") == 0)
793                   {
794                     ssize_t
795                       endian;
796 
797                     endian=ParseCommandOption(MagickEndianOptions,MagickFalse,
798                       options);
799                     if (endian < 0)
800                       break;
801                     image->endian=(EndianType) endian;
802                     break;
803                   }
804                 (void) SetImageProperty(image,keyword,options,exception);
805                 break;
806               }
807               case 'g':
808               case 'G':
809               {
810                 if (LocaleCompare(keyword,"gamma") == 0)
811                   {
812                     image->gamma=StringToDouble(options,(char **) NULL);
813                     break;
814                   }
815                 if (LocaleCompare(keyword,"gravity") == 0)
816                   {
817                     ssize_t
818                       gravity;
819 
820                     gravity=ParseCommandOption(MagickGravityOptions,MagickFalse,
821                       options);
822                     if (gravity < 0)
823                       break;
824                     image->gravity=(GravityType) gravity;
825                     break;
826                   }
827                 if (LocaleCompare(keyword,"green-primary") == 0)
828                   {
829                     flags=ParseGeometry(options,&geometry_info);
830                     image->chromaticity.green_primary.x=geometry_info.rho;
831                     image->chromaticity.green_primary.y=geometry_info.sigma;
832                     if ((flags & SigmaValue) == 0)
833                       image->chromaticity.green_primary.y=
834                         image->chromaticity.green_primary.x;
835                     break;
836                   }
837                 (void) SetImageProperty(image,keyword,options,exception);
838                 break;
839               }
840               case 'i':
841               case 'I':
842               {
843                 if (LocaleCompare(keyword,"id") == 0)
844                   {
845                     (void) CopyMagickString(id,options,MagickPathExtent);
846                     break;
847                   }
848                 if (LocaleCompare(keyword,"iterations") == 0)
849                   {
850                     image->iterations=StringToUnsignedLong(options);
851                     break;
852                   }
853                 (void) SetImageProperty(image,keyword,options,exception);
854                 break;
855               }
856               case 'm':
857               case 'M':
858               {
859                 if (LocaleCompare(keyword,"matte") == 0)
860                   {
861                     ssize_t
862                       matte;
863 
864                     matte=ParseCommandOption(MagickBooleanOptions,MagickFalse,
865                       options);
866                     if (matte < 0)
867                       break;
868                     image->alpha_trait=matte == 0 ? UndefinedPixelTrait :
869                       BlendPixelTrait;
870                     break;
871                   }
872                 if (LocaleCompare(keyword,"mattecolor") == 0)
873                   {
874                     (void) QueryColorCompliance(options,AllCompliance,
875                       &image->matte_color,exception);
876                     break;
877                   }
878                 if (LocaleCompare(keyword,"montage") == 0)
879                   {
880                     (void) CloneString(&image->montage,options);
881                     break;
882                   }
883                 (void) SetImageProperty(image,keyword,options,exception);
884                 break;
885               }
886               case 'o':
887               case 'O':
888               {
889                 if (LocaleCompare(keyword,"orientation") == 0)
890                   {
891                     ssize_t
892                       orientation;
893 
894                     orientation=ParseCommandOption(MagickOrientationOptions,
895                       MagickFalse,options);
896                     if (orientation < 0)
897                       break;
898                     image->orientation=(OrientationType) orientation;
899                     break;
900                   }
901                 (void) SetImageProperty(image,keyword,options,exception);
902                 break;
903               }
904               case 'p':
905               case 'P':
906               {
907                 if (LocaleCompare(keyword,"page") == 0)
908                   {
909                     char
910                       *geometry;
911 
912                     geometry=GetPageGeometry(options);
913                     (void) ParseAbsoluteGeometry(geometry,&image->page);
914                     geometry=DestroyString(geometry);
915                     break;
916                   }
917                 if (LocaleCompare(keyword,"pixel-intensity") == 0)
918                   {
919                     ssize_t
920                       intensity;
921 
922                     intensity=ParseCommandOption(MagickPixelIntensityOptions,
923                       MagickFalse,options);
924                     if (intensity < 0)
925                       break;
926                     image->intensity=(PixelIntensityMethod) intensity;
927                     break;
928                   }
929                 if (LocaleCompare(keyword,"profile") == 0)
930                   {
931                     if (profiles == (LinkedListInfo *) NULL)
932                       profiles=NewLinkedList(0);
933                     (void) AppendValueToLinkedList(profiles,
934                       AcquireString(options));
935                     break;
936                   }
937                 (void) SetImageProperty(image,keyword,options,exception);
938                 break;
939               }
940               case 'q':
941               case 'Q':
942               {
943                 if (LocaleCompare(keyword,"quality") == 0)
944                   {
945                     image->quality=StringToUnsignedLong(options);
946                     break;
947                   }
948                 if ((LocaleCompare(keyword,"quantum-format") == 0) ||
949                     (LocaleCompare(keyword,"quantum:format") == 0))
950                   {
951                     ssize_t
952                       format;
953 
954                     format=ParseCommandOption(MagickQuantumFormatOptions,
955                       MagickFalse,options);
956                     if (format < 0)
957                       break;
958                     quantum_format=(QuantumFormatType) format;
959                     break;
960                   }
961                 (void) SetImageProperty(image,keyword,options,exception);
962                 break;
963               }
964               case 'r':
965               case 'R':
966               {
967                 if (LocaleCompare(keyword,"red-primary") == 0)
968                   {
969                     flags=ParseGeometry(options,&geometry_info);
970                     image->chromaticity.red_primary.x=geometry_info.rho;
971                     image->chromaticity.red_primary.y=geometry_info.sigma;
972                     if ((flags & SigmaValue) == 0)
973                       image->chromaticity.red_primary.y=
974                         image->chromaticity.red_primary.x;
975                     break;
976                   }
977                 if (LocaleCompare(keyword,"rendering-intent") == 0)
978                   {
979                     ssize_t
980                       rendering_intent;
981 
982                     rendering_intent=ParseCommandOption(MagickIntentOptions,
983                       MagickFalse,options);
984                     if (rendering_intent < 0)
985                       break;
986                     image->rendering_intent=(RenderingIntent) rendering_intent;
987                     break;
988                   }
989                 if (LocaleCompare(keyword,"resolution") == 0)
990                   {
991                     flags=ParseGeometry(options,&geometry_info);
992                     image->resolution.x=geometry_info.rho;
993                     image->resolution.y=geometry_info.sigma;
994                     if ((flags & SigmaValue) == 0)
995                       image->resolution.y=image->resolution.x;
996                     break;
997                   }
998                 if (LocaleCompare(keyword,"rows") == 0)
999                   {
1000                     image->rows=StringToUnsignedLong(options);
1001                     break;
1002                   }
1003                 (void) SetImageProperty(image,keyword,options,exception);
1004                 break;
1005               }
1006               case 's':
1007               case 'S':
1008               {
1009                 if (LocaleCompare(keyword,"scene") == 0)
1010                   {
1011                     image->scene=StringToUnsignedLong(options);
1012                     break;
1013                   }
1014                 (void) SetImageProperty(image,keyword,options,exception);
1015                 break;
1016               }
1017               case 't':
1018               case 'T':
1019               {
1020                 if (LocaleCompare(keyword,"ticks-per-second") == 0)
1021                   {
1022                     image->ticks_per_second=(ssize_t) StringToLong(options);
1023                     break;
1024                   }
1025                 if (LocaleCompare(keyword,"tile-offset") == 0)
1026                   {
1027                     char
1028                       *geometry;
1029 
1030                     geometry=GetPageGeometry(options);
1031                     (void) ParseAbsoluteGeometry(geometry,&image->tile_offset);
1032                     geometry=DestroyString(geometry);
1033                     break;
1034                   }
1035                 if (LocaleCompare(keyword,"type") == 0)
1036                   {
1037                     ssize_t
1038                       type;
1039 
1040                     type=ParseCommandOption(MagickTypeOptions,MagickFalse,
1041                       options);
1042                     if (type < 0)
1043                       break;
1044                     image->type=(ImageType) type;
1045                     break;
1046                   }
1047                 (void) SetImageProperty(image,keyword,options,exception);
1048                 break;
1049               }
1050               case 'u':
1051               case 'U':
1052               {
1053                 if (LocaleCompare(keyword,"units") == 0)
1054                   {
1055                     ssize_t
1056                       units;
1057 
1058                     units=ParseCommandOption(MagickResolutionOptions,
1059                       MagickFalse,options);
1060                     if (units < 0)
1061                       break;
1062                     image->units=(ResolutionType) units;
1063                     break;
1064                   }
1065                 (void) SetImageProperty(image,keyword,options,exception);
1066                 break;
1067               }
1068               case 'v':
1069               case 'V':
1070               {
1071                 if (LocaleCompare(keyword,"version") == 0)
1072                   {
1073                     version=StringToDouble(options,(char **) NULL);
1074                     break;
1075                   }
1076                 (void) SetImageProperty(image,keyword,options,exception);
1077                 break;
1078               }
1079               case 'w':
1080               case 'W':
1081               {
1082                 if (LocaleCompare(keyword,"white-point") == 0)
1083                   {
1084                     flags=ParseGeometry(options,&geometry_info);
1085                     image->chromaticity.white_point.x=geometry_info.rho;
1086                     image->chromaticity.white_point.y=geometry_info.sigma;
1087                     if ((flags & SigmaValue) == 0)
1088                       image->chromaticity.white_point.y=
1089                         image->chromaticity.white_point.x;
1090                     break;
1091                   }
1092                 (void) SetImageProperty(image,keyword,options,exception);
1093                 break;
1094               }
1095               default:
1096               {
1097                 (void) SetImageProperty(image,keyword,options,exception);
1098                 break;
1099               }
1100             }
1101           }
1102         else
1103           c=ReadBlobByte(image);
1104       while (isspace((int) ((unsigned char) c)) != 0)
1105         c=ReadBlobByte(image);
1106     }
1107     options=DestroyString(options);
1108     (void) ReadBlobByte(image);
1109     /*
1110       Verify that required image information is defined.
1111     */
1112     if ((LocaleCompare(id,"ImageMagick") != 0) ||
1113         (image->storage_class == UndefinedClass) ||
1114         (image->compression == UndefinedCompression) ||
1115         (image->colorspace == UndefinedColorspace) ||
1116         (image->columns == 0) || (image->rows == 0) ||
1117         (image->depth == 0) || (image->depth > 64))
1118       {
1119         if (profiles != (LinkedListInfo *) NULL)
1120           profiles=DestroyLinkedList(profiles,RelinquishMagickMemory);
1121         if (image->previous == (Image *) NULL)
1122           ThrowMIFFException(CorruptImageError,"ImproperImageHeader");
1123         DeleteImageFromList(&image);
1124         (void) ThrowMagickException(exception,GetMagickModule(),
1125           CorruptImageError,"ImproperImageHeader","`%s'",image->filename);
1126         break;
1127       }
1128     if (image->montage != (char *) NULL)
1129       {
1130         char
1131           *p;
1132 
1133         /*
1134           Image directory.
1135         */
1136         extent=MagickPathExtent;
1137         image->directory=AcquireString((char *) NULL);
1138         p=image->directory;
1139         length=0;
1140         do
1141         {
1142           *p='\0';
1143           if ((length+MagickPathExtent) >= extent)
1144             {
1145               /*
1146                 Allocate more memory for the image directory.
1147               */
1148               extent<<=1;
1149               image->directory=(char *) ResizeQuantumMemory(image->directory,
1150                 extent+MagickPathExtent,sizeof(*image->directory));
1151               if (image->directory == (char *) NULL)
1152                 ThrowMIFFException(CorruptImageError,"UnableToReadImageData");
1153               p=image->directory+length;
1154             }
1155           c=ReadBlobByte(image);
1156           if (c == EOF)
1157             break;
1158           *p++=(char) c;
1159           length++;
1160         } while (c != (int) '\0');
1161       }
1162     if (profiles != (LinkedListInfo *) NULL)
1163       {
1164         const char
1165           *name;
1166 
1167         StringInfo
1168           *profile;
1169 
1170         /*
1171           Read image profiles.
1172         */
1173         ResetLinkedListIterator(profiles);
1174         name=(const char *) GetNextValueInLinkedList(profiles);
1175         while (name != (const char *) NULL)
1176         {
1177           length=ReadBlobMSBLong(image);
1178           if ((length == 0) || ((MagickSizeType) length > GetBlobSize(image)))
1179             break;
1180           profile=AcquireStringInfo(length);
1181           if (profile == (StringInfo *) NULL)
1182             break;
1183           count=ReadBlob(image,length,GetStringInfoDatum(profile));
1184           if (count != (ssize_t) length)
1185             {
1186               profile=DestroyStringInfo(profile);
1187               break;
1188             }
1189           status=SetImageProfile(image,name,profile,exception);
1190           profile=DestroyStringInfo(profile);
1191           if (status == MagickFalse)
1192             break;
1193           name=(const char *) GetNextValueInLinkedList(profiles);
1194         }
1195         profiles=DestroyLinkedList(profiles,RelinquishMagickMemory);
1196       }
1197     image->depth=GetImageQuantumDepth(image,MagickFalse);
1198     if (image->storage_class == PseudoClass)
1199       {
1200         unsigned char
1201           *colormap;
1202 
1203         /*
1204           Create image colormap.
1205         */
1206         packet_size=(size_t) (3UL*image->depth/8UL);
1207         if ((MagickSizeType) colors > GetBlobSize(image))
1208           ThrowMIFFException(CorruptImageError,"InsufficientImageDataInFile");
1209         if (((MagickSizeType) packet_size*colors) > GetBlobSize(image))
1210           ThrowMIFFException(CorruptImageError,"InsufficientImageDataInFile");
1211         status=AcquireImageColormap(image,colors != 0 ? colors : 256,exception);
1212         if (status == MagickFalse)
1213           ThrowMIFFException(ResourceLimitError,"MemoryAllocationFailed");
1214         if (colors != 0)
1215           {
1216             const unsigned char
1217               *p;
1218 
1219             /*
1220               Read image colormap from file.
1221             */
1222             colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
1223               packet_size*sizeof(*colormap));
1224             if (colormap == (unsigned char *) NULL)
1225               ThrowMIFFException(ResourceLimitError,"MemoryAllocationFailed");
1226             count=ReadBlob(image,packet_size*image->colors,colormap);
1227             p=colormap;
1228             switch (image->depth)
1229             {
1230               case 8:
1231               {
1232                 unsigned char
1233                   char_pixel;
1234 
1235                 for (i=0; i < (ssize_t) image->colors; i++)
1236                 {
1237                   p=PushCharPixel(p,&char_pixel);
1238                   image->colormap[i].red=(MagickRealType)
1239                     ScaleCharToQuantum(char_pixel);
1240                   p=PushCharPixel(p,&char_pixel);
1241                   image->colormap[i].green=(MagickRealType)
1242                     ScaleCharToQuantum(char_pixel);
1243                   p=PushCharPixel(p,&char_pixel);
1244                   image->colormap[i].blue=(MagickRealType)
1245                     ScaleCharToQuantum(char_pixel);
1246                 }
1247                 break;
1248               }
1249               case 16:
1250               {
1251                 unsigned short
1252                   short_pixel;
1253 
1254                 for (i=0; i < (ssize_t) image->colors; i++)
1255                 {
1256                   p=PushShortPixel(MSBEndian,p,&short_pixel);
1257                   image->colormap[i].red=(MagickRealType)
1258                     ScaleShortToQuantum(short_pixel);
1259                   p=PushShortPixel(MSBEndian,p,&short_pixel);
1260                   image->colormap[i].green=(MagickRealType)
1261                     ScaleShortToQuantum(short_pixel);
1262                   p=PushShortPixel(MSBEndian,p,&short_pixel);
1263                   image->colormap[i].blue=(MagickRealType)
1264                     ScaleShortToQuantum(short_pixel);
1265                 }
1266                 break;
1267               }
1268               case 32:
1269               default:
1270               {
1271                 unsigned int
1272                   long_pixel;
1273 
1274                 for (i=0; i < (ssize_t) image->colors; i++)
1275                 {
1276                   p=PushLongPixel(MSBEndian,p,&long_pixel);
1277                   image->colormap[i].red=(MagickRealType)
1278                     ScaleLongToQuantum(long_pixel);
1279                   p=PushLongPixel(MSBEndian,p,&long_pixel);
1280                   image->colormap[i].green=(MagickRealType)
1281                     ScaleLongToQuantum(long_pixel);
1282                   p=PushLongPixel(MSBEndian,p,&long_pixel);
1283                   image->colormap[i].blue=(MagickRealType)
1284                     ScaleLongToQuantum(long_pixel);
1285                 }
1286                 break;
1287               }
1288             }
1289             colormap=(unsigned char *) RelinquishMagickMemory(colormap);
1290           }
1291       }
1292     if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
1293       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1294         break;
1295     status=SetImageExtent(image,image->columns,image->rows,exception);
1296     if (status == MagickFalse)
1297       return(DestroyImageList(image));
1298     status=ResetImagePixels(image,exception);
1299     if (status == MagickFalse)
1300       return(DestroyImageList(image));
1301     /*
1302       Allocate image pixels.
1303     */
1304     quantum_info=AcquireQuantumInfo(image_info,image);
1305     if (quantum_info == (QuantumInfo *) NULL)
1306       ThrowMIFFException(ResourceLimitError,"MemoryAllocationFailed");
1307     if (quantum_format != UndefinedQuantumFormat)
1308       {
1309         status=SetQuantumFormat(image,quantum_info,quantum_format);
1310         if (status == MagickFalse)
1311           ThrowMIFFException(ResourceLimitError,"MemoryAllocationFailed");
1312       }
1313     packet_size=(size_t) (quantum_info->depth/8);
1314     if (image->storage_class == DirectClass)
1315       packet_size=(size_t) (3*quantum_info->depth/8);
1316     if (IsGrayColorspace(image->colorspace) != MagickFalse)
1317       packet_size=quantum_info->depth/8;
1318     if (image->alpha_trait != UndefinedPixelTrait)
1319       packet_size+=quantum_info->depth/8;
1320     if (image->colorspace == CMYKColorspace)
1321       packet_size+=quantum_info->depth/8;
1322     if (image->compression == RLECompression)
1323       packet_size++;
1324     compress_extent=MagickMax(MagickMax(BZipMaxExtent(packet_size*
1325       image->columns),LZMAMaxExtent(packet_size*image->columns)),
1326       ZipMaxExtent(packet_size*image->columns));
1327     if (compress_extent < (packet_size*image->columns))
1328       ThrowMIFFException(ResourceLimitError,"MemoryAllocationFailed");
1329     compress_pixels=(unsigned char *) AcquireQuantumMemory(compress_extent,
1330       sizeof(*compress_pixels));
1331     if (compress_pixels == (unsigned char *) NULL)
1332       ThrowMIFFException(ResourceLimitError,"MemoryAllocationFailed");
1333     /*
1334       Read image pixels.
1335     */
1336     quantum_type=RGBQuantum;
1337     if (image->alpha_trait != UndefinedPixelTrait)
1338       quantum_type=RGBAQuantum;
1339     if (image->colorspace == CMYKColorspace)
1340       {
1341         quantum_type=CMYKQuantum;
1342         if (image->alpha_trait != UndefinedPixelTrait)
1343           quantum_type=CMYKAQuantum;
1344       }
1345     if (IsGrayColorspace(image->colorspace) != MagickFalse)
1346       {
1347         quantum_type=GrayQuantum;
1348         if (image->alpha_trait != UndefinedPixelTrait)
1349           quantum_type=GrayAlphaQuantum;
1350       }
1351     if (image->storage_class == PseudoClass)
1352       {
1353         quantum_type=IndexQuantum;
1354         if (image->alpha_trait != UndefinedPixelTrait)
1355           quantum_type=IndexAlphaQuantum;
1356       }
1357     status=MagickTrue;
1358     GetPixelInfo(image,&pixel);
1359 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1360    (void) memset(&bzip_info,0,sizeof(bzip_info));
1361 #endif
1362 #if defined(MAGICKCORE_LZMA_DELEGATE)
1363     (void) memset(&allocator,0,sizeof(allocator));
1364 #endif
1365 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1366     (void) memset(&zip_info,0,sizeof(zip_info));
1367 #endif
1368     switch (image->compression)
1369     {
1370 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1371       case BZipCompression:
1372       {
1373         int
1374           code;
1375 
1376         bzip_info.bzalloc=AcquireBZIPMemory;
1377         bzip_info.bzfree=RelinquishBZIPMemory;
1378         bzip_info.opaque=(void *) image;
1379         code=BZ2_bzDecompressInit(&bzip_info,(int) image_info->verbose,
1380           MagickFalse);
1381         if (code != BZ_OK)
1382           status=MagickFalse;
1383         break;
1384       }
1385 #endif
1386 #if defined(MAGICKCORE_LZMA_DELEGATE)
1387       case LZMACompression:
1388       {
1389         int
1390           code;
1391 
1392         allocator.alloc=AcquireLZMAMemory;
1393         allocator.free=RelinquishLZMAMemory;
1394         allocator.opaque=(void *) image;
1395         lzma_info=initialize_lzma;
1396         lzma_info.allocator=(&allocator);
1397         code=lzma_auto_decoder(&lzma_info,(uint64_t) -1,0);
1398         if (code != LZMA_OK)
1399           status=MagickFalse;
1400         break;
1401       }
1402 #endif
1403 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1404       case LZWCompression:
1405       case ZipCompression:
1406       {
1407         int
1408           code;
1409 
1410         zip_info.zalloc=AcquireZIPMemory;
1411         zip_info.zfree=RelinquishZIPMemory;
1412         zip_info.opaque=(voidpf) image;
1413         code=inflateInit(&zip_info);
1414         if (code != Z_OK)
1415           status=MagickFalse;
1416         break;
1417       }
1418 #endif
1419       case RLECompression:
1420         break;
1421       default:
1422         break;
1423     }
1424     pixels=(unsigned char *) GetQuantumPixels(quantum_info);
1425     length=0;
1426     for (y=0; y < (ssize_t) image->rows; y++)
1427     {
1428       ssize_t
1429         x;
1430 
1431       Quantum
1432         *magick_restrict q;
1433 
1434       if (status == MagickFalse)
1435         break;
1436       q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1437       if (q == (Quantum *) NULL)
1438         break;
1439       extent=0;
1440       switch (image->compression)
1441       {
1442 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1443         case BZipCompression:
1444         {
1445           bzip_info.next_out=(char *) pixels;
1446           bzip_info.avail_out=(unsigned int) (packet_size*image->columns);
1447           do
1448           {
1449             int
1450               code;
1451 
1452             if (bzip_info.avail_in == 0)
1453               {
1454                 bzip_info.next_in=(char *) compress_pixels;
1455                 length=(size_t) BZipMaxExtent(packet_size*image->columns);
1456                 if (version != 0.0)
1457                   length=(size_t) ReadBlobMSBLong(image);
1458                 if (length <= compress_extent)
1459                   bzip_info.avail_in=(unsigned int) ReadBlob(image,length,
1460                     (unsigned char *) bzip_info.next_in);
1461                 if ((length > compress_extent) ||
1462                     ((size_t) bzip_info.avail_in != length))
1463                   {
1464                     (void) BZ2_bzDecompressEnd(&bzip_info);
1465                     ThrowMIFFException(CorruptImageError,
1466                       "UnableToReadImageData");
1467                   }
1468               }
1469             code=BZ2_bzDecompress(&bzip_info);
1470             if ((code != BZ_OK) && (code != BZ_STREAM_END))
1471               {
1472                 status=MagickFalse;
1473                 break;
1474               }
1475             if (code == BZ_STREAM_END)
1476               break;
1477           } while (bzip_info.avail_out != 0);
1478           extent=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1479             quantum_type,pixels,exception);
1480           break;
1481         }
1482 #endif
1483 #if defined(MAGICKCORE_LZMA_DELEGATE)
1484         case LZMACompression:
1485         {
1486           lzma_info.next_out=pixels;
1487           lzma_info.avail_out=packet_size*image->columns;
1488           do
1489           {
1490             int
1491               code;
1492 
1493             if (lzma_info.avail_in == 0)
1494               {
1495                 lzma_info.next_in=compress_pixels;
1496                 length=(size_t) ReadBlobMSBLong(image);
1497                 if (length <= compress_extent)
1498                   lzma_info.avail_in=(unsigned int) ReadBlob(image,length,
1499                     (unsigned char *) lzma_info.next_in);
1500                 if ((length > compress_extent) ||
1501                     (lzma_info.avail_in != length))
1502                   {
1503                     lzma_end(&lzma_info);
1504                     ThrowMIFFException(CorruptImageError,
1505                       "UnableToReadImageData");
1506                   }
1507               }
1508             code=lzma_code(&lzma_info,LZMA_RUN);
1509             if ((code != LZMA_OK) && (code != LZMA_STREAM_END))
1510               {
1511                 status=MagickFalse;
1512                 break;
1513               }
1514             if (code == LZMA_STREAM_END)
1515               break;
1516           } while (lzma_info.avail_out != 0);
1517           extent=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1518             quantum_type,pixels,exception);
1519           break;
1520         }
1521 #endif
1522 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1523         case LZWCompression:
1524         case ZipCompression:
1525         {
1526           zip_info.next_out=pixels;
1527           zip_info.avail_out=(uInt) (packet_size*image->columns);
1528           do
1529           {
1530             int
1531               code;
1532 
1533             if (zip_info.avail_in == 0)
1534               {
1535                 zip_info.next_in=compress_pixels;
1536                 length=(size_t) ZipMaxExtent(packet_size*image->columns);
1537                 if (version != 0.0)
1538                   length=(size_t) ReadBlobMSBLong(image);
1539                 if (length <= compress_extent)
1540                   zip_info.avail_in=(unsigned int) ReadBlob(image,length,
1541                     zip_info.next_in);
1542                 if ((length > compress_extent) ||
1543                     ((size_t) zip_info.avail_in != length))
1544                   {
1545                     (void) inflateEnd(&zip_info);
1546                     ThrowMIFFException(CorruptImageError,
1547                       "UnableToReadImageData");
1548                   }
1549               }
1550             code=inflate(&zip_info,Z_SYNC_FLUSH);
1551             if ((code != Z_OK) && (code != Z_STREAM_END))
1552               {
1553                 status=MagickFalse;
1554                 break;
1555               }
1556             if (code == Z_STREAM_END)
1557               break;
1558           } while (zip_info.avail_out != 0);
1559           extent=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1560             quantum_type,pixels,exception);
1561           break;
1562         }
1563 #endif
1564         case RLECompression:
1565         {
1566           for (x=0; x < (ssize_t) image->columns; x++)
1567           {
1568             if (length == 0)
1569               {
1570                 count=ReadBlob(image,packet_size,pixels);
1571                 if (count != (ssize_t) packet_size)
1572                   ThrowMIFFException(CorruptImageError,"UnableToReadImageData");
1573                 PushRunlengthPacket(image,pixels,&length,&pixel,exception);
1574               }
1575             length--;
1576             if (image->storage_class == PseudoClass)
1577               SetPixelIndex(image,ClampToQuantum(pixel.index),q);
1578             else
1579               {
1580                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1581                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1582                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1583                 if (image->colorspace == CMYKColorspace)
1584                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1585               }
1586             if (image->alpha_trait != UndefinedPixelTrait)
1587               SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1588             q+=GetPixelChannels(image);
1589           }
1590           extent=(size_t) x;
1591           break;
1592         }
1593         default:
1594         {
1595           const void
1596             *stream;
1597 
1598           stream=ReadBlobStream(image,packet_size*image->columns,pixels,&count);
1599           if (count != (ssize_t) (packet_size*image->columns))
1600             ThrowMIFFException(CorruptImageError,"UnableToReadImageData");
1601           extent=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1602             quantum_type,(unsigned char *) stream,exception);
1603           break;
1604         }
1605       }
1606       if (extent < image->columns)
1607         break;
1608       if (SyncAuthenticPixels(image,exception) == MagickFalse)
1609         break;
1610     }
1611     SetQuantumImageType(image,quantum_type);
1612     switch (image->compression)
1613     {
1614 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1615       case BZipCompression:
1616       {
1617         int
1618           code;
1619 
1620         if (version == 0.0)
1621           {
1622             MagickOffsetType
1623               offset;
1624 
1625             offset=SeekBlob(image,-((MagickOffsetType) bzip_info.avail_in),
1626               SEEK_CUR);
1627             if (offset < 0)
1628               {
1629                 (void) BZ2_bzDecompressEnd(&bzip_info);
1630                 ThrowMIFFException(CorruptImageError,"ImproperImageHeader");
1631               }
1632           }
1633         code=BZ2_bzDecompressEnd(&bzip_info);
1634         if (code != BZ_OK)
1635           status=MagickFalse;
1636         break;
1637       }
1638 #endif
1639 #if defined(MAGICKCORE_LZMA_DELEGATE)
1640       case LZMACompression:
1641       {
1642         int
1643           code;
1644 
1645         code=lzma_code(&lzma_info,LZMA_FINISH);
1646         if ((code != LZMA_STREAM_END) && (code != LZMA_OK))
1647           status=MagickFalse;
1648         lzma_end(&lzma_info);
1649         break;
1650       }
1651 #endif
1652 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1653       case LZWCompression:
1654       case ZipCompression:
1655       {
1656         int
1657           code;
1658 
1659         if (version == 0.0)
1660           {
1661             MagickOffsetType
1662               offset;
1663 
1664             offset=SeekBlob(image,-((MagickOffsetType) zip_info.avail_in),
1665               SEEK_CUR);
1666             if (offset < 0)
1667               {
1668                 (void) inflateEnd(&zip_info);
1669                 ThrowMIFFException(CorruptImageError,"ImproperImageHeader");
1670               }
1671           }
1672         code=inflateEnd(&zip_info);
1673         if (code != Z_OK)
1674           status=MagickFalse;
1675         break;
1676       }
1677 #endif
1678       default:
1679         break;
1680     }
1681     quantum_info=DestroyQuantumInfo(quantum_info);
1682     compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
1683     if (((y != (ssize_t) image->rows)) || (status == MagickFalse))
1684       {
1685         image=DestroyImageList(image);
1686         return((Image *) NULL);
1687       }
1688     if (EOFBlob(image) != MagickFalse)
1689       {
1690         ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1691           image->filename);
1692         break;
1693       }
1694     /*
1695       Proceed to next image.
1696     */
1697     if (image_info->number_scenes != 0)
1698       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1699         break;
1700     do
1701     {
1702       c=ReadBlobByte(image);
1703     } while ((isgraph((int) ((unsigned char) c)) == 0) && (c != EOF));
1704     if (c != EOF)
1705       {
1706         /*
1707           Allocate next image structure.
1708         */
1709         AcquireNextImage(image_info,image,exception);
1710         if (GetNextImageInList(image) == (Image *) NULL)
1711           {
1712             status=MagickFalse;
1713             break;
1714           }
1715         image=SyncNextImageInList(image);
1716         status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1717           GetBlobSize(image));
1718         if (status == MagickFalse)
1719           break;
1720       }
1721   } while (c != EOF);
1722   (void) CloseBlob(image);
1723   if (status == MagickFalse)
1724     return(DestroyImageList(image));
1725   return(GetFirstImageInList(image));
1726 }
1727 
1728 /*
1729 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1730 %                                                                             %
1731 %                                                                             %
1732 %                                                                             %
1733 %   R e g i s t e r M I F F I m a g e                                         %
1734 %                                                                             %
1735 %                                                                             %
1736 %                                                                             %
1737 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1738 %
1739 %  RegisterMIFFImage() adds properties for the MIFF image format to the list of
1740 %  supported formats.  The properties include the image format tag, a method to
1741 %  read and/or write the format, whether the format supports the saving of more
1742 %  than one frame to the same file or blob, whether the format supports native
1743 %  in-memory I/O, and a brief description of the format.
1744 %
1745 %  The format of the RegisterMIFFImage method is:
1746 %
1747 %      size_t RegisterMIFFImage(void)
1748 %
1749 */
RegisterMIFFImage(void)1750 ModuleExport size_t RegisterMIFFImage(void)
1751 {
1752   char
1753     version[MagickPathExtent];
1754 
1755   MagickInfo
1756     *entry;
1757 
1758   *version='\0';
1759 #if defined(MagickImageCoderSignatureText)
1760   (void) CopyMagickString(version,MagickLibVersionText,MagickPathExtent);
1761 #if defined(ZLIB_VERSION)
1762   (void) ConcatenateMagickString(version," with Zlib ",MagickPathExtent);
1763   (void) ConcatenateMagickString(version,ZLIB_VERSION,MagickPathExtent);
1764 #endif
1765 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1766   (void) ConcatenateMagickString(version," and BZlib",MagickPathExtent);
1767 #endif
1768 #endif
1769   entry=AcquireMagickInfo("MIFF","MIFF","Magick Image File Format");
1770   entry->decoder=(DecodeImageHandler *) ReadMIFFImage;
1771   entry->encoder=(EncodeImageHandler *) WriteMIFFImage;
1772   entry->magick=(IsImageFormatHandler *) IsMIFF;
1773   entry->flags|=CoderDecoderSeekableStreamFlag;
1774   if (*version != '\0')
1775     entry->version=ConstantString(version);
1776   (void) RegisterMagickInfo(entry);
1777   return(MagickImageCoderSignature);
1778 }
1779 
1780 /*
1781 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1782 %                                                                             %
1783 %                                                                             %
1784 %                                                                             %
1785 %   U n r e g i s t e r M I F F I m a g e                                     %
1786 %                                                                             %
1787 %                                                                             %
1788 %                                                                             %
1789 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1790 %
1791 %  UnregisterMIFFImage() removes format registrations made by the MIFF module
1792 %  from the list of supported formats.
1793 %
1794 %  The format of the UnregisterMIFFImage method is:
1795 %
1796 %      UnregisterMIFFImage(void)
1797 %
1798 */
UnregisterMIFFImage(void)1799 ModuleExport void UnregisterMIFFImage(void)
1800 {
1801   (void) UnregisterMagickInfo("MIFF");
1802 }
1803 
1804 /*
1805 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1806 %                                                                             %
1807 %                                                                             %
1808 %                                                                             %
1809 %   W r i t e M I F F I m a g e                                               %
1810 %                                                                             %
1811 %                                                                             %
1812 %                                                                             %
1813 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1814 %
1815 %  WriteMIFFImage() writes a MIFF image to a file.
1816 %
1817 %  The format of the WriteMIFFImage method is:
1818 %
1819 %      MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
1820 %        Image *image,ExceptionInfo *exception)
1821 %
1822 %  Compression code contributed by Kyle Shorter.
1823 %
1824 %  A description of each parameter follows:
1825 %
1826 %    o image_info: the image info.
1827 %
1828 %    o image: the image.
1829 %
1830 %    o exception: return any errors or warnings in this structure.
1831 %
1832 */
1833 
PopRunlengthPacket(Image * image,unsigned char * pixels,size_t length,PixelInfo * pixel)1834 static unsigned char *PopRunlengthPacket(Image *image,unsigned char *pixels,
1835   size_t length,PixelInfo *pixel)
1836 {
1837   if (image->storage_class != DirectClass)
1838     {
1839       unsigned int
1840         value;
1841 
1842       value=(unsigned int) ClampToQuantum(pixel->index);
1843       switch (image->depth)
1844       {
1845         case 32:
1846         default:
1847         {
1848           *pixels++=(unsigned char) (value >> 24);
1849           *pixels++=(unsigned char) (value >> 16);
1850         }
1851         case 16:
1852           *pixels++=(unsigned char) (value >> 8);
1853         case 8:
1854         {
1855           *pixels++=(unsigned char) value;
1856           break;
1857         }
1858       }
1859       switch (image->depth)
1860       {
1861         case 32:
1862         default:
1863         {
1864           unsigned int
1865             long_value;
1866 
1867           if (image->alpha_trait != UndefinedPixelTrait)
1868             {
1869               long_value=ScaleQuantumToLong(ClampToQuantum(pixel->alpha));
1870               pixels=PopLongPixel(MSBEndian,long_value,pixels);
1871             }
1872           break;
1873         }
1874         case 16:
1875         {
1876           unsigned short
1877             short_value;
1878 
1879           if (image->alpha_trait != UndefinedPixelTrait)
1880             {
1881               short_value=ScaleQuantumToShort(ClampToQuantum(pixel->alpha));
1882               pixels=PopShortPixel(MSBEndian,short_value,pixels);
1883             }
1884           break;
1885         }
1886         case 8:
1887         {
1888           unsigned char
1889             char_value;
1890 
1891           if (image->alpha_trait != UndefinedPixelTrait)
1892             {
1893               char_value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
1894                 pixel->alpha));
1895               pixels=PopCharPixel(char_value,pixels);
1896             }
1897           break;
1898         }
1899       }
1900       *pixels++=(unsigned char) length;
1901       return(pixels);
1902     }
1903   switch (image->depth)
1904   {
1905     case 32:
1906     default:
1907     {
1908       unsigned int
1909         value;
1910 
1911       value=ScaleQuantumToLong(ClampToQuantum(pixel->red));
1912       pixels=PopLongPixel(MSBEndian,value,pixels);
1913       if (IsGrayColorspace(image->colorspace) == MagickFalse)
1914         {
1915           value=ScaleQuantumToLong(ClampToQuantum(pixel->green));
1916           pixels=PopLongPixel(MSBEndian,value,pixels);
1917           value=ScaleQuantumToLong(ClampToQuantum(pixel->blue));
1918           pixels=PopLongPixel(MSBEndian,value,pixels);
1919         }
1920       if (image->colorspace == CMYKColorspace)
1921         {
1922           value=ScaleQuantumToLong(ClampToQuantum(pixel->black));
1923           pixels=PopLongPixel(MSBEndian,value,pixels);
1924         }
1925       if (image->alpha_trait != UndefinedPixelTrait)
1926         {
1927           value=ScaleQuantumToLong(ClampToQuantum(pixel->alpha));
1928           pixels=PopLongPixel(MSBEndian,value,pixels);
1929         }
1930       break;
1931     }
1932     case 16:
1933     {
1934       unsigned short
1935         value;
1936 
1937       value=ScaleQuantumToShort(ClampToQuantum(pixel->red));
1938       pixels=PopShortPixel(MSBEndian,value,pixels);
1939       if (IsGrayColorspace(image->colorspace) == MagickFalse)
1940         {
1941           value=ScaleQuantumToShort(ClampToQuantum(pixel->green));
1942           pixels=PopShortPixel(MSBEndian,value,pixels);
1943           value=ScaleQuantumToShort(ClampToQuantum(pixel->blue));
1944           pixels=PopShortPixel(MSBEndian,value,pixels);
1945         }
1946       if (image->colorspace == CMYKColorspace)
1947         {
1948           value=ScaleQuantumToShort(ClampToQuantum(pixel->black));
1949           pixels=PopShortPixel(MSBEndian,value,pixels);
1950         }
1951       if (image->alpha_trait != UndefinedPixelTrait)
1952         {
1953           value=ScaleQuantumToShort(ClampToQuantum(pixel->alpha));
1954           pixels=PopShortPixel(MSBEndian,value,pixels);
1955         }
1956       break;
1957     }
1958     case 8:
1959     {
1960       unsigned char
1961         value;
1962 
1963       value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(pixel->red));
1964       pixels=PopCharPixel(value,pixels);
1965       if (IsGrayColorspace(image->colorspace) == MagickFalse)
1966         {
1967           value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
1968             pixel->green));
1969           pixels=PopCharPixel(value,pixels);
1970           value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(pixel->blue));
1971           pixels=PopCharPixel(value,pixels);
1972         }
1973       if (image->colorspace == CMYKColorspace)
1974         {
1975           value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
1976             pixel->black));
1977           pixels=PopCharPixel(value,pixels);
1978         }
1979       if (image->alpha_trait != UndefinedPixelTrait)
1980         {
1981           value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
1982             pixel->alpha));
1983           pixels=PopCharPixel(value,pixels);
1984         }
1985       break;
1986     }
1987   }
1988   *pixels++=(unsigned char) length;
1989   return(pixels);
1990 }
1991 
WriteMIFFImage(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)1992 static MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
1993   Image *image,ExceptionInfo *exception)
1994 {
1995 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1996   bz_stream
1997     bzip_info;
1998 #endif
1999 
2000   char
2001     buffer[MagickPathExtent];
2002 
2003   CompressionType
2004     compression;
2005 
2006   const char
2007     *property,
2008     *value;
2009 
2010 #if defined(MAGICKCORE_LZMA_DELEGATE)
2011   lzma_allocator
2012     allocator;
2013 
2014   lzma_stream
2015     initialize_lzma = LZMA_STREAM_INIT,
2016     lzma_info;
2017 #endif
2018 
2019   MagickBooleanType
2020     status;
2021 
2022   MagickOffsetType
2023     scene;
2024 
2025   PixelInfo
2026     pixel,
2027     target;
2028 
2029   QuantumInfo
2030     *quantum_info;
2031 
2032   QuantumType
2033     quantum_type;
2034 
2035   ssize_t
2036     i;
2037 
2038   size_t
2039     imageListLength,
2040     length,
2041     packet_size;
2042 
2043   ssize_t
2044     y;
2045 
2046   unsigned char
2047     *compress_pixels,
2048     *pixels,
2049     *q;
2050 
2051 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2052   z_stream
2053     zip_info;
2054 #endif
2055 
2056   /*
2057     Open output image file.
2058   */
2059   assert(image_info != (const ImageInfo *) NULL);
2060   assert(image_info->signature == MagickCoreSignature);
2061   assert(image != (Image *) NULL);
2062   assert(image->signature == MagickCoreSignature);
2063   if (image->debug != MagickFalse)
2064     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2065   assert(exception != (ExceptionInfo *) NULL);
2066   assert(exception->signature == MagickCoreSignature);
2067   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2068   if (status == MagickFalse)
2069     return(status);
2070   scene=0;
2071   imageListLength=GetImageListLength(image);
2072   do
2073   {
2074     /*
2075       Allocate image pixels.
2076     */
2077     if ((image->storage_class == PseudoClass) &&
2078         (image->colors > (size_t) (GetQuantumRange(image->depth)+1)))
2079       (void) SetImageStorageClass(image,DirectClass,exception);
2080     image->depth=image->depth <= 8 ? 8UL : image->depth <= 16 ? 16UL : 32UL;
2081     quantum_info=AcquireQuantumInfo(image_info,image);
2082     if (quantum_info == (QuantumInfo *) NULL)
2083       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2084     if ((image->storage_class != PseudoClass) && (image->depth >= 16) &&
2085         (quantum_info->format == UndefinedQuantumFormat) &&
2086         (IsHighDynamicRangeImage(image,exception) != MagickFalse))
2087       {
2088         status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
2089         if (status == MagickFalse)
2090           {
2091             quantum_info=DestroyQuantumInfo(quantum_info);
2092             ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2093           }
2094       }
2095     else
2096       if (image->depth < 16)
2097         (void) DeleteImageProperty(image,"quantum:format");
2098     compression=UndefinedCompression;
2099     if (image_info->compression != UndefinedCompression)
2100       compression=image_info->compression;
2101     switch (compression)
2102     {
2103 #if !defined(MAGICKCORE_LZMA_DELEGATE)
2104       case LZMACompression: compression=NoCompression; break;
2105 #endif
2106 #if !defined(MAGICKCORE_ZLIB_DELEGATE)
2107       case LZWCompression:
2108       case ZipCompression: compression=NoCompression; break;
2109 #endif
2110 #if !defined(MAGICKCORE_BZLIB_DELEGATE)
2111       case BZipCompression: compression=NoCompression; break;
2112 #endif
2113       case RLECompression:
2114       {
2115         if (quantum_info->format == FloatingPointQuantumFormat)
2116           compression=NoCompression;
2117         GetPixelInfo(image,&target);
2118         break;
2119       }
2120       default:
2121         break;
2122     }
2123     packet_size=(size_t) (quantum_info->depth/8);
2124     if (image->storage_class == DirectClass)
2125       packet_size=(size_t) (3*quantum_info->depth/8);
2126     if (IsGrayColorspace(image->colorspace) != MagickFalse)
2127       packet_size=(size_t) (quantum_info->depth/8);
2128     if (image->alpha_trait != UndefinedPixelTrait)
2129       packet_size+=quantum_info->depth/8;
2130     if (image->colorspace == CMYKColorspace)
2131       packet_size+=quantum_info->depth/8;
2132     if (compression == RLECompression)
2133       packet_size++;
2134     length=MagickMax(BZipMaxExtent(packet_size*image->columns),ZipMaxExtent(
2135       packet_size*image->columns));
2136     if ((compression == BZipCompression) || (compression == ZipCompression))
2137       if (length != (size_t) ((unsigned int) length))
2138         compression=NoCompression;
2139     compress_pixels=(unsigned char *) AcquireQuantumMemory(length,
2140       sizeof(*compress_pixels));
2141     if (compress_pixels == (unsigned char *) NULL)
2142       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2143     /*
2144       Write MIFF header.
2145     */
2146     (void) WriteBlobString(image,"id=ImageMagick  version=1.0\n");
2147     (void) FormatLocaleString(buffer,MagickPathExtent,
2148       "class=%s  colors=%.20g  alpha-trait=%s\n",CommandOptionToMnemonic(
2149       MagickClassOptions,image->storage_class),(double) image->colors,
2150       CommandOptionToMnemonic(MagickPixelTraitOptions,(ssize_t)
2151       image->alpha_trait));
2152     (void) WriteBlobString(image,buffer);
2153     if (image->alpha_trait != UndefinedPixelTrait)
2154       (void) WriteBlobString(image,"matte=True\n");
2155     (void) FormatLocaleString(buffer,MagickPathExtent,
2156       "columns=%.20g  rows=%.20g  depth=%.20g\n",(double) image->columns,
2157       (double) image->rows,(double) image->depth);
2158     (void) WriteBlobString(image,buffer);
2159     if (image->type != UndefinedType)
2160       {
2161         (void) FormatLocaleString(buffer,MagickPathExtent,"type=%s\n",
2162           CommandOptionToMnemonic(MagickTypeOptions,image->type));
2163         (void) WriteBlobString(image,buffer);
2164       }
2165     if (image->colorspace != UndefinedColorspace)
2166       {
2167         (void) FormatLocaleString(buffer,MagickPathExtent,"colorspace=%s\n",
2168           CommandOptionToMnemonic(MagickColorspaceOptions,image->colorspace));
2169         (void) WriteBlobString(image,buffer);
2170       }
2171     if (image->intensity != UndefinedPixelIntensityMethod)
2172       {
2173         (void) FormatLocaleString(buffer,MagickPathExtent,
2174           "pixel-intensity=%s\n",CommandOptionToMnemonic(
2175           MagickPixelIntensityOptions,image->intensity));
2176         (void) WriteBlobString(image,buffer);
2177       }
2178     if (image->endian != UndefinedEndian)
2179       {
2180         (void) FormatLocaleString(buffer,MagickPathExtent,"endian=%s\n",
2181           CommandOptionToMnemonic(MagickEndianOptions,image->endian));
2182         (void) WriteBlobString(image,buffer);
2183       }
2184     if (compression != UndefinedCompression)
2185       {
2186         (void) FormatLocaleString(buffer,MagickPathExtent,"compression=%s  "
2187           "quality=%.20g\n",CommandOptionToMnemonic(MagickCompressOptions,
2188           compression),(double) image->quality);
2189         (void) WriteBlobString(image,buffer);
2190       }
2191     if (image->units != UndefinedResolution)
2192       {
2193         (void) FormatLocaleString(buffer,MagickPathExtent,"units=%s\n",
2194           CommandOptionToMnemonic(MagickResolutionOptions,image->units));
2195         (void) WriteBlobString(image,buffer);
2196       }
2197     if ((image->resolution.x != 0) || (image->resolution.y != 0))
2198       {
2199         (void) FormatLocaleString(buffer,MagickPathExtent,
2200           "resolution=%gx%g\n",image->resolution.x,image->resolution.y);
2201         (void) WriteBlobString(image,buffer);
2202       }
2203     if ((image->page.width != 0) || (image->page.height != 0))
2204       {
2205         (void) FormatLocaleString(buffer,MagickPathExtent,
2206           "page=%.20gx%.20g%+.20g%+.20g\n",(double) image->page.width,(double)
2207           image->page.height,(double) image->page.x,(double) image->page.y);
2208         (void) WriteBlobString(image,buffer);
2209       }
2210     else
2211       if ((image->page.x != 0) || (image->page.y != 0))
2212         {
2213           (void) FormatLocaleString(buffer,MagickPathExtent,"page=%+ld%+ld\n",
2214             (long) image->page.x,(long) image->page.y);
2215           (void) WriteBlobString(image,buffer);
2216         }
2217     if ((image->tile_offset.x != 0) || (image->tile_offset.y != 0))
2218       {
2219         (void) FormatLocaleString(buffer,MagickPathExtent,
2220           "tile-offset=%+ld%+ld\n",(long) image->tile_offset.x,(long)
2221           image->tile_offset.y);
2222         (void) WriteBlobString(image,buffer);
2223       }
2224     if ((GetNextImageInList(image) != (Image *) NULL) ||
2225         (GetPreviousImageInList(image) != (Image *) NULL))
2226       {
2227         if (image->scene == 0)
2228           (void) FormatLocaleString(buffer,MagickPathExtent,"iterations=%.20g  "
2229             "delay=%.20g  ticks-per-second=%.20g\n",(double) image->iterations,
2230             (double) image->delay,(double) image->ticks_per_second);
2231         else
2232           (void) FormatLocaleString(buffer,MagickPathExtent,"scene=%.20g  "
2233             "iterations=%.20g  delay=%.20g  ticks-per-second=%.20g\n",(double)
2234             image->scene,(double) image->iterations,(double) image->delay,
2235             (double) image->ticks_per_second);
2236         (void) WriteBlobString(image,buffer);
2237       }
2238     else
2239       {
2240         if (image->scene != 0)
2241           {
2242             (void) FormatLocaleString(buffer,MagickPathExtent,"scene=%.20g\n",
2243               (double) image->scene);
2244             (void) WriteBlobString(image,buffer);
2245           }
2246         if (image->iterations != 0)
2247           {
2248             (void) FormatLocaleString(buffer,MagickPathExtent,
2249               "iterations=%.20g\n",(double) image->iterations);
2250             (void) WriteBlobString(image,buffer);
2251           }
2252         if (image->delay != 0)
2253           {
2254             (void) FormatLocaleString(buffer,MagickPathExtent,"delay=%.20g\n",
2255               (double) image->delay);
2256             (void) WriteBlobString(image,buffer);
2257           }
2258         if (image->ticks_per_second != UndefinedTicksPerSecond)
2259           {
2260             (void) FormatLocaleString(buffer,MagickPathExtent,
2261               "ticks-per-second=%.20g\n",(double) image->ticks_per_second);
2262             (void) WriteBlobString(image,buffer);
2263           }
2264       }
2265     if (image->gravity != UndefinedGravity)
2266       {
2267         (void) FormatLocaleString(buffer,MagickPathExtent,"gravity=%s\n",
2268           CommandOptionToMnemonic(MagickGravityOptions,image->gravity));
2269         (void) WriteBlobString(image,buffer);
2270       }
2271     if (image->dispose != UndefinedDispose)
2272       {
2273         (void) FormatLocaleString(buffer,MagickPathExtent,"dispose=%s\n",
2274           CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
2275         (void) WriteBlobString(image,buffer);
2276       }
2277     if (image->rendering_intent != UndefinedIntent)
2278       {
2279         (void) FormatLocaleString(buffer,MagickPathExtent,
2280           "rendering-intent=%s\n",CommandOptionToMnemonic(MagickIntentOptions,
2281           image->rendering_intent));
2282         (void) WriteBlobString(image,buffer);
2283       }
2284     if (image->gamma != 0.0)
2285       {
2286         (void) FormatLocaleString(buffer,MagickPathExtent,"gamma=%g\n",
2287           image->gamma);
2288         (void) WriteBlobString(image,buffer);
2289       }
2290     if (image->chromaticity.white_point.x != 0.0)
2291       {
2292         /*
2293           Note chomaticity points.
2294         */
2295         (void) FormatLocaleString(buffer,MagickPathExtent,"red-primary=%g,"
2296           "%g  green-primary=%g,%g  blue-primary=%g,%g\n",
2297           image->chromaticity.red_primary.x,image->chromaticity.red_primary.y,
2298           image->chromaticity.green_primary.x,
2299           image->chromaticity.green_primary.y,
2300           image->chromaticity.blue_primary.x,
2301           image->chromaticity.blue_primary.y);
2302         (void) WriteBlobString(image,buffer);
2303         (void) FormatLocaleString(buffer,MagickPathExtent,
2304           "white-point=%g,%g\n",image->chromaticity.white_point.x,
2305           image->chromaticity.white_point.y);
2306         (void) WriteBlobString(image,buffer);
2307       }
2308     if (image->orientation != UndefinedOrientation)
2309       {
2310         (void) FormatLocaleString(buffer,MagickPathExtent,"orientation=%s\n",
2311           CommandOptionToMnemonic(MagickOrientationOptions,image->orientation));
2312         (void) WriteBlobString(image,buffer);
2313       }
2314     if (image->profiles != (void *) NULL)
2315       {
2316         const char
2317           *name;
2318 
2319         const StringInfo
2320           *profile;
2321 
2322         /*
2323           Write image profile names.
2324         */
2325         ResetImageProfileIterator(image);
2326         for (name=GetNextImageProfile(image); name != (const char *) NULL; )
2327         {
2328           profile=GetImageProfile(image,name);
2329           if (profile != (StringInfo *) NULL)
2330             {
2331               (void) FormatLocaleString(buffer,MagickPathExtent,"profile=%s\n",
2332                 name);
2333               (void) WriteBlobString(image,buffer);
2334             }
2335           name=GetNextImageProfile(image);
2336         }
2337       }
2338     if (image->montage != (char *) NULL)
2339       {
2340         (void) FormatLocaleString(buffer,MagickPathExtent,"montage=%s\n",
2341           image->montage);
2342         (void) WriteBlobString(image,buffer);
2343       }
2344     if (quantum_info->format == FloatingPointQuantumFormat)
2345       (void) SetImageProperty(image,"quantum:format","floating-point",
2346         exception);
2347     ResetImagePropertyIterator(image);
2348     property=GetNextImageProperty(image);
2349     while (property != (const char *) NULL)
2350     {
2351       (void) FormatLocaleString(buffer,MagickPathExtent,"%s=",property);
2352       (void) WriteBlobString(image,buffer);
2353       value=GetImageProperty(image,property,exception);
2354       if (value != (const char *) NULL)
2355         {
2356           length=strlen(value);
2357           for (i=0; i < (ssize_t) length; i++)
2358             if ((isspace((int) ((unsigned char) value[i])) != 0) ||
2359                 (value[i] == '}'))
2360               break;
2361           if ((i == (ssize_t) length) && (i != 0))
2362             (void) WriteBlob(image,length,(const unsigned char *) value);
2363           else
2364             {
2365               (void) WriteBlobByte(image,'{');
2366               if (strchr(value,'}') == (char *) NULL)
2367                 (void) WriteBlob(image,length,(const unsigned char *) value);
2368               else
2369                 for (i=0; i < (ssize_t) length; i++)
2370                 {
2371                   if (value[i] == (int) '}')
2372                     (void) WriteBlobByte(image,'\\');
2373                   (void) WriteBlobByte(image,(unsigned char) value[i]);
2374                 }
2375               (void) WriteBlobByte(image,'}');
2376             }
2377         }
2378       (void) WriteBlobByte(image,'\n');
2379       property=GetNextImageProperty(image);
2380     }
2381     (void) WriteBlobString(image,"\f\n:\032");
2382     if (image->montage != (char *) NULL)
2383       {
2384         /*
2385           Write montage tile directory.
2386         */
2387         if (image->directory != (char *) NULL)
2388           (void) WriteBlob(image,strlen(image->directory),(unsigned char *)
2389             image->directory);
2390         (void) WriteBlobByte(image,'\0');
2391       }
2392     if (image->profiles != 0)
2393       {
2394         const char
2395           *name;
2396 
2397         const StringInfo
2398           *profile;
2399 
2400         /*
2401           Write image profile blob.
2402         */
2403         ResetImageProfileIterator(image);
2404         name=GetNextImageProfile(image);
2405         while (name != (const char *) NULL)
2406         {
2407           profile=GetImageProfile(image,name);
2408           (void) WriteBlobMSBLong(image,(unsigned int)
2409             GetStringInfoLength(profile));
2410           (void) WriteBlob(image,GetStringInfoLength(profile),
2411             GetStringInfoDatum(profile));
2412           name=GetNextImageProfile(image);
2413         }
2414       }
2415     if (image->storage_class == PseudoClass)
2416       {
2417         size_t
2418           colormap_size;
2419 
2420         unsigned char
2421           *colormap;
2422 
2423         /*
2424           Allocate colormap.
2425         */
2426         colormap_size=(size_t) (3*quantum_info->depth/8);
2427         colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
2428           colormap_size*sizeof(*colormap));
2429         if (colormap == (unsigned char *) NULL)
2430           ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2431         /*
2432           Write colormap to file.
2433         */
2434         q=colormap;
2435         for (i=0; i < (ssize_t) image->colors; i++)
2436         {
2437           switch (quantum_info->depth)
2438           {
2439             case 32:
2440             default:
2441             {
2442               unsigned int
2443                 long_pixel;
2444 
2445               long_pixel=ScaleQuantumToLong((Quantum)
2446                 image->colormap[i].red);
2447               q=PopLongPixel(MSBEndian,long_pixel,q);
2448               long_pixel=ScaleQuantumToLong((Quantum)
2449                 image->colormap[i].green);
2450               q=PopLongPixel(MSBEndian,long_pixel,q);
2451               long_pixel=ScaleQuantumToLong((Quantum)
2452                 image->colormap[i].blue);
2453               q=PopLongPixel(MSBEndian,long_pixel,q);
2454               break;
2455             }
2456             case 16:
2457             {
2458               unsigned short
2459                 short_pixel;
2460 
2461               short_pixel=ScaleQuantumToShort((Quantum)
2462                 image->colormap[i].red);
2463               q=PopShortPixel(MSBEndian,short_pixel,q);
2464               short_pixel=ScaleQuantumToShort((Quantum)
2465                 image->colormap[i].green);
2466               q=PopShortPixel(MSBEndian,short_pixel,q);
2467               short_pixel=ScaleQuantumToShort((Quantum)
2468                 image->colormap[i].blue);
2469               q=PopShortPixel(MSBEndian,short_pixel,q);
2470               break;
2471             }
2472             case 8:
2473             {
2474               unsigned char
2475                 char_pixel;
2476 
2477               char_pixel=(unsigned char) ScaleQuantumToChar((Quantum)
2478                 image->colormap[i].red);
2479               q=PopCharPixel(char_pixel,q);
2480               char_pixel=(unsigned char) ScaleQuantumToChar((Quantum)
2481                 image->colormap[i].green);
2482               q=PopCharPixel(char_pixel,q);
2483               char_pixel=(unsigned char) ScaleQuantumToChar((Quantum)
2484                 image->colormap[i].blue);
2485               q=PopCharPixel(char_pixel,q);
2486               break;
2487             }
2488           }
2489         }
2490         (void) WriteBlob(image,colormap_size*image->colors,colormap);
2491         colormap=(unsigned char *) RelinquishMagickMemory(colormap);
2492       }
2493     /*
2494       Write image pixels to file.
2495     */
2496     status=MagickTrue;
2497     switch (compression)
2498     {
2499 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2500       case BZipCompression:
2501       {
2502         int
2503           code;
2504 
2505         (void) memset(&bzip_info,0,sizeof(bzip_info));
2506         bzip_info.bzalloc=AcquireBZIPMemory;
2507         bzip_info.bzfree=RelinquishBZIPMemory;
2508         bzip_info.opaque=(void *) NULL;
2509         code=BZ2_bzCompressInit(&bzip_info,(int) (image->quality ==
2510           UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,9)),
2511           (int) image_info->verbose,0);
2512         if (code != BZ_OK)
2513           status=MagickFalse;
2514         break;
2515       }
2516 #endif
2517 #if defined(MAGICKCORE_LZMA_DELEGATE)
2518       case LZMACompression:
2519       {
2520         int
2521           code;
2522 
2523         allocator.alloc=AcquireLZMAMemory;
2524         allocator.free=RelinquishLZMAMemory;
2525         allocator.opaque=(void *) NULL;
2526         lzma_info=initialize_lzma;
2527         lzma_info.allocator=&allocator;
2528         code=lzma_easy_encoder(&lzma_info,(uint32_t) (image->quality/10),
2529           LZMA_CHECK_SHA256);
2530         if (code != LZMA_OK)
2531           status=MagickTrue;
2532         break;
2533       }
2534 #endif
2535 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2536       case LZWCompression:
2537       case ZipCompression:
2538       {
2539         int
2540           code;
2541 
2542         zip_info.zalloc=AcquireZIPMemory;
2543         zip_info.zfree=RelinquishZIPMemory;
2544         zip_info.opaque=(void *) NULL;
2545         code=deflateInit(&zip_info,(int) (image->quality ==
2546           UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,9)));
2547         if (code != Z_OK)
2548           status=MagickFalse;
2549         break;
2550       }
2551 #endif
2552       default:
2553         break;
2554     }
2555     quantum_type=GetQuantumType(image,exception);
2556     pixels=(unsigned char *) GetQuantumPixels(quantum_info);
2557     for (y=0; y < (ssize_t) image->rows; y++)
2558     {
2559       const Quantum
2560         *magick_restrict p;
2561 
2562       ssize_t
2563         x;
2564 
2565       if (status == MagickFalse)
2566         break;
2567       p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2568       if (p == (const Quantum *) NULL)
2569         break;
2570       q=pixels;
2571       switch (compression)
2572       {
2573 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2574         case BZipCompression:
2575         {
2576           bzip_info.next_in=(char *) pixels;
2577           bzip_info.avail_in=(unsigned int) (packet_size*image->columns);
2578           (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2579             quantum_type,pixels,exception);
2580           do
2581           {
2582             int
2583               code;
2584 
2585             bzip_info.next_out=(char *) compress_pixels;
2586             bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size*
2587               image->columns);
2588             code=BZ2_bzCompress(&bzip_info,BZ_FLUSH);
2589             if (code < 0)
2590               status=MagickFalse;
2591             length=(size_t) (bzip_info.next_out-(char *) compress_pixels);
2592             if (length != 0)
2593               {
2594                 (void) WriteBlobMSBLong(image,(unsigned int) length);
2595                 (void) WriteBlob(image,length,compress_pixels);
2596               }
2597           } while (bzip_info.avail_in != 0);
2598           break;
2599         }
2600 #endif
2601 #if defined(MAGICKCORE_LZMA_DELEGATE)
2602         case LZMACompression:
2603         {
2604           lzma_info.next_in=pixels;
2605           lzma_info.avail_in=packet_size*image->columns;
2606           (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2607             quantum_type,pixels,exception);
2608           do
2609           {
2610             int
2611               code;
2612 
2613             lzma_info.next_out=compress_pixels;
2614             lzma_info.avail_out=LZMAMaxExtent(packet_size*image->columns);
2615             code=lzma_code(&lzma_info,LZMA_RUN);
2616             if (code != LZMA_OK)
2617               status=MagickFalse;
2618             length=(size_t) (lzma_info.next_out-compress_pixels);
2619             if (length != 0)
2620               {
2621                 (void) WriteBlobMSBLong(image,(unsigned int) length);
2622                 (void) WriteBlob(image,length,compress_pixels);
2623               }
2624           } while (lzma_info.avail_in != 0);
2625           break;
2626         }
2627 #endif
2628 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2629         case LZWCompression:
2630         case ZipCompression:
2631         {
2632           zip_info.next_in=pixels;
2633           zip_info.avail_in=(uInt) (packet_size*image->columns);
2634           (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2635             quantum_type,pixels,exception);
2636           do
2637           {
2638             int
2639               code;
2640 
2641             zip_info.next_out=compress_pixels;
2642             zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*image->columns);
2643             code=deflate(&zip_info,Z_SYNC_FLUSH);
2644             if (code != Z_OK)
2645               status=MagickFalse;
2646             length=(size_t) (zip_info.next_out-compress_pixels);
2647             if (length != 0)
2648               {
2649                 (void) WriteBlobMSBLong(image,(unsigned int) length);
2650                 (void) WriteBlob(image,length,compress_pixels);
2651               }
2652           } while (zip_info.avail_in != 0);
2653           break;
2654         }
2655 #endif
2656         case RLECompression:
2657         {
2658           length=0;
2659           GetPixelInfoPixel(image,p,&pixel);
2660           p+=GetPixelChannels(image);
2661           for (x=1; x < (ssize_t) image->columns; x++)
2662           {
2663             GetPixelInfoPixel(image,p,&target);
2664             if ((length < 255) &&
2665                 (IsPixelInfoEquivalent(&pixel,&target) != MagickFalse))
2666               length++;
2667             else
2668               {
2669                 q=PopRunlengthPacket(image,q,length,&pixel);
2670                 length=0;
2671               }
2672             GetPixelInfoPixel(image,p,&pixel);
2673             p+=GetPixelChannels(image);
2674           }
2675           q=PopRunlengthPacket(image,q,length,&pixel);
2676           (void) WriteBlob(image,(size_t) (q-pixels),pixels);
2677           break;
2678         }
2679         default:
2680         {
2681           (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2682             quantum_type,pixels,exception);
2683           (void) WriteBlob(image,packet_size*image->columns,pixels);
2684           break;
2685         }
2686       }
2687       if (image->previous == (Image *) NULL)
2688         {
2689           status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2690             image->rows);
2691           if (status == MagickFalse)
2692             break;
2693         }
2694     }
2695     switch (compression)
2696     {
2697 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2698       case BZipCompression:
2699       {
2700         int
2701           code;
2702 
2703         for ( ; ; )
2704         {
2705           if (status == MagickFalse)
2706             break;
2707           bzip_info.next_out=(char *) compress_pixels;
2708           bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size*
2709             image->columns);
2710           code=BZ2_bzCompress(&bzip_info,BZ_FINISH);
2711           length=(size_t) (bzip_info.next_out-(char *) compress_pixels);
2712           if (length != 0)
2713             {
2714               (void) WriteBlobMSBLong(image,(unsigned int) length);
2715               (void) WriteBlob(image,length,compress_pixels);
2716             }
2717           if (code == BZ_STREAM_END)
2718             break;
2719         }
2720         code=BZ2_bzCompressEnd(&bzip_info);
2721         if (code != BZ_OK)
2722           status=MagickFalse;
2723         break;
2724       }
2725 #endif
2726 #if defined(MAGICKCORE_LZMA_DELEGATE)
2727       case LZMACompression:
2728       {
2729         int
2730           code;
2731 
2732         for ( ; ; )
2733         {
2734           if (status == MagickFalse)
2735             break;
2736           lzma_info.next_out=compress_pixels;
2737           lzma_info.avail_out=packet_size*image->columns;
2738           code=lzma_code(&lzma_info,LZMA_FINISH);
2739           length=(size_t) (lzma_info.next_out-compress_pixels);
2740           if (length > 6)
2741             {
2742               (void) WriteBlobMSBLong(image,(unsigned int) length);
2743               (void) WriteBlob(image,length,compress_pixels);
2744             }
2745           if (code == LZMA_STREAM_END)
2746             break;
2747         }
2748         lzma_end(&lzma_info);
2749         break;
2750       }
2751 #endif
2752 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2753       case LZWCompression:
2754       case ZipCompression:
2755       {
2756         int
2757           code;
2758 
2759         for ( ; ; )
2760         {
2761           if (status == MagickFalse)
2762             break;
2763           zip_info.next_out=compress_pixels;
2764           zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*image->columns);
2765           code=deflate(&zip_info,Z_FINISH);
2766           length=(size_t) (zip_info.next_out-compress_pixels);
2767           if (length > 6)
2768             {
2769               (void) WriteBlobMSBLong(image,(unsigned int) length);
2770               (void) WriteBlob(image,length,compress_pixels);
2771             }
2772           if (code == Z_STREAM_END)
2773             break;
2774         }
2775         code=deflateEnd(&zip_info);
2776         if (code != Z_OK)
2777           status=MagickFalse;
2778         break;
2779       }
2780 #endif
2781       default:
2782         break;
2783     }
2784     quantum_info=DestroyQuantumInfo(quantum_info);
2785     compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
2786     if (GetNextImageInList(image) == (Image *) NULL)
2787       break;
2788     image=SyncNextImageInList(image);
2789     status=SetImageProgress(image,SaveImagesTag,scene++,imageListLength);
2790     if (status == MagickFalse)
2791       break;
2792   } while (image_info->adjoin != MagickFalse);
2793   (void) CloseBlob(image);
2794   return(status);
2795 }
2796