2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % PPPP RRRR OOO FFFFF IIIII L EEEEE %
7 % P P R R O O F I L E %
8 % PPPP RRRR O O FFF I L EEE %
10 % P R R OOO F IIIII LLLLL EEEEE %
13 % MagickCore Image Profile Methods %
20 % Copyright 1999-2015 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 "MagickCore/studio.h"
43 #include "MagickCore/attribute.h"
44 #include "MagickCore/cache.h"
45 #include "MagickCore/color.h"
46 #include "MagickCore/colorspace-private.h"
47 #include "MagickCore/configure.h"
48 #include "MagickCore/exception.h"
49 #include "MagickCore/exception-private.h"
50 #include "MagickCore/hashmap.h"
51 #include "MagickCore/image.h"
52 #include "MagickCore/memory_.h"
53 #include "MagickCore/monitor.h"
54 #include "MagickCore/monitor-private.h"
55 #include "MagickCore/option.h"
56 #include "MagickCore/option-private.h"
57 #include "MagickCore/pixel-accessor.h"
58 #include "MagickCore/profile.h"
59 #include "MagickCore/profile-private.h"
60 #include "MagickCore/property.h"
61 #include "MagickCore/quantum.h"
62 #include "MagickCore/quantum-private.h"
63 #include "MagickCore/resource_.h"
64 #include "MagickCore/splay-tree.h"
65 #include "MagickCore/string_.h"
66 #include "MagickCore/thread-private.h"
67 #include "MagickCore/token.h"
68 #include "MagickCore/utility.h"
69 #if defined(MAGICKCORE_LCMS_DELEGATE)
70 #if defined(MAGICKCORE_HAVE_LCMS_LCMS2_H)
72 #include <lcms/lcms2.h>
73 #elif defined(MAGICKCORE_HAVE_LCMS2_H)
76 #elif defined(MAGICKCORE_HAVE_LCMS_LCMS_H)
77 #include <lcms/lcms.h>
86 #if !defined(LCMS_VERSION) || (LCMS_VERSION < 2000)
87 #define cmsSigCmykData icSigCmykData
88 #define cmsSigGrayData icSigGrayData
89 #define cmsSigLabData icSigLabData
90 #define cmsSigLuvData icSigLuvData
91 #define cmsSigRgbData icSigRgbData
92 #define cmsSigXYZData icSigXYZData
93 #define cmsSigYCbCrData icSigYCbCrData
94 #define cmsSigLinkClass icSigLinkClass
95 #define cmsColorSpaceSignature icColorSpaceSignature
96 #define cmsUInt32Number DWORD
97 #define cmsSetLogErrorHandler(handler) cmsSetErrorHandler(handler)
98 #define cmsCreateTransformTHR(context,source_profile,source_type, \
99 target_profile,target_type,intent,flags) cmsCreateTransform(source_profile, \
100 source_type,target_profile,target_type,intent,flags);
101 #define cmsOpenProfileFromMemTHR(context,profile,length) \
102 cmsOpenProfileFromMem(profile,length)
108 static MagickBooleanType
109 SetImageProfileInternal(Image *,const char *,const StringInfo *,
110 const MagickBooleanType,ExceptionInfo *);
113 WriteTo8BimProfile(Image *,const char*,const StringInfo *);
133 typedef struct _CMSExceptionInfo
143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
147 % C l o n e I m a g e P r o f i l e s %
151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
153 % CloneImageProfiles() clones one or more image profiles.
155 % The format of the CloneImageProfiles method is:
157 % MagickBooleanType CloneImageProfiles(Image *image,
158 % const Image *clone_image)
160 % A description of each parameter follows:
162 % o image: the image.
164 % o clone_image: the clone image.
167 MagickExport MagickBooleanType CloneImageProfiles(Image *image,
168 const Image *clone_image)
170 assert(image != (Image *) NULL);
171 assert(image->signature == MagickSignature);
172 if (image->debug != MagickFalse)
173 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
174 assert(clone_image != (const Image *) NULL);
175 assert(clone_image->signature == MagickSignature);
176 if (clone_image->profiles != (void *) NULL)
178 if (image->profiles != (void *) NULL)
179 DestroyImageProfiles(image);
180 image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
181 (void *(*)(void *)) ConstantString,(void *(*)(void *)) CloneStringInfo);
187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
191 % D e l e t e I m a g e P r o f i l e %
195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
197 % DeleteImageProfile() deletes a profile from the image by its name.
199 % The format of the DeleteImageProfile method is:
201 % MagickBooleanTyupe DeleteImageProfile(Image *image,const char *name)
203 % A description of each parameter follows:
205 % o image: the image.
207 % o name: the profile name.
210 MagickExport MagickBooleanType DeleteImageProfile(Image *image,const char *name)
212 assert(image != (Image *) NULL);
213 assert(image->signature == MagickSignature);
214 if (image->debug != MagickFalse)
215 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
216 if (image->profiles == (SplayTreeInfo *) NULL)
218 WriteTo8BimProfile(image,name,(StringInfo *) NULL);
219 return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->profiles,name));
223 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227 % D e s t r o y I m a g e P r o f i l e s %
231 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233 % DestroyImageProfiles() releases memory associated with an image profile map.
235 % The format of the DestroyProfiles method is:
237 % void DestroyImageProfiles(Image *image)
239 % A description of each parameter follows:
241 % o image: the image.
244 MagickExport void DestroyImageProfiles(Image *image)
246 if (image->profiles != (SplayTreeInfo *) NULL)
247 image->profiles=DestroySplayTree((SplayTreeInfo *) image->profiles);
251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
255 % G e t I m a g e P r o f i l e %
259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261 % GetImageProfile() gets a profile associated with an image by name.
263 % The format of the GetImageProfile method is:
265 % const StringInfo *GetImageProfile(const Image *image,const char *name)
267 % A description of each parameter follows:
269 % o image: the image.
271 % o name: the profile name.
274 MagickExport const StringInfo *GetImageProfile(const Image *image,
280 assert(image != (Image *) NULL);
281 assert(image->signature == MagickSignature);
282 if (image->debug != MagickFalse)
283 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
284 if (image->profiles == (SplayTreeInfo *) NULL)
285 return((StringInfo *) NULL);
286 profile=(const StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
287 image->profiles,name);
292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296 % G e t N e x t I m a g e P r o f i l e %
300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
302 % GetNextImageProfile() gets the next profile name for an image.
304 % The format of the GetNextImageProfile method is:
306 % char *GetNextImageProfile(const Image *image)
308 % A description of each parameter follows:
310 % o hash_info: the hash info.
313 MagickExport char *GetNextImageProfile(const Image *image)
315 assert(image != (Image *) NULL);
316 assert(image->signature == MagickSignature);
317 if (image->debug != MagickFalse)
318 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
319 if (image->profiles == (SplayTreeInfo *) NULL)
320 return((char *) NULL);
321 return((char *) GetNextKeyInSplayTree((SplayTreeInfo *) image->profiles));
325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
329 % P r o f i l e I m a g e %
333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
335 % ProfileImage() associates, applies, or removes an ICM, IPTC, or generic
336 % profile with / to / from an image. If the profile is NULL, it is removed
337 % from the image otherwise added or applied. Use a name of '*' and a profile
338 % of NULL to remove all profiles from the image.
340 % ICC and ICM profiles are handled as follows: If the image does not have
341 % an associated color profile, the one you provide is associated with the
342 % image and the image pixels are not transformed. Otherwise, the colorspace
343 % transform defined by the existing and new profile are applied to the image
344 % pixels and the new profile is associated with the image.
346 % The format of the ProfileImage method is:
348 % MagickBooleanType ProfileImage(Image *image,const char *name,
349 % const void *datum,const size_t length,const MagickBooleanType clone)
351 % A description of each parameter follows:
353 % o image: the image.
355 % o name: Name of profile to add or remove: ICC, IPTC, or generic profile.
357 % o datum: the profile data.
359 % o length: the length of the profile.
361 % o clone: should be MagickFalse.
365 #if defined(MAGICKCORE_LCMS_DELEGATE)
367 static unsigned short **DestroyPixelThreadSet(unsigned short **pixels)
372 assert(pixels != (unsigned short **) NULL);
373 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
374 if (pixels[i] != (unsigned short *) NULL)
375 pixels[i]=(unsigned short *) RelinquishMagickMemory(pixels[i]);
376 pixels=(unsigned short **) RelinquishMagickMemory(pixels);
380 static unsigned short **AcquirePixelThreadSet(const size_t columns,
381 const size_t channels)
392 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
393 pixels=(unsigned short **) AcquireQuantumMemory(number_threads,
395 if (pixels == (unsigned short **) NULL)
396 return((unsigned short **) NULL);
397 (void) ResetMagickMemory(pixels,0,number_threads*sizeof(*pixels));
398 for (i=0; i < (ssize_t) number_threads; i++)
400 pixels[i]=(unsigned short *) AcquireQuantumMemory(columns,channels*
402 if (pixels[i] == (unsigned short *) NULL)
403 return(DestroyPixelThreadSet(pixels));
408 static cmsHTRANSFORM *DestroyTransformThreadSet(cmsHTRANSFORM *transform)
413 assert(transform != (cmsHTRANSFORM *) NULL);
414 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
415 if (transform[i] != (cmsHTRANSFORM) NULL)
416 cmsDeleteTransform(transform[i]);
417 transform=(cmsHTRANSFORM *) RelinquishMagickMemory(transform);
421 static cmsHTRANSFORM *AcquireTransformThreadSet(Image *image,
422 const cmsHPROFILE source_profile,const cmsUInt32Number source_type,
423 const cmsHPROFILE target_profile,const cmsUInt32Number target_type,
424 const int intent,const cmsUInt32Number flags)
435 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
436 transform=(cmsHTRANSFORM *) AcquireQuantumMemory(number_threads,
438 if (transform == (cmsHTRANSFORM *) NULL)
439 return((cmsHTRANSFORM *) NULL);
440 (void) ResetMagickMemory(transform,0,number_threads*sizeof(*transform));
441 for (i=0; i < (ssize_t) number_threads; i++)
443 transform[i]=cmsCreateTransformTHR((cmsContext) image,source_profile,
444 source_type,target_profile,target_type,intent,flags);
445 if (transform[i] == (cmsHTRANSFORM) NULL)
446 return(DestroyTransformThreadSet(transform));
452 #if defined(MAGICKCORE_LCMS_DELEGATE)
453 #if defined(LCMS_VERSION) && (LCMS_VERSION >= 2000)
454 static void CMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
466 cms_exception=(CMSExceptionInfo *) context;
467 image=cms_exception->image;
468 exception=cms_exception->exception;
469 if (image == (Image *) NULL)
471 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
472 "UnableToTransformColorspace","`%s'","unknown context");
475 if (image->debug != MagickFalse)
476 (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%u, %s",
477 severity,message != (char *) NULL ? message : "no message");
478 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
479 "UnableToTransformColorspace","`%s'",image->filename);
482 static int CMSExceptionHandler(int severity,const char *message)
484 (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%d, %s",
485 severity,message != (char *) NULL ? message : "no message");
491 static MagickBooleanType SetsRGBImageProfile(Image *image,
492 ExceptionInfo *exception)
497 0x00, 0x00, 0x0c, 0x8c, 0x61, 0x72, 0x67, 0x6c, 0x02, 0x20, 0x00, 0x00,
498 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
499 0x07, 0xde, 0x00, 0x01, 0x00, 0x06, 0x00, 0x16, 0x00, 0x0f, 0x00, 0x3a,
500 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
501 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00,
502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
503 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x61, 0x72, 0x67, 0x6c,
504 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
505 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
508 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x99,
509 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0xec, 0x00, 0x00, 0x00, 0x67,
510 0x64, 0x6d, 0x6e, 0x64, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70,
511 0x64, 0x6d, 0x64, 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88,
512 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x0c,
513 0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x00, 0x67,
514 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x24,
515 0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xe4, 0x00, 0x00, 0x00, 0x14,
516 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x24,
517 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x14,
518 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x14,
519 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x14,
520 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x58, 0x00, 0x00, 0x00, 0x14,
521 0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x6c, 0x00, 0x00, 0x00, 0x14,
522 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
523 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
524 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
525 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
526 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36,
527 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75, 0x69, 0x76,
528 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x77, 0x77,
529 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x31, 0x39,
530 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c,
531 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
532 0x00, 0x3f, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31,
533 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75,
534 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77,
535 0x77, 0x77, 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20,
536 0x31, 0x39, 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66,
537 0x69, 0x6c, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, 0x61,
539 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x72, 0x61, 0x65, 0x6d,
540 0x65, 0x20, 0x57, 0x2e, 0x20, 0x47, 0x69, 0x6c, 0x6c, 0x2e, 0x20, 0x52,
541 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f,
542 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
543 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x4e, 0x6f, 0x20, 0x57,
544 0x61, 0x72, 0x72, 0x61, 0x6e, 0x74, 0x79, 0x2c, 0x20, 0x55, 0x73, 0x65,
545 0x20, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e,
546 0x20, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20,
548 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
549 0x65, 0x63, 0x2e, 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
550 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74,
551 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
552 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
553 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
557 0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e,
558 0x31, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47,
559 0x42, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61,
560 0x63, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43,
562 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
563 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63,
564 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
565 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00,
568 0x43, 0x52, 0x54, 0x20, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
569 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
570 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
572 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa4, 0x7c,
578 0x00, 0x14, 0x5f, 0x30, 0x00, 0x10, 0xce, 0x02, 0x00, 0x03, 0xed, 0xb2,
579 0x00, 0x04, 0x13, 0x0a, 0x00, 0x03, 0x5c, 0x67, 0x00, 0x00, 0x00, 0x01,
580 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x0a, 0x3d,
581 0x00, 0x50, 0x00, 0x00, 0x00, 0x57, 0x1e, 0xb8, 0x6d, 0x65, 0x61, 0x73,
582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
583 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x58, 0x59, 0x5a, 0x20,
585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00,
586 0x00, 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa0,
589 0x00, 0x00, 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20,
590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x97, 0x00, 0x00, 0xb7, 0x87,
591 0x00, 0x00, 0x18, 0xd9, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
592 0x00, 0x00, 0x24, 0x9f, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0xb6, 0xc4,
593 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
594 0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19,
595 0x00, 0x1e, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37,
596 0x00, 0x3b, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54,
597 0x00, 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
598 0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00, 0x90,
599 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9, 0x00, 0xae,
600 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00, 0xc6, 0x00, 0xcb,
601 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0xeb,
602 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01, 0x01, 0x01, 0x07, 0x01, 0x0d,
603 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f, 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32,
604 0x01, 0x38, 0x01, 0x3e, 0x01, 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59,
605 0x01, 0x60, 0x01, 0x67, 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83,
606 0x01, 0x8b, 0x01, 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1,
607 0x01, 0xb9, 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1,
608 0x01, 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
609 0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02, 0x4b,
610 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a, 0x02, 0x84,
611 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02, 0xb6, 0x02, 0xc1,
612 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb, 0x02, 0xf5, 0x03, 0x00,
613 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2d, 0x03, 0x38, 0x03, 0x43,
614 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66, 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a,
615 0x03, 0x96, 0x03, 0xa2, 0x03, 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3,
616 0x03, 0xe0, 0x03, 0xec, 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20,
617 0x04, 0x2d, 0x04, 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71,
618 0x04, 0x7e, 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4,
619 0x04, 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
620 0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05, 0x77,
621 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5, 0x05, 0xd5,
622 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06, 0x27, 0x06, 0x37,
623 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b, 0x06, 0x8c, 0x06, 0x9d,
624 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06, 0xe3, 0x06, 0xf5, 0x07, 0x07,
625 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d, 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74,
626 0x07, 0x86, 0x07, 0x99, 0x07, 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5,
627 0x07, 0xf8, 0x08, 0x0b, 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a,
628 0x08, 0x6e, 0x08, 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2,
629 0x08, 0xe7, 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f,
630 0x09, 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
631 0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a, 0x54,
632 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5, 0x0a, 0xdc,
633 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b, 0x51, 0x0b, 0x69,
634 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8, 0x0b, 0xe1, 0x0b, 0xf9,
635 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c, 0x5c, 0x0c, 0x75, 0x0c, 0x8e,
636 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9, 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26,
637 0x0d, 0x40, 0x0d, 0x5a, 0x0d, 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3,
638 0x0d, 0xde, 0x0d, 0xf8, 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64,
639 0x0e, 0x7f, 0x0e, 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09,
640 0x0f, 0x25, 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3,
641 0x0f, 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
642 0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11, 0x13,
643 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa, 0x11, 0xc9,
644 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12, 0x64, 0x12, 0x84,
645 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03, 0x13, 0x23, 0x13, 0x43,
646 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13, 0xc5, 0x13, 0xe5, 0x14, 0x06,
647 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a, 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce,
648 0x14, 0xf0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b,
649 0x15, 0xbd, 0x15, 0xe0, 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c,
650 0x16, 0x8f, 0x16, 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41,
651 0x17, 0x65, 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b,
652 0x18, 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
653 0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19, 0xdd,
654 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e, 0x1a, 0xc5,
655 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b, 0x8a, 0x1b, 0xb2,
656 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52, 0x1c, 0x7b, 0x1c, 0xa3,
657 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d, 0x47, 0x1d, 0x70, 0x1d, 0x99,
658 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16, 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94,
659 0x1e, 0xbe, 0x1e, 0xe9, 0x1f, 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94,
660 0x1f, 0xbf, 0x1f, 0xea, 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98,
661 0x20, 0xc4, 0x20, 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1,
662 0x21, 0xce, 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf,
663 0x22, 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
664 0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24, 0xda,
665 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7, 0x25, 0xf7,
666 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26, 0xe8, 0x27, 0x18,
667 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc, 0x28, 0x0d, 0x28, 0x3f,
668 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29, 0x06, 0x29, 0x38, 0x29, 0x6b,
669 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02, 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b,
670 0x2a, 0xcf, 0x2b, 0x02, 0x2b, 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1,
671 0x2c, 0x05, 0x2c, 0x39, 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c,
672 0x2d, 0x41, 0x2d, 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c,
673 0x2e, 0x82, 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91,
674 0x2f, 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
675 0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32, 0x2a,
676 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46, 0x33, 0x7f,
677 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34, 0x9e, 0x34, 0xd8,
678 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2, 0x35, 0xfd, 0x36, 0x37,
679 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37, 0x24, 0x37, 0x60, 0x37, 0x9c,
680 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05,
681 0x39, 0x42, 0x39, 0x7f, 0x39, 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74,
682 0x3a, 0xb2, 0x3a, 0xef, 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8,
683 0x3c, 0x27, 0x3c, 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61,
684 0x3d, 0xa1, 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0,
685 0x3f, 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
686 0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41, 0xee,
687 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a, 0x43, 0x7d,
688 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44, 0xce, 0x45, 0x12,
689 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22, 0x46, 0x67, 0x46, 0xab,
690 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47, 0xc0, 0x48, 0x05, 0x48, 0x4b,
691 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d, 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0,
692 0x4a, 0x37, 0x4a, 0x7d, 0x4a, 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a,
693 0x4b, 0xe2, 0x4c, 0x2a, 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a,
694 0x4d, 0x93, 0x4d, 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00,
695 0x4f, 0x49, 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb,
696 0x51, 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
697 0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54, 0x42,
698 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2, 0x56, 0x0f,
699 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57, 0x92, 0x57, 0xe0,
700 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a, 0x59, 0x69, 0x59, 0xb8,
701 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a, 0xf5, 0x5b, 0x45, 0x5b, 0x95,
702 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86, 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78,
703 0x5d, 0xc9, 0x5e, 0x1a, 0x5e, 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61,
704 0x5f, 0xb3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f,
705 0x61, 0xa2, 0x61, 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43,
706 0x63, 0x97, 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d,
707 0x65, 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
708 0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69, 0x43,
709 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7, 0x6b, 0x4f,
710 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d, 0x08, 0x6d, 0x60,
711 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4, 0x6f, 0x1e, 0x6f, 0x78,
712 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70, 0xe0, 0x71, 0x3a, 0x71, 0x95,
713 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6, 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8,
714 0x74, 0x14, 0x74, 0x70, 0x74, 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1,
715 0x76, 0x3e, 0x76, 0x9b, 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11,
716 0x78, 0x6e, 0x78, 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46,
717 0x7a, 0xa5, 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81,
718 0x7c, 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
719 0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81, 0x0a,
720 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4, 0x83, 0x57,
721 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85, 0x47, 0x85, 0xab,
722 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b, 0x87, 0x9f, 0x88, 0x04,
723 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89, 0x99, 0x89, 0xfe, 0x8a, 0x64,
724 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96, 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca,
725 0x8d, 0x31, 0x8d, 0x98, 0x8d, 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36,
726 0x8f, 0x9e, 0x90, 0x06, 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8,
727 0x92, 0x11, 0x92, 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20,
728 0x94, 0x8a, 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f,
729 0x97, 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
730 0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b, 0xaf,
731 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2, 0x9e, 0x40,
732 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0, 0x69, 0xa0, 0xd8,
733 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96, 0xa3, 0x06, 0xa3, 0x76,
734 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5, 0x38, 0xa5, 0xa9, 0xa6, 0x1a,
735 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e, 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4,
736 0xa9, 0x37, 0xa9, 0xa9, 0xaa, 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75,
737 0xab, 0xe9, 0xac, 0x5c, 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d,
738 0xae, 0xa1, 0xaf, 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea,
739 0xb1, 0x60, 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae,
740 0xb4, 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
741 0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9, 0x4a,
742 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7, 0xbc, 0x21,
743 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe, 0x84, 0xbe, 0xff,
744 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec, 0xc1, 0x67, 0xc1, 0xe3,
745 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3, 0xd4, 0xc4, 0x51, 0xc4, 0xce,
746 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46, 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf,
747 0xc8, 0x3d, 0xc8, 0xbc, 0xc9, 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7,
748 0xcb, 0x36, 0xcb, 0xb6, 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5,
749 0xce, 0x36, 0xce, 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba,
750 0xd1, 0x3c, 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6,
751 0xd4, 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
752 0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9, 0xf1,
753 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a, 0xdd, 0x10,
754 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf, 0xaf, 0xe0, 0x36,
755 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53, 0xe2, 0xdb, 0xe3, 0x63,
756 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5, 0x84, 0xe6, 0x0d, 0xe6, 0x96,
757 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32, 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0,
758 0xea, 0x5b, 0xea, 0xe5, 0xeb, 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11,
759 0xed, 0x9c, 0xee, 0x28, 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58,
760 0xf0, 0xe5, 0xf1, 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7,
761 0xf4, 0x34, 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb,
762 0xf7, 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
763 0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd, 0xba,
764 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
773 assert(image != (Image *) NULL);
774 assert(image->signature == MagickSignature);
775 if (GetImageProfile(image,"icc") != (const StringInfo *) NULL)
777 profile=AcquireStringInfo(sizeof(sRGBProfile));
778 SetStringInfoDatum(profile,sRGBProfile);
779 status=SetImageProfile(image,"icc",profile,exception);
780 profile=DestroyStringInfo(profile);
784 MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
785 const void *datum,const size_t length,ExceptionInfo *exception)
787 #define ProfileImageTag "Profile/Image"
788 #define ThrowProfileException(severity,tag,context) \
790 if (source_profile != (cmsHPROFILE) NULL) \
791 (void) cmsCloseProfile(source_profile); \
792 if (target_profile != (cmsHPROFILE) NULL) \
793 (void) cmsCloseProfile(target_profile); \
794 ThrowBinaryException(severity,tag,context); \
803 assert(image != (Image *) NULL);
804 assert(image->signature == MagickSignature);
805 if (image->debug != MagickFalse)
806 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
807 assert(name != (const char *) NULL);
808 if ((datum == (const void *) NULL) || (length == 0))
814 Delete image profile(s).
816 ResetImageProfileIterator(image);
817 for (next=GetNextImageProfile(image); next != (const char *) NULL; )
819 if (IsOptionMember(next,name) != MagickFalse)
821 (void) DeleteImageProfile(image,next);
822 ResetImageProfileIterator(image);
824 next=GetNextImageProfile(image);
829 Add a ICC, IPTC, or generic profile to the image.
832 profile=AcquireStringInfo((size_t) length);
833 SetStringInfoDatum(profile,(unsigned char *) datum);
834 if ((LocaleCompare(name,"icc") != 0) && (LocaleCompare(name,"icm") != 0))
835 status=SetImageProfile(image,name,profile,exception);
841 icc_profile=GetImageProfile(image,"icc");
842 if ((icc_profile != (const StringInfo *) NULL) &&
843 (CompareStringInfo(icc_profile,profile) == 0))
848 value=GetImageProperty(image,"exif:ColorSpace",exception);
850 if (LocaleCompare(value,"1") != 0)
851 (void) SetsRGBImageProfile(image,exception);
852 value=GetImageProperty(image,"exif:InteroperabilityIndex",exception);
853 if (LocaleCompare(value,"R98.") != 0)
854 (void) SetsRGBImageProfile(image,exception);
856 value=GetImageProperty(image,"exif:InteroperabilityIndex",exception);
857 if (LocaleCompare(value,"R03.") != 0)
858 (void) SetAdobeRGB1998ImageProfile(image,exception);
860 icc_profile=GetImageProfile(image,"icc");
862 if ((icc_profile != (const StringInfo *) NULL) &&
863 (CompareStringInfo(icc_profile,profile) == 0))
865 profile=DestroyStringInfo(profile);
868 #if !defined(MAGICKCORE_LCMS_DELEGATE)
869 (void) ThrowMagickException(exception,GetMagickModule(),
870 MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn",
871 "'%s' (LCMS)",image->filename);
881 Transform pixel colors as defined by the color profiles.
883 cmsSetLogErrorHandler(CMSExceptionHandler);
884 cms_exception.image=image;
885 cms_exception.exception=exception;
886 (void) cms_exception;
887 source_profile=cmsOpenProfileFromMemTHR((cmsContext) &cms_exception,
888 GetStringInfoDatum(profile),(cmsUInt32Number)
889 GetStringInfoLength(profile));
890 if (source_profile == (cmsHPROFILE) NULL)
891 ThrowBinaryException(ResourceLimitError,
892 "ColorspaceColorProfileMismatch",name);
893 if ((cmsGetDeviceClass(source_profile) != cmsSigLinkClass) &&
894 (icc_profile == (StringInfo *) NULL))
895 status=SetImageProfile(image,name,profile,exception);
905 cmsColorSpaceSignature
936 **restrict source_pixels,
937 **restrict target_pixels;
939 target_profile=(cmsHPROFILE) NULL;
940 if (icc_profile != (StringInfo *) NULL)
942 target_profile=source_profile;
943 source_profile=cmsOpenProfileFromMemTHR((cmsContext)
944 &cms_exception,GetStringInfoDatum(icc_profile),
945 (cmsUInt32Number) GetStringInfoLength(icc_profile));
946 if (source_profile == (cmsHPROFILE) NULL)
947 ThrowProfileException(ResourceLimitError,
948 "ColorspaceColorProfileMismatch",name);
950 switch (cmsGetColorSpace(source_profile))
954 source_colorspace=CMYKColorspace;
955 source_type=(cmsUInt32Number) TYPE_CMYK_16;
961 source_colorspace=GRAYColorspace;
962 source_type=(cmsUInt32Number) TYPE_GRAY_16;
968 source_colorspace=LabColorspace;
969 source_type=(cmsUInt32Number) TYPE_Lab_16;
975 source_colorspace=YUVColorspace;
976 source_type=(cmsUInt32Number) TYPE_YUV_16;
982 source_colorspace=sRGBColorspace;
983 source_type=(cmsUInt32Number) TYPE_RGB_16;
989 source_colorspace=XYZColorspace;
990 source_type=(cmsUInt32Number) TYPE_XYZ_16;
994 case cmsSigYCbCrData:
996 source_colorspace=YCbCrColorspace;
997 source_type=(cmsUInt32Number) TYPE_YCbCr_16;
1003 source_colorspace=UndefinedColorspace;
1004 source_type=(cmsUInt32Number) TYPE_RGB_16;
1009 signature=cmsGetPCS(source_profile);
1010 if (target_profile != (cmsHPROFILE) NULL)
1011 signature=cmsGetColorSpace(target_profile);
1014 case cmsSigCmykData:
1016 target_colorspace=CMYKColorspace;
1017 target_type=(cmsUInt32Number) TYPE_CMYK_16;
1023 target_colorspace=LabColorspace;
1024 target_type=(cmsUInt32Number) TYPE_Lab_16;
1028 case cmsSigGrayData:
1030 target_colorspace=GRAYColorspace;
1031 target_type=(cmsUInt32Number) TYPE_GRAY_16;
1037 target_colorspace=YUVColorspace;
1038 target_type=(cmsUInt32Number) TYPE_YUV_16;
1044 target_colorspace=sRGBColorspace;
1045 target_type=(cmsUInt32Number) TYPE_RGB_16;
1051 target_colorspace=XYZColorspace;
1052 target_type=(cmsUInt32Number) TYPE_XYZ_16;
1056 case cmsSigYCbCrData:
1058 target_colorspace=YCbCrColorspace;
1059 target_type=(cmsUInt32Number) TYPE_YCbCr_16;
1065 target_colorspace=UndefinedColorspace;
1066 target_type=(cmsUInt32Number) TYPE_RGB_16;
1071 if ((source_colorspace == UndefinedColorspace) ||
1072 (target_colorspace == UndefinedColorspace))
1073 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1075 if ((source_colorspace == GRAYColorspace) &&
1076 (SetImageGray(image,exception) == MagickFalse))
1077 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1079 if ((source_colorspace == CMYKColorspace) &&
1080 (image->colorspace != CMYKColorspace))
1081 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1083 if ((source_colorspace == XYZColorspace) &&
1084 (image->colorspace != XYZColorspace))
1085 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1087 if ((source_colorspace == YCbCrColorspace) &&
1088 (image->colorspace != YCbCrColorspace))
1089 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1091 if ((source_colorspace != CMYKColorspace) &&
1092 (source_colorspace != LabColorspace) &&
1093 (source_colorspace != XYZColorspace) &&
1094 (source_colorspace != YCbCrColorspace) &&
1095 (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse))
1096 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1098 switch (image->rendering_intent)
1100 case AbsoluteIntent: intent=INTENT_ABSOLUTE_COLORIMETRIC; break;
1101 case PerceptualIntent: intent=INTENT_PERCEPTUAL; break;
1102 case RelativeIntent: intent=INTENT_RELATIVE_COLORIMETRIC; break;
1103 case SaturationIntent: intent=INTENT_SATURATION; break;
1104 default: intent=INTENT_PERCEPTUAL; break;
1106 flags=cmsFLAGS_HIGHRESPRECALC;
1107 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1108 if (image->black_point_compensation != MagickFalse)
1109 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1111 transform=AcquireTransformThreadSet(image,source_profile,
1112 source_type,target_profile,target_type,intent,flags);
1113 if (transform == (cmsHTRANSFORM *) NULL)
1114 ThrowProfileException(ImageError,"UnableToCreateColorTransform",
1117 Transform image as dictated by the source & target image profiles.
1119 source_pixels=AcquirePixelThreadSet(image->columns,source_channels);
1120 target_pixels=AcquirePixelThreadSet(image->columns,target_channels);
1121 if ((source_pixels == (unsigned short **) NULL) ||
1122 (target_pixels == (unsigned short **) NULL))
1124 transform=DestroyTransformThreadSet(transform);
1125 ThrowProfileException(ResourceLimitError,
1126 "MemoryAllocationFailed",image->filename);
1128 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1130 target_pixels=DestroyPixelThreadSet(target_pixels);
1131 source_pixels=DestroyPixelThreadSet(source_pixels);
1132 transform=DestroyTransformThreadSet(transform);
1133 if (source_profile != (cmsHPROFILE) NULL)
1134 (void) cmsCloseProfile(source_profile);
1135 if (target_profile != (cmsHPROFILE) NULL)
1136 (void) cmsCloseProfile(target_profile);
1137 return(MagickFalse);
1139 if (target_colorspace == CMYKColorspace)
1140 (void) SetImageColorspace(image,target_colorspace,exception);
1143 image_view=AcquireAuthenticCacheView(image,exception);
1144 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1145 #pragma omp parallel for schedule(static,4) shared(status) \
1146 magick_threads(image,image,image->rows,1)
1148 for (y=0; y < (ssize_t) image->rows; y++)
1151 id = GetOpenMPThreadId();
1162 register unsigned short
1165 if (status == MagickFalse)
1167 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1169 if (q == (Quantum *) NULL)
1174 p=source_pixels[id];
1175 for (x=0; x < (ssize_t) image->columns; x++)
1177 *p++=ScaleQuantumToShort(GetPixelRed(image,q));
1178 if (source_channels > 1)
1180 *p++=ScaleQuantumToShort(GetPixelGreen(image,q));
1181 *p++=ScaleQuantumToShort(GetPixelBlue(image,q));
1183 if (source_channels > 3)
1184 *p++=ScaleQuantumToShort(GetPixelBlack(image,q));
1185 q+=GetPixelChannels(image);
1187 cmsDoTransform(transform[id],source_pixels[id],target_pixels[id],
1188 (unsigned int) image->columns);
1189 p=target_pixels[id];
1190 q-=GetPixelChannels(image)*image->columns;
1191 for (x=0; x < (ssize_t) image->columns; x++)
1193 if (target_channels == 1)
1194 SetPixelGray(image,ScaleShortToQuantum(*p),q);
1196 SetPixelRed(image,ScaleShortToQuantum(*p),q);
1198 if (target_channels > 1)
1200 SetPixelGreen(image,ScaleShortToQuantum(*p),q);
1202 SetPixelBlue(image,ScaleShortToQuantum(*p),q);
1205 if (target_channels > 3)
1207 SetPixelBlack(image,ScaleShortToQuantum(*p),q);
1210 q+=GetPixelChannels(image);
1212 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1213 if (sync == MagickFalse)
1215 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1220 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1221 #pragma omp critical (MagickCore_ProfileImage)
1223 proceed=SetImageProgress(image,ProfileImageTag,progress++,
1225 if (proceed == MagickFalse)
1229 image_view=DestroyCacheView(image_view);
1230 (void) SetImageColorspace(image,target_colorspace,exception);
1235 image->type=image->alpha_trait == UndefinedPixelTrait ?
1236 TrueColorType : TrueColorAlphaType;
1239 case cmsSigCmykData:
1241 image->type=image->alpha_trait == UndefinedPixelTrait ?
1242 ColorSeparationType : ColorSeparationAlphaType;
1245 case cmsSigGrayData:
1247 image->type=image->alpha_trait == UndefinedPixelTrait ?
1248 GrayscaleType : GrayscaleAlphaType;
1254 target_pixels=DestroyPixelThreadSet(target_pixels);
1255 source_pixels=DestroyPixelThreadSet(source_pixels);
1256 transform=DestroyTransformThreadSet(transform);
1257 if (cmsGetDeviceClass(source_profile) != cmsSigLinkClass)
1258 status=SetImageProfile(image,name,profile,exception);
1259 if (target_profile != (cmsHPROFILE) NULL)
1260 (void) cmsCloseProfile(target_profile);
1262 (void) cmsCloseProfile(source_profile);
1266 profile=DestroyStringInfo(profile);
1271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1275 % R e m o v e I m a g e P r o f i l e %
1279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1281 % RemoveImageProfile() removes a named profile from the image and returns its
1284 % The format of the RemoveImageProfile method is:
1286 % void *RemoveImageProfile(Image *image,const char *name)
1288 % A description of each parameter follows:
1290 % o image: the image.
1292 % o name: the profile name.
1295 MagickExport StringInfo *RemoveImageProfile(Image *image,const char *name)
1300 assert(image != (Image *) NULL);
1301 assert(image->signature == MagickSignature);
1302 if (image->debug != MagickFalse)
1303 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1304 if (image->profiles == (SplayTreeInfo *) NULL)
1305 return((StringInfo *) NULL);
1306 WriteTo8BimProfile(image,name,(StringInfo *) NULL);
1307 profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
1308 image->profiles,name);
1313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1317 % R e s e t P r o f i l e I t e r a t o r %
1321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1323 % ResetImageProfileIterator() resets the image profile iterator. Use it in
1324 % conjunction with GetNextImageProfile() to iterate over all the profiles
1325 % associated with an image.
1327 % The format of the ResetImageProfileIterator method is:
1329 % ResetImageProfileIterator(Image *image)
1331 % A description of each parameter follows:
1333 % o image: the image.
1336 MagickExport void ResetImageProfileIterator(const Image *image)
1338 assert(image != (Image *) NULL);
1339 assert(image->signature == MagickSignature);
1340 if (image->debug != MagickFalse)
1341 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1342 if (image->profiles == (SplayTreeInfo *) NULL)
1344 ResetSplayTreeIterator((SplayTreeInfo *) image->profiles);
1348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1352 % S e t I m a g e P r o f i l e %
1356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1358 % SetImageProfile() adds a named profile to the image. If a profile with the
1359 % same name already exists, it is replaced. This method differs from the
1360 % ProfileImage() method in that it does not apply CMS color profiles.
1362 % The format of the SetImageProfile method is:
1364 % MagickBooleanType SetImageProfile(Image *image,const char *name,
1365 % const StringInfo *profile)
1367 % A description of each parameter follows:
1369 % o image: the image.
1371 % o name: the profile name, for example icc, exif, and 8bim (8bim is the
1372 % Photoshop wrapper for iptc profiles).
1374 % o profile: A StringInfo structure that contains the named profile.
1378 static void *DestroyProfile(void *profile)
1380 return((void *) DestroyStringInfo((StringInfo *) profile));
1383 static inline const unsigned char *ReadResourceByte(const unsigned char *p,
1384 unsigned char *quantum)
1390 static inline const unsigned char *ReadResourceLong(const unsigned char *p,
1391 unsigned int *quantum)
1393 *quantum=(size_t) (*p++ << 24);
1394 *quantum|=(size_t) (*p++ << 16);
1395 *quantum|=(size_t) (*p++ << 8);
1396 *quantum|=(size_t) (*p++ << 0);
1400 static inline const unsigned char *ReadResourceShort(const unsigned char *p,
1401 unsigned short *quantum)
1403 *quantum=(unsigned short) (*p++ << 8);
1404 *quantum|=(unsigned short) (*p++ << 0);
1406 }static inline void WriteResourceLong(unsigned char *p,
1407 const unsigned int quantum)
1412 buffer[0]=(unsigned char) (quantum >> 24);
1413 buffer[1]=(unsigned char) (quantum >> 16);
1414 buffer[2]=(unsigned char) (quantum >> 8);
1415 buffer[3]=(unsigned char) quantum;
1416 (void) CopyMagickMemory(p,buffer,4);
1419 static void WriteTo8BimProfile(Image *image,const char *name,
1420 const StringInfo *profile)
1426 register const unsigned char
1448 if (LocaleCompare(name,"icc") == 0)
1451 if (LocaleCompare(name,"iptc") == 0)
1454 if (LocaleCompare(name,"xmp") == 0)
1458 profile_8bim=(StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
1459 image->profiles,"8bim");
1460 if (profile_8bim == (StringInfo *) NULL)
1462 datum=GetStringInfoDatum(profile_8bim);
1463 length=GetStringInfoLength(profile_8bim);
1464 for (p=datum; p < (datum+length-16); )
1467 if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1470 p=ReadResourceShort(p,&id);
1471 p=ReadResourceByte(p,&length_byte);
1473 if (((length_byte+1) & 0x01) != 0)
1475 if (p > (datum+length-4))
1477 p=ReadResourceLong(p,&value);
1478 count=(ssize_t) value;
1479 if ((count & 0x01) != 0)
1481 if ((p > (datum+length-count)) || (count > (ssize_t) length))
1483 if (id != profile_id)
1498 extent=(datum+length)-(p+count);
1499 if (profile == (StringInfo *) NULL)
1502 extract_profile=AcquireStringInfo(offset+extent);
1503 (void) CopyMagickMemory(extract_profile->datum,datum,offset);
1508 extract_count=profile->length;
1509 if ((extract_count & 0x01) != 0)
1511 extract_profile=AcquireStringInfo(offset+extract_count+extent);
1512 (void) CopyMagickMemory(extract_profile->datum,datum,offset-4);
1513 WriteResourceLong(extract_profile->datum+offset-4,
1514 (unsigned int)profile->length);
1515 (void) CopyMagickMemory(extract_profile->datum+offset,
1516 profile->datum,profile->length);
1518 (void) CopyMagickMemory(extract_profile->datum+offset+extract_count,
1520 (void) AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1521 ConstantString("8bim"),CloneStringInfo(extract_profile));
1522 extract_profile=DestroyStringInfo(extract_profile);
1528 static void GetProfilesFromResourceBlock(Image *image,
1529 const StringInfo *resource_block,ExceptionInfo *exception)
1534 register const unsigned char
1555 datum=GetStringInfoDatum(resource_block);
1556 length=GetStringInfoLength(resource_block);
1557 for (p=datum; p < (datum+length-16); )
1559 if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1562 p=ReadResourceShort(p,&id);
1563 p=ReadResourceByte(p,&length_byte);
1565 if (((length_byte+1) & 0x01) != 0)
1567 if (p > (datum+length-4))
1569 p=ReadResourceLong(p,&value);
1570 count=(ssize_t) value;
1571 if ((p > (datum+length-count)) || (count > (ssize_t) length))
1586 p=ReadResourceLong(p,&resolution);
1587 image->resolution.x=((double) resolution)/65536.0;
1588 p=ReadResourceShort(p,&units)+2;
1589 p=ReadResourceLong(p,&resolution)+4;
1590 image->resolution.y=((double) resolution)/65536.0;
1592 Values are always stored as pixels per inch.
1594 if ((ResolutionType) units != PixelsPerCentimeterResolution)
1595 image->units=PixelsPerInchResolution;
1598 image->units=PixelsPerCentimeterResolution;
1599 image->resolution.x/=2.54;
1600 image->resolution.y/=2.54;
1609 profile=AcquireStringInfo(count);
1610 SetStringInfoDatum(profile,p);
1611 (void) SetImageProfileInternal(image,"iptc",profile,MagickTrue,
1613 profile=DestroyStringInfo(profile);
1630 profile=AcquireStringInfo(count);
1631 SetStringInfoDatum(profile,p);
1632 (void) SetImageProfileInternal(image,"icc",profile,MagickTrue,
1634 profile=DestroyStringInfo(profile);
1643 profile=AcquireStringInfo(count);
1644 SetStringInfoDatum(profile,p);
1645 (void) SetImageProfileInternal(image,"exif",profile,MagickTrue,
1647 profile=DestroyStringInfo(profile);
1656 profile=AcquireStringInfo(count);
1657 SetStringInfoDatum(profile,p);
1658 (void) SetImageProfileInternal(image,"xmp",profile,MagickTrue,
1660 profile=DestroyStringInfo(profile);
1670 if ((count & 0x01) != 0)
1675 static MagickBooleanType SetImageProfileInternal(Image *image,const char *name,
1676 const StringInfo *profile,const MagickBooleanType recursive,
1677 ExceptionInfo *exception)
1680 key[MagickPathExtent],
1681 property[MagickPathExtent];
1686 assert(image != (Image *) NULL);
1687 assert(image->signature == MagickSignature);
1688 if (image->debug != MagickFalse)
1689 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1690 if (image->profiles == (SplayTreeInfo *) NULL)
1691 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
1693 (void) CopyMagickString(key,name,MagickPathExtent);
1695 status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1696 ConstantString(key),CloneStringInfo(profile));
1697 if (status != MagickFalse)
1699 if (LocaleCompare(name,"8bim") == 0)
1700 GetProfilesFromResourceBlock(image,profile,exception);
1701 else if (recursive == MagickFalse)
1702 WriteTo8BimProfile(image,name,profile);
1705 Inject profile into image properties.
1707 (void) FormatLocaleString(property,MagickPathExtent,"%s:*",name);
1708 (void) GetImageProperty(image,property,exception);
1712 MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name,
1713 const StringInfo *profile,ExceptionInfo *exception)
1715 return(SetImageProfileInternal(image,name,profile,MagickFalse,exception));
1719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1723 % S y n c I m a g e P r o f i l e s %
1727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1729 % SyncImageProfiles() synchronizes image properties with the image profiles.
1730 % Currently we only support updating the EXIF resolution and orientation.
1732 % The format of the SyncImageProfiles method is:
1734 % MagickBooleanType SyncImageProfiles(Image *image)
1736 % A description of each parameter follows:
1738 % o image: the image.
1742 static inline int ReadProfileByte(unsigned char **p,size_t *length)
1754 static inline unsigned short ReadProfileShort(const EndianType endian,
1755 unsigned char *buffer)
1760 if (endian == LSBEndian)
1762 value=(unsigned short) ((buffer[1] << 8) | buffer[0]);
1763 return((unsigned short) (value & 0xffff));
1765 value=(unsigned short) ((((unsigned char *) buffer)[0] << 8) |
1766 ((unsigned char *) buffer)[1]);
1767 return((unsigned short) (value & 0xffff));
1770 static inline unsigned int ReadProfileLong(const EndianType endian,
1771 unsigned char *buffer)
1776 if (endian == LSBEndian)
1778 value=(unsigned int) ((buffer[3] << 24) | (buffer[2] << 16) |
1779 (buffer[1] << 8 ) | (buffer[0]));
1780 return((unsigned int) (value & 0xffffffff));
1782 value=(unsigned int) ((buffer[0] << 24) | (buffer[1] << 16) |
1783 (buffer[2] << 8) | buffer[3]);
1784 return((unsigned int) (value & 0xffffffff));
1787 static inline unsigned int ReadProfileMSBLong(unsigned char **p,size_t *length)
1794 value=ReadProfileLong(MSBEndian,*p);
1800 static inline unsigned short ReadProfileMSBShort(unsigned char **p,
1808 value=ReadProfileShort(MSBEndian,*p);
1814 static inline void WriteProfileLong(const EndianType endian,
1815 const size_t value,unsigned char *p)
1820 if (endian == LSBEndian)
1822 buffer[0]=(unsigned char) value;
1823 buffer[1]=(unsigned char) (value >> 8);
1824 buffer[2]=(unsigned char) (value >> 16);
1825 buffer[3]=(unsigned char) (value >> 24);
1826 (void) CopyMagickMemory(p,buffer,4);
1829 buffer[0]=(unsigned char) (value >> 24);
1830 buffer[1]=(unsigned char) (value >> 16);
1831 buffer[2]=(unsigned char) (value >> 8);
1832 buffer[3]=(unsigned char) value;
1833 (void) CopyMagickMemory(p,buffer,4);
1836 static void WriteProfileShort(const EndianType endian,
1837 const unsigned short value,unsigned char *p)
1842 if (endian == LSBEndian)
1844 buffer[0]=(unsigned char) value;
1845 buffer[1]=(unsigned char) (value >> 8);
1846 (void) CopyMagickMemory(p,buffer,2);
1849 buffer[0]=(unsigned char) (value >> 8);
1850 buffer[1]=(unsigned char) value;
1851 (void) CopyMagickMemory(p,buffer,2);
1854 static MagickBooleanType Sync8BimProfile(Image *image,StringInfo *profile)
1868 length=GetStringInfoLength(profile);
1869 p=GetStringInfoDatum(profile);
1872 if (ReadProfileByte(&p,&length) != 0x38)
1874 if (ReadProfileByte(&p,&length) != 0x42)
1876 if (ReadProfileByte(&p,&length) != 0x49)
1878 if (ReadProfileByte(&p,&length) != 0x4D)
1881 return(MagickFalse);
1882 id=ReadProfileMSBShort(&p,&length);
1883 count=(ssize_t) ReadProfileByte(&p,&length);
1884 if (count > (ssize_t) length)
1885 return(MagickFalse);
1887 if ((*p & 0x01) == 0)
1888 (void) ReadProfileByte(&p,&length);
1889 count=(ssize_t) ReadProfileMSBLong(&p,&length);
1890 if (count > (ssize_t) length)
1891 return(MagickFalse);
1892 if ((id == 0x3ED) && (count == 16))
1894 if (image->units == PixelsPerCentimeterResolution)
1895 WriteProfileLong(MSBEndian, (unsigned int) (image->resolution.x*2.54*
1898 WriteProfileLong(MSBEndian, (unsigned int) (image->resolution.x*
1900 WriteProfileShort(MSBEndian,(unsigned short) image->units,p+4);
1901 if (image->units == PixelsPerCentimeterResolution)
1902 WriteProfileLong(MSBEndian, (unsigned int) (image->resolution.y*2.54*
1905 WriteProfileLong(MSBEndian, (unsigned int) (image->resolution.y*
1907 WriteProfileShort(MSBEndian,(unsigned short) image->units,p+12);
1915 MagickBooleanType SyncExifProfile(Image *image,StringInfo *profile)
1917 #define MaxDirectoryStack 16
1918 #define EXIF_DELIMITER "\n"
1919 #define EXIF_NUM_FORMATS 12
1920 #define TAG_EXIF_OFFSET 0x8769
1921 #define TAG_INTEROP_OFFSET 0xa005
1923 typedef struct _DirectoryInfo
1933 directory_stack[MaxDirectoryStack];
1949 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
1956 Set EXIF resolution tag.
1958 length=GetStringInfoLength(profile);
1959 exif=GetStringInfoDatum(profile);
1961 return(MagickFalse);
1962 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
1963 if ((id != 0x4949) && (id != 0x4D4D))
1967 if (ReadProfileByte(&exif,&length) != 0x45)
1969 if (ReadProfileByte(&exif,&length) != 0x78)
1971 if (ReadProfileByte(&exif,&length) != 0x69)
1973 if (ReadProfileByte(&exif,&length) != 0x66)
1975 if (ReadProfileByte(&exif,&length) != 0x00)
1977 if (ReadProfileByte(&exif,&length) != 0x00)
1982 return(MagickFalse);
1983 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
1992 return(MagickFalse);
1993 if (ReadProfileShort(endian,exif+2) != 0x002a)
1994 return(MagickFalse);
1996 This the offset to the first IFD.
1998 offset=(ssize_t) ((int) ReadProfileLong(endian,exif+4));
1999 if ((offset < 0) || (size_t) offset >= length)
2000 return(MagickFalse);
2001 directory=exif+offset;
2009 directory=directory_stack[level].directory;
2010 entry=directory_stack[level].entry;
2012 if ((directory < exif) || (directory > (exif+length-2)))
2015 Determine how many entries there are in the current IFD.
2017 number_entries=ReadProfileShort(endian,directory);
2018 for ( ; entry < number_entries; entry++)
2023 register unsigned char
2034 q=(unsigned char *) (directory+2+(12*entry));
2035 tag_value=(ssize_t) ReadProfileShort(endian,q);
2036 format=(ssize_t) ReadProfileShort(endian,q+2);
2037 if ((format-1) >= EXIF_NUM_FORMATS)
2039 components=(ssize_t) ((int) ReadProfileLong(endian,q+4));
2040 number_bytes=(size_t) components*format_bytes[format];
2041 if ((ssize_t) number_bytes < components)
2042 break; /* prevent overflow */
2043 if (number_bytes <= 4)
2051 The directory entry contains an offset.
2053 offset=(ssize_t) ((int) ReadProfileLong(endian,q+8));
2054 if ((size_t) (offset+number_bytes) > length)
2056 if (~length < number_bytes)
2057 continue; /* prevent overflow */
2058 p=(unsigned char *) (exif+offset);
2064 (void) WriteProfileLong(endian,(size_t) (image->resolution.x+0.5),p);
2065 (void) WriteProfileLong(endian,1UL,p+4);
2070 (void) WriteProfileLong(endian,(size_t) (image->resolution.y+0.5),p);
2071 (void) WriteProfileLong(endian,1UL,p+4);
2076 if (number_bytes == 4)
2078 (void) WriteProfileLong(endian,(size_t) image->orientation,p);
2081 (void) WriteProfileShort(endian,(unsigned short) image->orientation,
2087 if (number_bytes == 4)
2089 (void) WriteProfileLong(endian,(size_t) (image->units+1),p);
2092 (void) WriteProfileShort(endian,(unsigned short) (image->units+1),p);
2098 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2103 offset=(ssize_t) ((int) ReadProfileLong(endian,p));
2104 if (((size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2106 directory_stack[level].directory=directory;
2108 directory_stack[level].entry=entry;
2110 directory_stack[level].directory=exif+offset;
2111 directory_stack[level].entry=0;
2113 if ((directory+2+(12*number_entries)) > (exif+length))
2115 offset=(ssize_t) ((int) ReadProfileLong(endian,directory+2+(12*
2117 if ((offset != 0) && ((size_t) offset < length) &&
2118 (level < (MaxDirectoryStack-2)))
2120 directory_stack[level].directory=exif+offset;
2121 directory_stack[level].entry=0;
2128 } while (level > 0);
2132 MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
2141 profile=(StringInfo *) GetImageProfile(image,"8BIM");
2142 if (profile != (StringInfo *) NULL)
2143 if (Sync8BimProfile(image,profile) == MagickFalse)
2145 profile=(StringInfo *) GetImageProfile(image,"EXIF");
2146 if (profile != (StringInfo *) NULL)
2147 if (SyncExifProfile(image,profile) == MagickFalse)