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