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-2011 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "MagickCore/studio.h"
43 #include "MagickCore/attribute.h"
44 #include "MagickCore/cache.h"
45 #include "MagickCore/color.h"
46 #include "MagickCore/colorspace-private.h"
47 #include "MagickCore/configure.h"
48 #include "MagickCore/exception.h"
49 #include "MagickCore/exception-private.h"
50 #include "MagickCore/hashmap.h"
51 #include "MagickCore/image.h"
52 #include "MagickCore/memory_.h"
53 #include "MagickCore/monitor.h"
54 #include "MagickCore/monitor-private.h"
55 #include "MagickCore/option.h"
56 #include "MagickCore/pixel-accessor.h"
57 #include "MagickCore/profile.h"
58 #include "MagickCore/profile-private.h"
59 #include "MagickCore/property.h"
60 #include "MagickCore/quantum.h"
61 #include "MagickCore/quantum-private.h"
62 #include "MagickCore/splay-tree.h"
63 #include "MagickCore/string_.h"
64 #include "MagickCore/thread-private.h"
65 #include "MagickCore/token.h"
66 #include "MagickCore/utility.h"
67 #if defined(MAGICKCORE_LCMS_DELEGATE)
68 #if defined(MAGICKCORE_HAVE_LCMS_LCMS2_H)
70 #include <lcms/lcms2.h>
71 #elif defined(MAGICKCORE_HAVE_LCMS2_H)
74 #elif defined(MAGICKCORE_HAVE_LCMS_LCMS_H)
75 #include <lcms/lcms.h>
84 #if !defined(LCMS_VERSION) || (LCMS_VERSION < 2000)
85 #define cmsSigCmykData icSigCmykData
86 #define cmsSigGrayData icSigGrayData
87 #define cmsSigLabData icSigLabData
88 #define cmsSigLuvData icSigLuvData
89 #define cmsSigRgbData icSigRgbData
90 #define cmsSigXYZData icSigXYZData
91 #define cmsSigYCbCrData icSigYCbCrData
92 #define cmsSigLinkClass icSigLinkClass
93 #define cmsColorSpaceSignature icColorSpaceSignature
94 #define cmsUInt32Number DWORD
95 #define cmsSetLogErrorHandler(handler) cmsSetErrorHandler(handler)
96 #define cmsCreateTransformTHR(context,source_profile,source_type, \
97 target_profile,target_type,intent,flags) cmsCreateTransform(source_profile, \
98 source_type,target_profile,target_type,intent,flags);
99 #define cmsOpenProfileFromMemTHR(context,profile,length) \
100 cmsOpenProfileFromMem(profile,length)
104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
108 % C l o n e I m a g e P r o f i l e s %
112 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
114 % CloneImageProfiles() clones one or more image profiles.
116 % The format of the CloneImageProfiles method is:
118 % MagickBooleanType CloneImageProfiles(Image *image,
119 % const Image *clone_image)
121 % A description of each parameter follows:
123 % o image: the image.
125 % o clone_image: the clone image.
128 MagickExport MagickBooleanType CloneImageProfiles(Image *image,
129 const Image *clone_image)
131 assert(image != (Image *) NULL);
132 assert(image->signature == MagickSignature);
133 if (image->debug != MagickFalse)
134 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
135 assert(clone_image != (const Image *) NULL);
136 assert(clone_image->signature == MagickSignature);
137 image->color_profile.length=clone_image->color_profile.length;
138 image->color_profile.info=clone_image->color_profile.info;
139 image->iptc_profile.length=clone_image->iptc_profile.length;
140 image->iptc_profile.info=clone_image->iptc_profile.info;
141 if (clone_image->profiles != (void *) NULL)
142 image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
143 (void *(*)(void *)) ConstantString,(void *(*)(void *)) CloneStringInfo);
148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
152 % D e l e t e I m a g e P r o f i l e %
156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
158 % DeleteImageProfile() deletes a profile from the image by its name.
160 % The format of the DeleteImageProfile method is:
162 % MagickBooleanTyupe DeleteImageProfile(Image *image,const char *name)
164 % A description of each parameter follows:
166 % o image: the image.
168 % o name: the profile name.
171 MagickExport MagickBooleanType DeleteImageProfile(Image *image,const char *name)
173 assert(image != (Image *) NULL);
174 assert(image->signature == MagickSignature);
175 if (image->debug != MagickFalse)
176 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
177 if (image->profiles == (SplayTreeInfo *) NULL)
179 return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->profiles,name));
183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
187 % D e s t r o y I m a g e P r o f i l e s %
191 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
193 % DestroyImageProfiles() releases memory associated with an image profile map.
195 % The format of the DestroyProfiles method is:
197 % void DestroyImageProfiles(Image *image)
199 % A description of each parameter follows:
201 % o image: the image.
204 MagickExport void DestroyImageProfiles(Image *image)
206 if (image->profiles != (SplayTreeInfo *) NULL)
207 image->profiles=DestroySplayTree((SplayTreeInfo *) image->profiles);
211 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
215 % G e t I m a g e P r o f i l e %
219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
221 % GetImageProfile() gets a profile associated with an image by name.
223 % The format of the GetImageProfile method is:
225 % const StringInfo *GetImageProfile(const Image *image,const char *name)
227 % A description of each parameter follows:
229 % o image: the image.
231 % o name: the profile name.
234 MagickExport const StringInfo *GetImageProfile(const Image *image,
243 assert(image != (Image *) NULL);
244 assert(image->signature == MagickSignature);
245 if (image->debug != MagickFalse)
246 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
247 if (image->profiles == (SplayTreeInfo *) NULL)
248 return((StringInfo *) NULL);
249 (void) CopyMagickString(key,name,MaxTextExtent);
250 profile=(const StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
251 image->profiles,key);
256 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260 % G e t N e x t I m a g e P r o f i l e %
264 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
266 % GetNextImageProfile() gets the next profile name for an image.
268 % The format of the GetNextImageProfile method is:
270 % char *GetNextImageProfile(const Image *image)
272 % A description of each parameter follows:
274 % o hash_info: the hash info.
277 MagickExport char *GetNextImageProfile(const Image *image)
279 assert(image != (Image *) NULL);
280 assert(image->signature == MagickSignature);
281 if (image->debug != MagickFalse)
282 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
283 if (image->profiles == (SplayTreeInfo *) NULL)
284 return((char *) NULL);
285 return((char *) GetNextKeyInSplayTree((SplayTreeInfo *) image->profiles));
289 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
293 % P r o f i l e I m a g e %
297 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
299 % ProfileImage() associates, applies, or removes an ICM, IPTC, or generic
300 % profile with / to / from an image. If the profile is NULL, it is removed
301 % from the image otherwise added or applied. Use a name of '*' and a profile
302 % of NULL to remove all profiles from the image.
304 % ICC and ICM profiles are handled as follows: If the image does not have
305 % an associated color profile, the one you provide is associated with the
306 % image and the image pixels are not transformed. Otherwise, the colorspace
307 % transform defined by the existing and new profile are applied to the image
308 % pixels and the new profile is associated with the image.
310 % The format of the ProfileImage method is:
312 % MagickBooleanType ProfileImage(Image *image,const char *name,
313 % const void *datum,const size_t length,const MagickBooleanType clone)
315 % A description of each parameter follows:
317 % o image: the image.
319 % o name: Name of profile to add or remove: ICC, IPTC, or generic profile.
321 % o datum: the profile data.
323 % o length: the length of the profile.
325 % o clone: should be MagickFalse.
329 #if defined(MAGICKCORE_LCMS_DELEGATE)
331 static unsigned short **DestroyPixelThreadSet(unsigned short **pixels)
336 assert(pixels != (unsigned short **) NULL);
337 for (i=0; i < (ssize_t) GetOpenMPMaximumThreads(); i++)
338 if (pixels[i] != (unsigned short *) NULL)
339 pixels[i]=(unsigned short *) RelinquishMagickMemory(pixels[i]);
340 pixels=(unsigned short **) RelinquishMagickMemory(pixels);
344 static unsigned short **AcquirePixelThreadSet(const size_t columns,
345 const size_t channels)
356 number_threads=GetOpenMPMaximumThreads();
357 pixels=(unsigned short **) AcquireQuantumMemory(number_threads,
359 if (pixels == (unsigned short **) NULL)
360 return((unsigned short **) NULL);
361 (void) ResetMagickMemory(pixels,0,number_threads*sizeof(*pixels));
362 for (i=0; i < (ssize_t) number_threads; i++)
364 pixels[i]=(unsigned short *) AcquireQuantumMemory(columns,channels*
366 if (pixels[i] == (unsigned short *) NULL)
367 return(DestroyPixelThreadSet(pixels));
372 static cmsHTRANSFORM *DestroyTransformThreadSet(cmsHTRANSFORM *transform)
377 assert(transform != (cmsHTRANSFORM *) NULL);
378 for (i=0; i < (ssize_t) GetOpenMPMaximumThreads(); i++)
379 if (transform[i] != (cmsHTRANSFORM) NULL)
380 cmsDeleteTransform(transform[i]);
381 transform=(cmsHTRANSFORM *) RelinquishMagickMemory(transform);
385 static cmsHTRANSFORM *AcquireTransformThreadSet(Image *image,
386 const cmsHPROFILE source_profile,const cmsUInt32Number source_type,
387 const cmsHPROFILE target_profile,const cmsUInt32Number target_type,
388 const int intent,const cmsUInt32Number flags)
399 number_threads=GetOpenMPMaximumThreads();
400 transform=(cmsHTRANSFORM *) AcquireQuantumMemory(number_threads,
402 if (transform == (cmsHTRANSFORM *) NULL)
403 return((cmsHTRANSFORM *) NULL);
404 (void) ResetMagickMemory(transform,0,number_threads*sizeof(*transform));
405 for (i=0; i < (ssize_t) number_threads; i++)
407 transform[i]=cmsCreateTransformTHR(image,source_profile,source_type,
408 target_profile,target_type,intent,flags);
409 if (transform[i] == (cmsHTRANSFORM) NULL)
410 return(DestroyTransformThreadSet(transform));
416 static MagickBooleanType SetAdobeRGB1998ImageProfile(Image *image)
419 AdobeRGB1998Profile[] =
421 0x00, 0x00, 0x02, 0x30, 0x41, 0x44, 0x42, 0x45, 0x02, 0x10, 0x00,
422 0x00, 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59,
423 0x5a, 0x20, 0x07, 0xd0, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x13, 0x00,
424 0x33, 0x00, 0x3b, 0x61, 0x63, 0x73, 0x70, 0x41, 0x50, 0x50, 0x4c,
425 0x00, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x00,
426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
427 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00,
428 0x00, 0xd3, 0x2d, 0x41, 0x44, 0x42, 0x45, 0x00, 0x00, 0x00, 0x00,
429 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
433 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
434 0x32, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00,
435 0x00, 0x6b, 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x9c, 0x00,
436 0x00, 0x00, 0x14, 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x01, 0xb0,
437 0x00, 0x00, 0x00, 0x14, 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01,
438 0xc4, 0x00, 0x00, 0x00, 0x0e, 0x67, 0x54, 0x52, 0x43, 0x00, 0x00,
439 0x01, 0xd4, 0x00, 0x00, 0x00, 0x0e, 0x62, 0x54, 0x52, 0x43, 0x00,
440 0x00, 0x01, 0xe4, 0x00, 0x00, 0x00, 0x0e, 0x72, 0x58, 0x59, 0x5a,
441 0x00, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x00, 0x14, 0x67, 0x58, 0x59,
442 0x5a, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x14, 0x62, 0x58,
443 0x59, 0x5a, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x14, 0x74,
444 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x70, 0x79,
445 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x32, 0x30, 0x30, 0x30, 0x20,
446 0x41, 0x64, 0x6f, 0x62, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65,
447 0x6d, 0x73, 0x20, 0x49, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72,
448 0x61, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x41, 0x64, 0x6f,
450 0x62, 0x65, 0x20, 0x52, 0x47, 0x42, 0x20, 0x28, 0x31, 0x39, 0x39,
451 0x38, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
458 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00,
459 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00,
460 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
461 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
462 0x00, 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
463 0x00, 0x01, 0x02, 0x33, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76, 0x00,
464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x33, 0x00, 0x00,
465 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466 0x01, 0x02, 0x33, 0x00, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00,
467 0x00, 0x00, 0x00, 0x00, 0x9c, 0x18, 0x00, 0x00, 0x4f, 0xa5, 0x00,
468 0x00, 0x04, 0xfc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
469 0x00, 0x00, 0x34, 0x8d, 0x00, 0x00, 0xa0, 0x2c, 0x00, 0x00, 0x0f,
470 0x95, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
471 0x26, 0x31, 0x00, 0x00, 0x10, 0x2f, 0x00, 0x00, 0xbe, 0x9c
480 assert(image != (Image *) NULL);
481 assert(image->signature == MagickSignature);
482 if (GetImageProfile(image,"icm") != (const StringInfo *) NULL)
484 profile=AcquireStringInfo(sizeof(AdobeRGB1998Profile));
485 SetStringInfoDatum(profile,AdobeRGB1998Profile);
486 status=SetImageProfile(image,"icm",profile);
487 profile=DestroyStringInfo(profile);
491 static MagickBooleanType SetsRGBImageProfile(Image *image)
496 0x00, 0x00, 0x0c, 0x48, 0x4c, 0x69, 0x6e, 0x6f, 0x02, 0x10, 0x00,
497 0x00, 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59,
498 0x5a, 0x20, 0x07, 0xce, 0x00, 0x02, 0x00, 0x09, 0x00, 0x06, 0x00,
499 0x31, 0x00, 0x00, 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54,
500 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47,
501 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
502 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00,
503 0x00, 0xd3, 0x2d, 0x48, 0x50, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
504 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
505 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
508 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00,
509 0x33, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00,
510 0x00, 0x6c, 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0xf0, 0x00,
511 0x00, 0x00, 0x14, 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x02, 0x04,
512 0x00, 0x00, 0x00, 0x14, 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x02,
513 0x18, 0x00, 0x00, 0x00, 0x14, 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00,
514 0x02, 0x2c, 0x00, 0x00, 0x00, 0x14, 0x62, 0x58, 0x59, 0x5a, 0x00,
515 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x14, 0x64, 0x6d, 0x6e, 0x64,
516 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70, 0x64, 0x6d, 0x64,
517 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88, 0x76, 0x75,
518 0x65, 0x64, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x86, 0x76,
519 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xd4, 0x00, 0x00, 0x00, 0x24,
520 0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00,
521 0x14, 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x04, 0x0c, 0x00, 0x00,
522 0x00, 0x24, 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x04, 0x30, 0x00,
523 0x00, 0x00, 0x0c, 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x3c,
524 0x00, 0x00, 0x08, 0x0c, 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04,
525 0x3c, 0x00, 0x00, 0x08, 0x0c, 0x62, 0x54, 0x52, 0x43, 0x00, 0x00,
526 0x04, 0x3c, 0x00, 0x00, 0x08, 0x0c, 0x74, 0x65, 0x78, 0x74, 0x00,
527 0x00, 0x00, 0x00, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
528 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, 0x39, 0x38, 0x20,
529 0x48, 0x65, 0x77, 0x6c, 0x65, 0x74, 0x74, 0x2d, 0x50, 0x61, 0x63,
530 0x6b, 0x61, 0x72, 0x64, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e,
531 0x79, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
532 0x00, 0x00, 0x00, 0x12, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45,
533 0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00,
534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
535 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39,
536 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00,
537 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
540 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xcc, 0x58,
543 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5a,
545 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa2, 0x00, 0x00,
546 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20, 0x00,
547 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x99, 0x00, 0x00, 0xb7, 0x85,
548 0x00, 0x00, 0x18, 0xda, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00,
549 0x00, 0x00, 0x00, 0x24, 0xa0, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00,
550 0xb6, 0xcf, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00,
551 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74, 0x70,
552 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
553 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74, 0x70,
555 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
556 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00,
561 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43, 0x20, 0x36, 0x31,
562 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44, 0x65, 0x66,
563 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63, 0x6f,
564 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
565 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43, 0x20,
567 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
568 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20,
569 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63,
570 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73,
573 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x52, 0x65,
574 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65,
575 0x77, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74,
576 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 0x43, 0x36,
577 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x52, 0x65,
579 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65,
580 0x77, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74,
581 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 0x43, 0x36,
582 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00,
583 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585 0x00, 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
586 0xa4, 0xfe, 0x00, 0x14, 0x5f, 0x2e, 0x00, 0x10, 0xcf, 0x14, 0x00,
587 0x03, 0xed, 0xcc, 0x00, 0x04, 0x13, 0x0b, 0x00, 0x03, 0x5c, 0x9e,
588 0x00, 0x00, 0x00, 0x01, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00,
589 0x00, 0x00, 0x4c, 0x09, 0x56, 0x00, 0x50, 0x00, 0x00, 0x00, 0x57,
590 0x1f, 0xe7, 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00,
591 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
593 0x8f, 0x00, 0x00, 0x00, 0x02, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00,
594 0x00, 0x00, 0x43, 0x52, 0x54, 0x20, 0x63, 0x75, 0x72, 0x76, 0x00,
595 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x05,
596 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19, 0x00, 0x1e, 0x00,
597 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37, 0x00, 0x3b,
598 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54, 0x00,
599 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
600 0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00,
601 0x90, 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9,
602 0x00, 0xae, 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00,
603 0xc6, 0x00, 0xcb, 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0,
604 0x00, 0xe5, 0x00, 0xeb, 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01,
605 0x01, 0x01, 0x07, 0x01, 0x0d, 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f,
606 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32, 0x01, 0x38, 0x01, 0x3e, 0x01,
607 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59, 0x01, 0x60, 0x01, 0x67,
608 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83, 0x01, 0x8b, 0x01,
609 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1, 0x01, 0xb9,
610 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1, 0x01,
611 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
612 0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02,
613 0x4b, 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a,
614 0x02, 0x84, 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02,
615 0xb6, 0x02, 0xc1, 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb,
616 0x02, 0xf5, 0x03, 0x00, 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03,
617 0x2d, 0x03, 0x38, 0x03, 0x43, 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66,
618 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a, 0x03, 0x96, 0x03, 0xa2, 0x03,
619 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3, 0x03, 0xe0, 0x03, 0xec,
620 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20, 0x04, 0x2d, 0x04,
621 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71, 0x04, 0x7e,
622 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4, 0x04,
623 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
624 0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05,
625 0x77, 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5,
626 0x05, 0xd5, 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06,
627 0x27, 0x06, 0x37, 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b,
628 0x06, 0x8c, 0x06, 0x9d, 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06,
629 0xe3, 0x06, 0xf5, 0x07, 0x07, 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d,
630 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74, 0x07, 0x86, 0x07, 0x99, 0x07,
631 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5, 0x07, 0xf8, 0x08, 0x0b,
632 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a, 0x08, 0x6e, 0x08,
633 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2, 0x08, 0xe7,
634 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f, 0x09,
635 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
636 0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a,
637 0x54, 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5,
638 0x0a, 0xdc, 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b,
639 0x51, 0x0b, 0x69, 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8,
640 0x0b, 0xe1, 0x0b, 0xf9, 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c,
641 0x5c, 0x0c, 0x75, 0x0c, 0x8e, 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9,
642 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26, 0x0d, 0x40, 0x0d, 0x5a, 0x0d,
643 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3, 0x0d, 0xde, 0x0d, 0xf8,
644 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64, 0x0e, 0x7f, 0x0e,
645 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09, 0x0f, 0x25,
646 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3, 0x0f,
647 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
648 0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11,
649 0x13, 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa,
650 0x11, 0xc9, 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12,
651 0x64, 0x12, 0x84, 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03,
652 0x13, 0x23, 0x13, 0x43, 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13,
653 0xc5, 0x13, 0xe5, 0x14, 0x06, 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a,
654 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce, 0x14, 0xf0, 0x15, 0x12, 0x15,
655 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b, 0x15, 0xbd, 0x15, 0xe0,
656 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c, 0x16, 0x8f, 0x16,
657 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41, 0x17, 0x65,
658 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b, 0x18,
659 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
660 0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19,
661 0xdd, 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e,
662 0x1a, 0xc5, 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b,
663 0x8a, 0x1b, 0xb2, 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52,
664 0x1c, 0x7b, 0x1c, 0xa3, 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d,
665 0x47, 0x1d, 0x70, 0x1d, 0x99, 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16,
666 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94, 0x1e, 0xbe, 0x1e, 0xe9, 0x1f,
667 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94, 0x1f, 0xbf, 0x1f, 0xea,
668 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98, 0x20, 0xc4, 0x20,
669 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1, 0x21, 0xce,
670 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf, 0x22,
671 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
672 0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24,
673 0xda, 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7,
674 0x25, 0xf7, 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26,
675 0xe8, 0x27, 0x18, 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc,
676 0x28, 0x0d, 0x28, 0x3f, 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29,
677 0x06, 0x29, 0x38, 0x29, 0x6b, 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02,
678 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b, 0x2a, 0xcf, 0x2b, 0x02, 0x2b,
679 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1, 0x2c, 0x05, 0x2c, 0x39,
680 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c, 0x2d, 0x41, 0x2d,
681 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c, 0x2e, 0x82,
682 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91, 0x2f,
683 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
684 0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32,
685 0x2a, 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46,
686 0x33, 0x7f, 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34,
687 0x9e, 0x34, 0xd8, 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2,
688 0x35, 0xfd, 0x36, 0x37, 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37,
689 0x24, 0x37, 0x60, 0x37, 0x9c, 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50,
690 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05, 0x39, 0x42, 0x39, 0x7f, 0x39,
691 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74, 0x3a, 0xb2, 0x3a, 0xef,
692 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8, 0x3c, 0x27, 0x3c,
693 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61, 0x3d, 0xa1,
694 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0, 0x3f,
695 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
696 0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41,
697 0xee, 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a,
698 0x43, 0x7d, 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44,
699 0xce, 0x45, 0x12, 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22,
700 0x46, 0x67, 0x46, 0xab, 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47,
701 0xc0, 0x48, 0x05, 0x48, 0x4b, 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d,
702 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0, 0x4a, 0x37, 0x4a, 0x7d, 0x4a,
703 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a, 0x4b, 0xe2, 0x4c, 0x2a,
704 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a, 0x4d, 0x93, 0x4d,
705 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00, 0x4f, 0x49,
706 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb, 0x51,
707 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
708 0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54,
709 0x42, 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2,
710 0x56, 0x0f, 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57,
711 0x92, 0x57, 0xe0, 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a,
712 0x59, 0x69, 0x59, 0xb8, 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a,
713 0xf5, 0x5b, 0x45, 0x5b, 0x95, 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86,
714 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78, 0x5d, 0xc9, 0x5e, 0x1a, 0x5e,
715 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61, 0x5f, 0xb3, 0x60, 0x05,
716 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f, 0x61, 0xa2, 0x61,
717 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43, 0x63, 0x97,
718 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d, 0x65,
719 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
720 0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69,
721 0x43, 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7,
722 0x6b, 0x4f, 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d,
723 0x08, 0x6d, 0x60, 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4,
724 0x6f, 0x1e, 0x6f, 0x78, 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70,
725 0xe0, 0x71, 0x3a, 0x71, 0x95, 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6,
726 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8, 0x74, 0x14, 0x74, 0x70, 0x74,
727 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1, 0x76, 0x3e, 0x76, 0x9b,
728 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11, 0x78, 0x6e, 0x78,
729 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46, 0x7a, 0xa5,
730 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81, 0x7c,
731 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
732 0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81,
733 0x0a, 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4,
734 0x83, 0x57, 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85,
735 0x47, 0x85, 0xab, 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b,
736 0x87, 0x9f, 0x88, 0x04, 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89,
737 0x99, 0x89, 0xfe, 0x8a, 0x64, 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96,
738 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca, 0x8d, 0x31, 0x8d, 0x98, 0x8d,
739 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36, 0x8f, 0x9e, 0x90, 0x06,
740 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8, 0x92, 0x11, 0x92,
741 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20, 0x94, 0x8a,
742 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f, 0x97,
743 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
744 0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b,
745 0xaf, 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2,
746 0x9e, 0x40, 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0,
747 0x69, 0xa0, 0xd8, 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96,
748 0xa3, 0x06, 0xa3, 0x76, 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5,
749 0x38, 0xa5, 0xa9, 0xa6, 0x1a, 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e,
750 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4, 0xa9, 0x37, 0xa9, 0xa9, 0xaa,
751 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75, 0xab, 0xe9, 0xac, 0x5c,
752 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d, 0xae, 0xa1, 0xaf,
753 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea, 0xb1, 0x60,
754 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae, 0xb4,
755 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
756 0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9,
757 0x4a, 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7,
758 0xbc, 0x21, 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe,
759 0x84, 0xbe, 0xff, 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec,
760 0xc1, 0x67, 0xc1, 0xe3, 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3,
761 0xd4, 0xc4, 0x51, 0xc4, 0xce, 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46,
762 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf, 0xc8, 0x3d, 0xc8, 0xbc, 0xc9,
763 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7, 0xcb, 0x36, 0xcb, 0xb6,
764 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5, 0xce, 0x36, 0xce,
765 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba, 0xd1, 0x3c,
766 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6, 0xd4,
767 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
768 0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9,
769 0xf1, 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a,
770 0xdd, 0x10, 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf,
771 0xaf, 0xe0, 0x36, 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53,
772 0xe2, 0xdb, 0xe3, 0x63, 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5,
773 0x84, 0xe6, 0x0d, 0xe6, 0x96, 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32,
774 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0, 0xea, 0x5b, 0xea, 0xe5, 0xeb,
775 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11, 0xed, 0x9c, 0xee, 0x28,
776 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58, 0xf0, 0xe5, 0xf1,
777 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7, 0xf4, 0x34,
778 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb, 0xf7,
779 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
780 0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd,
781 0xba, 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
790 assert(image != (Image *) NULL);
791 assert(image->signature == MagickSignature);
792 if (GetImageProfile(image,"icm") != (const StringInfo *) NULL)
794 profile=AcquireStringInfo(sizeof(sRGBProfile));
795 SetStringInfoDatum(profile,sRGBProfile);
796 status=SetImageProfile(image,"icm",profile);
797 profile=DestroyStringInfo(profile);
800 #if defined(MAGICKCORE_LCMS_DELEGATE)
801 #if defined(LCMS_VERSION) && (LCMS_VERSION >= 2000)
802 static void LCMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
808 (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%u, %s",
809 severity,message != (char *) NULL ? message : "no message");
810 image=(Image *) context;
811 if (image != (Image *) NULL)
812 (void) ThrowMagickException(&image->exception,GetMagickModule(),
813 ImageWarning,"UnableToTransformColorspace","`%s'",image->filename);
817 static int LCMSExceptionHandler(int severity,const char *message)
819 (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%d, %s",
820 severity,message != (char *) NULL ? message : "no message");
826 MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
827 const void *datum,const size_t length,
828 const MagickBooleanType magick_unused(clone))
830 #define ProfileImageTag "Profile/Image"
831 #define ThrowProfileException(severity,tag,context) \
833 if (source_profile != (cmsHPROFILE) NULL) \
834 (void) cmsCloseProfile(source_profile); \
835 if (target_profile != (cmsHPROFILE) NULL) \
836 (void) cmsCloseProfile(target_profile); \
837 ThrowBinaryException(severity,tag,context); \
849 assert(image != (Image *) NULL);
850 assert(image->signature == MagickSignature);
851 if (image->debug != MagickFalse)
852 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
853 assert(name != (const char *) NULL);
854 exception=(&image->exception);
855 if ((datum == (const void *) NULL) || (length == 0))
868 Delete image profile(s).
870 names=ConstantString(name);
871 (void) SubstituteString(&names,","," ");
872 arguments=StringToArgv(names,&number_arguments);
873 names=DestroyString(names);
874 if (arguments == (char **) NULL)
876 ResetImageProfileIterator(image);
877 for (name=GetNextImageProfile(image); name != (const char *) NULL; )
879 for (i=1; i < (ssize_t) number_arguments; i++)
881 if ((*arguments[i] == '!') &&
882 (LocaleCompare(name,arguments[i]+1) == 0))
884 if (GlobExpression(name,arguments[i],MagickTrue) != MagickFalse)
886 (void) DeleteImageProfile(image,name);
887 ResetImageProfileIterator(image);
891 name=GetNextImageProfile(image);
893 for (i=0; i < (ssize_t) number_arguments; i++)
894 arguments[i]=DestroyString(arguments[i]);
895 arguments=(char **) RelinquishMagickMemory(arguments);
899 Add a ICC, IPTC, or generic profile to the image.
902 profile=AcquireStringInfo((size_t) length);
903 SetStringInfoDatum(profile,(unsigned char *) datum);
904 if ((LocaleCompare(name,"icc") != 0) && (LocaleCompare(name,"icm") != 0))
905 status=SetImageProfile(image,name,profile);
911 icc_profile=GetImageProfile(image,"icc");
912 if ((icc_profile != (const StringInfo *) NULL) &&
913 (CompareStringInfo(icc_profile,profile) == 0))
918 value=GetImageProperty(image,"exif:ColorSpace");
919 if (LocaleCompare(value,"1") != 0)
920 (void) SetsRGBImageProfile(image);
921 value=GetImageProperty(image,"exif:InteroperabilityIndex");
922 if (LocaleCompare(value,"R98.") != 0)
923 (void) SetsRGBImageProfile(image);
924 value=GetImageProperty(image,"exif:InteroperabilityIndex");
925 if (LocaleCompare(value,"R03.") != 0)
926 (void) SetAdobeRGB1998ImageProfile(image);
927 icc_profile=GetImageProfile(image,"icc");
929 if ((icc_profile != (const StringInfo *) NULL) &&
930 (CompareStringInfo(icc_profile,profile) == 0))
932 profile=DestroyStringInfo(profile);
935 #if !defined(MAGICKCORE_LCMS_DELEGATE)
936 (void) ThrowMagickException(&image->exception,GetMagickModule(),
937 MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn",
938 "`%s' (LCMS)",image->filename);
945 Transform pixel colors as defined by the color profiles.
947 cmsSetLogErrorHandler(LCMSExceptionHandler);
948 source_profile=cmsOpenProfileFromMemTHR(image,
949 GetStringInfoDatum(profile),(cmsUInt32Number)
950 GetStringInfoLength(profile));
951 if (source_profile == (cmsHPROFILE) NULL)
952 ThrowBinaryException(ResourceLimitError,
953 "ColorspaceColorProfileMismatch",name);
954 if ((cmsGetDeviceClass(source_profile) != cmsSigLinkClass) &&
955 (icc_profile == (StringInfo *) NULL))
956 status=SetImageProfile(image,name,profile);
966 cmsColorSpaceSignature
997 **restrict source_pixels,
998 **restrict target_pixels;
1000 target_profile=(cmsHPROFILE) NULL;
1001 if (icc_profile != (StringInfo *) NULL)
1003 target_profile=source_profile;
1004 source_profile=cmsOpenProfileFromMemTHR(image,
1005 GetStringInfoDatum(icc_profile),(cmsUInt32Number)
1006 GetStringInfoLength(icc_profile));
1007 if (source_profile == (cmsHPROFILE) NULL)
1008 ThrowProfileException(ResourceLimitError,
1009 "ColorspaceColorProfileMismatch",name);
1011 switch (cmsGetColorSpace(source_profile))
1013 case cmsSigCmykData:
1015 source_colorspace=CMYKColorspace;
1016 source_type=(cmsUInt32Number) TYPE_CMYK_16;
1020 case cmsSigGrayData:
1022 source_colorspace=GRAYColorspace;
1023 source_type=(cmsUInt32Number) TYPE_GRAY_16;
1029 source_colorspace=LabColorspace;
1030 source_type=(cmsUInt32Number) TYPE_Lab_16;
1036 source_colorspace=YUVColorspace;
1037 source_type=(cmsUInt32Number) TYPE_YUV_16;
1043 source_colorspace=RGBColorspace;
1044 source_type=(cmsUInt32Number) TYPE_RGB_16;
1050 source_colorspace=XYZColorspace;
1051 source_type=(cmsUInt32Number) TYPE_XYZ_16;
1055 case cmsSigYCbCrData:
1057 source_colorspace=YCbCrColorspace;
1058 source_type=(cmsUInt32Number) TYPE_YCbCr_16;
1064 source_colorspace=UndefinedColorspace;
1065 source_type=(cmsUInt32Number) TYPE_RGB_16;
1070 signature=cmsGetPCS(source_profile);
1071 if (target_profile != (cmsHPROFILE) NULL)
1072 signature=cmsGetColorSpace(target_profile);
1075 case cmsSigCmykData:
1077 target_colorspace=CMYKColorspace;
1078 target_type=(cmsUInt32Number) TYPE_CMYK_16;
1084 target_colorspace=LabColorspace;
1085 target_type=(cmsUInt32Number) TYPE_Lab_16;
1089 case cmsSigGrayData:
1091 target_colorspace=GRAYColorspace;
1092 target_type=(cmsUInt32Number) TYPE_GRAY_16;
1098 target_colorspace=YUVColorspace;
1099 target_type=(cmsUInt32Number) TYPE_YUV_16;
1105 target_colorspace=RGBColorspace;
1106 target_type=(cmsUInt32Number) TYPE_RGB_16;
1112 target_colorspace=XYZColorspace;
1113 target_type=(cmsUInt32Number) TYPE_XYZ_16;
1117 case cmsSigYCbCrData:
1119 target_colorspace=YCbCrColorspace;
1120 target_type=(cmsUInt32Number) TYPE_YCbCr_16;
1126 target_colorspace=UndefinedColorspace;
1127 target_type=(cmsUInt32Number) TYPE_RGB_16;
1132 if ((source_colorspace == UndefinedColorspace) ||
1133 (target_colorspace == UndefinedColorspace))
1134 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1136 if ((source_colorspace == GRAYColorspace) &&
1137 (IsImageGray(image,exception) == MagickFalse))
1138 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1140 if ((source_colorspace == CMYKColorspace) &&
1141 (image->colorspace != CMYKColorspace))
1142 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1144 if ((source_colorspace == XYZColorspace) &&
1145 (image->colorspace != XYZColorspace))
1146 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1148 if ((source_colorspace == YCbCrColorspace) &&
1149 (image->colorspace != YCbCrColorspace))
1150 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1152 if ((source_colorspace != CMYKColorspace) &&
1153 (source_colorspace != GRAYColorspace) &&
1154 (source_colorspace != LabColorspace) &&
1155 (source_colorspace != XYZColorspace) &&
1156 (source_colorspace != YCbCrColorspace) &&
1157 (IsRGBColorspace(image->colorspace) == MagickFalse))
1158 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1160 switch (image->rendering_intent)
1162 case AbsoluteIntent: intent=INTENT_ABSOLUTE_COLORIMETRIC; break;
1163 case PerceptualIntent: intent=INTENT_PERCEPTUAL; break;
1164 case RelativeIntent: intent=INTENT_RELATIVE_COLORIMETRIC; break;
1165 case SaturationIntent: intent=INTENT_SATURATION; break;
1166 default: intent=INTENT_PERCEPTUAL; break;
1168 flags=cmsFLAGS_HIGHRESPRECALC;
1169 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1170 if (image->black_point_compensation != MagickFalse)
1171 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1173 transform=AcquireTransformThreadSet(image,source_profile,
1174 source_type,target_profile,target_type,intent,flags);
1175 if (transform == (cmsHTRANSFORM *) NULL)
1176 ThrowProfileException(ImageError,"UnableToCreateColorTransform",
1179 Transform image as dictated by the source & target image profiles.
1181 source_pixels=AcquirePixelThreadSet(image->columns,source_channels);
1182 target_pixels=AcquirePixelThreadSet(image->columns,target_channels);
1183 if ((source_pixels == (unsigned short **) NULL) ||
1184 (target_pixels == (unsigned short **) NULL))
1186 transform=DestroyTransformThreadSet(transform);
1187 ThrowProfileException(ResourceLimitError,
1188 "MemoryAllocationFailed",image->filename);
1190 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1192 target_pixels=DestroyPixelThreadSet(target_pixels);
1193 source_pixels=DestroyPixelThreadSet(source_pixels);
1194 transform=DestroyTransformThreadSet(transform);
1195 if (source_profile != (cmsHPROFILE) NULL)
1196 (void) cmsCloseProfile(source_profile);
1197 if (target_profile != (cmsHPROFILE) NULL)
1198 (void) cmsCloseProfile(target_profile);
1199 return(MagickFalse);
1201 if (target_colorspace == CMYKColorspace)
1202 (void) SetImageColorspace(image,target_colorspace,exception);
1205 image_view=AcquireCacheView(image);
1206 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1207 #pragma omp parallel for schedule(dynamic,4) shared(status)
1209 for (y=0; y < (ssize_t) image->rows; y++)
1212 id = GetOpenMPThreadId();
1223 register unsigned short
1226 if (status == MagickFalse)
1228 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1230 if (q == (Quantum *) NULL)
1235 p=source_pixels[id];
1236 for (x=0; x < (ssize_t) image->columns; x++)
1238 *p++=ScaleQuantumToShort(GetPixelRed(image,q));
1239 if (source_channels > 1)
1241 *p++=ScaleQuantumToShort(GetPixelGreen(image,q));
1242 *p++=ScaleQuantumToShort(GetPixelBlue(image,q));
1244 if (source_channels > 3)
1245 *p++=ScaleQuantumToShort(GetPixelBlack(image,q));
1246 q+=GetPixelChannels(image);
1248 cmsDoTransform(transform[id],source_pixels[id],target_pixels[id],
1249 (unsigned int) image->columns);
1250 p=target_pixels[id];
1251 q-=image->columns*GetPixelChannels(image);
1252 for (x=0; x < (ssize_t) image->columns; x++)
1254 SetPixelRed(image,ScaleShortToQuantum(*p),q);
1255 SetPixelGreen(image,GetPixelRed(image,q),q);
1256 SetPixelBlue(image,GetPixelRed(image,q),q);
1258 if (target_channels > 1)
1260 SetPixelGreen(image,ScaleShortToQuantum(*p),q);
1262 SetPixelBlue(image,ScaleShortToQuantum(*p),q);
1265 if (target_channels > 3)
1267 SetPixelBlack(image,ScaleShortToQuantum(*p),q);
1270 q+=GetPixelChannels(image);
1272 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1273 if (sync == MagickFalse)
1275 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1280 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1281 #pragma omp critical (MagickCore_ProfileImage)
1283 proceed=SetImageProgress(image,ProfileImageTag,progress++,
1285 if (proceed == MagickFalse)
1289 image_view=DestroyCacheView(image_view);
1290 (void) SetImageColorspace(image,target_colorspace,exception);
1295 image->type=image->matte == MagickFalse ? TrueColorType :
1299 case cmsSigCmykData:
1301 image->type=image->matte == MagickFalse ? ColorSeparationType :
1302 ColorSeparationMatteType;
1305 case cmsSigGrayData:
1307 image->type=image->matte == MagickFalse ? GrayscaleType :
1314 target_pixels=DestroyPixelThreadSet(target_pixels);
1315 source_pixels=DestroyPixelThreadSet(source_pixels);
1316 transform=DestroyTransformThreadSet(transform);
1317 if (cmsGetDeviceClass(source_profile) != cmsSigLinkClass)
1318 status=SetImageProfile(image,name,profile);
1319 if (target_profile != (cmsHPROFILE) NULL)
1320 (void) cmsCloseProfile(target_profile);
1322 (void) cmsCloseProfile(source_profile);
1326 profile=DestroyStringInfo(profile);
1331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1335 % R e m o v e I m a g e P r o f i l e %
1339 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1341 % RemoveImageProfile() removes a named profile from the image and returns its
1344 % The format of the RemoveImageProfile method is:
1346 % void *RemoveImageProfile(Image *image,const char *name)
1348 % A description of each parameter follows:
1350 % o image: the image.
1352 % o name: the profile name.
1355 MagickExport StringInfo *RemoveImageProfile(Image *image,const char *name)
1360 assert(image != (Image *) NULL);
1361 assert(image->signature == MagickSignature);
1362 if (image->debug != MagickFalse)
1363 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1364 if (image->profiles == (SplayTreeInfo *) NULL)
1365 return((StringInfo *) NULL);
1366 profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
1367 image->profiles,name);
1372 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1376 % R e s e t P r o f i l e I t e r a t o r %
1380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1382 % ResetImageProfileIterator() resets the image profile iterator. Use it in
1383 % conjunction with GetNextImageProfile() to iterate over all the profiles
1384 % associated with an image.
1386 % The format of the ResetImageProfileIterator method is:
1388 % ResetImageProfileIterator(Image *image)
1390 % A description of each parameter follows:
1392 % o image: the image.
1395 MagickExport void ResetImageProfileIterator(const Image *image)
1397 assert(image != (Image *) NULL);
1398 assert(image->signature == MagickSignature);
1399 if (image->debug != MagickFalse)
1400 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1401 if (image->profiles == (SplayTreeInfo *) NULL)
1403 ResetSplayTreeIterator((SplayTreeInfo *) image->profiles);
1407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1411 % S e t I m a g e P r o f i l e %
1415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1417 % SetImageProfile() adds a named profile to the image. If a profile with the
1418 % same name already exists, it is replaced. This method differs from the
1419 % ProfileImage() method in that it does not apply CMS color profiles.
1421 % The format of the SetImageProfile method is:
1423 % MagickBooleanType SetImageProfile(Image *image,const char *name,
1424 % const StringInfo *profile)
1426 % A description of each parameter follows:
1428 % o image: the image.
1430 % o name: the profile name, for example icc, exif, and 8bim (8bim is the
1431 % Photoshop wrapper for iptc profiles).
1433 % o profile: A StringInfo structure that contains the named profile.
1437 static void *DestroyProfile(void *profile)
1439 return((void *) DestroyStringInfo((StringInfo *) profile));
1442 static inline const unsigned char *ReadResourceByte(const unsigned char *p,
1443 unsigned char *quantum)
1449 static inline const unsigned char *ReadResourceBytes(const unsigned char *p,
1450 const ssize_t count,unsigned char *quantum)
1455 for (i=0; i < count; i++)
1460 static inline const unsigned char *ReadResourceLong(const unsigned char *p,
1463 *quantum=(size_t) (*p++ << 24);
1464 *quantum|=(size_t) (*p++ << 16);
1465 *quantum|=(size_t) (*p++ << 8);
1466 *quantum|=(size_t) (*p++ << 0);
1470 static inline const unsigned char *ReadResourceShort(const unsigned char *p,
1471 unsigned short *quantum)
1473 *quantum=(unsigned short) (*p++ << 8);
1474 *quantum|=(unsigned short) (*p++ << 0);
1478 static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
1479 const StringInfo *resource_block)
1484 register const unsigned char
1502 datum=GetStringInfoDatum(resource_block);
1503 length=GetStringInfoLength(resource_block);
1504 for (p=datum; p < (datum+length-16); )
1506 if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1509 p=ReadResourceShort(p,&id);
1510 p=ReadResourceByte(p,&length_byte);
1512 if (((length_byte+1) & 0x01) != 0)
1514 if (p > (datum+length-4))
1516 p=ReadResourceLong(p,&count);
1517 if ((p > (datum+length-count)) || (count > length))
1529 p=ReadResourceShort(p,&resolution)+6;
1530 image->x_resolution=(double) resolution;
1531 p=ReadResourceShort(p,&resolution)+6;
1532 image->y_resolution=(double) resolution;
1540 profile=AcquireStringInfo(count);
1541 SetStringInfoDatum(profile,p);
1542 (void) SetImageProfile(image,"iptc",profile);
1543 profile=DestroyStringInfo(profile);
1560 profile=AcquireStringInfo(count);
1561 SetStringInfoDatum(profile,p);
1562 (void) SetImageProfile(image,"icc",profile);
1563 profile=DestroyStringInfo(profile);
1572 profile=AcquireStringInfo(count);
1573 SetStringInfoDatum(profile,p);
1574 (void) SetImageProfile(image,"exif",profile);
1575 profile=DestroyStringInfo(profile);
1584 profile=AcquireStringInfo(count);
1585 SetStringInfoDatum(profile,p);
1586 (void) SetImageProfile(image,"xmp",profile);
1587 profile=DestroyStringInfo(profile);
1597 if ((count & 0x01) != 0)
1603 MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name,
1604 const StringInfo *profile)
1608 property[MaxTextExtent];
1613 assert(image != (Image *) NULL);
1614 assert(image->signature == MagickSignature);
1615 if (image->debug != MagickFalse)
1616 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1617 if (image->profiles == (SplayTreeInfo *) NULL)
1618 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
1620 (void) CopyMagickString(key,name,MaxTextExtent);
1621 status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1622 ConstantString(key),CloneStringInfo(profile));
1623 if ((status != MagickFalse) &&
1624 ((LocaleCompare(name,"iptc") == 0) || (LocaleCompare(name,"8bim") == 0)))
1625 (void) GetProfilesFromResourceBlock(image,profile);
1627 Inject profile into image properties.
1629 (void) FormatLocaleString(property,MaxTextExtent,"%s:sans",name);
1630 (void) GetImageProperty(image,property);
1635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1639 % S y n c I m a g e P r o f i l e s %
1643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1645 % SyncImageProfiles() synchronizes image properties with the image profiles.
1646 % Currently we only support updating the EXIF resolution and orientation.
1648 % The format of the SyncImageProfiles method is:
1650 % MagickBooleanType SyncImageProfiles(Image *image)
1652 % A description of each parameter follows:
1654 % o image: the image.
1658 static inline int ReadProfileByte(unsigned char **p,size_t *length)
1670 static inline unsigned short ReadProfileShort(const EndianType endian,
1671 unsigned char *buffer)
1676 if (endian == MSBEndian)
1678 value=(unsigned short) ((((unsigned char *) buffer)[0] << 8) |
1679 ((unsigned char *) buffer)[1]);
1680 return((unsigned short) (value & 0xffff));
1682 value=(unsigned short) ((buffer[1] << 8) | buffer[0]);
1683 return((unsigned short) (value & 0xffff));
1686 static inline size_t ReadProfileLong(const EndianType endian,
1687 unsigned char *buffer)
1692 if (endian == MSBEndian)
1694 value=(size_t) ((buffer[0] << 24) | (buffer[1] << 16) |
1695 (buffer[2] << 8) | buffer[3]);
1696 return((size_t) (value & 0xffffffff));
1698 value=(size_t) ((buffer[3] << 24) | (buffer[2] << 16) |
1699 (buffer[1] << 8 ) | (buffer[0]));
1700 return((size_t) (value & 0xffffffff));
1703 static inline void WriteProfileLong(const EndianType endian,
1704 const size_t value,unsigned char *p)
1709 if (endian == MSBEndian)
1711 buffer[0]=(unsigned char) (value >> 24);
1712 buffer[1]=(unsigned char) (value >> 16);
1713 buffer[2]=(unsigned char) (value >> 8);
1714 buffer[3]=(unsigned char) value;
1715 (void) CopyMagickMemory(p,buffer,4);
1718 buffer[0]=(unsigned char) value;
1719 buffer[1]=(unsigned char) (value >> 8);
1720 buffer[2]=(unsigned char) (value >> 16);
1721 buffer[3]=(unsigned char) (value >> 24);
1722 (void) CopyMagickMemory(p,buffer,4);
1725 static void WriteProfileShort(const EndianType endian,
1726 const unsigned short value,unsigned char *p)
1731 if (endian == MSBEndian)
1733 buffer[0]=(unsigned char) (value >> 8);
1734 buffer[1]=(unsigned char) value;
1735 (void) CopyMagickMemory(p,buffer,2);
1738 buffer[0]=(unsigned char) value;
1739 buffer[1]=(unsigned char) (value >> 8);
1740 (void) CopyMagickMemory(p,buffer,2);
1743 MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
1745 #define MaxDirectoryStack 16
1746 #define EXIF_DELIMITER "\n"
1747 #define EXIF_NUM_FORMATS 12
1748 #define TAG_EXIF_OFFSET 0x8769
1749 #define TAG_INTEROP_OFFSET 0xa005
1751 typedef struct _DirectoryInfo
1761 directory_stack[MaxDirectoryStack];
1779 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
1789 Set EXIF resolution tag.
1791 profile=(StringInfo *) GetImageProfile(image,"EXIF");
1792 if (profile == (StringInfo *) NULL)
1794 length=GetStringInfoLength(profile);
1795 exif=GetStringInfoDatum(profile);
1798 if (ReadProfileByte(&exif,&length) != 0x45)
1800 if (ReadProfileByte(&exif,&length) != 0x78)
1802 if (ReadProfileByte(&exif,&length) != 0x69)
1804 if (ReadProfileByte(&exif,&length) != 0x66)
1806 if (ReadProfileByte(&exif,&length) != 0x00)
1808 if (ReadProfileByte(&exif,&length) != 0x00)
1813 return(MagickFalse);
1814 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
1822 return(MagickFalse);
1823 if (ReadProfileShort(endian,exif+2) != 0x002a)
1824 return(MagickFalse);
1826 This the offset to the first IFD.
1828 offset=(int) ReadProfileLong(endian,exif+4);
1829 if ((size_t) offset >= length)
1830 return(MagickFalse);
1831 directory=exif+offset;
1839 directory=directory_stack[level].directory;
1840 entry=directory_stack[level].entry;
1843 Determine how many entries there are in the current IFD.
1845 number_entries=ReadProfileShort(endian,directory);
1846 for ( ; entry < number_entries; entry++)
1851 register unsigned char
1862 q=(unsigned char *) (directory+2+(12*entry));
1863 tag_value=(ssize_t) ReadProfileShort(endian,q);
1864 format=(ssize_t) ReadProfileShort(endian,q+2);
1865 if ((format-1) >= EXIF_NUM_FORMATS)
1867 components=(int) ReadProfileLong(endian,q+4);
1868 number_bytes=(size_t) components*format_bytes[format];
1869 if (number_bytes <= 4)
1877 The directory entry contains an offset.
1879 offset=(int) ReadProfileLong(endian,q+8);
1880 if ((size_t) (offset+number_bytes) > length)
1882 p=(unsigned char *) (exif+offset);
1888 (void) WriteProfileLong(endian,(size_t)
1889 (image->x_resolution+0.5),p);
1890 (void) WriteProfileLong(endian,1UL,p+4);
1895 (void) WriteProfileLong(endian,(size_t)
1896 (image->y_resolution+0.5),p);
1897 (void) WriteProfileLong(endian,1UL,p+4);
1902 (void) WriteProfileShort(endian,(unsigned short)
1903 image->orientation,p);
1908 (void) WriteProfileShort(endian,(unsigned short)
1909 (image->units+1),p);
1915 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
1920 offset=(size_t) ReadProfileLong(endian,p);
1921 if ((offset < length) && (level < (MaxDirectoryStack-2)))
1923 directory_stack[level].directory=directory;
1925 directory_stack[level].entry=entry;
1927 directory_stack[level].directory=exif+offset;
1928 directory_stack[level].entry=0;
1930 if ((directory+2+(12*number_entries)) > (exif+length))
1932 offset=(size_t) ReadProfileLong(endian,directory+2+(12*
1934 if ((offset != 0) && (offset < length) &&
1935 (level < (MaxDirectoryStack-2)))
1937 directory_stack[level].directory=exif+offset;
1938 directory_stack[level].entry=0;
1945 } while (level > 0);