2
% Copyright (C) 2003 GraphicsMagick Group
3
% Copyright (C) 2002 ImageMagick Studio
5
% This program is covered by multiple licenses, which are described in
6
% Copyright.txt. You should have received a copy of Copyright.txt with this
7
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
9
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
20
% Read/Write Magick Persistant Cache Image Format. %
29
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38
#include "magick/studio.h"
39
#include "magick/attribute.h"
40
#include "magick/cache.h"
41
#include "magick/blob.h"
42
#include "magick/color.h"
43
#include "magick/magick.h"
44
#include "magick/monitor.h"
45
#include "magick/utility.h"
51
WriteMPCImage(const ImageInfo *,Image *);
54
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
62
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
64
% Method IsMPC returns True if the image format type, identified by the
65
% magick string, is an Magick Persistent Cache image.
67
% The format of the IsMPC method is:
69
% unsigned int IsMPC(const unsigned char *magick,const size_t length)
71
% A description of each parameter follows:
73
% o status: Method IsMPC returns True if the image format type is MPC.
75
% o magick: This string is generally the first few bytes of an image file
78
% o length: Specifies the length of the magick string.
82
static unsigned int IsMPC(const unsigned char *magick,const size_t length)
86
if (LocaleNCompare((char *) magick,"id=MagickCache",14) == 0)
92
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
96
% R e a d C A C H E I m a g e %
100
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102
% Method ReadMPCImage reads an Magick Persistent Cache image file and returns
103
% it. It allocates the memory necessary for the new Image structure and
104
% returns a pointer to the new image.
106
% The format of the ReadMPCImage method is:
108
% Image *ReadMPCImage(const ImageInfo *image_info,ExceptionInfo *exception)
110
% Decompression code contributed by Kyle Shorter.
112
% A description of each parameter follows:
114
% o image: Method ReadMPCImage returns a pointer to the image after
115
% reading. A null image is returned if there is a memory shortage or
116
% if the image cannot be read.
118
% o image_info: Specifies a pointer to a ImageInfo structure.
120
% o exception: return any errors or warnings in this structure.
124
static Image *ReadMPCImage(const ImageInfo *image_info,ExceptionInfo *exception)
127
cache_filename[MaxTextExtent],
129
keyword[MaxTextExtent],
132
ExtendedSignedIntegralType
144
register unsigned char
159
assert(image_info != (const ImageInfo *) NULL);
160
assert(image_info->signature == MagickSignature);
161
assert(exception != (ExceptionInfo *) NULL);
162
assert(exception->signature == MagickSignature);
163
image=AllocateImage(image_info);
164
status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
166
ThrowReaderException(FileOpenError,UnableToOpenFile,image);
167
(void) strncpy(cache_filename,image->filename,MaxTextExtent-1);
168
AppendImageFormat("cache",cache_filename);
169
c=ReadBlobByte(image);
173
return((Image *) NULL);
180
Decode image header; header terminates one character beyond a ':'.
182
length=MaxTextExtent;
183
values=AllocateString((char *) NULL);
184
quantum_depth=QuantumDepth;
186
image->compression=NoCompression;
187
while (isgraph(c) && (c != ':'))
198
Read comment-- any text between { }.
200
length=MaxTextExtent;
201
comment=AllocateString((char *) NULL);
203
for ( ; comment != (char *) NULL; p++)
205
c=ReadBlobByte(image);
206
if ((c == EOF) || (c == '}'))
208
if ((p-comment+1) >= length)
212
MagickReallocMemory(comment,length);
213
if (comment == (char *) NULL)
215
p=comment+strlen(comment);
219
if (comment == (char *) NULL)
220
ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
223
(void) SetImageAttribute(image,"comment",comment);
224
MagickFreeMemory(comment);
225
c=ReadBlobByte(image);
231
Determine a keyword and its value.
236
if ((p-keyword) < (MaxTextExtent-1))
238
c=ReadBlobByte(image);
239
} while (isalnum(c) || (c == '-'));
241
while (isspace(c) || (c == '='))
242
c=ReadBlobByte(image);
244
while ((c != '}') && (c != EOF))
246
if ((p-values+1) >= (int) length)
250
MagickReallocMemory(values,length);
251
if (values == (char *) NULL)
253
p=values+strlen(values);
255
if (values == (char *) NULL)
256
ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
258
c=ReadBlobByte(image);
265
Assign a value to the specified keyword.
272
if (LocaleCompare(keyword,"background-color") == 0)
274
(void) QueryColorDatabase(values,&image->background_color,
278
if (LocaleCompare(keyword,"blue-primary") == 0)
280
(void) sscanf(values,"%lf,%lf",
281
&image->chromaticity.blue_primary.x,
282
&image->chromaticity.blue_primary.y);
285
if (LocaleCompare(keyword,"border-color") == 0)
287
(void) QueryColorDatabase(values,&image->border_color,
291
(void) SetImageAttribute(image,keyword,
292
*values == '{' ? values+1 : values);
298
if (LocaleCompare(keyword,"class") == 0)
300
image->storage_class=UndefinedClass;
301
if (LocaleCompare(values,"PseudoClass") == 0)
302
image->storage_class=PseudoClass;
304
if (LocaleCompare(values,"DirectClass") == 0)
305
image->storage_class=DirectClass;
308
if (LocaleCompare(keyword,"colors") == 0)
310
image->colors=atol(values);
313
if (LocaleCompare(keyword,"colorspace") == 0)
315
image->colorspace=UndefinedColorspace;
316
if (LocaleCompare(values,"CMYK") == 0)
317
image->colorspace=CMYKColorspace;
319
if (LocaleCompare(values,"RGB") == 0)
320
image->colorspace=RGBColorspace;
323
if (LocaleCompare(keyword,"compression") == 0)
328
compression=UndefinedCompression;
329
if (LocaleCompare("None",values) == 0)
330
compression=NoCompression;
331
if (LocaleCompare("BZip",values) == 0)
332
compression=BZipCompression;
333
if (LocaleCompare("Fax",values) == 0)
334
compression=FaxCompression;
335
if (LocaleCompare("Group4",values) == 0)
336
compression=Group4Compression;
337
if (LocaleCompare("JPEG",values) == 0)
338
compression=JPEGCompression;
339
if (LocaleCompare("Lossless",values) == 0)
340
compression=LosslessJPEGCompression;
341
if (LocaleCompare("LZW",values) == 0)
342
compression=LZWCompression;
343
if (LocaleCompare("RLE",values) == 0)
344
compression=RLECompression;
345
if (LocaleCompare("Zip",values) == 0)
346
compression=ZipCompression;
347
image->compression=compression;
350
if (LocaleCompare(keyword,"columns") == 0)
352
image->columns= atol(values);
355
(void) SetImageAttribute(image,keyword,
356
*values == '{' ? values+1 : values);
362
if (LocaleCompare(keyword,"delay") == 0)
364
image->delay=atol(values);
367
if (LocaleCompare(keyword,"depth") == 0)
369
image->depth=atol(values);
372
if (LocaleCompare(keyword,"dispose") == 0)
374
image->dispose=(DisposeType) atol(values);
375
if (LocaleCompare(values,"Background") == 0)
376
image->dispose=BackgroundDispose;
378
if (LocaleCompare(values,"None") == 0)
379
image->dispose=NoneDispose;
381
if (LocaleCompare(values,"Previous") == 0)
382
image->dispose=PreviousDispose;
385
(void) SetImageAttribute(image,keyword,
386
*values == '{' ? values+1 : values);
392
if (LocaleCompare(keyword,"error") == 0)
394
image->error.mean_error_per_pixel=atof(values);
397
(void) SetImageAttribute(image,keyword,
398
*values == '{' ? values+1 : values);
404
if (LocaleCompare(keyword,"gamma") == 0)
406
image->gamma=atof(values);
409
if (LocaleCompare(keyword,"grayscale") == 0)
411
image->is_grayscale=(LocaleCompare(values,"True") == 0) ||
412
(LocaleCompare(values,"true") == 0);
415
if (LocaleCompare(keyword,"green-primary") == 0)
417
(void) sscanf(values,"%lf,%lf",
418
&image->chromaticity.green_primary.x,
419
&image->chromaticity.green_primary.y);
422
(void) SetImageAttribute(image,keyword,
423
*values == '{' ? values+1 : values);
429
if (LocaleCompare(keyword,"id") == 0)
431
(void) strncpy(id,values,MaxTextExtent-1);
434
if (LocaleCompare(keyword,"iterations") == 0)
436
image->iterations=atol(values);
439
(void) SetImageAttribute(image,keyword,
440
*values == '{' ? values+1 : values);
446
if (LocaleCompare(keyword,"matte") == 0)
448
image->matte=(LocaleCompare(values,"True") == 0) ||
449
(LocaleCompare(values,"true") == 0);
452
if (LocaleCompare(keyword,"matte-color") == 0)
454
(void) QueryColorDatabase(values,&image->matte_color,
458
if (LocaleCompare(keyword,"maximum-error") == 0)
460
image->error.normalized_maximum_error=atof(values);
463
if (LocaleCompare(keyword,"mean-error") == 0)
465
image->error.normalized_mean_error=atof(values);
468
if (LocaleCompare(keyword,"monochrome") == 0)
470
image->is_monochrome=(LocaleCompare(values,"True") == 0) ||
471
(LocaleCompare(values,"true") == 0);
474
if (LocaleCompare(keyword,"montage") == 0)
476
(void) CloneString(&image->montage,values);
479
(void) SetImageAttribute(image,keyword,
480
*values == '{' ? values+1 : values);
486
if (LocaleCompare(keyword,"page") == 0)
491
geometry=GetPageGeometry(values);
492
(void) GetGeometry(geometry,&image->page.x,&image->page.y,
493
&image->page.width,&image->page.height);
494
MagickFreeMemory(geometry);
497
if (LocaleNCompare(keyword,"profile-",8) == 0)
499
if (LocaleCompare(keyword,"profile-icc") == 0)
501
image->color_profile.length=atol(values);
504
if (LocaleCompare(keyword,"profile-iptc") == 0)
506
image->iptc_profile.length=atol(values);
509
i=(long) image->generic_profiles;
510
if (image->generic_profile == (ProfileInfo *) NULL)
511
image->generic_profile=MagickAllocateMemory(ProfileInfo *,
512
sizeof(ProfileInfo));
514
MagickReallocMemory(image->generic_profile,
515
(i+1)*sizeof(ProfileInfo));
516
if (image->generic_profile == (ProfileInfo *) NULL)
517
ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
518
image->generic_profile[i].name=AllocateString(keyword+8);
519
image->generic_profile[i].length=atol(values);
520
image->generic_profile[i].info=(unsigned char *) NULL;
521
image->generic_profiles++;
524
(void) SetImageAttribute(image,keyword,
525
*values == '{' ? values+1 : values);
531
if (LocaleCompare(keyword,"opaque") == 0)
533
image->matte=(LocaleCompare(values,"True") == 0) ||
534
(LocaleCompare(values,"true") == 0);
537
(void) SetImageAttribute(image,keyword,
538
*values == '{' ? values+1 : values);
544
if (LocaleCompare(keyword,"quantum-depth") == 0)
546
quantum_depth=atol(values);
549
(void) SetImageAttribute(image,keyword,
550
*values == '{' ? values+1 : values);
556
if (LocaleCompare(keyword,"red-primary") == 0)
558
(void) sscanf(values,"%lf,%lf",
559
&image->chromaticity.red_primary.x,
560
&image->chromaticity.red_primary.y);
563
if (LocaleCompare(keyword,"rendering-intent") == 0)
565
image->rendering_intent=UndefinedIntent;
566
if (LocaleCompare(values,"Saturation") == 0)
567
image->rendering_intent=SaturationIntent;
569
if (LocaleCompare(values,"perceptual") == 0)
570
image->rendering_intent=PerceptualIntent;
572
if (LocaleCompare(values,"absolute") == 0)
573
image->rendering_intent=AbsoluteIntent;
575
if (LocaleCompare(values,"relative") == 0)
576
image->rendering_intent=RelativeIntent;
579
if (LocaleCompare(keyword,"resolution") == 0)
581
(void) GetMagickDimension(values,&image->x_resolution,
582
&image->y_resolution);
585
if (LocaleCompare(keyword,"rows") == 0)
587
image->rows=atol(values);
590
(void) SetImageAttribute(image,keyword,
591
*values == '{' ? values+1 : values);
597
if (LocaleCompare(keyword,"scene") == 0)
599
image->scene=atol(values);
602
(void) SetImageAttribute(image,keyword,
603
*values == '{' ? values+1 : values);
609
if (LocaleCompare(keyword,"units") == 0)
611
image->units=UndefinedResolution;
612
if (LocaleCompare(values,"pixels-per-inch") == 0)
613
image->units=PixelsPerInchResolution;
615
if (LocaleCompare(values,"pixels-per-centimeter") == 0)
616
image->units=PixelsPerCentimeterResolution;
619
(void) SetImageAttribute(image,keyword,
620
*values == '{' ? values+1 : values);
626
if (LocaleCompare(keyword,"white-point") == 0)
628
(void) sscanf(values,"%lf,%lf",
629
&image->chromaticity.white_point.x,
630
&image->chromaticity.white_point.y);
633
(void) SetImageAttribute(image,keyword,
634
*values == '{' ? values+1 : values);
639
(void) SetImageAttribute(image,keyword,
640
*values == '{' ? values+1 : values);
646
c=ReadBlobByte(image);
648
c=ReadBlobByte(image);
650
MagickFreeMemory(values);
651
(void) ReadBlobByte(image);
653
Verify that required image information is defined.
655
if ((LocaleCompare(id,"MagickCache") != 0) ||
656
(image->storage_class == UndefinedClass) ||
657
(image->compression == UndefinedCompression) || (image->columns == 0) ||
659
ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
660
if (quantum_depth != QuantumDepth)
661
ThrowReaderException(CacheError,InconsistentPersistentCacheDepth,image);
662
if (image->montage != (char *) NULL)
670
image->directory=AllocateString((char *) NULL);
671
if (image->directory == (char *) NULL)
672
ThrowReaderException(CorruptImageError,UnableToReadImageData,image);
677
if (((strlen(image->directory)+1) % MaxTextExtent) == 0)
680
Allocate more memory for the image directory.
682
MagickReallocMemory(image->directory,
683
(strlen(image->directory)+MaxTextExtent+1));
684
if (image->directory == (char *) NULL)
685
ThrowReaderException(CorruptImageError,UnableToReadImageData,
687
p=image->directory+strlen(image->directory);
689
c=ReadBlobByte(image);
693
if (image->color_profile.length != 0)
698
image->color_profile.info=MagickAllocateMemory(unsigned char *,
699
image->color_profile.length);
700
if (image->color_profile.info == (unsigned char *) NULL)
701
ThrowReaderException(CorruptImageError,UnableToReadColorProfile,
703
(void) ReadBlob(image,image->color_profile.length,
704
image->color_profile.info);
706
if (image->iptc_profile.length != 0)
711
image->iptc_profile.info=MagickAllocateMemory(unsigned char *,
712
image->iptc_profile.length);
713
if (image->iptc_profile.info == (unsigned char *) NULL)
714
ThrowReaderException(CorruptImageError,UnableToReadIPTCProfile,
716
(void) ReadBlob(image,image->iptc_profile.length,
717
image->iptc_profile.info);
719
if (image->generic_profiles != 0)
724
for (i=0; i < (long) image->generic_profiles; i++)
726
if (image->generic_profile[i].length == 0)
728
image->generic_profile[i].info=MagickAllocateMemory(unsigned char *,
729
image->generic_profile[i].length);
730
if (image->generic_profile[i].info == (unsigned char *) NULL)
731
ThrowReaderException(CorruptImageError,UnableToReadGenericProfile,
733
(void) ReadBlob(image,image->generic_profile[i].length,
734
image->generic_profile[i].info);
737
if (image->storage_class == PseudoClass)
740
Create image colormap.
742
if (!AllocateImageColormap(image,image->colors))
743
ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
745
if (image->colors == 0)
746
for (i=0; i < 256; i++)
748
image->colormap[i].red=ScaleCharToQuantum(i);
749
image->colormap[i].green=ScaleCharToQuantum(i);
750
image->colormap[i].blue=ScaleCharToQuantum(i);
762
Read image colormap from file.
764
packet_size=image->depth > 8 ? 6 : 3;
765
colormap=MagickAllocateMemory(unsigned char *,packet_size*image->colors);
766
if (colormap == (unsigned char *) NULL)
767
ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
769
(void) ReadBlob(image,packet_size*image->colors,colormap);
771
if (image->depth <= 8)
772
for (i=0; i < (long) image->colors; i++)
774
image->colormap[i].red=ScaleCharToQuantum(*p++);
775
image->colormap[i].green=ScaleCharToQuantum(*p++);
776
image->colormap[i].blue=ScaleCharToQuantum(*p++);
779
for (i=0; i < (long) image->colors; i++)
781
image->colormap[i].red=(*p++ << 8);
782
image->colormap[i].red|=(*p++);
783
image->colormap[i].green=(*p++ << 8);
784
image->colormap[i].green|=(*p++);
785
image->colormap[i].blue=(*p++ << 8);
786
image->colormap[i].blue|=(*p++);
788
MagickFreeMemory(colormap);
793
ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
797
if (image_info->ping && (image_info->subrange != 0))
798
if (image->scene >= (image_info->subimage+image_info->subrange-1))
801
Attach persistent pixel cache.
803
status=PersistCache(image,cache_filename,True,&offset,exception);
805
ThrowReaderException(CacheError,UnableToPeristPixelCache,image);
807
Proceed to next image.
811
c=ReadBlobByte(image);
812
} while (!isgraph(c) && (c != EOF));
816
Allocate next image structure.
818
AllocateNextImage(image_info,image);
819
if (image->next == (Image *) NULL)
821
DestroyImageList(image);
822
return((Image *) NULL);
824
image=SyncNextImageInList(image);
825
status=MagickMonitor(LoadImagesText,TellBlob(image),GetBlobSize(image),
831
while (image->previous != (Image *) NULL)
832
image=image->previous;
838
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
842
% R e g i s t e r M P C I m a g e %
846
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
848
% Method RegisterMPCImage adds attributes for the Cache image format to
849
% the list of supported formats. The attributes include the image format
850
% tag, a method to read and/or write the format, whether the format
851
% supports the saving of more than one frame to the same file or blob,
852
% whether the format supports native in-memory I/O, and a brief
853
% description of the format.
855
% The format of the RegisterMPCImage method is:
857
% RegisterMPCImage(void)
860
ModuleExport void RegisterMPCImage(void)
865
entry=SetMagickInfo("CACHE");
866
entry->description=AcquireString("Magick Persistent Cache image format");
867
entry->module=AcquireString("CACHE");
868
(void) RegisterMagickInfo(entry);
869
entry=SetMagickInfo("MPC");
870
entry->decoder=(DecoderHandler) ReadMPCImage;
871
entry->encoder=(EncoderHandler) WriteMPCImage;
872
entry->magick=(MagickHandler) IsMPC;
873
entry->description=AcquireString("Magick Persistent Cache image format");
874
entry->module=AcquireString("MPC");
875
(void) RegisterMagickInfo(entry);
879
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
883
% U n r e g i s t e r M P C I m a g e %
887
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
889
% Method UnregisterMPCImage removes format registrations made by the
890
% MPC module from the list of supported formats.
892
% The format of the UnregisterMPCImage method is:
894
% UnregisterMPCImage(void)
897
ModuleExport void UnregisterMPCImage(void)
899
(void) UnregisterMagickInfo("CACHE");
900
(void) UnregisterMagickInfo("MPC");
904
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
908
% W r i t e M P C I m a g e %
912
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
914
% Method WriteMPCImage writes an Magick Persistent Cache image to a file.
916
% The format of the WriteMPCImage method is:
918
% unsigned int WriteMPCImage(const ImageInfo *image_info,Image *image)
920
% A description of each parameter follows:
922
% o status: Method WriteMPCImage return True if the image is written.
923
% False is returned if there is a memory shortage or if the image file
926
% o image_info: Specifies a pointer to a ImageInfo structure.
928
% o image: A pointer to an Image structure.
932
static unsigned int WriteMPCImage(const ImageInfo *image_info,Image *image)
935
buffer[MaxTextExtent],
936
cache_filename[MaxTextExtent];
941
ExtendedSignedIntegralType
954
Open persistent cache.
956
assert(image_info != (const ImageInfo *) NULL);
957
assert(image_info->signature == MagickSignature);
958
assert(image != (Image *) NULL);
959
assert(image->signature == MagickSignature);
960
status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
962
ThrowWriterException(FileOpenError,UnableToOpenFile,image);
963
(void) strncpy(cache_filename,image->filename,MaxTextExtent-1);
964
AppendImageFormat("cache",cache_filename);
970
Write persistent cache meta-information.
972
(void) WriteBlobString(image,"id=MagickCache\n");
973
FormatString(buffer,"quantum-depth=%d\n",QuantumDepth);
974
(void) WriteBlobString(image,buffer);
975
if (image->storage_class == PseudoClass)
976
FormatString(buffer,"class=PseudoClass colors=%lu matte=%s\n",
977
image->colors,image->matte ? "True" : "False");
979
if (image->colorspace == CMYKColorspace)
980
FormatString(buffer,"class=DirectClass colorspace=CMYK matte=%s\n",
981
image->matte ? "True" : "False");
983
FormatString(buffer,"class=DirectClass matte=%s\n",
984
image->matte ? "True" : "False");
985
(void) WriteBlobString(image,buffer);
986
switch (image->compression)
991
(void) WriteBlobString(image,"compression=None\n");
994
case BZipCompression:
996
(void) WriteBlobString(image,"compression=BZip\n");
1001
(void) WriteBlobString(image,"compression=Fax\n");
1004
case Group4Compression:
1006
(void) WriteBlobString(image,"compression=Group4\n");
1009
case JPEGCompression:
1011
(void) WriteBlobString(image,"compression=JPEG\n");
1014
case LosslessJPEGCompression:
1016
(void) WriteBlobString(image,"compression=Lossless\n");
1019
case LZWCompression:
1021
(void) WriteBlobString(image,"compression=LZW\n");
1024
case RLECompression:
1026
(void) WriteBlobString(image,"compression=RLE\n");
1029
case ZipCompression:
1031
(void) WriteBlobString(image,"compression=Zip\n");
1035
FormatString(buffer,"columns=%lu rows=%lu depth=%lu\n",image->columns,
1036
image->rows,image->depth);
1037
(void) WriteBlobString(image,buffer);
1038
if (image->is_monochrome != MagickFalse)
1040
FormatString(buffer,"monochrome=True\n");
1041
(void) WriteBlobString(image,buffer);
1043
if (image->is_grayscale != MagickFalse)
1045
FormatString(buffer,"grayscale=True\n");
1046
(void) WriteBlobString(image,buffer);
1048
if ((image->x_resolution != 0) && (image->y_resolution != 0))
1051
units[MaxTextExtent];
1054
Set image resolution.
1056
(void) strcpy(units,"undefined");
1057
if (image->units == PixelsPerInchResolution)
1058
(void) strcpy(units,"pixels-per-inch");
1059
if (image->units == PixelsPerCentimeterResolution)
1060
(void) strcpy(units,"pixels-per-centimeter");
1061
FormatString(buffer,"Resolution=%gx%g units=%.1024s\n",
1062
image->x_resolution,image->y_resolution,units);
1063
(void) WriteBlobString(image,buffer);
1065
if ((image->page.width != 0) && (image->page.height != 0))
1067
FormatString(buffer,"page=%lux%lu%+ld%+ld\n",image->page.width,
1068
image->page.height,image->page.x,image->page.y);
1069
(void) WriteBlobString(image,buffer);
1071
if ((image->next != (Image *) NULL) || (image->previous != (Image *) NULL))
1073
if (image->scene == 0)
1074
FormatString(buffer,"iterations=%lu delay=%lu\n",image->iterations,
1077
FormatString(buffer,"scene=%lu iterations=%lu delay=%lu\n",
1078
image->scene,image->iterations,image->delay);
1079
(void) WriteBlobString(image,buffer);
1083
if (image->scene != 0)
1085
FormatString(buffer,"scene=%lu\n",image->scene);
1086
(void) WriteBlobString(image,buffer);
1088
if (image->iterations != 0)
1090
FormatString(buffer,"iterations=%lu\n",image->iterations);
1091
(void) WriteBlobString(image,buffer);
1093
if (image->delay != 0)
1095
FormatString(buffer,"delay=%lu\n",image->delay);
1096
(void) WriteBlobString(image,buffer);
1099
if (image->dispose != UndefinedDispose)
1101
if (image->dispose == BackgroundDispose)
1102
(void) strcpy(buffer,"dispose=background\n");
1104
if (image->dispose == NoneDispose)
1105
(void) strcpy(buffer,"dispose=none\n");
1107
(void) strcpy(buffer,"dispose=previous\n");
1108
(void) WriteBlobString(image,buffer);
1110
if (image->error.mean_error_per_pixel != 0.0)
1112
FormatString(buffer,"error=%g mean-error=%g maximum-error=%g\n",
1113
image->error.mean_error_per_pixel,image->error.normalized_mean_error,
1114
image->error.normalized_maximum_error);
1115
(void) WriteBlobString(image,buffer);
1117
if (image->rendering_intent != UndefinedIntent)
1119
if (image->rendering_intent == SaturationIntent)
1120
(void) WriteBlobString(image,"rendering-intent=saturation\n");
1122
if (image->rendering_intent == PerceptualIntent)
1123
(void) WriteBlobString(image,"rendering-intent=perceptual\n");
1125
if (image->rendering_intent == AbsoluteIntent)
1126
(void) WriteBlobString(image,"rendering-intent=absolute\n");
1128
(void) WriteBlobString(image,"rendering-intent=relative\n");
1130
if (image->gamma != 0.0)
1132
FormatString(buffer,"gamma=%g\n",image->gamma);
1133
(void) WriteBlobString(image,buffer);
1135
if (image->chromaticity.white_point.x != 0.0)
1138
Note chomaticity points.
1140
FormatString(buffer,
1141
"red-primary=%g,%g green-primary=%g,%g blue-primary=%g,%g\n",
1142
image->chromaticity.red_primary.x,image->chromaticity.red_primary.y,
1143
image->chromaticity.green_primary.x,
1144
image->chromaticity.green_primary.y,
1145
image->chromaticity.blue_primary.x,
1146
image->chromaticity.blue_primary.y);
1147
(void) WriteBlobString(image,buffer);
1148
FormatString(buffer,"white-point=%g,%g\n",
1149
image->chromaticity.white_point.x,image->chromaticity.white_point.y);
1150
(void) WriteBlobString(image,buffer);
1152
if (image->color_profile.length != 0)
1154
FormatString(buffer,"profile-icc=%lu\n",(unsigned long)
1155
image->color_profile.length);
1156
(void) WriteBlobString(image,buffer);
1158
if (image->iptc_profile.length != 0)
1160
FormatString(buffer,"profile-iptc=%lu\n",(unsigned long)
1161
image->iptc_profile.length);
1162
(void) WriteBlobString(image,buffer);
1164
if (image->generic_profiles != 0)
1169
for (i=0; i < (long) image->generic_profiles; i++)
1171
FormatString(buffer,"profile-%s=%lu\n",
1172
image->generic_profile[i].name == (char *) NULL ? "generic" :
1173
image->generic_profile[i].name,(unsigned long)
1174
image->generic_profile[i].length);
1175
(void) WriteBlobString(image,buffer);
1178
if (image->montage != (char *) NULL)
1180
FormatString(buffer,"montage=%.1024s\n",image->montage);
1181
(void) WriteBlobString(image,buffer);
1183
attribute=GetImageAttribute(image,(char *) NULL);
1184
for ( ; attribute != (const ImageAttribute *) NULL; attribute=attribute->next)
1186
if (attribute->value != NULL)
1191
FormatString(buffer,"%.1024s=",attribute->key);
1192
(void) WriteBlobString(image,buffer);
1193
for (j=0; j < (long) strlen(attribute->value); j++)
1194
if (isspace((int) attribute->value[j]))
1196
if (j < (long) strlen(attribute->value))
1197
(void) WriteBlobByte(image,'{');
1198
(void) WriteBlobString(image,attribute->value);
1199
if (j < (long) strlen(attribute->value))
1200
(void) WriteBlobByte(image,'}');
1201
(void) WriteBlobByte(image,'\n');
1204
(void) WriteBlobString(image,"\f\n:\032");
1205
if (image->montage != (char *) NULL)
1208
Write montage tile directory.
1210
if (image->directory != (char *) NULL)
1211
(void) WriteBlobString(image,image->directory);
1212
(void) WriteBlobByte(image,'\0');
1214
if (image->color_profile.length != 0)
1215
(void) WriteBlob(image,image->color_profile.length,
1216
image->color_profile.info);
1217
if (image->iptc_profile.length != 0)
1218
(void) WriteBlob(image,image->iptc_profile.length,
1219
image->iptc_profile.info);
1220
if (image->generic_profiles != 0)
1225
for (i=0; i < (long) image->generic_profiles; i++)
1227
if (image->generic_profile[i].length == 0)
1229
(void) WriteBlob(image,image->generic_profile[i].length,
1230
image->generic_profile[i].info);
1233
if (image->storage_class == PseudoClass)
1235
register unsigned char
1247
packet_size=image->depth > 8 ? 6 : 3;
1248
colormap=MagickAllocateMemory(unsigned char *,packet_size*image->colors);
1249
if (colormap == (unsigned char *) NULL)
1252
Write colormap to file.
1255
if (image->depth <= 8)
1256
for (i=0; i < (long) image->colors; i++)
1258
*q++=image->colormap[i].red;
1259
*q++=image->colormap[i].green;
1260
*q++=image->colormap[i].blue;
1263
for (i=0; i < (long) image->colors; i++)
1265
*q++=image->colormap[i].red >> 8;
1266
*q++=image->colormap[i].red & 0xff;
1267
*q++=image->colormap[i].green >> 8;
1268
*q++=image->colormap[i].green & 0xff;
1269
*q++=image->colormap[i].blue >> 8;
1270
*q++=image->colormap[i].blue & 0xff;
1272
(void) WriteBlob(image,packet_size*image->colors,colormap);
1273
MagickFreeMemory(colormap);
1276
Initialize persistent pixel cache.
1278
status=PersistCache(image,cache_filename,False,&offset,&image->exception);
1279
if (status == False)
1280
ThrowWriterException(CacheError,UnableToPeristPixelCache,image);
1281
if (image->next == (Image *) NULL)
1283
image=SyncNextImageInList(image);
1284
status=MagickMonitor(SaveImagesText,scene++,GetImageListLength(image),
1286
if (status == False)
1288
} while (image_info->adjoin);
1289
if (image_info->adjoin)
1290
while (image->previous != (Image *) NULL)
1291
image=image->previous;