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-2018 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://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/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>
83 #if !defined(MAGICKCORE_HDRI_SUPPORT)
84 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
86 #define LCMSScaleSource(pixel) ScaleQuantumToShort(pixel)
87 #define LCMSScaleTarget(pixel) ScaleShortToQuantum(pixel)
88 typedef unsigned short
90 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
92 #define LCMSScaleSource(pixel) (pixel)
93 #define LCMSScaleTarget(pixel) (pixel)
94 typedef unsigned short
100 #define LCMSScaleSource(pixel) (source_scale*QuantumScale*(pixel))
101 #define LCMSScaleTarget(pixel) ClampToQuantum(target_scale*QuantumRange*(pixel))
109 static MagickBooleanType
110 SetImageProfileInternal(Image *,const char *,const StringInfo *,
111 const MagickBooleanType,ExceptionInfo *);
114 WriteTo8BimProfile(Image *,const char*,const StringInfo *);
134 typedef struct _CMSExceptionInfo
144 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
148 % C l o n e I m a g e P r o f i l e s %
152 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
154 % CloneImageProfiles() clones one or more image profiles.
156 % The format of the CloneImageProfiles method is:
158 % MagickBooleanType CloneImageProfiles(Image *image,
159 % const Image *clone_image)
161 % A description of each parameter follows:
163 % o image: the image.
165 % o clone_image: the clone image.
168 MagickExport MagickBooleanType CloneImageProfiles(Image *image,
169 const Image *clone_image)
171 assert(image != (Image *) NULL);
172 assert(image->signature == MagickCoreSignature);
173 if (image->debug != MagickFalse)
174 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
175 assert(clone_image != (const Image *) NULL);
176 assert(clone_image->signature == MagickCoreSignature);
177 if (clone_image->profiles != (void *) NULL)
179 if (image->profiles != (void *) NULL)
180 DestroyImageProfiles(image);
181 image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
182 (void *(*)(void *)) ConstantString,(void *(*)(void *)) CloneStringInfo);
188 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
192 % D e l e t e I m a g e P r o f i l e %
196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
198 % DeleteImageProfile() deletes a profile from the image by its name.
200 % The format of the DeleteImageProfile method is:
202 % MagickBooleanTyupe DeleteImageProfile(Image *image,const char *name)
204 % A description of each parameter follows:
206 % o image: the image.
208 % o name: the profile name.
211 MagickExport MagickBooleanType DeleteImageProfile(Image *image,const char *name)
213 assert(image != (Image *) NULL);
214 assert(image->signature == MagickCoreSignature);
215 if (image->debug != MagickFalse)
216 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
217 if (image->profiles == (SplayTreeInfo *) NULL)
219 WriteTo8BimProfile(image,name,(StringInfo *) NULL);
220 return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->profiles,name));
224 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228 % D e s t r o y I m a g e P r o f i l e s %
232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
234 % DestroyImageProfiles() releases memory associated with an image profile map.
236 % The format of the DestroyProfiles method is:
238 % void DestroyImageProfiles(Image *image)
240 % A description of each parameter follows:
242 % o image: the image.
245 MagickExport void DestroyImageProfiles(Image *image)
247 if (image->profiles != (SplayTreeInfo *) NULL)
248 image->profiles=DestroySplayTree((SplayTreeInfo *) image->profiles);
252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
256 % G e t I m a g e P r o f i l e %
260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
262 % GetImageProfile() gets a profile associated with an image by name.
264 % The format of the GetImageProfile method is:
266 % const StringInfo *GetImageProfile(const Image *image,const char *name)
268 % A description of each parameter follows:
270 % o image: the image.
272 % o name: the profile name.
275 MagickExport const StringInfo *GetImageProfile(const Image *image,
281 assert(image != (Image *) NULL);
282 assert(image->signature == MagickCoreSignature);
283 if (image->debug != MagickFalse)
284 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
285 if (image->profiles == (SplayTreeInfo *) NULL)
286 return((StringInfo *) NULL);
287 profile=(const StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
288 image->profiles,name);
293 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
297 % G e t N e x t I m a g e P r o f i l e %
301 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
303 % GetNextImageProfile() gets the next profile name for an image.
305 % The format of the GetNextImageProfile method is:
307 % char *GetNextImageProfile(const Image *image)
309 % A description of each parameter follows:
311 % o hash_info: the hash info.
314 MagickExport char *GetNextImageProfile(const Image *image)
316 assert(image != (Image *) NULL);
317 assert(image->signature == MagickCoreSignature);
318 if (image->debug != MagickFalse)
319 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
320 if (image->profiles == (SplayTreeInfo *) NULL)
321 return((char *) NULL);
322 return((char *) GetNextKeyInSplayTree((SplayTreeInfo *) image->profiles));
326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
330 % P r o f i l e I m a g e %
334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
336 % ProfileImage() associates, applies, or removes an ICM, IPTC, or generic
337 % profile with / to / from an image. If the profile is NULL, it is removed
338 % from the image otherwise added or applied. Use a name of '*' and a profile
339 % of NULL to remove all profiles from the image.
341 % ICC and ICM profiles are handled as follows: If the image does not have
342 % an associated color profile, the one you provide is associated with the
343 % image and the image pixels are not transformed. Otherwise, the colorspace
344 % transform defined by the existing and new profile are applied to the image
345 % pixels and the new profile is associated with the image.
347 % The format of the ProfileImage method is:
349 % MagickBooleanType ProfileImage(Image *image,const char *name,
350 % const void *datum,const size_t length,const MagickBooleanType clone)
352 % A description of each parameter follows:
354 % o image: the image.
356 % o name: Name of profile to add or remove: ICC, IPTC, or generic profile.
358 % o datum: the profile data.
360 % o length: the length of the profile.
362 % o clone: should be MagickFalse.
366 #if defined(MAGICKCORE_LCMS_DELEGATE)
367 static LCMSType **DestroyPixelThreadSet(LCMSType **pixels)
372 if (pixels != (LCMSType **) NULL)
373 return((LCMSType **) NULL);
374 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
375 if (pixels[i] != (LCMSType *) NULL)
376 pixels[i]=(LCMSType *) RelinquishMagickMemory(pixels[i]);
377 pixels=(LCMSType **) RelinquishMagickMemory(pixels);
381 static LCMSType **AcquirePixelThreadSet(const size_t columns,
382 const size_t channels)
393 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
394 pixels=(LCMSType **) AcquireQuantumMemory(number_threads,sizeof(*pixels));
395 if (pixels == (LCMSType **) NULL)
396 return((LCMSType **) NULL);
397 (void) memset(pixels,0,number_threads*sizeof(*pixels));
398 for (i=0; i < (ssize_t) number_threads; i++)
400 pixels[i]=(LCMSType *) AcquireQuantumMemory(columns,channels*
402 if (pixels[i] == (LCMSType *) 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) memset(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 static void CMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
465 cms_exception=(CMSExceptionInfo *) context;
466 if (cms_exception == (CMSExceptionInfo *) NULL)
468 exception=cms_exception->exception;
469 if (exception == (ExceptionInfo *) NULL)
471 image=cms_exception->image;
472 if (image == (Image *) NULL)
474 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
475 "UnableToTransformColorspace","`%s'","unknown context");
478 if (image->debug != MagickFalse)
479 (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%u, %s",
480 severity,message != (char *) NULL ? message : "no message");
481 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
482 "UnableToTransformColorspace","`%s'",image->filename);
486 static MagickBooleanType SetsRGBImageProfile(Image *image,
487 ExceptionInfo *exception)
492 0x00, 0x00, 0x0c, 0x8c, 0x61, 0x72, 0x67, 0x6c, 0x02, 0x20, 0x00, 0x00,
493 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
494 0x07, 0xde, 0x00, 0x01, 0x00, 0x06, 0x00, 0x16, 0x00, 0x0f, 0x00, 0x3a,
495 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
496 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00,
497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
498 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x61, 0x72, 0x67, 0x6c,
499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
500 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
501 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
503 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x99,
504 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0xec, 0x00, 0x00, 0x00, 0x67,
505 0x64, 0x6d, 0x6e, 0x64, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70,
506 0x64, 0x6d, 0x64, 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88,
507 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x0c,
508 0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x00, 0x67,
509 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x24,
510 0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xe4, 0x00, 0x00, 0x00, 0x14,
511 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x24,
512 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x14,
513 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x14,
514 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x14,
515 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x58, 0x00, 0x00, 0x00, 0x14,
516 0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x6c, 0x00, 0x00, 0x00, 0x14,
517 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
518 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
519 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
520 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
521 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36,
522 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75, 0x69, 0x76,
523 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x77, 0x77,
524 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x31, 0x39,
525 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c,
526 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
527 0x00, 0x3f, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31,
528 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75,
529 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77,
530 0x77, 0x77, 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20,
531 0x31, 0x39, 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66,
532 0x69, 0x6c, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, 0x61,
534 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x72, 0x61, 0x65, 0x6d,
535 0x65, 0x20, 0x57, 0x2e, 0x20, 0x47, 0x69, 0x6c, 0x6c, 0x2e, 0x20, 0x52,
536 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f,
537 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
538 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x4e, 0x6f, 0x20, 0x57,
539 0x61, 0x72, 0x72, 0x61, 0x6e, 0x74, 0x79, 0x2c, 0x20, 0x55, 0x73, 0x65,
540 0x20, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e,
541 0x20, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20,
543 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
544 0x65, 0x63, 0x2e, 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74,
546 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
547 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
549 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
550 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
551 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
552 0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e,
553 0x31, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47,
554 0x42, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61,
555 0x63, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43,
557 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
558 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63,
559 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
560 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 0x00, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00,
563 0x43, 0x52, 0x54, 0x20, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
565 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
567 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa4, 0x7c,
573 0x00, 0x14, 0x5f, 0x30, 0x00, 0x10, 0xce, 0x02, 0x00, 0x03, 0xed, 0xb2,
574 0x00, 0x04, 0x13, 0x0a, 0x00, 0x03, 0x5c, 0x67, 0x00, 0x00, 0x00, 0x01,
575 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x0a, 0x3d,
576 0x00, 0x50, 0x00, 0x00, 0x00, 0x57, 0x1e, 0xb8, 0x6d, 0x65, 0x61, 0x73,
577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x58, 0x59, 0x5a, 0x20,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00,
581 0x00, 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa0,
584 0x00, 0x00, 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20,
585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x97, 0x00, 0x00, 0xb7, 0x87,
586 0x00, 0x00, 0x18, 0xd9, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
587 0x00, 0x00, 0x24, 0x9f, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0xb6, 0xc4,
588 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
589 0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19,
590 0x00, 0x1e, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37,
591 0x00, 0x3b, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54,
592 0x00, 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
593 0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00, 0x90,
594 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9, 0x00, 0xae,
595 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00, 0xc6, 0x00, 0xcb,
596 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0xeb,
597 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01, 0x01, 0x01, 0x07, 0x01, 0x0d,
598 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f, 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32,
599 0x01, 0x38, 0x01, 0x3e, 0x01, 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59,
600 0x01, 0x60, 0x01, 0x67, 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83,
601 0x01, 0x8b, 0x01, 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1,
602 0x01, 0xb9, 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1,
603 0x01, 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
604 0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02, 0x4b,
605 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a, 0x02, 0x84,
606 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02, 0xb6, 0x02, 0xc1,
607 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb, 0x02, 0xf5, 0x03, 0x00,
608 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2d, 0x03, 0x38, 0x03, 0x43,
609 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66, 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a,
610 0x03, 0x96, 0x03, 0xa2, 0x03, 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3,
611 0x03, 0xe0, 0x03, 0xec, 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20,
612 0x04, 0x2d, 0x04, 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71,
613 0x04, 0x7e, 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4,
614 0x04, 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
615 0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05, 0x77,
616 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5, 0x05, 0xd5,
617 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06, 0x27, 0x06, 0x37,
618 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b, 0x06, 0x8c, 0x06, 0x9d,
619 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06, 0xe3, 0x06, 0xf5, 0x07, 0x07,
620 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d, 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74,
621 0x07, 0x86, 0x07, 0x99, 0x07, 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5,
622 0x07, 0xf8, 0x08, 0x0b, 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a,
623 0x08, 0x6e, 0x08, 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2,
624 0x08, 0xe7, 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f,
625 0x09, 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
626 0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a, 0x54,
627 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5, 0x0a, 0xdc,
628 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b, 0x51, 0x0b, 0x69,
629 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8, 0x0b, 0xe1, 0x0b, 0xf9,
630 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c, 0x5c, 0x0c, 0x75, 0x0c, 0x8e,
631 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9, 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26,
632 0x0d, 0x40, 0x0d, 0x5a, 0x0d, 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3,
633 0x0d, 0xde, 0x0d, 0xf8, 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64,
634 0x0e, 0x7f, 0x0e, 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09,
635 0x0f, 0x25, 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3,
636 0x0f, 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
637 0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11, 0x13,
638 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa, 0x11, 0xc9,
639 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12, 0x64, 0x12, 0x84,
640 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03, 0x13, 0x23, 0x13, 0x43,
641 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13, 0xc5, 0x13, 0xe5, 0x14, 0x06,
642 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a, 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce,
643 0x14, 0xf0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b,
644 0x15, 0xbd, 0x15, 0xe0, 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c,
645 0x16, 0x8f, 0x16, 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41,
646 0x17, 0x65, 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b,
647 0x18, 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
648 0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19, 0xdd,
649 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e, 0x1a, 0xc5,
650 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b, 0x8a, 0x1b, 0xb2,
651 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52, 0x1c, 0x7b, 0x1c, 0xa3,
652 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d, 0x47, 0x1d, 0x70, 0x1d, 0x99,
653 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16, 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94,
654 0x1e, 0xbe, 0x1e, 0xe9, 0x1f, 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94,
655 0x1f, 0xbf, 0x1f, 0xea, 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98,
656 0x20, 0xc4, 0x20, 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1,
657 0x21, 0xce, 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf,
658 0x22, 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
659 0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24, 0xda,
660 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7, 0x25, 0xf7,
661 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26, 0xe8, 0x27, 0x18,
662 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc, 0x28, 0x0d, 0x28, 0x3f,
663 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29, 0x06, 0x29, 0x38, 0x29, 0x6b,
664 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02, 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b,
665 0x2a, 0xcf, 0x2b, 0x02, 0x2b, 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1,
666 0x2c, 0x05, 0x2c, 0x39, 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c,
667 0x2d, 0x41, 0x2d, 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c,
668 0x2e, 0x82, 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91,
669 0x2f, 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
670 0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32, 0x2a,
671 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46, 0x33, 0x7f,
672 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34, 0x9e, 0x34, 0xd8,
673 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2, 0x35, 0xfd, 0x36, 0x37,
674 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37, 0x24, 0x37, 0x60, 0x37, 0x9c,
675 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05,
676 0x39, 0x42, 0x39, 0x7f, 0x39, 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74,
677 0x3a, 0xb2, 0x3a, 0xef, 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8,
678 0x3c, 0x27, 0x3c, 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61,
679 0x3d, 0xa1, 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0,
680 0x3f, 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
681 0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41, 0xee,
682 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a, 0x43, 0x7d,
683 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44, 0xce, 0x45, 0x12,
684 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22, 0x46, 0x67, 0x46, 0xab,
685 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47, 0xc0, 0x48, 0x05, 0x48, 0x4b,
686 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d, 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0,
687 0x4a, 0x37, 0x4a, 0x7d, 0x4a, 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a,
688 0x4b, 0xe2, 0x4c, 0x2a, 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a,
689 0x4d, 0x93, 0x4d, 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00,
690 0x4f, 0x49, 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb,
691 0x51, 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
692 0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54, 0x42,
693 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2, 0x56, 0x0f,
694 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57, 0x92, 0x57, 0xe0,
695 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a, 0x59, 0x69, 0x59, 0xb8,
696 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a, 0xf5, 0x5b, 0x45, 0x5b, 0x95,
697 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86, 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78,
698 0x5d, 0xc9, 0x5e, 0x1a, 0x5e, 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61,
699 0x5f, 0xb3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f,
700 0x61, 0xa2, 0x61, 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43,
701 0x63, 0x97, 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d,
702 0x65, 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
703 0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69, 0x43,
704 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7, 0x6b, 0x4f,
705 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d, 0x08, 0x6d, 0x60,
706 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4, 0x6f, 0x1e, 0x6f, 0x78,
707 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70, 0xe0, 0x71, 0x3a, 0x71, 0x95,
708 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6, 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8,
709 0x74, 0x14, 0x74, 0x70, 0x74, 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1,
710 0x76, 0x3e, 0x76, 0x9b, 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11,
711 0x78, 0x6e, 0x78, 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46,
712 0x7a, 0xa5, 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81,
713 0x7c, 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
714 0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81, 0x0a,
715 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4, 0x83, 0x57,
716 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85, 0x47, 0x85, 0xab,
717 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b, 0x87, 0x9f, 0x88, 0x04,
718 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89, 0x99, 0x89, 0xfe, 0x8a, 0x64,
719 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96, 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca,
720 0x8d, 0x31, 0x8d, 0x98, 0x8d, 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36,
721 0x8f, 0x9e, 0x90, 0x06, 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8,
722 0x92, 0x11, 0x92, 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20,
723 0x94, 0x8a, 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f,
724 0x97, 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
725 0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b, 0xaf,
726 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2, 0x9e, 0x40,
727 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0, 0x69, 0xa0, 0xd8,
728 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96, 0xa3, 0x06, 0xa3, 0x76,
729 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5, 0x38, 0xa5, 0xa9, 0xa6, 0x1a,
730 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e, 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4,
731 0xa9, 0x37, 0xa9, 0xa9, 0xaa, 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75,
732 0xab, 0xe9, 0xac, 0x5c, 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d,
733 0xae, 0xa1, 0xaf, 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea,
734 0xb1, 0x60, 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae,
735 0xb4, 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
736 0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9, 0x4a,
737 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7, 0xbc, 0x21,
738 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe, 0x84, 0xbe, 0xff,
739 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec, 0xc1, 0x67, 0xc1, 0xe3,
740 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3, 0xd4, 0xc4, 0x51, 0xc4, 0xce,
741 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46, 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf,
742 0xc8, 0x3d, 0xc8, 0xbc, 0xc9, 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7,
743 0xcb, 0x36, 0xcb, 0xb6, 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5,
744 0xce, 0x36, 0xce, 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba,
745 0xd1, 0x3c, 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6,
746 0xd4, 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
747 0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9, 0xf1,
748 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a, 0xdd, 0x10,
749 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf, 0xaf, 0xe0, 0x36,
750 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53, 0xe2, 0xdb, 0xe3, 0x63,
751 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5, 0x84, 0xe6, 0x0d, 0xe6, 0x96,
752 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32, 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0,
753 0xea, 0x5b, 0xea, 0xe5, 0xeb, 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11,
754 0xed, 0x9c, 0xee, 0x28, 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58,
755 0xf0, 0xe5, 0xf1, 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7,
756 0xf4, 0x34, 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb,
757 0xf7, 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
758 0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd, 0xba,
759 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
768 assert(image != (Image *) NULL);
769 assert(image->signature == MagickCoreSignature);
770 if (GetImageProfile(image,"icc") != (const StringInfo *) NULL)
772 profile=AcquireStringInfo(sizeof(sRGBProfile));
773 SetStringInfoDatum(profile,sRGBProfile);
774 status=SetImageProfile(image,"icc",profile,exception);
775 profile=DestroyStringInfo(profile);
779 MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
780 const void *datum,const size_t length,ExceptionInfo *exception)
782 #define ProfileImageTag "Profile/Image"
783 #define ThrowProfileException(severity,tag,context) \
785 if (source_profile != (cmsHPROFILE) NULL) \
786 (void) cmsCloseProfile(source_profile); \
787 if (target_profile != (cmsHPROFILE) NULL) \
788 (void) cmsCloseProfile(target_profile); \
789 ThrowBinaryException(severity,tag,context); \
798 assert(image != (Image *) NULL);
799 assert(image->signature == MagickCoreSignature);
800 if (image->debug != MagickFalse)
801 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
802 assert(name != (const char *) NULL);
803 if ((datum == (const void *) NULL) || (length == 0))
809 Delete image profile(s).
811 ResetImageProfileIterator(image);
812 for (next=GetNextImageProfile(image); next != (const char *) NULL; )
814 if (IsOptionMember(next,name) != MagickFalse)
816 (void) DeleteImageProfile(image,next);
817 ResetImageProfileIterator(image);
819 next=GetNextImageProfile(image);
824 Add a ICC, IPTC, or generic profile to the image.
827 profile=AcquireStringInfo((size_t) length);
828 SetStringInfoDatum(profile,(unsigned char *) datum);
829 if ((LocaleCompare(name,"icc") != 0) && (LocaleCompare(name,"icm") != 0))
830 status=SetImageProfile(image,name,profile,exception);
836 icc_profile=GetImageProfile(image,"icc");
837 if ((icc_profile != (const StringInfo *) NULL) &&
838 (CompareStringInfo(icc_profile,profile) == 0))
843 value=GetImageProperty(image,"exif:ColorSpace",exception);
845 if (LocaleCompare(value,"1") != 0)
846 (void) SetsRGBImageProfile(image,exception);
847 value=GetImageProperty(image,"exif:InteroperabilityIndex",exception);
848 if (LocaleCompare(value,"R98.") != 0)
849 (void) SetsRGBImageProfile(image,exception);
851 value=GetImageProperty(image,"exif:InteroperabilityIndex",exception);
852 if (LocaleCompare(value,"R03.") != 0)
853 (void) SetAdobeRGB1998ImageProfile(image,exception);
855 icc_profile=GetImageProfile(image,"icc");
857 if ((icc_profile != (const StringInfo *) NULL) &&
858 (CompareStringInfo(icc_profile,profile) == 0))
860 profile=DestroyStringInfo(profile);
863 #if !defined(MAGICKCORE_LCMS_DELEGATE)
864 (void) ThrowMagickException(exception,GetMagickModule(),
865 MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn",
866 "'%s' (LCMS)",image->filename);
876 Transform pixel colors as defined by the color profiles.
878 cmsSetLogErrorHandler(CMSExceptionHandler);
879 cms_exception.image=image;
880 cms_exception.exception=exception;
881 (void) cms_exception;
882 source_profile=cmsOpenProfileFromMemTHR((cmsContext) &cms_exception,
883 GetStringInfoDatum(profile),(cmsUInt32Number)
884 GetStringInfoLength(profile));
885 if (source_profile == (cmsHPROFILE) NULL)
886 ThrowBinaryException(ResourceLimitError,
887 "ColorspaceColorProfileMismatch",name);
888 if ((cmsGetDeviceClass(source_profile) != cmsSigLinkClass) &&
889 (icc_profile == (StringInfo *) NULL))
890 status=SetImageProfile(image,name,profile,exception);
900 cmsColorSpaceSignature
907 *magick_restrict transform;
918 **magick_restrict source_pixels,
919 **magick_restrict target_pixels;
921 #if defined(LCMSHDRI)
937 target_profile=(cmsHPROFILE) NULL;
938 if (icc_profile != (StringInfo *) NULL)
940 target_profile=source_profile;
941 source_profile=cmsOpenProfileFromMemTHR((cmsContext)
942 &cms_exception,GetStringInfoDatum(icc_profile),
943 (cmsUInt32Number) GetStringInfoLength(icc_profile));
944 if (source_profile == (cmsHPROFILE) NULL)
945 ThrowProfileException(ResourceLimitError,
946 "ColorspaceColorProfileMismatch",name);
948 #if defined(LCMSHDRI)
952 switch (cmsGetColorSpace(source_profile))
956 source_colorspace=CMYKColorspace;
958 #if defined(LCMSHDRI)
959 source_type=(cmsUInt32Number) TYPE_CMYK_DBL;
962 source_type=(cmsUInt32Number) TYPE_CMYK_16;
968 source_colorspace=GRAYColorspace;
970 #if defined(LCMSHDRI)
971 source_type=(cmsUInt32Number) TYPE_GRAY_DBL;
973 source_type=(cmsUInt32Number) TYPE_GRAY_16;
979 source_colorspace=LabColorspace;
980 #if defined(LCMSHDRI)
981 source_type=(cmsUInt32Number) TYPE_Lab_DBL;
984 source_type=(cmsUInt32Number) TYPE_Lab_16;
988 #if !defined(LCMSHDRI)
991 source_colorspace=YUVColorspace;
992 source_type=(cmsUInt32Number) TYPE_YUV_16;
998 source_colorspace=sRGBColorspace;
999 #if defined(LCMSHDRI)
1000 source_type=(cmsUInt32Number) TYPE_RGB_DBL;
1002 source_type=(cmsUInt32Number) TYPE_RGB_16;
1008 source_colorspace=XYZColorspace;
1009 #if defined(LCMSHDRI)
1010 source_type=(cmsUInt32Number) TYPE_XYZ_DBL;
1012 source_type=(cmsUInt32Number) TYPE_XYZ_16;
1016 #if !defined(LCMSHDRI)
1017 case cmsSigYCbCrData:
1019 source_colorspace=YUVColorspace;
1020 source_type=(cmsUInt32Number) TYPE_YCbCr_16;
1025 ThrowProfileException(ImageError,
1026 "ColorspaceColorProfileMismatch",name);
1028 (void) source_colorspace;
1029 signature=cmsGetPCS(source_profile);
1030 if (target_profile != (cmsHPROFILE) NULL)
1031 signature=cmsGetColorSpace(target_profile);
1032 #if defined(LCMSHDRI)
1038 case cmsSigCmykData:
1040 target_colorspace=CMYKColorspace;
1042 #if defined(LCMSHDRI)
1043 target_type=(cmsUInt32Number) TYPE_CMYK_DBL;
1046 target_type=(cmsUInt32Number) TYPE_CMYK_16;
1050 case cmsSigGrayData:
1052 target_colorspace=GRAYColorspace;
1054 #if defined(LCMSHDRI)
1055 target_type=(cmsUInt32Number) TYPE_GRAY_DBL;
1057 target_type=(cmsUInt32Number) TYPE_GRAY_16;
1063 target_colorspace=LabColorspace;
1064 #if defined(LCMSHDRI)
1065 target_type=(cmsUInt32Number) TYPE_Lab_DBL;
1068 target_type=(cmsUInt32Number) TYPE_Lab_16;
1072 #if !defined(LCMSHDRI)
1075 target_colorspace=YUVColorspace;
1076 target_type=(cmsUInt32Number) TYPE_YUV_16;
1082 target_colorspace=sRGBColorspace;
1083 #if defined(LCMSHDRI)
1084 target_type=(cmsUInt32Number) TYPE_RGB_DBL;
1086 target_type=(cmsUInt32Number) TYPE_RGB_16;
1092 target_colorspace=XYZColorspace;
1093 #if defined(LCMSHDRI)
1094 target_type=(cmsUInt32Number) TYPE_XYZ_DBL;
1096 target_type=(cmsUInt32Number) TYPE_XYZ_16;
1100 #if !defined(LCMSHDRI)
1101 case cmsSigYCbCrData:
1103 target_colorspace=YUVColorspace;
1104 target_type=(cmsUInt32Number) TYPE_YCbCr_16;
1109 ThrowProfileException(ImageError,
1110 "ColorspaceColorProfileMismatch",name);
1112 switch (image->rendering_intent)
1114 case AbsoluteIntent: intent=INTENT_ABSOLUTE_COLORIMETRIC; break;
1115 case PerceptualIntent: intent=INTENT_PERCEPTUAL; break;
1116 case RelativeIntent: intent=INTENT_RELATIVE_COLORIMETRIC; break;
1117 case SaturationIntent: intent=INTENT_SATURATION; break;
1118 default: intent=INTENT_PERCEPTUAL; break;
1120 flags=cmsFLAGS_HIGHRESPRECALC;
1121 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1122 if (image->black_point_compensation != MagickFalse)
1123 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1125 transform=AcquireTransformThreadSet(image,source_profile,
1126 source_type,target_profile,target_type,intent,flags);
1127 if (transform == (cmsHTRANSFORM *) NULL)
1128 ThrowProfileException(ImageError,"UnableToCreateColorTransform",
1131 Transform image as dictated by the source & target image profiles.
1133 source_pixels=AcquirePixelThreadSet(image->columns,source_channels);
1134 target_pixels=AcquirePixelThreadSet(image->columns,target_channels);
1135 if ((source_pixels == (LCMSType **) NULL) ||
1136 (target_pixels == (LCMSType **) NULL))
1138 target_pixels=DestroyPixelThreadSet(target_pixels);
1139 source_pixels=DestroyPixelThreadSet(source_pixels);
1140 transform=DestroyTransformThreadSet(transform);
1141 ThrowProfileException(ResourceLimitError,
1142 "MemoryAllocationFailed",image->filename);
1144 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1146 target_pixels=DestroyPixelThreadSet(target_pixels);
1147 source_pixels=DestroyPixelThreadSet(source_pixels);
1148 transform=DestroyTransformThreadSet(transform);
1149 if (source_profile != (cmsHPROFILE) NULL)
1150 (void) cmsCloseProfile(source_profile);
1151 if (target_profile != (cmsHPROFILE) NULL)
1152 (void) cmsCloseProfile(target_profile);
1153 return(MagickFalse);
1155 if (target_colorspace == CMYKColorspace)
1156 (void) SetImageColorspace(image,target_colorspace,exception);
1158 image_view=AcquireAuthenticCacheView(image,exception);
1159 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1160 #pragma omp parallel for schedule(static) shared(status) \
1161 magick_number_threads(image,image,image->rows,1)
1163 for (y=0; y < (ssize_t) image->rows; y++)
1166 id = GetOpenMPThreadId();
1180 if (status == MagickFalse)
1182 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1184 if (q == (Quantum *) NULL)
1189 p=source_pixels[id];
1190 for (x=0; x < (ssize_t) image->columns; x++)
1192 *p++=LCMSScaleSource(GetPixelRed(image,q));
1193 if (source_channels > 1)
1195 *p++=LCMSScaleSource(GetPixelGreen(image,q));
1196 *p++=LCMSScaleSource(GetPixelBlue(image,q));
1198 if (source_channels > 3)
1199 *p++=LCMSScaleSource(GetPixelBlack(image,q));
1200 q+=GetPixelChannels(image);
1202 cmsDoTransform(transform[id],source_pixels[id],target_pixels[id],
1203 (unsigned int) image->columns);
1204 p=target_pixels[id];
1205 q-=GetPixelChannels(image)*image->columns;
1206 for (x=0; x < (ssize_t) image->columns; x++)
1208 if (target_channels == 1)
1209 SetPixelGray(image,LCMSScaleTarget(*p),q);
1211 SetPixelRed(image,LCMSScaleTarget(*p),q);
1213 if (target_channels > 1)
1215 SetPixelGreen(image,LCMSScaleTarget(*p),q);
1217 SetPixelBlue(image,LCMSScaleTarget(*p),q);
1220 if (target_channels > 3)
1222 SetPixelBlack(image,LCMSScaleTarget(*p),q);
1225 q+=GetPixelChannels(image);
1227 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1228 if (sync == MagickFalse)
1230 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1235 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1236 #pragma omp critical (MagickCore_ProfileImage)
1238 proceed=SetImageProgress(image,ProfileImageTag,progress++,
1240 if (proceed == MagickFalse)
1244 image_view=DestroyCacheView(image_view);
1245 (void) SetImageColorspace(image,target_colorspace,exception);
1250 image->type=image->alpha_trait == UndefinedPixelTrait ?
1251 TrueColorType : TrueColorAlphaType;
1254 case cmsSigCmykData:
1256 image->type=image->alpha_trait == UndefinedPixelTrait ?
1257 ColorSeparationType : ColorSeparationAlphaType;
1260 case cmsSigGrayData:
1262 image->type=image->alpha_trait == UndefinedPixelTrait ?
1263 GrayscaleType : GrayscaleAlphaType;
1269 target_pixels=DestroyPixelThreadSet(target_pixels);
1270 source_pixels=DestroyPixelThreadSet(source_pixels);
1271 transform=DestroyTransformThreadSet(transform);
1272 if ((status != MagickFalse) &&
1273 (cmsGetDeviceClass(source_profile) != cmsSigLinkClass))
1274 status=SetImageProfile(image,name,profile,exception);
1275 if (target_profile != (cmsHPROFILE) NULL)
1276 (void) cmsCloseProfile(target_profile);
1278 (void) cmsCloseProfile(source_profile);
1282 profile=DestroyStringInfo(profile);
1287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1291 % R e m o v e I m a g e P r o f i l e %
1295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1297 % RemoveImageProfile() removes a named profile from the image and returns its
1300 % The format of the RemoveImageProfile method is:
1302 % void *RemoveImageProfile(Image *image,const char *name)
1304 % A description of each parameter follows:
1306 % o image: the image.
1308 % o name: the profile name.
1311 MagickExport StringInfo *RemoveImageProfile(Image *image,const char *name)
1316 assert(image != (Image *) NULL);
1317 assert(image->signature == MagickCoreSignature);
1318 if (image->debug != MagickFalse)
1319 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1320 if (image->profiles == (SplayTreeInfo *) NULL)
1321 return((StringInfo *) NULL);
1322 WriteTo8BimProfile(image,name,(StringInfo *) NULL);
1323 profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
1324 image->profiles,name);
1329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1333 % R e s e t P r o f i l e I t e r a t o r %
1337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1339 % ResetImageProfileIterator() resets the image profile iterator. Use it in
1340 % conjunction with GetNextImageProfile() to iterate over all the profiles
1341 % associated with an image.
1343 % The format of the ResetImageProfileIterator method is:
1345 % ResetImageProfileIterator(Image *image)
1347 % A description of each parameter follows:
1349 % o image: the image.
1352 MagickExport void ResetImageProfileIterator(const Image *image)
1354 assert(image != (Image *) NULL);
1355 assert(image->signature == MagickCoreSignature);
1356 if (image->debug != MagickFalse)
1357 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1358 if (image->profiles == (SplayTreeInfo *) NULL)
1360 ResetSplayTreeIterator((SplayTreeInfo *) image->profiles);
1364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1368 % S e t I m a g e P r o f i l e %
1372 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1374 % SetImageProfile() adds a named profile to the image. If a profile with the
1375 % same name already exists, it is replaced. This method differs from the
1376 % ProfileImage() method in that it does not apply CMS color profiles.
1378 % The format of the SetImageProfile method is:
1380 % MagickBooleanType SetImageProfile(Image *image,const char *name,
1381 % const StringInfo *profile)
1383 % A description of each parameter follows:
1385 % o image: the image.
1387 % o name: the profile name, for example icc, exif, and 8bim (8bim is the
1388 % Photoshop wrapper for iptc profiles).
1390 % o profile: A StringInfo structure that contains the named profile.
1394 static void *DestroyProfile(void *profile)
1396 return((void *) DestroyStringInfo((StringInfo *) profile));
1399 static inline const unsigned char *ReadResourceByte(const unsigned char *p,
1400 unsigned char *quantum)
1406 static inline const unsigned char *ReadResourceLong(const unsigned char *p,
1407 unsigned int *quantum)
1409 *quantum=(unsigned int) (*p++) << 24;
1410 *quantum|=(unsigned int) (*p++) << 16;
1411 *quantum|=(unsigned int) (*p++) << 8;
1412 *quantum|=(unsigned int) (*p++);
1416 static inline const unsigned char *ReadResourceShort(const unsigned char *p,
1417 unsigned short *quantum)
1419 *quantum=(unsigned short) (*p++) << 8;
1420 *quantum|=(unsigned short) (*p++);
1424 static inline void WriteResourceLong(unsigned char *p,
1425 const unsigned int quantum)
1430 buffer[0]=(unsigned char) (quantum >> 24);
1431 buffer[1]=(unsigned char) (quantum >> 16);
1432 buffer[2]=(unsigned char) (quantum >> 8);
1433 buffer[3]=(unsigned char) quantum;
1434 (void) memcpy(p,buffer,4);
1437 static void WriteTo8BimProfile(Image *image,const char *name,
1438 const StringInfo *profile)
1444 register const unsigned char
1466 if (LocaleCompare(name,"icc") == 0)
1469 if (LocaleCompare(name,"iptc") == 0)
1472 if (LocaleCompare(name,"xmp") == 0)
1476 profile_8bim=(StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
1477 image->profiles,"8bim");
1478 if (profile_8bim == (StringInfo *) NULL)
1480 datum=GetStringInfoDatum(profile_8bim);
1481 length=GetStringInfoLength(profile_8bim);
1482 for (p=datum; p < (datum+length-16); )
1485 if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1488 p=ReadResourceShort(p,&id);
1489 p=ReadResourceByte(p,&length_byte);
1491 if (((length_byte+1) & 0x01) != 0)
1493 if (p > (datum+length-4))
1495 p=ReadResourceLong(p,&value);
1496 count=(ssize_t) value;
1497 if ((count & 0x01) != 0)
1499 if ((count < 0) || (p > (datum+length-count)) || (count > (ssize_t) length))
1501 if (id != profile_id)
1516 extent=(datum+length)-(p+count);
1517 if (profile == (StringInfo *) NULL)
1520 extract_profile=AcquireStringInfo(offset+extent);
1521 (void) memcpy(extract_profile->datum,datum,offset);
1526 extract_extent=profile->length;
1527 if ((extract_extent & 0x01) != 0)
1529 extract_profile=AcquireStringInfo(offset+extract_extent+extent);
1530 (void) memcpy(extract_profile->datum,datum,offset-4);
1531 WriteResourceLong(extract_profile->datum+offset-4,(unsigned int)
1533 (void) memcpy(extract_profile->datum+offset,
1534 profile->datum,profile->length);
1536 (void) memcpy(extract_profile->datum+offset+extract_extent,
1538 (void) AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1539 ConstantString("8bim"),CloneStringInfo(extract_profile));
1540 extract_profile=DestroyStringInfo(extract_profile);
1546 static void GetProfilesFromResourceBlock(Image *image,
1547 const StringInfo *resource_block,ExceptionInfo *exception)
1552 register const unsigned char
1573 datum=GetStringInfoDatum(resource_block);
1574 length=GetStringInfoLength(resource_block);
1575 for (p=datum; p < (datum+length-16); )
1577 if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1580 p=ReadResourceShort(p,&id);
1581 p=ReadResourceByte(p,&length_byte);
1583 if (((length_byte+1) & 0x01) != 0)
1585 if (p > (datum+length-4))
1587 p=ReadResourceLong(p,&value);
1588 count=(ssize_t) value;
1589 if ((p > (datum+length-count)) || (count > (ssize_t) length) || (count < 0))
1606 p=ReadResourceLong(p,&resolution);
1607 image->resolution.x=((double) resolution)/65536.0;
1608 p=ReadResourceShort(p,&units)+2;
1609 p=ReadResourceLong(p,&resolution)+4;
1610 image->resolution.y=((double) resolution)/65536.0;
1612 Values are always stored as pixels per inch.
1614 if ((ResolutionType) units != PixelsPerCentimeterResolution)
1615 image->units=PixelsPerInchResolution;
1618 image->units=PixelsPerCentimeterResolution;
1619 image->resolution.x/=2.54;
1620 image->resolution.y/=2.54;
1629 profile=AcquireStringInfo(count);
1630 SetStringInfoDatum(profile,p);
1631 (void) SetImageProfileInternal(image,"iptc",profile,MagickTrue,
1633 profile=DestroyStringInfo(profile);
1650 profile=AcquireStringInfo(count);
1651 SetStringInfoDatum(profile,p);
1652 (void) SetImageProfileInternal(image,"icc",profile,MagickTrue,
1654 profile=DestroyStringInfo(profile);
1663 profile=AcquireStringInfo(count);
1664 SetStringInfoDatum(profile,p);
1665 (void) SetImageProfileInternal(image,"exif",profile,MagickTrue,
1667 profile=DestroyStringInfo(profile);
1676 profile=AcquireStringInfo(count);
1677 SetStringInfoDatum(profile,p);
1678 (void) SetImageProfileInternal(image,"xmp",profile,MagickTrue,
1680 profile=DestroyStringInfo(profile);
1690 if ((count & 0x01) != 0)
1695 static MagickBooleanType SetImageProfileInternal(Image *image,const char *name,
1696 const StringInfo *profile,const MagickBooleanType recursive,
1697 ExceptionInfo *exception)
1700 key[MagickPathExtent],
1701 property[MagickPathExtent];
1706 assert(image != (Image *) NULL);
1707 assert(image->signature == MagickCoreSignature);
1708 if (image->debug != MagickFalse)
1709 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1710 if (image->profiles == (SplayTreeInfo *) NULL)
1711 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
1713 (void) CopyMagickString(key,name,MagickPathExtent);
1715 status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1716 ConstantString(key),CloneStringInfo(profile));
1717 if (status != MagickFalse)
1719 if (LocaleCompare(name,"8bim") == 0)
1720 GetProfilesFromResourceBlock(image,profile,exception);
1722 if (recursive == MagickFalse)
1723 WriteTo8BimProfile(image,name,profile);
1726 Inject profile into image properties.
1728 (void) FormatLocaleString(property,MagickPathExtent,"%s:*",name);
1729 (void) GetImageProperty(image,property,exception);
1733 MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name,
1734 const StringInfo *profile,ExceptionInfo *exception)
1736 return(SetImageProfileInternal(image,name,profile,MagickFalse,exception));
1740 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1744 % S y n c I m a g e P r o f i l e s %
1748 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1750 % SyncImageProfiles() synchronizes image properties with the image profiles.
1751 % Currently we only support updating the EXIF resolution and orientation.
1753 % The format of the SyncImageProfiles method is:
1755 % MagickBooleanType SyncImageProfiles(Image *image)
1757 % A description of each parameter follows:
1759 % o image: the image.
1763 static inline int ReadProfileByte(unsigned char **p,size_t *length)
1775 static inline signed short ReadProfileShort(const EndianType endian,
1776 unsigned char *buffer)
1790 if (endian == LSBEndian)
1792 value=(unsigned short) buffer[1] << 8;
1793 value|=(unsigned short) buffer[0];
1794 quantum.unsigned_value=value & 0xffff;
1795 return(quantum.signed_value);
1797 value=(unsigned short) buffer[0] << 8;
1798 value|=(unsigned short) buffer[1];
1799 quantum.unsigned_value=value & 0xffff;
1800 return(quantum.signed_value);
1803 static inline signed int ReadProfileLong(const EndianType endian,
1804 unsigned char *buffer)
1818 if (endian == LSBEndian)
1820 value=(unsigned int) buffer[3] << 24;
1821 value|=(unsigned int) buffer[2] << 16;
1822 value|=(unsigned int) buffer[1] << 8;
1823 value|=(unsigned int) buffer[0];
1824 quantum.unsigned_value=value & 0xffffffff;
1825 return(quantum.signed_value);
1827 value=(unsigned int) buffer[0] << 24;
1828 value|=(unsigned int) buffer[1] << 16;
1829 value|=(unsigned int) buffer[2] << 8;
1830 value|=(unsigned int) buffer[3];
1831 quantum.unsigned_value=value & 0xffffffff;
1832 return(quantum.signed_value);
1835 static inline signed int ReadProfileMSBLong(unsigned char **p,size_t *length)
1842 value=ReadProfileLong(MSBEndian,*p);
1848 static inline signed short ReadProfileMSBShort(unsigned char **p,
1856 value=ReadProfileShort(MSBEndian,*p);
1862 static inline void WriteProfileLong(const EndianType endian,
1863 const size_t value,unsigned char *p)
1868 if (endian == LSBEndian)
1870 buffer[0]=(unsigned char) value;
1871 buffer[1]=(unsigned char) (value >> 8);
1872 buffer[2]=(unsigned char) (value >> 16);
1873 buffer[3]=(unsigned char) (value >> 24);
1874 (void) memcpy(p,buffer,4);
1877 buffer[0]=(unsigned char) (value >> 24);
1878 buffer[1]=(unsigned char) (value >> 16);
1879 buffer[2]=(unsigned char) (value >> 8);
1880 buffer[3]=(unsigned char) value;
1881 (void) memcpy(p,buffer,4);
1884 static void WriteProfileShort(const EndianType endian,
1885 const unsigned short value,unsigned char *p)
1890 if (endian == LSBEndian)
1892 buffer[0]=(unsigned char) value;
1893 buffer[1]=(unsigned char) (value >> 8);
1894 (void) memcpy(p,buffer,2);
1897 buffer[0]=(unsigned char) (value >> 8);
1898 buffer[1]=(unsigned char) value;
1899 (void) memcpy(p,buffer,2);
1902 static MagickBooleanType Sync8BimProfile(Image *image,StringInfo *profile)
1916 length=GetStringInfoLength(profile);
1917 p=GetStringInfoDatum(profile);
1920 if (ReadProfileByte(&p,&length) != 0x38)
1922 if (ReadProfileByte(&p,&length) != 0x42)
1924 if (ReadProfileByte(&p,&length) != 0x49)
1926 if (ReadProfileByte(&p,&length) != 0x4D)
1929 return(MagickFalse);
1930 id=ReadProfileMSBShort(&p,&length);
1931 count=(ssize_t) ReadProfileByte(&p,&length);
1932 if ((count >= (ssize_t) length) || (count < 0))
1933 return(MagickFalse);
1936 if ((*p & 0x01) == 0)
1937 (void) ReadProfileByte(&p,&length);
1938 count=(ssize_t) ReadProfileMSBLong(&p,&length);
1939 if ((count > (ssize_t) length) || (count < 0))
1940 return(MagickFalse);
1941 if ((id == 0x3ED) && (count == 16))
1943 if (image->units == PixelsPerCentimeterResolution)
1944 WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.x*2.54*
1947 WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.x*
1949 WriteProfileShort(MSBEndian,(unsigned short) image->units,p+4);
1950 if (image->units == PixelsPerCentimeterResolution)
1951 WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.y*2.54*
1954 WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.y*
1956 WriteProfileShort(MSBEndian,(unsigned short) image->units,p+12);
1964 MagickBooleanType SyncExifProfile(Image *image,StringInfo *profile)
1966 #define MaxDirectoryStack 16
1967 #define EXIF_DELIMITER "\n"
1968 #define EXIF_NUM_FORMATS 12
1969 #define TAG_EXIF_OFFSET 0x8769
1970 #define TAG_INTEROP_OFFSET 0xa005
1972 typedef struct _DirectoryInfo
1982 directory_stack[MaxDirectoryStack];
2001 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
2008 Set EXIF resolution tag.
2010 length=GetStringInfoLength(profile);
2011 exif=GetStringInfoDatum(profile);
2013 return(MagickFalse);
2014 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2015 if ((id != 0x4949) && (id != 0x4D4D))
2019 if (ReadProfileByte(&exif,&length) != 0x45)
2021 if (ReadProfileByte(&exif,&length) != 0x78)
2023 if (ReadProfileByte(&exif,&length) != 0x69)
2025 if (ReadProfileByte(&exif,&length) != 0x66)
2027 if (ReadProfileByte(&exif,&length) != 0x00)
2029 if (ReadProfileByte(&exif,&length) != 0x00)
2034 return(MagickFalse);
2035 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2044 return(MagickFalse);
2045 if (ReadProfileShort(endian,exif+2) != 0x002a)
2046 return(MagickFalse);
2048 This the offset to the first IFD.
2050 offset=(ssize_t) ReadProfileLong(endian,exif+4);
2051 if ((offset < 0) || ((size_t) offset >= length))
2052 return(MagickFalse);
2053 directory=exif+offset;
2056 exif_resources=NewSplayTree((int (*)(const void *,const void *)) NULL,
2057 (void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2063 directory=directory_stack[level].directory;
2064 entry=directory_stack[level].entry;
2066 if ((directory < exif) || (directory > (exif+length-2)))
2069 Determine how many entries there are in the current IFD.
2071 number_entries=ReadProfileShort(endian,directory);
2072 for ( ; entry < number_entries; entry++)
2077 register unsigned char
2088 q=(unsigned char *) (directory+2+(12*entry));
2089 if (q > (exif+length-12))
2090 break; /* corrupt EXIF */
2091 if (GetValueFromSplayTree(exif_resources,q) == q)
2093 (void) AddValueToSplayTree(exif_resources,q,q);
2094 tag_value=(ssize_t) ReadProfileShort(endian,q);
2095 format=(ssize_t) ReadProfileShort(endian,q+2);
2096 if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2098 components=(int) ReadProfileLong(endian,q+4);
2100 break; /* corrupt EXIF */
2101 number_bytes=(size_t) components*format_bytes[format];
2102 if ((ssize_t) number_bytes < components)
2103 break; /* prevent overflow */
2104 if (number_bytes <= 4)
2109 The directory entry contains an offset.
2111 offset=(ssize_t) ReadProfileLong(endian,q+8);
2112 if ((offset < 0) || ((size_t) (offset+number_bytes) > length))
2114 if (~length < number_bytes)
2115 continue; /* prevent overflow */
2116 p=(unsigned char *) (exif+offset);
2122 (void) WriteProfileLong(endian,(size_t) (image->resolution.x+0.5),p);
2123 (void) WriteProfileLong(endian,1UL,p+4);
2128 (void) WriteProfileLong(endian,(size_t) (image->resolution.y+0.5),p);
2129 (void) WriteProfileLong(endian,1UL,p+4);
2134 if (number_bytes == 4)
2136 (void) WriteProfileLong(endian,(size_t) image->orientation,p);
2139 (void) WriteProfileShort(endian,(unsigned short) image->orientation,
2145 if (number_bytes == 4)
2147 (void) WriteProfileLong(endian,(size_t) (image->units+1),p);
2150 (void) WriteProfileShort(endian,(unsigned short) (image->units+1),p);
2156 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2158 offset=(ssize_t) ReadProfileLong(endian,p);
2159 if (((size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2161 directory_stack[level].directory=directory;
2163 directory_stack[level].entry=entry;
2165 directory_stack[level].directory=exif+offset;
2166 directory_stack[level].entry=0;
2168 if ((directory+2+(12*number_entries)) > (exif+length))
2170 offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2172 if ((offset != 0) && ((size_t) offset < length) &&
2173 (level < (MaxDirectoryStack-2)))
2175 directory_stack[level].directory=exif+offset;
2176 directory_stack[level].entry=0;
2183 } while (level > 0);
2184 exif_resources=DestroySplayTree(exif_resources);
2188 MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
2197 profile=(StringInfo *) GetImageProfile(image,"8BIM");
2198 if (profile != (StringInfo *) NULL)
2199 if (Sync8BimProfile(image,profile) == MagickFalse)
2201 profile=(StringInfo *) GetImageProfile(image,"EXIF");
2202 if (profile != (StringInfo *) NULL)
2203 if (SyncExifProfile(image,profile) == MagickFalse)