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