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-2019 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 % https://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/image.h"
51 #include "MagickCore/linked-list.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>
78 #if defined(MAGICKCORE_XML_DELEGATE)
79 # if defined(MAGICKCORE_WINDOWS_SUPPORT)
80 # if !defined(__MINGW32__)
81 # include <win32config.h>
84 # include <libxml/parser.h>
85 # include <libxml/tree.h>
92 #if !defined(MAGICKCORE_HDRI_SUPPORT)
93 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
95 #define LCMSScaleSource(pixel) ScaleQuantumToShort(pixel)
96 #define LCMSScaleTarget(pixel) ScaleShortToQuantum(pixel)
97 typedef unsigned short
99 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
101 #define LCMSScaleSource(pixel) (pixel)
102 #define LCMSScaleTarget(pixel) (pixel)
103 typedef unsigned short
108 #if defined(LCMSHDRI)
109 #define LCMSScaleSource(pixel) (source_scale*QuantumScale*(pixel))
110 #define LCMSScaleTarget(pixel) ClampToQuantum(target_scale*QuantumRange*(pixel))
118 static MagickBooleanType
119 SetImageProfileInternal(Image *,const char *,const StringInfo *,
120 const MagickBooleanType,ExceptionInfo *);
123 WriteTo8BimProfile(Image *,const char*,const StringInfo *);
143 typedef struct _CMSExceptionInfo
153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
157 % C l o n e I m a g e P r o f i l e s %
161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
163 % CloneImageProfiles() clones one or more image profiles.
165 % The format of the CloneImageProfiles method is:
167 % MagickBooleanType CloneImageProfiles(Image *image,
168 % const Image *clone_image)
170 % A description of each parameter follows:
172 % o image: the image.
174 % o clone_image: the clone image.
177 MagickExport MagickBooleanType CloneImageProfiles(Image *image,
178 const Image *clone_image)
180 assert(image != (Image *) NULL);
181 assert(image->signature == MagickCoreSignature);
182 if (image->debug != MagickFalse)
183 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
184 assert(clone_image != (const Image *) NULL);
185 assert(clone_image->signature == MagickCoreSignature);
186 if (clone_image->profiles != (void *) NULL)
188 if (image->profiles != (void *) NULL)
189 DestroyImageProfiles(image);
190 image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
191 (void *(*)(void *)) ConstantString,(void *(*)(void *)) CloneStringInfo);
197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
201 % D e l e t e I m a g e P r o f i l e %
205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
207 % DeleteImageProfile() deletes a profile from the image by its name.
209 % The format of the DeleteImageProfile method is:
211 % MagickBooleanTyupe DeleteImageProfile(Image *image,const char *name)
213 % A description of each parameter follows:
215 % o image: the image.
217 % o name: the profile name.
220 MagickExport MagickBooleanType DeleteImageProfile(Image *image,const char *name)
222 assert(image != (Image *) NULL);
223 assert(image->signature == MagickCoreSignature);
224 if (image->debug != MagickFalse)
225 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
226 if (image->profiles == (SplayTreeInfo *) NULL)
228 WriteTo8BimProfile(image,name,(StringInfo *) NULL);
229 return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->profiles,name));
233 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
237 % D e s t r o y I m a g e P r o f i l e s %
241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
243 % DestroyImageProfiles() releases memory associated with an image profile map.
245 % The format of the DestroyProfiles method is:
247 % void DestroyImageProfiles(Image *image)
249 % A description of each parameter follows:
251 % o image: the image.
254 MagickExport void DestroyImageProfiles(Image *image)
256 if (image->profiles != (SplayTreeInfo *) NULL)
257 image->profiles=DestroySplayTree((SplayTreeInfo *) image->profiles);
261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
265 % G e t I m a g e P r o f i l e %
269 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271 % GetImageProfile() gets a profile associated with an image by name.
273 % The format of the GetImageProfile method is:
275 % const StringInfo *GetImageProfile(const Image *image,const char *name)
277 % A description of each parameter follows:
279 % o image: the image.
281 % o name: the profile name.
284 MagickExport const StringInfo *GetImageProfile(const Image *image,
290 assert(image != (Image *) NULL);
291 assert(image->signature == MagickCoreSignature);
292 if (image->debug != MagickFalse)
293 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
294 if (image->profiles == (SplayTreeInfo *) NULL)
295 return((StringInfo *) NULL);
296 profile=(const StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
297 image->profiles,name);
302 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
306 % G e t N e x t I m a g e P r o f i l e %
310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
312 % GetNextImageProfile() gets the next profile name for an image.
314 % The format of the GetNextImageProfile method is:
316 % char *GetNextImageProfile(const Image *image)
318 % A description of each parameter follows:
320 % o hash_info: the hash info.
323 MagickExport char *GetNextImageProfile(const Image *image)
325 assert(image != (Image *) NULL);
326 assert(image->signature == MagickCoreSignature);
327 if (image->debug != MagickFalse)
328 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
329 if (image->profiles == (SplayTreeInfo *) NULL)
330 return((char *) NULL);
331 return((char *) GetNextKeyInSplayTree((SplayTreeInfo *) image->profiles));
335 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
339 % P r o f i l e I m a g e %
343 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
345 % ProfileImage() associates, applies, or removes an ICM, IPTC, or generic
346 % profile with / to / from an image. If the profile is NULL, it is removed
347 % from the image otherwise added or applied. Use a name of '*' and a profile
348 % of NULL to remove all profiles from the image.
350 % ICC and ICM profiles are handled as follows: If the image does not have
351 % an associated color profile, the one you provide is associated with the
352 % image and the image pixels are not transformed. Otherwise, the colorspace
353 % transform defined by the existing and new profile are applied to the image
354 % pixels and the new profile is associated with the image.
356 % The format of the ProfileImage method is:
358 % MagickBooleanType ProfileImage(Image *image,const char *name,
359 % const void *datum,const size_t length,const MagickBooleanType clone)
361 % A description of each parameter follows:
363 % o image: the image.
365 % o name: Name of profile to add or remove: ICC, IPTC, or generic profile.
367 % o datum: the profile data.
369 % o length: the length of the profile.
371 % o clone: should be MagickFalse.
375 #if defined(MAGICKCORE_LCMS_DELEGATE)
376 static LCMSType **DestroyPixelThreadSet(LCMSType **pixels)
381 if (pixels != (LCMSType **) NULL)
382 return((LCMSType **) NULL);
383 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
384 if (pixels[i] != (LCMSType *) NULL)
385 pixels[i]=(LCMSType *) RelinquishMagickMemory(pixels[i]);
386 pixels=(LCMSType **) RelinquishMagickMemory(pixels);
390 static LCMSType **AcquirePixelThreadSet(const size_t columns,
391 const size_t channels)
402 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
403 pixels=(LCMSType **) AcquireQuantumMemory(number_threads,sizeof(*pixels));
404 if (pixels == (LCMSType **) NULL)
405 return((LCMSType **) NULL);
406 (void) memset(pixels,0,number_threads*sizeof(*pixels));
407 for (i=0; i < (ssize_t) number_threads; i++)
409 pixels[i]=(LCMSType *) AcquireQuantumMemory(columns,channels*
411 if (pixels[i] == (LCMSType *) NULL)
412 return(DestroyPixelThreadSet(pixels));
417 static cmsHTRANSFORM *DestroyTransformThreadSet(cmsHTRANSFORM *transform)
422 assert(transform != (cmsHTRANSFORM *) NULL);
423 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
424 if (transform[i] != (cmsHTRANSFORM) NULL)
425 cmsDeleteTransform(transform[i]);
426 transform=(cmsHTRANSFORM *) RelinquishMagickMemory(transform);
430 static cmsHTRANSFORM *AcquireTransformThreadSet(
431 const cmsHPROFILE source_profile,const cmsUInt32Number source_type,
432 const cmsHPROFILE target_profile,const cmsUInt32Number target_type,
433 const int intent,const cmsUInt32Number flags,
434 CMSExceptionInfo *cms_exception)
445 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
446 transform=(cmsHTRANSFORM *) AcquireQuantumMemory(number_threads,
448 if (transform == (cmsHTRANSFORM *) NULL)
449 return((cmsHTRANSFORM *) NULL);
450 (void) memset(transform,0,number_threads*sizeof(*transform));
451 for (i=0; i < (ssize_t) number_threads; i++)
453 transform[i]=cmsCreateTransformTHR((cmsContext) cms_exception,
454 source_profile,source_type,target_profile,target_type,intent,flags);
455 if (transform[i] == (cmsHTRANSFORM) NULL)
456 return(DestroyTransformThreadSet(transform));
462 #if defined(MAGICKCORE_LCMS_DELEGATE)
463 static void CMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
475 cms_exception=(CMSExceptionInfo *) context;
476 if (cms_exception == (CMSExceptionInfo *) NULL)
478 exception=cms_exception->exception;
479 if (exception == (ExceptionInfo *) NULL)
481 image=cms_exception->image;
482 if (image == (Image *) NULL)
484 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
485 "UnableToTransformColorspace","`%s'","unknown context");
488 if (image->debug != MagickFalse)
489 (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%u, %s",
490 severity,message != (char *) NULL ? message : "no message");
491 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
492 "UnableToTransformColorspace","`%s'",image->filename);
496 static MagickBooleanType SetsRGBImageProfile(Image *image,
497 ExceptionInfo *exception)
502 0x00, 0x00, 0x0c, 0x8c, 0x61, 0x72, 0x67, 0x6c, 0x02, 0x20, 0x00, 0x00,
503 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
504 0x07, 0xde, 0x00, 0x01, 0x00, 0x06, 0x00, 0x16, 0x00, 0x0f, 0x00, 0x3a,
505 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
506 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00,
507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
508 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x61, 0x72, 0x67, 0x6c,
509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
513 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x99,
514 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0xec, 0x00, 0x00, 0x00, 0x67,
515 0x64, 0x6d, 0x6e, 0x64, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70,
516 0x64, 0x6d, 0x64, 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88,
517 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x0c,
518 0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x00, 0x67,
519 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x24,
520 0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xe4, 0x00, 0x00, 0x00, 0x14,
521 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x24,
522 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x14,
523 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x14,
524 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x14,
525 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x58, 0x00, 0x00, 0x00, 0x14,
526 0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x6c, 0x00, 0x00, 0x00, 0x14,
527 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
528 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
529 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
530 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
531 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36,
532 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75, 0x69, 0x76,
533 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x77, 0x77,
534 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x31, 0x39,
535 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c,
536 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
537 0x00, 0x3f, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31,
538 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75,
539 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77,
540 0x77, 0x77, 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20,
541 0x31, 0x39, 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66,
542 0x69, 0x6c, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, 0x61,
544 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x72, 0x61, 0x65, 0x6d,
545 0x65, 0x20, 0x57, 0x2e, 0x20, 0x47, 0x69, 0x6c, 0x6c, 0x2e, 0x20, 0x52,
546 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f,
547 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
548 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x4e, 0x6f, 0x20, 0x57,
549 0x61, 0x72, 0x72, 0x61, 0x6e, 0x74, 0x79, 0x2c, 0x20, 0x55, 0x73, 0x65,
550 0x20, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e,
551 0x20, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20,
553 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
554 0x65, 0x63, 0x2e, 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74,
556 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
557 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
562 0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e,
563 0x31, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47,
564 0x42, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61,
565 0x63, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43,
567 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
568 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63,
569 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
570 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572 0x00, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00,
573 0x43, 0x52, 0x54, 0x20, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
575 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
577 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa4, 0x7c,
583 0x00, 0x14, 0x5f, 0x30, 0x00, 0x10, 0xce, 0x02, 0x00, 0x03, 0xed, 0xb2,
584 0x00, 0x04, 0x13, 0x0a, 0x00, 0x03, 0x5c, 0x67, 0x00, 0x00, 0x00, 0x01,
585 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x0a, 0x3d,
586 0x00, 0x50, 0x00, 0x00, 0x00, 0x57, 0x1e, 0xb8, 0x6d, 0x65, 0x61, 0x73,
587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
588 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589 0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x58, 0x59, 0x5a, 0x20,
590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00,
591 0x00, 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa0,
594 0x00, 0x00, 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20,
595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x97, 0x00, 0x00, 0xb7, 0x87,
596 0x00, 0x00, 0x18, 0xd9, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x24, 0x9f, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0xb6, 0xc4,
598 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
599 0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19,
600 0x00, 0x1e, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37,
601 0x00, 0x3b, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54,
602 0x00, 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
603 0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00, 0x90,
604 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9, 0x00, 0xae,
605 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00, 0xc6, 0x00, 0xcb,
606 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0xeb,
607 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01, 0x01, 0x01, 0x07, 0x01, 0x0d,
608 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f, 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32,
609 0x01, 0x38, 0x01, 0x3e, 0x01, 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59,
610 0x01, 0x60, 0x01, 0x67, 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83,
611 0x01, 0x8b, 0x01, 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1,
612 0x01, 0xb9, 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1,
613 0x01, 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
614 0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02, 0x4b,
615 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a, 0x02, 0x84,
616 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02, 0xb6, 0x02, 0xc1,
617 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb, 0x02, 0xf5, 0x03, 0x00,
618 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2d, 0x03, 0x38, 0x03, 0x43,
619 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66, 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a,
620 0x03, 0x96, 0x03, 0xa2, 0x03, 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3,
621 0x03, 0xe0, 0x03, 0xec, 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20,
622 0x04, 0x2d, 0x04, 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71,
623 0x04, 0x7e, 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4,
624 0x04, 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
625 0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05, 0x77,
626 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5, 0x05, 0xd5,
627 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06, 0x27, 0x06, 0x37,
628 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b, 0x06, 0x8c, 0x06, 0x9d,
629 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06, 0xe3, 0x06, 0xf5, 0x07, 0x07,
630 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d, 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74,
631 0x07, 0x86, 0x07, 0x99, 0x07, 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5,
632 0x07, 0xf8, 0x08, 0x0b, 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a,
633 0x08, 0x6e, 0x08, 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2,
634 0x08, 0xe7, 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f,
635 0x09, 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
636 0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a, 0x54,
637 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5, 0x0a, 0xdc,
638 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b, 0x51, 0x0b, 0x69,
639 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8, 0x0b, 0xe1, 0x0b, 0xf9,
640 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c, 0x5c, 0x0c, 0x75, 0x0c, 0x8e,
641 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9, 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26,
642 0x0d, 0x40, 0x0d, 0x5a, 0x0d, 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3,
643 0x0d, 0xde, 0x0d, 0xf8, 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64,
644 0x0e, 0x7f, 0x0e, 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09,
645 0x0f, 0x25, 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3,
646 0x0f, 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
647 0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11, 0x13,
648 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa, 0x11, 0xc9,
649 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12, 0x64, 0x12, 0x84,
650 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03, 0x13, 0x23, 0x13, 0x43,
651 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13, 0xc5, 0x13, 0xe5, 0x14, 0x06,
652 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a, 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce,
653 0x14, 0xf0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b,
654 0x15, 0xbd, 0x15, 0xe0, 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c,
655 0x16, 0x8f, 0x16, 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41,
656 0x17, 0x65, 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b,
657 0x18, 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
658 0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19, 0xdd,
659 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e, 0x1a, 0xc5,
660 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b, 0x8a, 0x1b, 0xb2,
661 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52, 0x1c, 0x7b, 0x1c, 0xa3,
662 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d, 0x47, 0x1d, 0x70, 0x1d, 0x99,
663 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16, 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94,
664 0x1e, 0xbe, 0x1e, 0xe9, 0x1f, 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94,
665 0x1f, 0xbf, 0x1f, 0xea, 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98,
666 0x20, 0xc4, 0x20, 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1,
667 0x21, 0xce, 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf,
668 0x22, 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
669 0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24, 0xda,
670 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7, 0x25, 0xf7,
671 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26, 0xe8, 0x27, 0x18,
672 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc, 0x28, 0x0d, 0x28, 0x3f,
673 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29, 0x06, 0x29, 0x38, 0x29, 0x6b,
674 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02, 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b,
675 0x2a, 0xcf, 0x2b, 0x02, 0x2b, 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1,
676 0x2c, 0x05, 0x2c, 0x39, 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c,
677 0x2d, 0x41, 0x2d, 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c,
678 0x2e, 0x82, 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91,
679 0x2f, 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
680 0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32, 0x2a,
681 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46, 0x33, 0x7f,
682 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34, 0x9e, 0x34, 0xd8,
683 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2, 0x35, 0xfd, 0x36, 0x37,
684 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37, 0x24, 0x37, 0x60, 0x37, 0x9c,
685 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05,
686 0x39, 0x42, 0x39, 0x7f, 0x39, 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74,
687 0x3a, 0xb2, 0x3a, 0xef, 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8,
688 0x3c, 0x27, 0x3c, 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61,
689 0x3d, 0xa1, 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0,
690 0x3f, 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
691 0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41, 0xee,
692 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a, 0x43, 0x7d,
693 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44, 0xce, 0x45, 0x12,
694 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22, 0x46, 0x67, 0x46, 0xab,
695 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47, 0xc0, 0x48, 0x05, 0x48, 0x4b,
696 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d, 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0,
697 0x4a, 0x37, 0x4a, 0x7d, 0x4a, 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a,
698 0x4b, 0xe2, 0x4c, 0x2a, 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a,
699 0x4d, 0x93, 0x4d, 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00,
700 0x4f, 0x49, 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb,
701 0x51, 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
702 0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54, 0x42,
703 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2, 0x56, 0x0f,
704 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57, 0x92, 0x57, 0xe0,
705 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a, 0x59, 0x69, 0x59, 0xb8,
706 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a, 0xf5, 0x5b, 0x45, 0x5b, 0x95,
707 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86, 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78,
708 0x5d, 0xc9, 0x5e, 0x1a, 0x5e, 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61,
709 0x5f, 0xb3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f,
710 0x61, 0xa2, 0x61, 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43,
711 0x63, 0x97, 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d,
712 0x65, 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
713 0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69, 0x43,
714 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7, 0x6b, 0x4f,
715 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d, 0x08, 0x6d, 0x60,
716 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4, 0x6f, 0x1e, 0x6f, 0x78,
717 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70, 0xe0, 0x71, 0x3a, 0x71, 0x95,
718 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6, 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8,
719 0x74, 0x14, 0x74, 0x70, 0x74, 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1,
720 0x76, 0x3e, 0x76, 0x9b, 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11,
721 0x78, 0x6e, 0x78, 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46,
722 0x7a, 0xa5, 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81,
723 0x7c, 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
724 0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81, 0x0a,
725 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4, 0x83, 0x57,
726 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85, 0x47, 0x85, 0xab,
727 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b, 0x87, 0x9f, 0x88, 0x04,
728 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89, 0x99, 0x89, 0xfe, 0x8a, 0x64,
729 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96, 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca,
730 0x8d, 0x31, 0x8d, 0x98, 0x8d, 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36,
731 0x8f, 0x9e, 0x90, 0x06, 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8,
732 0x92, 0x11, 0x92, 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20,
733 0x94, 0x8a, 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f,
734 0x97, 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
735 0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b, 0xaf,
736 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2, 0x9e, 0x40,
737 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0, 0x69, 0xa0, 0xd8,
738 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96, 0xa3, 0x06, 0xa3, 0x76,
739 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5, 0x38, 0xa5, 0xa9, 0xa6, 0x1a,
740 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e, 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4,
741 0xa9, 0x37, 0xa9, 0xa9, 0xaa, 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75,
742 0xab, 0xe9, 0xac, 0x5c, 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d,
743 0xae, 0xa1, 0xaf, 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea,
744 0xb1, 0x60, 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae,
745 0xb4, 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
746 0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9, 0x4a,
747 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7, 0xbc, 0x21,
748 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe, 0x84, 0xbe, 0xff,
749 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec, 0xc1, 0x67, 0xc1, 0xe3,
750 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3, 0xd4, 0xc4, 0x51, 0xc4, 0xce,
751 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46, 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf,
752 0xc8, 0x3d, 0xc8, 0xbc, 0xc9, 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7,
753 0xcb, 0x36, 0xcb, 0xb6, 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5,
754 0xce, 0x36, 0xce, 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba,
755 0xd1, 0x3c, 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6,
756 0xd4, 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
757 0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9, 0xf1,
758 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a, 0xdd, 0x10,
759 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf, 0xaf, 0xe0, 0x36,
760 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53, 0xe2, 0xdb, 0xe3, 0x63,
761 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5, 0x84, 0xe6, 0x0d, 0xe6, 0x96,
762 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32, 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0,
763 0xea, 0x5b, 0xea, 0xe5, 0xeb, 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11,
764 0xed, 0x9c, 0xee, 0x28, 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58,
765 0xf0, 0xe5, 0xf1, 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7,
766 0xf4, 0x34, 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb,
767 0xf7, 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
768 0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd, 0xba,
769 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
778 assert(image != (Image *) NULL);
779 assert(image->signature == MagickCoreSignature);
780 if (GetImageProfile(image,"icc") != (const StringInfo *) NULL)
782 profile=AcquireStringInfo(sizeof(sRGBProfile));
783 SetStringInfoDatum(profile,sRGBProfile);
784 status=SetImageProfile(image,"icc",profile,exception);
785 profile=DestroyStringInfo(profile);
789 MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
790 const void *datum,const size_t length,ExceptionInfo *exception)
792 #define ProfileImageTag "Profile/Image"
793 #define ThrowProfileException(severity,tag,context) \
795 if (source_profile != (cmsHPROFILE) NULL) \
796 (void) cmsCloseProfile(source_profile); \
797 if (target_profile != (cmsHPROFILE) NULL) \
798 (void) cmsCloseProfile(target_profile); \
799 ThrowBinaryException(severity,tag,context); \
808 assert(image != (Image *) NULL);
809 assert(image->signature == MagickCoreSignature);
810 if (image->debug != MagickFalse)
811 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
812 assert(name != (const char *) NULL);
813 if ((datum == (const void *) NULL) || (length == 0))
819 Delete image profile(s).
821 ResetImageProfileIterator(image);
822 for (next=GetNextImageProfile(image); next != (const char *) NULL; )
824 if (IsOptionMember(next,name) != MagickFalse)
826 (void) DeleteImageProfile(image,next);
827 ResetImageProfileIterator(image);
829 next=GetNextImageProfile(image);
834 Add a ICC, IPTC, or generic profile to the image.
837 profile=AcquireStringInfo((size_t) length);
838 SetStringInfoDatum(profile,(unsigned char *) datum);
839 if ((LocaleCompare(name,"icc") != 0) && (LocaleCompare(name,"icm") != 0))
840 status=SetImageProfile(image,name,profile,exception);
846 icc_profile=GetImageProfile(image,"icc");
847 if ((icc_profile != (const StringInfo *) NULL) &&
848 (CompareStringInfo(icc_profile,profile) == 0))
853 value=GetImageProperty(image,"exif:ColorSpace",exception);
855 if (LocaleCompare(value,"1") != 0)
856 (void) SetsRGBImageProfile(image,exception);
857 value=GetImageProperty(image,"exif:InteroperabilityIndex",exception);
858 if (LocaleCompare(value,"R98.") != 0)
859 (void) SetsRGBImageProfile(image,exception);
861 value=GetImageProperty(image,"exif:InteroperabilityIndex",exception);
862 if (LocaleCompare(value,"R03.") != 0)
863 (void) SetAdobeRGB1998ImageProfile(image,exception);
865 icc_profile=GetImageProfile(image,"icc");
867 if ((icc_profile != (const StringInfo *) NULL) &&
868 (CompareStringInfo(icc_profile,profile) == 0))
870 profile=DestroyStringInfo(profile);
873 #if !defined(MAGICKCORE_LCMS_DELEGATE)
874 (void) ThrowMagickException(exception,GetMagickModule(),
875 MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn",
876 "'%s' (LCMS)",image->filename);
886 Transform pixel colors as defined by the color profiles.
888 cmsSetLogErrorHandler(CMSExceptionHandler);
889 cms_exception.image=image;
890 cms_exception.exception=exception;
891 (void) cms_exception;
892 source_profile=cmsOpenProfileFromMemTHR((cmsContext) &cms_exception,
893 GetStringInfoDatum(profile),(cmsUInt32Number)
894 GetStringInfoLength(profile));
895 if (source_profile == (cmsHPROFILE) NULL)
896 ThrowBinaryException(ResourceLimitError,
897 "ColorspaceColorProfileMismatch",name);
898 if ((cmsGetDeviceClass(source_profile) != cmsSigLinkClass) &&
899 (icc_profile == (StringInfo *) NULL))
900 status=SetImageProfile(image,name,profile,exception);
910 cmsColorSpaceSignature
917 *magick_restrict transform;
928 **magick_restrict source_pixels,
929 **magick_restrict target_pixels;
931 #if defined(LCMSHDRI)
947 target_profile=(cmsHPROFILE) NULL;
948 if (icc_profile != (StringInfo *) NULL)
950 target_profile=source_profile;
951 source_profile=cmsOpenProfileFromMemTHR((cmsContext)
952 &cms_exception,GetStringInfoDatum(icc_profile),
953 (cmsUInt32Number) GetStringInfoLength(icc_profile));
954 if (source_profile == (cmsHPROFILE) NULL)
955 ThrowProfileException(ResourceLimitError,
956 "ColorspaceColorProfileMismatch",name);
958 #if defined(LCMSHDRI)
961 source_colorspace=sRGBColorspace;
963 switch (cmsGetColorSpace(source_profile))
967 source_colorspace=CMYKColorspace;
969 #if defined(LCMSHDRI)
970 source_type=(cmsUInt32Number) TYPE_CMYK_DBL;
973 source_type=(cmsUInt32Number) TYPE_CMYK_16;
979 source_colorspace=GRAYColorspace;
981 #if defined(LCMSHDRI)
982 source_type=(cmsUInt32Number) TYPE_GRAY_DBL;
984 source_type=(cmsUInt32Number) TYPE_GRAY_16;
990 source_colorspace=LabColorspace;
991 #if defined(LCMSHDRI)
992 source_type=(cmsUInt32Number) TYPE_Lab_DBL;
995 source_type=(cmsUInt32Number) TYPE_Lab_16;
999 #if !defined(LCMSHDRI)
1002 source_colorspace=YUVColorspace;
1003 source_type=(cmsUInt32Number) TYPE_YUV_16;
1009 source_colorspace=sRGBColorspace;
1010 #if defined(LCMSHDRI)
1011 source_type=(cmsUInt32Number) TYPE_RGB_DBL;
1013 source_type=(cmsUInt32Number) TYPE_RGB_16;
1019 source_colorspace=XYZColorspace;
1020 #if defined(LCMSHDRI)
1021 source_type=(cmsUInt32Number) TYPE_XYZ_DBL;
1023 source_type=(cmsUInt32Number) TYPE_XYZ_16;
1027 #if !defined(LCMSHDRI)
1028 case cmsSigYCbCrData:
1030 source_colorspace=YUVColorspace;
1031 source_type=(cmsUInt32Number) TYPE_YCbCr_16;
1036 ThrowProfileException(ImageError,
1037 "ColorspaceColorProfileMismatch",name);
1039 (void) source_colorspace;
1040 signature=cmsGetPCS(source_profile);
1041 if (target_profile != (cmsHPROFILE) NULL)
1042 signature=cmsGetColorSpace(target_profile);
1043 #if defined(LCMSHDRI)
1049 case cmsSigCmykData:
1051 target_colorspace=CMYKColorspace;
1053 #if defined(LCMSHDRI)
1054 target_type=(cmsUInt32Number) TYPE_CMYK_DBL;
1057 target_type=(cmsUInt32Number) TYPE_CMYK_16;
1061 case cmsSigGrayData:
1063 target_colorspace=GRAYColorspace;
1065 #if defined(LCMSHDRI)
1066 target_type=(cmsUInt32Number) TYPE_GRAY_DBL;
1068 target_type=(cmsUInt32Number) TYPE_GRAY_16;
1074 target_colorspace=LabColorspace;
1075 #if defined(LCMSHDRI)
1076 target_type=(cmsUInt32Number) TYPE_Lab_DBL;
1079 target_type=(cmsUInt32Number) TYPE_Lab_16;
1083 #if !defined(LCMSHDRI)
1086 target_colorspace=YUVColorspace;
1087 target_type=(cmsUInt32Number) TYPE_YUV_16;
1093 target_colorspace=sRGBColorspace;
1094 #if defined(LCMSHDRI)
1095 target_type=(cmsUInt32Number) TYPE_RGB_DBL;
1097 target_type=(cmsUInt32Number) TYPE_RGB_16;
1103 target_colorspace=XYZColorspace;
1104 #if defined(LCMSHDRI)
1105 target_type=(cmsUInt32Number) TYPE_XYZ_DBL;
1107 target_type=(cmsUInt32Number) TYPE_XYZ_16;
1111 #if !defined(LCMSHDRI)
1112 case cmsSigYCbCrData:
1114 target_colorspace=YUVColorspace;
1115 target_type=(cmsUInt32Number) TYPE_YCbCr_16;
1120 ThrowProfileException(ImageError,
1121 "ColorspaceColorProfileMismatch",name);
1123 switch (image->rendering_intent)
1125 case AbsoluteIntent: intent=INTENT_ABSOLUTE_COLORIMETRIC; break;
1126 case PerceptualIntent: intent=INTENT_PERCEPTUAL; break;
1127 case RelativeIntent: intent=INTENT_RELATIVE_COLORIMETRIC; break;
1128 case SaturationIntent: intent=INTENT_SATURATION; break;
1129 default: intent=INTENT_PERCEPTUAL; break;
1131 flags=cmsFLAGS_HIGHRESPRECALC;
1132 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1133 if (image->black_point_compensation != MagickFalse)
1134 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1136 transform=AcquireTransformThreadSet(source_profile,source_type,
1137 target_profile,target_type,intent,flags,&cms_exception);
1138 if (transform == (cmsHTRANSFORM *) NULL)
1139 ThrowProfileException(ImageError,"UnableToCreateColorTransform",
1142 Transform image as dictated by the source & target image profiles.
1144 source_pixels=AcquirePixelThreadSet(image->columns,source_channels);
1145 target_pixels=AcquirePixelThreadSet(image->columns,target_channels);
1146 if ((source_pixels == (LCMSType **) NULL) ||
1147 (target_pixels == (LCMSType **) NULL))
1149 target_pixels=DestroyPixelThreadSet(target_pixels);
1150 source_pixels=DestroyPixelThreadSet(source_pixels);
1151 transform=DestroyTransformThreadSet(transform);
1152 ThrowProfileException(ResourceLimitError,
1153 "MemoryAllocationFailed",image->filename);
1155 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1157 target_pixels=DestroyPixelThreadSet(target_pixels);
1158 source_pixels=DestroyPixelThreadSet(source_pixels);
1159 transform=DestroyTransformThreadSet(transform);
1160 if (source_profile != (cmsHPROFILE) NULL)
1161 (void) cmsCloseProfile(source_profile);
1162 if (target_profile != (cmsHPROFILE) NULL)
1163 (void) cmsCloseProfile(target_profile);
1164 return(MagickFalse);
1166 if (target_colorspace == CMYKColorspace)
1167 (void) SetImageColorspace(image,target_colorspace,exception);
1169 image_view=AcquireAuthenticCacheView(image,exception);
1170 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1171 #pragma omp parallel for schedule(static) shared(status) \
1172 magick_number_threads(image,image,image->rows,1)
1174 for (y=0; y < (ssize_t) image->rows; y++)
1177 id = GetOpenMPThreadId();
1191 if (status == MagickFalse)
1193 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1195 if (q == (Quantum *) NULL)
1200 p=source_pixels[id];
1201 for (x=0; x < (ssize_t) image->columns; x++)
1203 *p++=LCMSScaleSource(GetPixelRed(image,q));
1204 if (source_channels > 1)
1206 *p++=LCMSScaleSource(GetPixelGreen(image,q));
1207 *p++=LCMSScaleSource(GetPixelBlue(image,q));
1209 if (source_channels > 3)
1210 *p++=LCMSScaleSource(GetPixelBlack(image,q));
1211 q+=GetPixelChannels(image);
1213 cmsDoTransform(transform[id],source_pixels[id],target_pixels[id],
1214 (unsigned int) image->columns);
1215 p=target_pixels[id];
1216 q-=GetPixelChannels(image)*image->columns;
1217 for (x=0; x < (ssize_t) image->columns; x++)
1219 if (target_channels == 1)
1220 SetPixelGray(image,LCMSScaleTarget(*p),q);
1222 SetPixelRed(image,LCMSScaleTarget(*p),q);
1224 if (target_channels > 1)
1226 SetPixelGreen(image,LCMSScaleTarget(*p),q);
1228 SetPixelBlue(image,LCMSScaleTarget(*p),q);
1231 if (target_channels > 3)
1233 SetPixelBlack(image,LCMSScaleTarget(*p),q);
1236 q+=GetPixelChannels(image);
1238 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1239 if (sync == MagickFalse)
1241 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1246 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1250 proceed=SetImageProgress(image,ProfileImageTag,progress,
1252 if (proceed == MagickFalse)
1256 image_view=DestroyCacheView(image_view);
1257 (void) SetImageColorspace(image,target_colorspace,exception);
1262 image->type=image->alpha_trait == UndefinedPixelTrait ?
1263 TrueColorType : TrueColorAlphaType;
1266 case cmsSigCmykData:
1268 image->type=image->alpha_trait == UndefinedPixelTrait ?
1269 ColorSeparationType : ColorSeparationAlphaType;
1272 case cmsSigGrayData:
1274 image->type=image->alpha_trait == UndefinedPixelTrait ?
1275 GrayscaleType : GrayscaleAlphaType;
1281 target_pixels=DestroyPixelThreadSet(target_pixels);
1282 source_pixels=DestroyPixelThreadSet(source_pixels);
1283 transform=DestroyTransformThreadSet(transform);
1284 if ((status != MagickFalse) &&
1285 (cmsGetDeviceClass(source_profile) != cmsSigLinkClass))
1286 status=SetImageProfile(image,name,profile,exception);
1287 if (target_profile != (cmsHPROFILE) NULL)
1288 (void) cmsCloseProfile(target_profile);
1290 (void) cmsCloseProfile(source_profile);
1294 profile=DestroyStringInfo(profile);
1299 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1303 % R e m o v e I m a g e P r o f i l e %
1307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1309 % RemoveImageProfile() removes a named profile from the image and returns its
1312 % The format of the RemoveImageProfile method is:
1314 % void *RemoveImageProfile(Image *image,const char *name)
1316 % A description of each parameter follows:
1318 % o image: the image.
1320 % o name: the profile name.
1323 MagickExport StringInfo *RemoveImageProfile(Image *image,const char *name)
1328 assert(image != (Image *) NULL);
1329 assert(image->signature == MagickCoreSignature);
1330 if (image->debug != MagickFalse)
1331 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1332 if (image->profiles == (SplayTreeInfo *) NULL)
1333 return((StringInfo *) NULL);
1334 WriteTo8BimProfile(image,name,(StringInfo *) NULL);
1335 profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
1336 image->profiles,name);
1341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1345 % R e s e t P r o f i l e I t e r a t o r %
1349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1351 % ResetImageProfileIterator() resets the image profile iterator. Use it in
1352 % conjunction with GetNextImageProfile() to iterate over all the profiles
1353 % associated with an image.
1355 % The format of the ResetImageProfileIterator method is:
1357 % ResetImageProfileIterator(Image *image)
1359 % A description of each parameter follows:
1361 % o image: the image.
1364 MagickExport void ResetImageProfileIterator(const Image *image)
1366 assert(image != (Image *) NULL);
1367 assert(image->signature == MagickCoreSignature);
1368 if (image->debug != MagickFalse)
1369 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1370 if (image->profiles == (SplayTreeInfo *) NULL)
1372 ResetSplayTreeIterator((SplayTreeInfo *) image->profiles);
1376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1380 % S e t I m a g e P r o f i l e %
1384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1386 % SetImageProfile() adds a named profile to the image. If a profile with the
1387 % same name already exists, it is replaced. This method differs from the
1388 % ProfileImage() method in that it does not apply CMS color profiles.
1390 % The format of the SetImageProfile method is:
1392 % MagickBooleanType SetImageProfile(Image *image,const char *name,
1393 % const StringInfo *profile)
1395 % A description of each parameter follows:
1397 % o image: the image.
1399 % o name: the profile name, for example icc, exif, and 8bim (8bim is the
1400 % Photoshop wrapper for iptc profiles).
1402 % o profile: A StringInfo structure that contains the named profile.
1406 static void *DestroyProfile(void *profile)
1408 return((void *) DestroyStringInfo((StringInfo *) profile));
1411 static inline const unsigned char *ReadResourceByte(const unsigned char *p,
1412 unsigned char *quantum)
1418 static inline const unsigned char *ReadResourceLong(const unsigned char *p,
1419 unsigned int *quantum)
1421 *quantum=(unsigned int) (*p++) << 24;
1422 *quantum|=(unsigned int) (*p++) << 16;
1423 *quantum|=(unsigned int) (*p++) << 8;
1424 *quantum|=(unsigned int) (*p++);
1428 static inline const unsigned char *ReadResourceShort(const unsigned char *p,
1429 unsigned short *quantum)
1431 *quantum=(unsigned short) (*p++) << 8;
1432 *quantum|=(unsigned short) (*p++);
1436 static inline void WriteResourceLong(unsigned char *p,
1437 const unsigned int quantum)
1442 buffer[0]=(unsigned char) (quantum >> 24);
1443 buffer[1]=(unsigned char) (quantum >> 16);
1444 buffer[2]=(unsigned char) (quantum >> 8);
1445 buffer[3]=(unsigned char) quantum;
1446 (void) memcpy(p,buffer,4);
1449 static void WriteTo8BimProfile(Image *image,const char *name,
1450 const StringInfo *profile)
1456 register const unsigned char
1478 if (LocaleCompare(name,"icc") == 0)
1481 if (LocaleCompare(name,"iptc") == 0)
1484 if (LocaleCompare(name,"xmp") == 0)
1488 profile_8bim=(StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
1489 image->profiles,"8bim");
1490 if (profile_8bim == (StringInfo *) NULL)
1492 datum=GetStringInfoDatum(profile_8bim);
1493 length=GetStringInfoLength(profile_8bim);
1494 for (p=datum; p < (datum+length-16); )
1497 if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1500 p=ReadResourceShort(p,&id);
1501 p=ReadResourceByte(p,&length_byte);
1503 if (((length_byte+1) & 0x01) != 0)
1505 if (p > (datum+length-4))
1507 p=ReadResourceLong(p,&value);
1508 count=(ssize_t) value;
1509 if ((count & 0x01) != 0)
1511 if ((count < 0) || (p > (datum+length-count)) || (count > (ssize_t) length))
1513 if (id != profile_id)
1528 extent=(datum+length)-(p+count);
1529 if (profile == (StringInfo *) NULL)
1532 extract_profile=AcquireStringInfo(offset+extent);
1533 (void) memcpy(extract_profile->datum,datum,offset);
1538 extract_extent=profile->length;
1539 if ((extract_extent & 0x01) != 0)
1541 extract_profile=AcquireStringInfo(offset+extract_extent+extent);
1542 (void) memcpy(extract_profile->datum,datum,offset-4);
1543 WriteResourceLong(extract_profile->datum+offset-4,(unsigned int)
1545 (void) memcpy(extract_profile->datum+offset,
1546 profile->datum,profile->length);
1548 (void) memcpy(extract_profile->datum+offset+extract_extent,
1550 (void) AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1551 ConstantString("8bim"),CloneStringInfo(extract_profile));
1552 extract_profile=DestroyStringInfo(extract_profile);
1558 static void GetProfilesFromResourceBlock(Image *image,
1559 const StringInfo *resource_block,ExceptionInfo *exception)
1564 register const unsigned char
1585 datum=GetStringInfoDatum(resource_block);
1586 length=GetStringInfoLength(resource_block);
1587 for (p=datum; p < (datum+length-16); )
1589 if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1592 p=ReadResourceShort(p,&id);
1593 p=ReadResourceByte(p,&length_byte);
1595 if (((length_byte+1) & 0x01) != 0)
1597 if (p > (datum+length-4))
1599 p=ReadResourceLong(p,&value);
1600 count=(ssize_t) value;
1601 if ((p > (datum+length-count)) || (count > (ssize_t) length) || (count < 0))
1618 p=ReadResourceLong(p,&resolution);
1619 image->resolution.x=((double) resolution)/65536.0;
1620 p=ReadResourceShort(p,&units)+2;
1621 p=ReadResourceLong(p,&resolution)+4;
1622 image->resolution.y=((double) resolution)/65536.0;
1624 Values are always stored as pixels per inch.
1626 if ((ResolutionType) units != PixelsPerCentimeterResolution)
1627 image->units=PixelsPerInchResolution;
1630 image->units=PixelsPerCentimeterResolution;
1631 image->resolution.x/=2.54;
1632 image->resolution.y/=2.54;
1641 profile=AcquireStringInfo(count);
1642 SetStringInfoDatum(profile,p);
1643 (void) SetImageProfileInternal(image,"iptc",profile,MagickTrue,
1645 profile=DestroyStringInfo(profile);
1662 profile=AcquireStringInfo(count);
1663 SetStringInfoDatum(profile,p);
1664 (void) SetImageProfileInternal(image,"icc",profile,MagickTrue,
1666 profile=DestroyStringInfo(profile);
1675 profile=AcquireStringInfo(count);
1676 SetStringInfoDatum(profile,p);
1677 (void) SetImageProfileInternal(image,"exif",profile,MagickTrue,
1679 profile=DestroyStringInfo(profile);
1688 profile=AcquireStringInfo(count);
1689 SetStringInfoDatum(profile,p);
1690 (void) SetImageProfileInternal(image,"xmp",profile,MagickTrue,
1692 profile=DestroyStringInfo(profile);
1702 if ((count & 0x01) != 0)
1707 #if defined(MAGICKCORE_XML_DELEGATE)
1708 static MagickBooleanType ValidateXMPProfile(const StringInfo *profile)
1716 document=xmlReadMemory((const char *) GetStringInfoDatum(profile),(int)
1717 GetStringInfoLength(profile),"xmp.xml",NULL,XML_PARSE_NOERROR |
1718 XML_PARSE_NOWARNING);
1719 if (document == (xmlDocPtr) NULL)
1720 return(MagickFalse);
1721 xmlFreeDoc(document);
1725 static unsigned char *FindNeedleInHaystack(unsigned char *haystack,
1734 length=strlen(needle);
1735 for (c=haystack; *c != '\0'; c++)
1736 if (LocaleNCompare((const char *) c,needle,length) == 0)
1738 return((unsigned char *) NULL);
1741 static MagickBooleanType ValidateXMPProfile(const StringInfo *profile)
1746 p=FindNeedleInHaystack(GetStringInfoDatum(profile),"x:xmpmeta");
1747 if (p == (unsigned char *) NULL)
1748 p=FindNeedleInHaystack(GetStringInfoDatum(profile),"rdf:RDF");
1749 return(p == (unsigned char *) NULL ? MagickFalse : MagickTrue);
1753 static MagickBooleanType SetImageProfileInternal(Image *image,const char *name,
1754 const StringInfo *profile,const MagickBooleanType recursive,
1755 ExceptionInfo *exception)
1758 key[MagickPathExtent],
1759 property[MagickPathExtent];
1764 assert(image != (Image *) NULL);
1765 assert(image->signature == MagickCoreSignature);
1766 if (image->debug != MagickFalse)
1767 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1768 if ((LocaleCompare(name,"xmp") == 0) &&
1769 (ValidateXMPProfile(profile) == MagickFalse))
1771 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
1772 "CorruptImageProfile","`%s'",name);
1775 if (image->profiles == (SplayTreeInfo *) NULL)
1776 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
1778 (void) CopyMagickString(key,name,MagickPathExtent);
1780 status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1781 ConstantString(key),CloneStringInfo(profile));
1782 if (status != MagickFalse)
1784 if (LocaleCompare(name,"8bim") == 0)
1785 GetProfilesFromResourceBlock(image,profile,exception);
1787 if (recursive == MagickFalse)
1788 WriteTo8BimProfile(image,name,profile);
1791 Inject profile into image properties.
1793 (void) FormatLocaleString(property,MagickPathExtent,"%s:*",name);
1794 (void) GetImageProperty(image,property,exception);
1798 MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name,
1799 const StringInfo *profile,ExceptionInfo *exception)
1801 return(SetImageProfileInternal(image,name,profile,MagickFalse,exception));
1805 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1809 % S y n c I m a g e P r o f i l e s %
1813 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1815 % SyncImageProfiles() synchronizes image properties with the image profiles.
1816 % Currently we only support updating the EXIF resolution and orientation.
1818 % The format of the SyncImageProfiles method is:
1820 % MagickBooleanType SyncImageProfiles(Image *image)
1822 % A description of each parameter follows:
1824 % o image: the image.
1828 static inline int ReadProfileByte(unsigned char **p,size_t *length)
1840 static inline signed short ReadProfileShort(const EndianType endian,
1841 unsigned char *buffer)
1855 if (endian == LSBEndian)
1857 value=(unsigned short) buffer[1] << 8;
1858 value|=(unsigned short) buffer[0];
1859 quantum.unsigned_value=value & 0xffff;
1860 return(quantum.signed_value);
1862 value=(unsigned short) buffer[0] << 8;
1863 value|=(unsigned short) buffer[1];
1864 quantum.unsigned_value=value & 0xffff;
1865 return(quantum.signed_value);
1868 static inline signed int ReadProfileLong(const EndianType endian,
1869 unsigned char *buffer)
1883 if (endian == LSBEndian)
1885 value=(unsigned int) buffer[3] << 24;
1886 value|=(unsigned int) buffer[2] << 16;
1887 value|=(unsigned int) buffer[1] << 8;
1888 value|=(unsigned int) buffer[0];
1889 quantum.unsigned_value=value & 0xffffffff;
1890 return(quantum.signed_value);
1892 value=(unsigned int) buffer[0] << 24;
1893 value|=(unsigned int) buffer[1] << 16;
1894 value|=(unsigned int) buffer[2] << 8;
1895 value|=(unsigned int) buffer[3];
1896 quantum.unsigned_value=value & 0xffffffff;
1897 return(quantum.signed_value);
1900 static inline signed int ReadProfileMSBLong(unsigned char **p,size_t *length)
1907 value=ReadProfileLong(MSBEndian,*p);
1913 static inline signed short ReadProfileMSBShort(unsigned char **p,
1921 value=ReadProfileShort(MSBEndian,*p);
1927 static inline void WriteProfileLong(const EndianType endian,
1928 const size_t value,unsigned char *p)
1933 if (endian == LSBEndian)
1935 buffer[0]=(unsigned char) value;
1936 buffer[1]=(unsigned char) (value >> 8);
1937 buffer[2]=(unsigned char) (value >> 16);
1938 buffer[3]=(unsigned char) (value >> 24);
1939 (void) memcpy(p,buffer,4);
1942 buffer[0]=(unsigned char) (value >> 24);
1943 buffer[1]=(unsigned char) (value >> 16);
1944 buffer[2]=(unsigned char) (value >> 8);
1945 buffer[3]=(unsigned char) value;
1946 (void) memcpy(p,buffer,4);
1949 static void WriteProfileShort(const EndianType endian,
1950 const unsigned short value,unsigned char *p)
1955 if (endian == LSBEndian)
1957 buffer[0]=(unsigned char) value;
1958 buffer[1]=(unsigned char) (value >> 8);
1959 (void) memcpy(p,buffer,2);
1962 buffer[0]=(unsigned char) (value >> 8);
1963 buffer[1]=(unsigned char) value;
1964 (void) memcpy(p,buffer,2);
1967 static MagickBooleanType Sync8BimProfile(Image *image,StringInfo *profile)
1981 length=GetStringInfoLength(profile);
1982 p=GetStringInfoDatum(profile);
1985 if (ReadProfileByte(&p,&length) != 0x38)
1987 if (ReadProfileByte(&p,&length) != 0x42)
1989 if (ReadProfileByte(&p,&length) != 0x49)
1991 if (ReadProfileByte(&p,&length) != 0x4D)
1994 return(MagickFalse);
1995 id=ReadProfileMSBShort(&p,&length);
1996 count=(ssize_t) ReadProfileByte(&p,&length);
1997 if ((count >= (ssize_t) length) || (count < 0))
1998 return(MagickFalse);
2001 if ((*p & 0x01) == 0)
2002 (void) ReadProfileByte(&p,&length);
2003 count=(ssize_t) ReadProfileMSBLong(&p,&length);
2004 if ((count > (ssize_t) length) || (count < 0))
2005 return(MagickFalse);
2006 if ((id == 0x3ED) && (count == 16))
2008 if (image->units == PixelsPerCentimeterResolution)
2009 WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.x*2.54*
2012 WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.x*
2014 WriteProfileShort(MSBEndian,(unsigned short) image->units,p+4);
2015 if (image->units == PixelsPerCentimeterResolution)
2016 WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.y*2.54*
2019 WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.y*
2021 WriteProfileShort(MSBEndian,(unsigned short) image->units,p+12);
2029 MagickBooleanType SyncExifProfile(Image *image,StringInfo *profile)
2031 #define MaxDirectoryStack 16
2032 #define EXIF_DELIMITER "\n"
2033 #define EXIF_NUM_FORMATS 12
2034 #define TAG_EXIF_OFFSET 0x8769
2035 #define TAG_INTEROP_OFFSET 0xa005
2037 typedef struct _DirectoryInfo
2047 directory_stack[MaxDirectoryStack];
2066 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
2073 Set EXIF resolution tag.
2075 length=GetStringInfoLength(profile);
2076 exif=GetStringInfoDatum(profile);
2078 return(MagickFalse);
2079 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2080 if ((id != 0x4949) && (id != 0x4D4D))
2084 if (ReadProfileByte(&exif,&length) != 0x45)
2086 if (ReadProfileByte(&exif,&length) != 0x78)
2088 if (ReadProfileByte(&exif,&length) != 0x69)
2090 if (ReadProfileByte(&exif,&length) != 0x66)
2092 if (ReadProfileByte(&exif,&length) != 0x00)
2094 if (ReadProfileByte(&exif,&length) != 0x00)
2099 return(MagickFalse);
2100 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2109 return(MagickFalse);
2110 if (ReadProfileShort(endian,exif+2) != 0x002a)
2111 return(MagickFalse);
2113 This the offset to the first IFD.
2115 offset=(ssize_t) ReadProfileLong(endian,exif+4);
2116 if ((offset < 0) || ((size_t) offset >= length))
2117 return(MagickFalse);
2118 directory=exif+offset;
2121 exif_resources=NewSplayTree((int (*)(const void *,const void *)) NULL,
2122 (void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2128 directory=directory_stack[level].directory;
2129 entry=directory_stack[level].entry;
2131 if ((directory < exif) || (directory > (exif+length-2)))
2134 Determine how many entries there are in the current IFD.
2136 number_entries=ReadProfileShort(endian,directory);
2137 for ( ; entry < number_entries; entry++)
2142 register unsigned char
2153 q=(unsigned char *) (directory+2+(12*entry));
2154 if (q > (exif+length-12))
2155 break; /* corrupt EXIF */
2156 if (GetValueFromSplayTree(exif_resources,q) == q)
2158 (void) AddValueToSplayTree(exif_resources,q,q);
2159 tag_value=(ssize_t) ReadProfileShort(endian,q);
2160 format=(ssize_t) ReadProfileShort(endian,q+2);
2161 if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2163 components=(int) ReadProfileLong(endian,q+4);
2165 break; /* corrupt EXIF */
2166 number_bytes=(size_t) components*format_bytes[format];
2167 if ((ssize_t) number_bytes < components)
2168 break; /* prevent overflow */
2169 if (number_bytes <= 4)
2174 The directory entry contains an offset.
2176 offset=(ssize_t) ReadProfileLong(endian,q+8);
2177 if ((offset < 0) || ((size_t) (offset+number_bytes) > length))
2179 if (~length < number_bytes)
2180 continue; /* prevent overflow */
2181 p=(unsigned char *) (exif+offset);
2187 (void) WriteProfileLong(endian,(size_t) (image->resolution.x+0.5),p);
2188 if (number_bytes == 8)
2189 (void) WriteProfileLong(endian,1UL,p+4);
2194 (void) WriteProfileLong(endian,(size_t) (image->resolution.y+0.5),p);
2195 if (number_bytes == 8)
2196 (void) WriteProfileLong(endian,1UL,p+4);
2201 if (number_bytes == 4)
2203 (void) WriteProfileLong(endian,(size_t) image->orientation,p);
2206 (void) WriteProfileShort(endian,(unsigned short) image->orientation,
2212 if (number_bytes == 4)
2214 (void) WriteProfileLong(endian,(size_t) (image->units+1),p);
2217 (void) WriteProfileShort(endian,(unsigned short) (image->units+1),p);
2223 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2225 offset=(ssize_t) ReadProfileLong(endian,p);
2226 if (((size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2228 directory_stack[level].directory=directory;
2230 directory_stack[level].entry=entry;
2232 directory_stack[level].directory=exif+offset;
2233 directory_stack[level].entry=0;
2235 if ((directory+2+(12*number_entries)) > (exif+length))
2237 offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2239 if ((offset != 0) && ((size_t) offset < length) &&
2240 (level < (MaxDirectoryStack-2)))
2242 directory_stack[level].directory=exif+offset;
2243 directory_stack[level].entry=0;
2250 } while (level > 0);
2251 exif_resources=DestroySplayTree(exif_resources);
2255 MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
2264 profile=(StringInfo *) GetImageProfile(image,"8BIM");
2265 if (profile != (StringInfo *) NULL)
2266 if (Sync8BimProfile(image,profile) == MagickFalse)
2268 profile=(StringInfo *) GetImageProfile(image,"EXIF");
2269 if (profile != (StringInfo *) NULL)
2270 if (SyncExifProfile(image,profile) == MagickFalse)