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