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