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