2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % M M IIIII FFFFF FFFFF %
13 % Read/Write MIFF Image Format %
20 % Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "magick/studio.h"
43 #include "magick/attribute.h"
44 #include "magick/blob.h"
45 #include "magick/blob-private.h"
46 #include "magick/cache.h"
47 #include "magick/color.h"
48 #include "magick/colormap-private.h"
49 #include "magick/color-private.h"
50 #include "magick/colorspace.h"
51 #include "magick/constitute.h"
52 #include "magick/exception.h"
53 #include "magick/exception-private.h"
54 #include "magick/hashmap.h"
55 #include "magick/geometry.h"
56 #include "magick/image.h"
57 #include "magick/image-private.h"
58 #include "magick/list.h"
59 #include "magick/magick.h"
60 #include "magick/memory_.h"
61 #include "magick/module.h"
62 #include "magick/monitor.h"
63 #include "magick/monitor-private.h"
64 #include "magick/option.h"
65 #include "magick/pixel.h"
66 #include "magick/profile.h"
67 #include "magick/property.h"
68 #include "magick/quantum-private.h"
69 #include "magick/static.h"
70 #include "magick/statistic.h"
71 #include "magick/string_.h"
72 #include "magick/string-private.h"
73 #if defined(MAGICKCORE_ZLIB_DELEGATE)
76 #if defined(MAGICKCORE_BZLIB_DELEGATE)
83 static MagickBooleanType
84 WriteMIFFImage(const ImageInfo *,Image *);
87 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
95 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
97 % IsMIFF() returns MagickTrue if the image format type, identified by the
98 % magick string, is MIFF.
100 % The format of the IsMIFF method is:
102 % MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length)
104 % A description of each parameter follows:
106 % o magick: compare image format pattern against these bytes.
108 % o length: Specifies the length of the magick string.
111 static MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length)
115 if (LocaleNCompare((const char *) magick,"id=ImageMagick",14) == 0)
121 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
125 % R e a d M I F F I m a g e %
129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
131 % ReadMIFFImage() reads a MIFF image file and returns it. It allocates the
132 % memory necessary for the new Image structure and returns a pointer to the
135 % The format of the ReadMIFFImage method is:
137 % Image *ReadMIFFImage(const ImageInfo *image_info,
138 % ExceptionInfo *exception)
140 % Decompression code contributed by Kyle Shorter.
142 % A description of each parameter follows:
144 % o image_info: the image info.
146 % o exception: return any errors or warnings in this structure.
150 #if defined(MAGICKCORE_BZLIB_DELEGATE)
151 static void *AcquireBZIPMemory(void *context,int items,int size)
154 return((void *) AcquireQuantumMemory((size_t) items,(size_t) size));
158 #if defined(MAGICKCORE_ZLIB_DELEGATE)
159 static voidpf AcquireZIPMemory(voidpf context,unsigned int items,
163 return((voidpf) AcquireQuantumMemory(items,size));
167 static inline size_t MagickMax(const size_t x,const size_t y)
174 static inline size_t MagickMin(const size_t x,const size_t y)
181 static void PushRunlengthPacket(Image *image,const unsigned char *pixels,
182 size_t *length,PixelPacket *pixel,IndexPacket *index)
188 if (image->storage_class == PseudoClass)
190 *index=(IndexPacket) 0;
191 switch (image->depth)
195 *index=ConstrainColormapIndex(image,
196 (*p << 24) | (*(p+1) << 16) | (*(p+2) << 8) | *(p+3));
202 *index=ConstrainColormapIndex(image,(*p << 8) | *(p+1));
208 *index=ConstrainColormapIndex(image,*p);
213 (void) ThrowMagickException(&image->exception,GetMagickModule(),
214 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
216 *pixel=image->colormap[(long) *index];
217 switch (image->depth)
224 if (image->matte != MagickFalse)
226 p=PushCharPixel(p,&quantum);
227 pixel->opacity=ScaleCharToQuantum(quantum);
236 if (image->matte != MagickFalse)
238 p=PushShortPixel(MSBEndian,p,&quantum);
239 pixel->opacity=(Quantum) (quantum >> (image->depth-
240 MAGICKCORE_QUANTUM_DEPTH));
249 if (image->matte != MagickFalse)
251 p=PushLongPixel(MSBEndian,p,&quantum);
252 pixel->opacity=(Quantum) (quantum >> (image->depth-
253 MAGICKCORE_QUANTUM_DEPTH));
258 (void) ThrowMagickException(&image->exception,GetMagickModule(),
259 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
261 *length=(size_t) (*p++)+1;
264 switch (image->depth)
271 p=PushCharPixel(p,&quantum);
272 pixel->red=ScaleCharToQuantum(quantum);
273 p=PushCharPixel(p,&quantum);
274 pixel->green=ScaleCharToQuantum(quantum);
275 p=PushCharPixel(p,&quantum);
276 pixel->blue=ScaleCharToQuantum(quantum);
277 if (image->matte != MagickFalse)
279 p=PushCharPixel(p,&quantum);
280 pixel->opacity=ScaleCharToQuantum(quantum);
282 if (image->colorspace == CMYKColorspace)
284 p=PushCharPixel(p,&quantum);
285 *index=ScaleCharToQuantum(quantum);
294 p=PushShortPixel(MSBEndian,p,&quantum);
295 pixel->red=(Quantum) (quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH));
296 p=PushShortPixel(MSBEndian,p,&quantum);
297 pixel->green=(Quantum) (quantum >> (image->depth-
298 MAGICKCORE_QUANTUM_DEPTH));
299 p=PushShortPixel(MSBEndian,p,&quantum);
300 pixel->blue=(Quantum) (quantum >> (image->depth-
301 MAGICKCORE_QUANTUM_DEPTH));
302 if (image->matte != MagickFalse)
304 p=PushShortPixel(MSBEndian,p,&quantum);
305 pixel->opacity=(Quantum) (quantum >> (image->depth-
306 MAGICKCORE_QUANTUM_DEPTH));
308 if (image->colorspace == CMYKColorspace)
310 p=PushShortPixel(MSBEndian,p,&quantum);
311 *index=(IndexPacket) (quantum >> (image->depth-
312 MAGICKCORE_QUANTUM_DEPTH));
321 p=PushLongPixel(MSBEndian,p,&quantum);
322 pixel->red=(Quantum) (quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH));
323 p=PushLongPixel(MSBEndian,p,&quantum);
324 pixel->green=(Quantum) (quantum >> (image->depth-
325 MAGICKCORE_QUANTUM_DEPTH));
326 p=PushLongPixel(MSBEndian,p,&quantum);
327 pixel->blue=(Quantum) (quantum >> (image->depth-
328 MAGICKCORE_QUANTUM_DEPTH));
329 if (image->matte != MagickFalse)
331 p=PushLongPixel(MSBEndian,p,&quantum);
332 pixel->opacity=(Quantum) (quantum >> (image->depth-
333 MAGICKCORE_QUANTUM_DEPTH));
335 if (image->colorspace == CMYKColorspace)
337 p=PushLongPixel(MSBEndian,p,&quantum);
338 *index=(IndexPacket) (quantum >> (image->depth-
339 MAGICKCORE_QUANTUM_DEPTH));
344 (void) ThrowMagickException(&image->exception,GetMagickModule(),
345 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
347 *length=(size_t) (*p++)+1;
350 #if defined(MAGICKCORE_ZLIB_DELEGATE)
351 static void RelinquishZIPMemory(voidpf context,voidpf memory)
354 memory=RelinquishMagickMemory(memory);
358 #if defined(MAGICKCORE_BZLIB_DELEGATE)
359 static void RelinquishBZIPMemory(void *context,void *memory)
362 memory=RelinquishMagickMemory(memory);
366 static Image *ReadMIFFImage(const ImageInfo *image_info,
367 ExceptionInfo *exception)
369 #define BZipMaxExtent(x) ((x)+((x)/100)+600)
370 #define ZipMaxExtent(x) ((x)+(((x)+7) >> 3)+(((x)+63) >> 6)+11)
372 #if defined(MAGICKCORE_BZLIB_DELEGATE)
379 keyword[MaxTextExtent],
442 #if defined(MAGICKCORE_ZLIB_DELEGATE)
450 assert(image_info != (const ImageInfo *) NULL);
451 assert(image_info->signature == MagickSignature);
452 if (image_info->debug != MagickFalse)
453 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
454 image_info->filename);
455 assert(exception != (ExceptionInfo *) NULL);
456 assert(exception->signature == MagickSignature);
457 image=AcquireImage(image_info);
458 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
459 if (status == MagickFalse)
461 image=DestroyImageList(image);
462 return((Image *) NULL);
465 Decode image header; header terminates one character beyond a ':'.
467 c=ReadBlobByte(image);
469 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
472 (void) ResetMagickMemory(keyword,0,sizeof(keyword));
477 Decode image header; header terminates one character beyond a ':'.
479 length=MaxTextExtent;
480 options=AcquireString((char *) NULL);
481 quantum_format=UndefinedQuantumFormat;
482 profiles=(LinkedListInfo *) NULL;
485 image->compression=NoCompression;
486 while ((isgraph(c) != MagickFalse) && (c != (int) ':'))
497 Read comment-- any text between { }.
499 length=MaxTextExtent;
500 comment=AcquireString((char *) NULL);
501 for (p=comment; comment != (char *) NULL; p++)
503 c=ReadBlobByte(image);
504 if ((c == EOF) || (c == (int) '}'))
506 if ((size_t) (p-comment+1) >= length)
510 comment=(char *) ResizeQuantumMemory(comment,length+
511 MaxTextExtent,sizeof(*comment));
512 if (comment == (char *) NULL)
514 p=comment+strlen(comment);
518 if (comment == (char *) NULL)
519 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
521 (void) SetImageProperty(image,"comment",comment);
522 comment=DestroyString(comment);
523 c=ReadBlobByte(image);
526 if (isalnum(c) != MagickFalse)
534 if (isspace((int) ((unsigned char) c)) != 0)
538 if ((size_t) (p-keyword) < (MaxTextExtent-1))
540 c=ReadBlobByte(image);
544 while (isspace((int) ((unsigned char) c)) != 0)
545 c=ReadBlobByte(image);
549 Get the keyword value.
551 c=ReadBlobByte(image);
552 while ((c != (int) '}') && (c != EOF))
554 if ((size_t) (p-options+1) >= length)
558 options=(char *) ResizeQuantumMemory(options,length+
559 MaxTextExtent,sizeof(*options));
560 if (options == (char *) NULL)
562 p=options+strlen(options);
564 if (options == (char *) NULL)
565 ThrowReaderException(ResourceLimitError,
566 "MemoryAllocationFailed");
568 c=ReadBlobByte(image);
570 if (isspace((int) ((unsigned char) c)) != 0)
576 (void) CopyMagickString(options,options+1,MaxTextExtent);
578 Assign a value to the specified keyword.
585 if (LocaleCompare(keyword,"background-color") == 0)
587 (void) QueryColorDatabase(options,&image->background_color,
591 if (LocaleCompare(keyword,"blue-primary") == 0)
593 flags=ParseGeometry(options,&geometry_info);
594 image->chromaticity.blue_primary.x=geometry_info.rho;
595 image->chromaticity.blue_primary.y=geometry_info.sigma;
596 if ((flags & SigmaValue) == 0)
597 image->chromaticity.blue_primary.y=
598 image->chromaticity.blue_primary.x;
601 if (LocaleCompare(keyword,"border-color") == 0)
603 (void) QueryColorDatabase(options,&image->border_color,
607 (void) SetImageProperty(image,keyword,options);
613 if (LocaleCompare(keyword,"class") == 0)
618 storage_class=ParseMagickOption(MagickClassOptions,
619 MagickFalse,options);
620 if (storage_class < 0)
622 image->storage_class=(ClassType) storage_class;
625 if (LocaleCompare(keyword,"colors") == 0)
627 colors=StringToUnsignedLong(options);
630 if (LocaleCompare(keyword,"colorspace") == 0)
635 colorspace=ParseMagickOption(MagickColorspaceOptions,
636 MagickFalse,options);
639 image->colorspace=(ColorspaceType) colorspace;
642 if (LocaleCompare(keyword,"compression") == 0)
647 compression=ParseMagickOption(MagickCompressOptions,
648 MagickFalse,options);
651 image->compression=(CompressionType) compression;
654 if (LocaleCompare(keyword,"columns") == 0)
656 image->columns=StringToUnsignedLong(options);
659 (void) SetImageProperty(image,keyword,options);
665 if (LocaleCompare(keyword,"delay") == 0)
667 image->delay=StringToUnsignedLong(options);
670 if (LocaleCompare(keyword,"depth") == 0)
672 image->depth=StringToUnsignedLong(options);
675 if (LocaleCompare(keyword,"dispose") == 0)
680 dispose=ParseMagickOption(MagickDisposeOptions,MagickFalse,
684 image->dispose=(DisposeType) dispose;
687 (void) SetImageProperty(image,keyword,options);
693 if (LocaleCompare(keyword,"endian") == 0)
698 endian=ParseMagickOption(MagickEndianOptions,MagickFalse,
702 image->endian=(EndianType) endian;
705 (void) SetImageProperty(image,keyword,options);
711 if (LocaleCompare(keyword,"gamma") == 0)
713 image->gamma=StringToDouble(options);
716 if (LocaleCompare(keyword,"gravity") == 0)
721 gravity=ParseMagickOption(MagickGravityOptions,MagickFalse,
725 image->gravity=(GravityType) gravity;
728 if (LocaleCompare(keyword,"green-primary") == 0)
730 flags=ParseGeometry(options,&geometry_info);
731 image->chromaticity.green_primary.x=geometry_info.rho;
732 image->chromaticity.green_primary.y=geometry_info.sigma;
733 if ((flags & SigmaValue) == 0)
734 image->chromaticity.green_primary.y=
735 image->chromaticity.green_primary.x;
738 (void) SetImageProperty(image,keyword,options);
744 if (LocaleCompare(keyword,"id") == 0)
746 (void) CopyMagickString(id,options,MaxTextExtent);
749 if (LocaleCompare(keyword,"iterations") == 0)
751 image->iterations=StringToUnsignedLong(options);
754 (void) SetImageProperty(image,keyword,options);
760 if (LocaleCompare(keyword,"matte") == 0)
765 matte=ParseMagickOption(MagickBooleanOptions,MagickFalse,
769 image->matte=(MagickBooleanType) matte;
772 if (LocaleCompare(keyword,"matte-color") == 0)
774 (void) QueryColorDatabase(options,&image->matte_color,
778 if (LocaleCompare(keyword,"montage") == 0)
780 (void) CloneString(&image->montage,options);
783 (void) SetImageProperty(image,keyword,options);
789 if (LocaleCompare(keyword,"opaque") == 0)
794 matte=ParseMagickOption(MagickBooleanOptions,MagickFalse,
798 image->matte=(MagickBooleanType) matte;
801 if (LocaleCompare(keyword,"orientation") == 0)
806 orientation=ParseMagickOption(MagickOrientationOptions,
807 MagickFalse,options);
810 image->orientation=(OrientationType) orientation;
813 (void) SetImageProperty(image,keyword,options);
819 if (LocaleCompare(keyword,"page") == 0)
824 geometry=GetPageGeometry(options);
825 (void) ParseAbsoluteGeometry(geometry,&image->page);
826 geometry=DestroyString(geometry);
829 if ((LocaleNCompare(keyword,"profile:",8) == 0) ||
830 (LocaleNCompare(keyword,"profile-",8) == 0))
835 if (profiles == (LinkedListInfo *) NULL)
836 profiles=NewLinkedList(0);
837 (void) AppendValueToLinkedList(profiles,
838 AcquireString(keyword+8));
839 profile=AcquireStringInfo((size_t) StringToLong(options));
840 (void) SetImageProfile(image,keyword+8,profile);
841 profile=DestroyStringInfo(profile);
844 (void) SetImageProperty(image,keyword,options);
850 if (LocaleCompare(keyword,"quality") == 0)
852 image->quality=StringToUnsignedLong(options);
855 if ((LocaleCompare(keyword,"quantum-format") == 0) ||
856 (LocaleCompare(keyword,"quantum:format") == 0))
861 format=ParseMagickOption(MagickQuantumFormatOptions,
862 MagickFalse,options);
865 quantum_format=(QuantumFormatType) format;
868 (void) SetImageProperty(image,keyword,options);
874 if (LocaleCompare(keyword,"red-primary") == 0)
876 flags=ParseGeometry(options,&geometry_info);
877 image->chromaticity.red_primary.x=geometry_info.rho;
878 image->chromaticity.red_primary.y=geometry_info.sigma;
879 if ((flags & SigmaValue) == 0)
880 image->chromaticity.red_primary.y=
881 image->chromaticity.red_primary.x;
884 if (LocaleCompare(keyword,"rendering-intent") == 0)
889 rendering_intent=ParseMagickOption(MagickIntentOptions,
890 MagickFalse,options);
891 if (rendering_intent < 0)
893 image->rendering_intent=(RenderingIntent) rendering_intent;
896 if (LocaleCompare(keyword,"resolution") == 0)
898 flags=ParseGeometry(options,&geometry_info);
899 image->x_resolution=geometry_info.rho;
900 image->y_resolution=geometry_info.sigma;
901 if ((flags & SigmaValue) == 0)
902 image->y_resolution=image->x_resolution;
905 if (LocaleCompare(keyword,"rows") == 0)
907 image->rows=StringToUnsignedLong(options);
910 (void) SetImageProperty(image,keyword,options);
916 if (LocaleCompare(keyword,"scene") == 0)
918 image->scene=StringToUnsignedLong(options);
921 (void) SetImageProperty(image,keyword,options);
927 if (LocaleCompare(keyword,"ticks-per-second") == 0)
929 image->ticks_per_second=StringToLong(options);
932 if (LocaleCompare(keyword,"tile-offset") == 0)
937 geometry=GetPageGeometry(options);
938 (void) ParseAbsoluteGeometry(geometry,&image->tile_offset);
939 geometry=DestroyString(geometry);
942 if (LocaleCompare(keyword,"type") == 0)
947 type=ParseMagickOption(MagickTypeOptions,MagickFalse,
951 image->type=(ImageType) type;
954 (void) SetImageProperty(image,keyword,options);
960 if (LocaleCompare(keyword,"units") == 0)
965 units=ParseMagickOption(MagickResolutionOptions,MagickFalse,
969 image->units=(ResolutionType) units;
972 (void) SetImageProperty(image,keyword,options);
978 if (LocaleCompare(keyword,"version") == 0)
980 version=StringToDouble(options);
983 (void) SetImageProperty(image,keyword,options);
989 if (LocaleCompare(keyword,"white-point") == 0)
991 flags=ParseGeometry(options,&geometry_info);
992 image->chromaticity.white_point.x=geometry_info.rho;
993 image->chromaticity.white_point.y=geometry_info.rho;
994 if ((flags & SigmaValue) != 0)
995 image->chromaticity.white_point.y=
996 image->chromaticity.white_point.x;
999 (void) SetImageProperty(image,keyword,options);
1004 (void) SetImageProperty(image,keyword,options);
1010 c=ReadBlobByte(image);
1011 while (isspace((int) ((unsigned char) c)) != 0)
1012 c=ReadBlobByte(image);
1014 options=DestroyString(options);
1015 (void) ReadBlobByte(image);
1017 Verify that required image information is defined.
1019 if ((LocaleCompare(id,"ImageMagick") != 0) ||
1020 (image->storage_class == UndefinedClass) ||
1021 (image->columns == 0) || (image->rows == 0))
1022 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1023 if (image->montage != (char *) NULL)
1031 length=MaxTextExtent;
1032 image->directory=AcquireString((char *) NULL);
1037 if ((strlen(image->directory)+MaxTextExtent) >= length)
1040 Allocate more memory for the image directory.
1043 image->directory=(char *) ResizeQuantumMemory(image->directory,
1044 length+MaxTextExtent,sizeof(*image->directory));
1045 if (image->directory == (char *) NULL)
1046 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1047 p=image->directory+strlen(image->directory);
1049 c=ReadBlobByte(image);
1051 } while (c != (int) '\0');
1053 if (profiles != (LinkedListInfo *) NULL)
1062 Read image profiles.
1064 ResetLinkedListIterator(profiles);
1065 name=(const char *) GetNextValueInLinkedList(profiles);
1066 while (name != (const char *) NULL)
1068 profile=GetImageProfile(image,name);
1069 if (profile != (StringInfo *) NULL)
1071 register unsigned char
1074 p=GetStringInfoDatum(profile);
1075 count=ReadBlob(image,GetStringInfoLength(profile),p);
1077 name=(const char *) GetNextValueInLinkedList(profiles);
1079 profiles=DestroyLinkedList(profiles,RelinquishMagickMemory);
1081 image->depth=GetImageQuantumDepth(image,MagickFalse);
1082 if (image->storage_class == PseudoClass)
1085 Create image colormap.
1087 status=AcquireImageColormap(image,colors != 0 ? colors : 256);
1088 if (status == MagickFalse)
1089 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1099 Read image colormap from file.
1101 packet_size=(size_t) (3UL*image->depth/8UL);
1102 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
1103 packet_size*sizeof(*colormap));
1104 if (colormap == (unsigned char *) NULL)
1105 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1106 count=ReadBlob(image,packet_size*image->colors,colormap);
1108 switch (image->depth)
1111 ThrowReaderException(CorruptImageError,
1112 "ImageDepthNotSupported");
1118 for (i=0; i < (long) image->colors; i++)
1120 p=PushCharPixel(p,&pixel);
1121 image->colormap[i].red=ScaleCharToQuantum(pixel);
1122 p=PushCharPixel(p,&pixel);
1123 image->colormap[i].green=ScaleCharToQuantum(pixel);
1124 p=PushCharPixel(p,&pixel);
1125 image->colormap[i].blue=ScaleCharToQuantum(pixel);
1134 for (i=0; i < (long) image->colors; i++)
1136 p=PushShortPixel(MSBEndian,p,&pixel);
1137 image->colormap[i].red=ScaleShortToQuantum(pixel);
1138 p=PushShortPixel(MSBEndian,p,&pixel);
1139 image->colormap[i].green=ScaleShortToQuantum(pixel);
1140 p=PushShortPixel(MSBEndian,p,&pixel);
1141 image->colormap[i].blue=ScaleShortToQuantum(pixel);
1150 for (i=0; i < (long) image->colors; i++)
1152 p=PushLongPixel(MSBEndian,p,&pixel);
1153 image->colormap[i].red=ScaleLongToQuantum(pixel);
1154 p=PushLongPixel(MSBEndian,p,&pixel);
1155 image->colormap[i].green=ScaleLongToQuantum(pixel);
1156 p=PushLongPixel(MSBEndian,p,&pixel);
1157 image->colormap[i].blue=ScaleLongToQuantum(pixel);
1162 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
1165 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
1166 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1169 Allocate image pixels.
1171 quantum_info=AcquireQuantumInfo(image_info,image);
1172 if (quantum_info == (QuantumInfo *) NULL)
1173 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1174 if (quantum_format != UndefinedQuantumFormat)
1176 status=SetQuantumFormat(image,quantum_info,quantum_format);
1177 if (status == MagickFalse)
1178 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1180 packet_size=(size_t) (quantum_info->depth/8);
1181 if (image->storage_class == DirectClass)
1182 packet_size=(size_t) (3*quantum_info->depth/8);
1183 if (image->matte != MagickFalse)
1184 packet_size+=quantum_info->depth/8;
1185 if (image->colorspace == CMYKColorspace)
1186 packet_size+=quantum_info->depth/8;
1187 if (image->compression == RLECompression)
1189 length=image->columns;
1190 length=MagickMax(BZipMaxExtent(packet_size*image->columns),ZipMaxExtent(
1191 packet_size*image->columns));
1192 compress_pixels=(unsigned char *) AcquireQuantumMemory(length,
1193 sizeof(*compress_pixels));
1194 if (compress_pixels == (unsigned char *) NULL)
1195 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1199 quantum_type=RGBQuantum;
1200 if (image->matte != MagickFalse)
1201 quantum_type=RGBAQuantum;
1202 if (image->colorspace == CMYKColorspace)
1204 quantum_type=CMYKQuantum;
1205 if (image->matte != MagickFalse)
1206 quantum_type=CMYKAQuantum;
1208 if (image->storage_class == PseudoClass)
1210 quantum_type=IndexQuantum;
1211 if (image->matte != MagickFalse)
1212 quantum_type=IndexAlphaQuantum;
1214 if (image->colorspace == GRAYColorspace)
1216 quantum_type=GrayQuantum;
1217 if (image->matte != MagickFalse)
1218 quantum_type=GrayAlphaQuantum;
1220 pixels=GetQuantumPixels(quantum_info);
1221 index=(IndexPacket) 0;
1223 for (y=0; y < (long) image->rows; y++)
1225 register IndexPacket
1231 register PixelPacket
1234 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1235 if (q == (PixelPacket *) NULL)
1237 indexes=GetAuthenticIndexQueue(image);
1238 switch (image->compression)
1240 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1241 case LZWCompression:
1242 case ZipCompression:
1246 zip_info.zalloc=AcquireZIPMemory;
1247 zip_info.zfree=RelinquishZIPMemory;
1248 zip_info.opaque=(voidpf) NULL;
1249 code=inflateInit(&zip_info);
1252 zip_info.avail_in=0;
1254 zip_info.next_out=pixels;
1255 zip_info.avail_out=(uInt) (packet_size*image->columns);
1258 if (zip_info.avail_in == 0)
1260 zip_info.next_in=compress_pixels;
1261 length=(size_t) ZipMaxExtent(packet_size*image->columns);
1263 length=(size_t) ReadBlobMSBLong(image);
1264 zip_info.avail_in=(unsigned int) ReadBlob(image,length,
1267 if (inflate(&zip_info,Z_SYNC_FLUSH) == Z_STREAM_END)
1269 } while (zip_info.avail_out != 0);
1270 if (y == (long) (image->rows-1))
1277 offset=SeekBlob(image,-((MagickOffsetType) zip_info.avail_in),
1280 ThrowReaderException(CorruptImageError,
1281 "ImproperImageHeader");
1283 code=inflateEnd(&zip_info);
1287 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1288 quantum_type,pixels,exception);
1292 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1293 case BZipCompression:
1297 bzip_info.bzalloc=AcquireBZIPMemory;
1298 bzip_info.bzfree=RelinquishBZIPMemory;
1299 bzip_info.opaque=(void *) NULL;
1300 code=BZ2_bzDecompressInit(&bzip_info,(int) image_info->verbose,
1304 bzip_info.avail_in=0;
1306 bzip_info.next_out=(char *) pixels;
1307 bzip_info.avail_out=(unsigned int) (packet_size*image->columns);
1310 if (bzip_info.avail_in == 0)
1312 bzip_info.next_in=(char *) compress_pixels;
1313 length=(size_t) BZipMaxExtent(packet_size*image->columns);
1315 length=(size_t) ReadBlobMSBLong(image);
1316 bzip_info.avail_in=(unsigned int) ReadBlob(image,length,
1317 (unsigned char *) bzip_info.next_in);
1319 if (BZ2_bzDecompress(&bzip_info) == BZ_STREAM_END)
1321 } while (bzip_info.avail_out != 0);
1322 if (y == (long) (image->rows-1))
1329 offset=SeekBlob(image,-((MagickOffsetType)
1330 bzip_info.avail_in),SEEK_CUR);
1332 ThrowReaderException(CorruptImageError,
1333 "ImproperImageHeader");
1335 code=BZ2_bzDecompressEnd(&bzip_info);
1339 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1340 quantum_type,pixels,exception);
1344 case RLECompression:
1348 (void) ResetMagickMemory(&pixel,0,sizeof(pixel));
1349 pixel.opacity=(Quantum) TransparentOpacity;
1350 index=(IndexPacket) 0;
1352 for (x=0; x < (long) image->columns; x++)
1356 count=ReadBlob(image,packet_size,pixels);
1357 PushRunlengthPacket(image,pixels,&length,&pixel,&index);
1360 if ((image->storage_class == PseudoClass) ||
1361 (image->colorspace == CMYKColorspace))
1369 count=ReadBlob(image,packet_size*image->columns,pixels);
1370 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1371 quantum_type,pixels,exception);
1375 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1378 SetQuantumImageType(image,quantum_type);
1379 quantum_info=DestroyQuantumInfo(quantum_info);
1380 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
1381 if (((y != (long) image->rows)) || (status == MagickFalse))
1383 image=DestroyImageList(image);
1384 return((Image *) NULL);
1386 if (EOFBlob(image) != MagickFalse)
1388 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1393 Proceed to next image.
1395 if (image_info->number_scenes != 0)
1396 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1400 c=ReadBlobByte(image);
1401 } while ((isgraph(c) == MagickFalse) && (c != EOF));
1405 Allocate next image structure.
1407 AcquireNextImage(image_info,image);
1408 if (GetNextImageInList(image) == (Image *) NULL)
1410 image=DestroyImageList(image);
1411 return((Image *) NULL);
1413 image=SyncNextImageInList(image);
1414 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1415 GetBlobSize(image));
1416 if (status == MagickFalse)
1420 (void) CloseBlob(image);
1421 return(GetFirstImageInList(image));
1425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1429 % R e g i s t e r M I F F I m a g e %
1433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1435 % RegisterMIFFImage() adds properties for the MIFF image format to the list of
1436 % supported formats. The properties include the image format tag, a method to
1437 % read and/or write the format, whether the format supports the saving of more
1438 % than one frame to the same file or blob, whether the format supports native
1439 % in-memory I/O, and a brief description of the format.
1441 % The format of the RegisterMIFFImage method is:
1443 % unsigned long RegisterMIFFImage(void)
1446 ModuleExport unsigned long RegisterMIFFImage(void)
1449 version[MaxTextExtent];
1455 #if defined(MagickImageCoderSignatureText)
1456 (void) CopyMagickString(version,MagickLibVersionText,MaxTextExtent);
1457 #if defined(ZLIB_VERSION)
1458 (void) ConcatenateMagickString(version," with Zlib ",MaxTextExtent);
1459 (void) ConcatenateMagickString(version,ZLIB_VERSION,MaxTextExtent);
1461 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1462 (void) ConcatenateMagickString(version," and BZlib",MaxTextExtent);
1465 entry=SetMagickInfo("MIFF");
1466 entry->decoder=(DecodeImageHandler *) ReadMIFFImage;
1467 entry->encoder=(EncodeImageHandler *) WriteMIFFImage;
1468 entry->magick=(IsImageFormatHandler *) IsMIFF;
1469 entry->description=ConstantString("Magick Image File Format");
1470 if (*version != '\0')
1471 entry->version=ConstantString(version);
1472 entry->module=ConstantString("MIFF");
1473 (void) RegisterMagickInfo(entry);
1474 return(MagickImageCoderSignature);
1478 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1482 % U n r e g i s t e r M I F F I m a g e %
1486 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1488 % UnregisterMIFFImage() removes format registrations made by the MIFF module
1489 % from the list of supported formats.
1491 % The format of the UnregisterMIFFImage method is:
1493 % UnregisterMIFFImage(void)
1496 ModuleExport void UnregisterMIFFImage(void)
1498 (void) UnregisterMagickInfo("MIFF");
1502 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1506 % W r i t e M I F F I m a g e %
1510 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1512 % WriteMIFFImage() writes a MIFF image to a file.
1514 % The format of the WriteMIFFImage method is:
1516 % MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
1519 % Compression code contributed by Kyle Shorter.
1521 % A description of each parameter follows:
1523 % o image_info: the image info.
1525 % o image: the image.
1529 static unsigned char *PopRunlengthPacket(Image *image,unsigned char *pixels,
1530 size_t length,PixelPacket pixel,IndexPacket index)
1532 if (image->storage_class != DirectClass)
1534 switch (image->depth)
1538 *pixels++=(unsigned char) ((unsigned long) index >> 24);
1539 *pixels++=(unsigned char) ((unsigned long) index >> 16);
1542 *pixels++=(unsigned char) ((unsigned long) index >> 8);
1545 *pixels++=(unsigned char) index;
1549 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1550 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1552 switch (image->depth)
1559 if (image->matte != MagickFalse)
1561 value=ScaleQuantumToLong(pixel.opacity);
1562 pixels=PopLongPixel(MSBEndian,value,pixels);
1571 if (image->matte != MagickFalse)
1573 value=ScaleQuantumToShort(pixel.opacity);
1574 pixels=PopShortPixel(MSBEndian,value,pixels);
1583 if (image->matte != MagickFalse)
1585 value=(unsigned char) ScaleQuantumToChar(pixel.opacity);
1586 pixels=PopCharPixel(value,pixels);
1591 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1592 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1594 *pixels++=(unsigned char) length;
1597 switch (image->depth)
1604 value=ScaleQuantumToLong(pixel.red);
1605 pixels=PopLongPixel(MSBEndian,value,pixels);
1606 value=ScaleQuantumToLong(pixel.green);
1607 pixels=PopLongPixel(MSBEndian,value,pixels);
1608 value=ScaleQuantumToLong(pixel.blue);
1609 pixels=PopLongPixel(MSBEndian,value,pixels);
1610 if (image->matte != MagickFalse)
1612 value=ScaleQuantumToLong(pixel.opacity);
1613 pixels=PopLongPixel(MSBEndian,value,pixels);
1615 if (image->colorspace == CMYKColorspace)
1617 value=ScaleQuantumToLong(index);
1618 pixels=PopLongPixel(MSBEndian,value,pixels);
1627 value=ScaleQuantumToShort(pixel.red);
1628 pixels=PopShortPixel(MSBEndian,value,pixels);
1629 value=ScaleQuantumToShort(pixel.green);
1630 pixels=PopShortPixel(MSBEndian,value,pixels);
1631 value=ScaleQuantumToShort(pixel.blue);
1632 pixels=PopShortPixel(MSBEndian,value,pixels);
1633 if (image->matte != MagickFalse)
1635 value=ScaleQuantumToShort(pixel.opacity);
1636 pixels=PopShortPixel(MSBEndian,value,pixels);
1638 if (image->colorspace == CMYKColorspace)
1640 value=ScaleQuantumToShort(index);
1641 pixels=PopShortPixel(MSBEndian,value,pixels);
1650 value=(unsigned char) ScaleQuantumToChar(pixel.red);
1651 pixels=PopCharPixel(value,pixels);
1652 value=(unsigned char) ScaleQuantumToChar(pixel.green);
1653 pixels=PopCharPixel(value,pixels);
1654 value=(unsigned char) ScaleQuantumToChar(pixel.blue);
1655 pixels=PopCharPixel(value,pixels);
1656 if (image->matte != MagickFalse)
1658 value=(unsigned char) ScaleQuantumToChar(pixel.opacity);
1659 pixels=PopCharPixel(value,pixels);
1661 if (image->colorspace == CMYKColorspace)
1663 value=(unsigned char) ScaleQuantumToChar(index);
1664 pixels=PopCharPixel(value,pixels);
1669 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1670 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1672 *pixels++=(unsigned char) length;
1676 static MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
1679 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1685 buffer[MaxTextExtent];
1730 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1736 Open output image file.
1738 assert(image_info != (const ImageInfo *) NULL);
1739 assert(image_info->signature == MagickSignature);
1740 assert(image != (Image *) NULL);
1741 assert(image->signature == MagickSignature);
1742 if (image->debug != MagickFalse)
1743 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1744 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1745 if (status == MagickFalse)
1752 Allocate image pixels.
1754 image->depth=image->depth <= 8 ? 8UL : image->depth <= 16 ? 16UL :
1755 image->depth <= 32 ? 32UL : 64UL;
1756 quantum_info=AcquireQuantumInfo(image_info,image);
1757 if (quantum_info == (QuantumInfo *) NULL)
1758 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1759 if ((image->storage_class != PseudoClass) && (image->depth >= 32) &&
1760 (quantum_info->format == UndefinedQuantumFormat) &&
1761 (IsHighDynamicRangeImage(image,&image->exception) != MagickFalse))
1763 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1764 if (status == MagickFalse)
1765 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1767 if ((image->storage_class == PseudoClass) &&
1768 (image->colors > (unsigned long) (GetQuantumRange(image->depth)+1)))
1769 (void) SetImageStorageClass(image,DirectClass);
1770 if (IsGrayImage(image,&image->exception) != MagickFalse)
1772 image->storage_class=DirectClass;
1773 (void) SetImageColorspace(image,GRAYColorspace);
1775 compression=image->compression;
1776 if (image_info->compression != UndefinedCompression)
1777 compression=image_info->compression;
1778 switch (compression)
1780 #if !defined(MAGICKCORE_ZLIB_DELEGATE)
1781 case LZWCompression:
1782 case ZipCompression: compression=NoCompression; break;
1784 #if !defined(MAGICKCORE_BZLIB_DELEGATE)
1785 case BZipCompression: compression=NoCompression; break;
1787 case RLECompression:
1789 if (quantum_info->format == FloatingPointQuantumFormat)
1790 compression=NoCompression;
1796 packet_size=(size_t) (quantum_info->depth/8);
1797 if (image->storage_class == DirectClass)
1798 packet_size=(size_t) (3*quantum_info->depth/8);
1799 if (image->matte != MagickFalse)
1800 packet_size+=quantum_info->depth/8;
1801 if (image->colorspace == CMYKColorspace)
1802 packet_size+=quantum_info->depth/8;
1803 if (compression == RLECompression)
1805 length=image->columns;
1806 length=MagickMax(BZipMaxExtent(packet_size*image->columns),ZipMaxExtent(
1807 packet_size*image->columns));
1808 if ((compression == BZipCompression) || (compression == ZipCompression))
1809 if (length != (size_t) ((unsigned int) length))
1810 compression=NoCompression;
1811 compress_pixels=(unsigned char *) AcquireQuantumMemory(length,
1812 sizeof(*compress_pixels));
1813 if (compress_pixels == (unsigned char *) NULL)
1814 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1818 (void) WriteBlobString(image,"id=ImageMagick version=1.0\n");
1819 (void) FormatMagickString(buffer,MaxTextExtent,
1820 "class=%s colors=%lu matte=%s\n",MagickOptionToMnemonic(
1821 MagickClassOptions,image->storage_class),image->colors,
1822 MagickOptionToMnemonic(MagickBooleanOptions,(long) image->matte));
1823 (void) WriteBlobString(image,buffer);
1824 (void) FormatMagickString(buffer,MaxTextExtent,"columns=%lu rows=%lu "
1825 "depth=%lu\n",image->columns,image->rows,image->depth);
1826 (void) WriteBlobString(image,buffer);
1827 if (image->type != UndefinedType)
1829 (void) FormatMagickString(buffer,MaxTextExtent,"type=%s\n",
1830 MagickOptionToMnemonic(MagickTypeOptions,image->type));
1831 (void) WriteBlobString(image,buffer);
1833 if (image->colorspace != UndefinedColorspace)
1835 (void) FormatMagickString(buffer,MaxTextExtent,"colorspace=%s\n",
1836 MagickOptionToMnemonic(MagickColorspaceOptions,image->colorspace));
1837 (void) WriteBlobString(image,buffer);
1839 if (compression != UndefinedCompression)
1841 (void) FormatMagickString(buffer,MaxTextExtent,"compression=%s "
1842 "quality=%lu\n",MagickOptionToMnemonic(MagickCompressOptions,
1843 compression),image->quality);
1844 (void) WriteBlobString(image,buffer);
1846 if (image->units != UndefinedResolution)
1848 (void) FormatMagickString(buffer,MaxTextExtent,"units=%s\n",
1849 MagickOptionToMnemonic(MagickResolutionOptions,image->units));
1850 (void) WriteBlobString(image,buffer);
1852 if ((image->x_resolution != 0) || (image->y_resolution != 0))
1854 (void) FormatMagickString(buffer,MaxTextExtent,
1855 "resolution=%gx%g\n",image->x_resolution,image->y_resolution);
1856 (void) WriteBlobString(image,buffer);
1858 if ((image->page.width != 0) || (image->page.height != 0))
1860 (void) FormatMagickString(buffer,MaxTextExtent,"page=%lux%lu%+ld%+ld\n",
1861 image->page.width,image->page.height,image->page.x,image->page.y);
1862 (void) WriteBlobString(image,buffer);
1865 if ((image->page.x != 0) || (image->page.y != 0))
1867 (void) FormatMagickString(buffer,MaxTextExtent,"page=%+ld%+ld\n",
1868 image->page.x,image->page.y);
1869 (void) WriteBlobString(image,buffer);
1871 if ((image->tile_offset.x != 0) || (image->tile_offset.y != 0))
1873 (void) FormatMagickString(buffer,MaxTextExtent,"tile-offset=%+ld%+ld\n",
1874 image->tile_offset.x,image->tile_offset.y);
1875 (void) WriteBlobString(image,buffer);
1877 if ((GetNextImageInList(image) != (Image *) NULL) ||
1878 (GetPreviousImageInList(image) != (Image *) NULL))
1880 if (image->scene == 0)
1881 (void) FormatMagickString(buffer,MaxTextExtent,"iterations=%lu "
1882 "delay=%lu ticks-per-second=%lu\n",image->iterations,image->delay,
1883 image->ticks_per_second);
1885 (void) FormatMagickString(buffer,MaxTextExtent,"scene=%lu "
1886 "iterations=%lu delay=%lu ticks-per-second=%lu\n",image->scene,
1887 image->iterations,image->delay,image->ticks_per_second);
1888 (void) WriteBlobString(image,buffer);
1892 if (image->scene != 0)
1894 (void) FormatMagickString(buffer,MaxTextExtent,"scene=%lu\n",
1896 (void) WriteBlobString(image,buffer);
1898 if (image->iterations != 0)
1900 (void) FormatMagickString(buffer,MaxTextExtent,"iterations=%lu\n",
1902 (void) WriteBlobString(image,buffer);
1904 if (image->delay != 0)
1906 (void) FormatMagickString(buffer,MaxTextExtent,"delay=%lu\n",
1908 (void) WriteBlobString(image,buffer);
1910 if (image->ticks_per_second != UndefinedTicksPerSecond)
1912 (void) FormatMagickString(buffer,MaxTextExtent,
1913 "ticks-per-second=%lu\n",image->ticks_per_second);
1914 (void) WriteBlobString(image,buffer);
1917 if (image->gravity != UndefinedGravity)
1919 (void) FormatMagickString(buffer,MaxTextExtent,"gravity=%s\n",
1920 MagickOptionToMnemonic(MagickGravityOptions,image->gravity));
1921 (void) WriteBlobString(image,buffer);
1923 if (image->dispose != UndefinedDispose)
1925 (void) FormatMagickString(buffer,MaxTextExtent,"dispose=%s\n",
1926 MagickOptionToMnemonic(MagickDisposeOptions,image->dispose));
1927 (void) WriteBlobString(image,buffer);
1929 if (image->rendering_intent != UndefinedIntent)
1931 (void) FormatMagickString(buffer,MaxTextExtent,
1932 "rendering-intent=%s\n",
1933 MagickOptionToMnemonic(MagickIntentOptions,image->rendering_intent));
1934 (void) WriteBlobString(image,buffer);
1936 if (image->gamma != 0.0)
1938 (void) FormatMagickString(buffer,MaxTextExtent,"gamma=%g\n",
1940 (void) WriteBlobString(image,buffer);
1942 if (image->chromaticity.white_point.x != 0.0)
1945 Note chomaticity points.
1947 (void) FormatMagickString(buffer,MaxTextExtent,"red-primary=%g,"
1948 "%g green-primary=%g,%g blue-primary=%g,%g\n",
1949 image->chromaticity.red_primary.x,image->chromaticity.red_primary.y,
1950 image->chromaticity.green_primary.x,
1951 image->chromaticity.green_primary.y,
1952 image->chromaticity.blue_primary.x,
1953 image->chromaticity.blue_primary.y);
1954 (void) WriteBlobString(image,buffer);
1955 (void) FormatMagickString(buffer,MaxTextExtent,
1956 "white-point=%g,%g\n",image->chromaticity.white_point.x,
1957 image->chromaticity.white_point.y);
1958 (void) WriteBlobString(image,buffer);
1960 if (image->orientation != UndefinedOrientation)
1962 (void) FormatMagickString(buffer,MaxTextExtent,"orientation=%s\n",
1963 MagickOptionToMnemonic(MagickOrientationOptions,image->orientation));
1964 (void) WriteBlobString(image,buffer);
1966 if (image->profiles != (void *) NULL)
1975 Write image profiles.
1977 ResetImageProfileIterator(image);
1978 name=GetNextImageProfile(image);
1979 while (name != (const char *) NULL)
1981 profile=GetImageProfile(image,name);
1982 if (profile != (StringInfo *) NULL)
1984 (void) FormatMagickString(buffer,MaxTextExtent,"profile:%s=%lu\n",
1985 name,(unsigned long) GetStringInfoLength(profile));
1986 (void) WriteBlobString(image,buffer);
1988 name=GetNextImageProfile(image);
1991 if (image->montage != (char *) NULL)
1993 (void) FormatMagickString(buffer,MaxTextExtent,"montage=%s\n",
1995 (void) WriteBlobString(image,buffer);
1997 if (quantum_info->format == FloatingPointQuantumFormat)
1998 (void) SetImageProperty(image,"quantum:format","floating-point");
1999 ResetImagePropertyIterator(image);
2000 property=GetNextImageProperty(image);
2001 while (property != (const char *) NULL)
2003 (void) FormatMagickString(buffer,MaxTextExtent,"%s=",property);
2004 (void) WriteBlobString(image,buffer);
2005 value=GetImageProperty(image,property);
2006 if (value != (const char *) NULL)
2008 for (i=0; i < (long) strlen(value); i++)
2009 if (isspace((int) ((unsigned char) value[i])) != 0)
2011 if (i <= (long) strlen(value))
2012 (void) WriteBlobByte(image,'{');
2013 (void) WriteBlob(image,strlen(value),(const unsigned char *) value);
2014 if (i <= (long) strlen(value))
2015 (void) WriteBlobByte(image,'}');
2017 (void) WriteBlobByte(image,'\n');
2018 property=GetNextImageProperty(image);
2020 (void) WriteBlobString(image,"\f\n:\032");
2021 if (image->montage != (char *) NULL)
2024 Write montage tile directory.
2026 if (image->directory != (char *) NULL)
2027 (void) WriteBlob(image,strlen(image->directory),(unsigned char *)
2029 (void) WriteBlobByte(image,'\0');
2031 if (image->profiles != (void *) NULL)
2042 ResetImageProfileIterator(image);
2043 name=GetNextImageProfile(image);
2044 while (name != (const char *) NULL)
2046 profile=GetImageProfile(image,name);
2047 (void) WriteBlob(image,GetStringInfoLength(profile),
2048 GetStringInfoDatum(profile));
2049 name=GetNextImageProfile(image);
2052 if (image->storage_class == PseudoClass)
2064 packet_size=(size_t) (3*quantum_info->depth/8);
2065 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
2066 packet_size*sizeof(*colormap));
2067 if (colormap == (unsigned char *) NULL)
2068 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2070 Write colormap to file.
2073 for (i=0; i < (long) image->colors; i++)
2075 switch (quantum_info->depth)
2078 ThrowWriterException(CorruptImageError,"ImageDepthNotSupported");
2081 register unsigned long
2084 pixel=ScaleQuantumToLong(image->colormap[i].red);
2085 q=PopLongPixel(MSBEndian,pixel,q);
2086 pixel=ScaleQuantumToLong(image->colormap[i].green);
2087 q=PopLongPixel(MSBEndian,pixel,q);
2088 pixel=ScaleQuantumToLong(image->colormap[i].blue);
2089 q=PopLongPixel(MSBEndian,pixel,q);
2094 register unsigned short
2097 pixel=ScaleQuantumToShort(image->colormap[i].red);
2098 q=PopShortPixel(MSBEndian,pixel,q);
2099 pixel=ScaleQuantumToShort(image->colormap[i].green);
2100 q=PopShortPixel(MSBEndian,pixel,q);
2101 pixel=ScaleQuantumToShort(image->colormap[i].blue);
2102 q=PopShortPixel(MSBEndian,pixel,q);
2107 register unsigned char
2110 pixel=(unsigned char) ScaleQuantumToChar(image->colormap[i].red);
2111 q=PopCharPixel(pixel,q);
2112 pixel=(unsigned char) ScaleQuantumToChar(
2113 image->colormap[i].green);
2114 q=PopCharPixel(pixel,q);
2115 pixel=(unsigned char) ScaleQuantumToChar(image->colormap[i].blue);
2116 q=PopCharPixel(pixel,q);
2121 (void) WriteBlob(image,packet_size*image->colors,colormap);
2122 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
2125 Write image pixels to file.
2127 quantum_type=GetQuantumType(image,&image->exception);
2128 pixels=GetQuantumPixels(quantum_info);
2130 for (y=0; y < (long) image->rows; y++)
2132 register const IndexPacket
2135 register const PixelPacket
2141 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2142 if (p == (const PixelPacket *) NULL)
2144 indexes=GetVirtualIndexQueue(image);
2146 switch (compression)
2148 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2149 case LZWCompression:
2150 case ZipCompression:
2154 zip_info.zalloc=AcquireZIPMemory;
2155 zip_info.zfree=RelinquishZIPMemory;
2156 zip_info.opaque=(voidpf) NULL;
2157 code=deflateInit(&zip_info,(int) (image->quality ==
2158 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,
2163 zip_info.next_in=pixels;
2164 zip_info.avail_in=(uInt) (packet_size*image->columns);
2165 (void) ExportQuantumPixels(image,(const CacheView *) NULL,
2166 quantum_info,quantum_type,pixels,&image->exception);
2169 zip_info.next_out=compress_pixels;
2170 zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*image->columns);
2171 code=deflate(&zip_info,Z_SYNC_FLUSH);
2174 length=(size_t) (zip_info.next_out-compress_pixels);
2177 (void) WriteBlobMSBLong(image,(unsigned int) length);
2178 (void) WriteBlob(image,length,compress_pixels);
2180 } while (zip_info.avail_in != 0);
2181 if (y == (long) (image->rows-1))
2185 zip_info.next_out=compress_pixels;
2186 zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*
2188 code=deflate(&zip_info,Z_FINISH);
2189 length=(size_t) (zip_info.next_out-compress_pixels);
2192 (void) WriteBlobMSBLong(image,(unsigned int) length);
2193 (void) WriteBlob(image,length,compress_pixels);
2195 if (code == Z_STREAM_END)
2198 status=deflateEnd(&zip_info) == 0 ? MagickTrue : MagickFalse;
2203 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2204 case BZipCompression:
2208 bzip_info.bzalloc=AcquireBZIPMemory;
2209 bzip_info.bzfree=RelinquishBZIPMemory;
2210 bzip_info.opaque=(void *) NULL;
2211 code=BZ2_bzCompressInit(&bzip_info,(int) (image->quality ==
2212 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,
2214 (int) image_info->verbose,0);
2218 bzip_info.next_in=(char *) pixels;
2219 bzip_info.avail_in=(unsigned int) (packet_size*image->columns);
2220 (void) ExportQuantumPixels(image,(const CacheView *) NULL,
2221 quantum_info,quantum_type,pixels,&image->exception);
2224 bzip_info.next_out=(char *) compress_pixels;
2225 bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size*
2227 code=BZ2_bzCompress(&bzip_info,BZ_FLUSH);
2230 length=(size_t) (bzip_info.next_out-(char *) compress_pixels);
2233 (void) WriteBlobMSBLong(image,(unsigned int) length);
2234 (void) WriteBlob(image,length,compress_pixels);
2236 } while (bzip_info.avail_in != 0);
2237 if (y == (long) (image->rows-1))
2241 bzip_info.next_out=(char *) compress_pixels;
2242 bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size*
2244 code=BZ2_bzCompress(&bzip_info,BZ_FINISH);
2245 length=(size_t) (bzip_info.next_out-(char *) compress_pixels);
2248 (void) WriteBlobMSBLong(image,(unsigned int) length);
2249 (void) WriteBlob(image,length,compress_pixels);
2251 if (code == BZ_STREAM_END)
2254 status=BZ2_bzCompressEnd(&bzip_info) == 0 ? MagickTrue :
2260 case RLECompression:
2263 index=(IndexPacket) 0;
2264 if (indexes != (IndexPacket *) NULL)
2267 for (x=0; x < (long) image->columns; x++)
2269 if ((length < 255) && (x < (long) (image->columns-1)) &&
2270 (IsColorEqual(p,&pixel) != MagickFalse) &&
2271 ((image->matte == MagickFalse) ||
2272 (p->opacity == pixel.opacity)) &&
2273 ((indexes == (IndexPacket *) NULL) || (index == indexes[x])))
2278 q=PopRunlengthPacket(image,q,length,pixel,index);
2282 if (indexes != (IndexPacket *) NULL)
2286 q=PopRunlengthPacket(image,q,length,pixel,index);
2287 (void) WriteBlob(image,(size_t) (q-pixels),pixels);
2292 (void) ExportQuantumPixels(image,(const CacheView *) NULL,
2293 quantum_info,quantum_type,pixels,&image->exception);
2294 (void) WriteBlob(image,packet_size*image->columns,pixels);
2298 if ((image->previous == (Image *) NULL) &&
2299 (SetImageProgress(image,SaveImageTag,y,image->rows) == MagickFalse))
2302 quantum_info=DestroyQuantumInfo(quantum_info);
2303 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
2304 if (GetNextImageInList(image) == (Image *) NULL)
2306 image=SyncNextImageInList(image);
2307 status=SetImageProgress(image,SaveImagesTag,scene++,
2308 GetImageListLength(image));
2309 if (status == MagickFalse)
2311 } while (image_info->adjoin != MagickFalse);
2312 (void) CloseBlob(image);