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-2010 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 "magick/studio.h"
43 #include "magick/cache.h"
44 #include "magick/color.h"
45 #include "magick/configure.h"
46 #include "magick/exception.h"
47 #include "magick/exception-private.h"
48 #include "magick/hashmap.h"
49 #include "magick/image.h"
50 #include "magick/memory_.h"
51 #include "magick/monitor.h"
52 #include "magick/monitor-private.h"
53 #include "magick/option.h"
54 #include "magick/profile.h"
55 #include "magick/property.h"
56 #include "magick/quantum.h"
57 #include "magick/quantum-private.h"
58 #include "magick/splay-tree.h"
59 #include "magick/string_.h"
60 #include "magick/thread-private.h"
61 #include "magick/token.h"
62 #include "magick/utility.h"
63 #if defined(MAGICKCORE_LCMS_DELEGATE)
64 #if defined(MAGICKCORE_HAVE_LCMS_LCMS2_H)
66 #include <lcms/lcms2.h>
67 #elif defined(MAGICKCORE_HAVE_LCMS2_H)
70 #elif defined(MAGICKCORE_HAVE_LCMS_LCMS_H)
71 #include <lcms/lcms.h>
78 * Define declarations.
80 #if defined(MAGICKCORE_LCMS_DELEGATE)
81 #if defined(LCMS_VERSION) && (LCMS_VERSION < 2000)
82 #define cmsUInt32Number DWORD
83 #define cmsSigCmykData icSigCmykData
84 #define cmsSigGrayData icSigGrayData
85 #define cmsSigLabData icSigLabData
86 #define cmsSigLuvData icSigLuvData
87 #define cmsSigRgbData icSigRgbData
88 #define cmsSigXYZData icSigXYZData
89 #define cmsSigYCbCrData icSigYCbCrData
90 #define cmsSigLinkClass icSigLinkClass
91 #define cmsColorSpaceSignature icColorSpaceSignature
96 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
100 % C l o n e I m a g e P r o f i l e s %
104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
106 % CloneImageProfiles() clones one or more image profiles.
108 % The format of the CloneImageProfiles method is:
110 % MagickBooleanType CloneImageProfiles(Image *image,
111 % const Image *clone_image)
113 % A description of each parameter follows:
115 % o image: the image.
117 % o clone_image: the clone image.
120 MagickExport MagickBooleanType CloneImageProfiles(Image *image,
121 const Image *clone_image)
123 assert(image != (Image *) NULL);
124 assert(image->signature == MagickSignature);
125 if (image->debug != MagickFalse)
126 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
127 assert(clone_image != (const Image *) NULL);
128 assert(clone_image->signature == MagickSignature);
129 image->color_profile.length=clone_image->color_profile.length;
130 image->color_profile.info=clone_image->color_profile.info;
131 image->iptc_profile.length=clone_image->iptc_profile.length;
132 image->iptc_profile.info=clone_image->iptc_profile.info;
133 if (clone_image->profiles != (void *) NULL)
134 image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
135 (void *(*)(void *)) ConstantString,(void *(*)(void *)) CloneStringInfo);
140 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
144 % D e l e t e I m a g e P r o f i l e %
148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
150 % DeleteImageProfile() deletes a profile from the image by its name.
152 % The format of the DeleteImageProfile method is:
154 % MagickBooleanTyupe DeleteImageProfile(Image *image,const char *name)
156 % A description of each parameter follows:
158 % o image: the image.
160 % o name: the profile name.
163 MagickExport MagickBooleanType DeleteImageProfile(Image *image,const char *name)
165 assert(image != (Image *) NULL);
166 assert(image->signature == MagickSignature);
167 if (image->debug != MagickFalse)
168 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
169 if (image->profiles == (SplayTreeInfo *) NULL)
171 if (LocaleCompare(name,"icc") == 0)
174 Continue to support deprecated color profile for now.
176 image->color_profile.length=0;
177 image->color_profile.info=(unsigned char *) NULL;
179 if (LocaleCompare(name,"iptc") == 0)
182 Continue to support deprecated IPTC profile for now.
184 image->iptc_profile.length=0;
185 image->iptc_profile.info=(unsigned char *) NULL;
187 return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->profiles,name));
191 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
195 % D e s t r o y I m a g e P r o f i l e s %
199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
201 % DestroyImageProfiles() releases memory associated with an image profile map.
203 % The format of the DestroyProfiles method is:
205 % void DestroyImageProfiles(Image *image)
207 % A description of each parameter follows:
209 % o image: the image.
212 MagickExport void DestroyImageProfiles(Image *image)
214 if (image->profiles != (SplayTreeInfo *) NULL)
215 image->profiles=DestroySplayTree((SplayTreeInfo *) image->profiles);
219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
223 % G e t I m a g e P r o f i l e %
227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
229 % GetImageProfile() gets a profile associated with an image by name.
231 % The format of the GetImageProfile method is:
233 % const StringInfo *GetImageProfile(const Image *image,const char *name)
235 % A description of each parameter follows:
237 % o image: the image.
239 % o name: the profile name.
242 MagickExport const StringInfo *GetImageProfile(const Image *image,
251 assert(image != (Image *) NULL);
252 assert(image->signature == MagickSignature);
253 if (image->debug != MagickFalse)
254 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
255 if (image->profiles == (SplayTreeInfo *) NULL)
256 return((StringInfo *) NULL);
257 (void) CopyMagickString(key,name,MaxTextExtent);
258 profile=(const StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
259 image->profiles,key);
264 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
268 % G e t N e x t I m a g e P r o f i l e %
272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274 % GetNextImageProfile() gets the next profile name for an image.
276 % The format of the GetNextImageProfile method is:
278 % char *GetNextImageProfile(const Image *image)
280 % A description of each parameter follows:
282 % o hash_info: the hash info.
285 MagickExport char *GetNextImageProfile(const Image *image)
287 assert(image != (Image *) NULL);
288 assert(image->signature == MagickSignature);
289 if (image->debug != MagickFalse)
290 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
291 if (image->profiles == (SplayTreeInfo *) NULL)
292 return((char *) NULL);
293 return((char *) GetNextKeyInSplayTree((SplayTreeInfo *) image->profiles));
297 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
301 % P r o f i l e I m a g e %
305 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307 % ProfileImage() associates, applies, or removes an ICM, IPTC, or generic
308 % profile with / to / from an image. If the profile is NULL, it is removed
309 % from the image otherwise added or applied. Use a name of '*' and a profile
310 % of NULL to remove all profiles from the image.
312 % ICC and ICM profiles are handled as follows: If the image does not have
313 % an associated color profile, the one you provide is associated with the
314 % image and the image pixels are not transformed. Otherwise, the colorspace
315 % transform defined by the existing and new profile are applied to the image
316 % pixels and the new profile is associated with the image.
318 % The format of the ProfileImage method is:
320 % MagickBooleanType ProfileImage(Image *image,const char *name,
321 % const void *datum,const size_t length,const MagickBooleanType clone)
323 % A description of each parameter follows:
325 % o image: the image.
327 % o name: Name of profile to add or remove: ICC, IPTC, or generic profile.
329 % o datum: the profile data.
331 % o length: the length of the profile.
333 % o clone: should be MagickFalse.
337 #if defined(MAGICKCORE_LCMS_DELEGATE)
339 static unsigned short **DestroyPixelThreadSet(unsigned short **pixels)
344 assert(pixels != (unsigned short **) NULL);
345 for (i=0; i < (long) GetOpenMPMaximumThreads(); i++)
346 if (pixels[i] != (unsigned short *) NULL)
347 pixels[i]=(unsigned short *) RelinquishMagickMemory(pixels[i]);
348 pixels=(unsigned short **) RelinquishAlignedMemory(pixels);
352 static unsigned short **AcquirePixelThreadSet(const size_t columns,
353 const size_t channels)
364 number_threads=GetOpenMPMaximumThreads();
365 pixels=(unsigned short **) AcquireAlignedMemory(number_threads,
367 if (pixels == (unsigned short **) NULL)
368 return((unsigned short **) NULL);
369 (void) ResetMagickMemory(pixels,0,number_threads*sizeof(*pixels));
370 for (i=0; i < (long) number_threads; i++)
372 pixels[i]=(unsigned short *) AcquireQuantumMemory(columns,channels*
374 if (pixels[i] == (unsigned short *) NULL)
375 return(DestroyPixelThreadSet(pixels));
380 static cmsHTRANSFORM *DestroyTransformThreadSet(cmsHTRANSFORM *transform)
385 assert(transform != (cmsHTRANSFORM *) NULL);
386 for (i=0; i < (long) GetOpenMPMaximumThreads(); i++)
387 if (transform[i] != (cmsHTRANSFORM) NULL)
388 cmsDeleteTransform(transform[i]);
389 transform=(cmsHTRANSFORM *) RelinquishAlignedMemory(transform);
393 static cmsHTRANSFORM *AcquireTransformThreadSet(
394 const cmsHPROFILE source_profile,const cmsUInt32Number source_type,
395 const cmsHPROFILE target_profile,const cmsUInt32Number target_type,
396 const int intent,const cmsUInt32Number flags)
407 number_threads=GetOpenMPMaximumThreads();
408 transform=(cmsHTRANSFORM *) AcquireAlignedMemory(number_threads,
410 if (transform == (cmsHTRANSFORM *) NULL)
411 return((cmsHTRANSFORM *) NULL);
412 (void) ResetMagickMemory(transform,0,number_threads*sizeof(*transform));
413 for (i=0; i < (long) number_threads; i++)
415 transform[i]=cmsCreateTransform(source_profile,source_type,target_profile,
416 target_type,intent,flags);
417 if (transform[i] == (cmsHTRANSFORM) NULL)
418 return(DestroyTransformThreadSet(transform));
424 static MagickBooleanType SetAdobeRGB1998ImageProfile(Image *image)
427 AdobeRGB1998Profile[] =
429 0x00, 0x00, 0x02, 0x30, 0x41, 0x44, 0x42, 0x45, 0x02, 0x10, 0x00,
430 0x00, 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59,
431 0x5a, 0x20, 0x07, 0xd0, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x13, 0x00,
432 0x33, 0x00, 0x3b, 0x61, 0x63, 0x73, 0x70, 0x41, 0x50, 0x50, 0x4c,
433 0x00, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x00,
434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
435 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00,
436 0x00, 0xd3, 0x2d, 0x41, 0x44, 0x42, 0x45, 0x00, 0x00, 0x00, 0x00,
437 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
438 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
441 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
442 0x32, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00,
443 0x00, 0x6b, 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x9c, 0x00,
444 0x00, 0x00, 0x14, 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x01, 0xb0,
445 0x00, 0x00, 0x00, 0x14, 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01,
446 0xc4, 0x00, 0x00, 0x00, 0x0e, 0x67, 0x54, 0x52, 0x43, 0x00, 0x00,
447 0x01, 0xd4, 0x00, 0x00, 0x00, 0x0e, 0x62, 0x54, 0x52, 0x43, 0x00,
448 0x00, 0x01, 0xe4, 0x00, 0x00, 0x00, 0x0e, 0x72, 0x58, 0x59, 0x5a,
449 0x00, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x00, 0x14, 0x67, 0x58, 0x59,
450 0x5a, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x14, 0x62, 0x58,
451 0x59, 0x5a, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x14, 0x74,
452 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x70, 0x79,
453 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x32, 0x30, 0x30, 0x30, 0x20,
454 0x41, 0x64, 0x6f, 0x62, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65,
455 0x6d, 0x73, 0x20, 0x49, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72,
456 0x61, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x41, 0x64, 0x6f,
458 0x62, 0x65, 0x20, 0x52, 0x47, 0x42, 0x20, 0x28, 0x31, 0x39, 0x39,
459 0x38, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
461 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00,
467 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00,
468 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
470 0x00, 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
471 0x00, 0x01, 0x02, 0x33, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76, 0x00,
472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x33, 0x00, 0x00,
473 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474 0x01, 0x02, 0x33, 0x00, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00,
475 0x00, 0x00, 0x00, 0x00, 0x9c, 0x18, 0x00, 0x00, 0x4f, 0xa5, 0x00,
476 0x00, 0x04, 0xfc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
477 0x00, 0x00, 0x34, 0x8d, 0x00, 0x00, 0xa0, 0x2c, 0x00, 0x00, 0x0f,
478 0x95, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
479 0x26, 0x31, 0x00, 0x00, 0x10, 0x2f, 0x00, 0x00, 0xbe, 0x9c
488 assert(image != (Image *) NULL);
489 assert(image->signature == MagickSignature);
490 if (GetImageProfile(image,"icm") != (const StringInfo *) NULL)
492 profile=AcquireStringInfo(sizeof(AdobeRGB1998Profile));
493 SetStringInfoDatum(profile,AdobeRGB1998Profile);
494 status=SetImageProfile(image,"icm",profile);
495 profile=DestroyStringInfo(profile);
499 static MagickBooleanType SetsRGBImageProfile(Image *image)
504 0x00, 0x00, 0x0c, 0x48, 0x4c, 0x69, 0x6e, 0x6f, 0x02, 0x10, 0x00,
505 0x00, 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59,
506 0x5a, 0x20, 0x07, 0xce, 0x00, 0x02, 0x00, 0x09, 0x00, 0x06, 0x00,
507 0x31, 0x00, 0x00, 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54,
508 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47,
509 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00,
511 0x00, 0xd3, 0x2d, 0x48, 0x50, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
516 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00,
517 0x33, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00,
518 0x00, 0x6c, 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0xf0, 0x00,
519 0x00, 0x00, 0x14, 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x02, 0x04,
520 0x00, 0x00, 0x00, 0x14, 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x02,
521 0x18, 0x00, 0x00, 0x00, 0x14, 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00,
522 0x02, 0x2c, 0x00, 0x00, 0x00, 0x14, 0x62, 0x58, 0x59, 0x5a, 0x00,
523 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x14, 0x64, 0x6d, 0x6e, 0x64,
524 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70, 0x64, 0x6d, 0x64,
525 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88, 0x76, 0x75,
526 0x65, 0x64, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x86, 0x76,
527 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xd4, 0x00, 0x00, 0x00, 0x24,
528 0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00,
529 0x14, 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x04, 0x0c, 0x00, 0x00,
530 0x00, 0x24, 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x04, 0x30, 0x00,
531 0x00, 0x00, 0x0c, 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x3c,
532 0x00, 0x00, 0x08, 0x0c, 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04,
533 0x3c, 0x00, 0x00, 0x08, 0x0c, 0x62, 0x54, 0x52, 0x43, 0x00, 0x00,
534 0x04, 0x3c, 0x00, 0x00, 0x08, 0x0c, 0x74, 0x65, 0x78, 0x74, 0x00,
535 0x00, 0x00, 0x00, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
536 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, 0x39, 0x38, 0x20,
537 0x48, 0x65, 0x77, 0x6c, 0x65, 0x74, 0x74, 0x2d, 0x50, 0x61, 0x63,
538 0x6b, 0x61, 0x72, 0x64, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e,
539 0x79, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
540 0x00, 0x00, 0x00, 0x12, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45,
541 0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00,
542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
543 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39,
544 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
549 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
550 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xcc, 0x58,
551 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5a,
553 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa2, 0x00, 0x00,
554 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20, 0x00,
555 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x99, 0x00, 0x00, 0xb7, 0x85,
556 0x00, 0x00, 0x18, 0xda, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00,
557 0x00, 0x00, 0x00, 0x24, 0xa0, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00,
558 0xb6, 0xcf, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00,
559 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74, 0x70,
560 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
561 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74, 0x70,
563 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
564 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00,
569 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43, 0x20, 0x36, 0x31,
570 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44, 0x65, 0x66,
571 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63, 0x6f,
572 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
573 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43, 0x20,
575 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
576 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20,
577 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63,
578 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73,
581 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x52, 0x65,
582 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65,
583 0x77, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74,
584 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 0x43, 0x36,
585 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00,
586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x52, 0x65,
587 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65,
588 0x77, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74,
589 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 0x43, 0x36,
590 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00,
591 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 0x00, 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
594 0xa4, 0xfe, 0x00, 0x14, 0x5f, 0x2e, 0x00, 0x10, 0xcf, 0x14, 0x00,
595 0x03, 0xed, 0xcc, 0x00, 0x04, 0x13, 0x0b, 0x00, 0x03, 0x5c, 0x9e,
596 0x00, 0x00, 0x00, 0x01, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x4c, 0x09, 0x56, 0x00, 0x50, 0x00, 0x00, 0x00, 0x57,
598 0x1f, 0xe7, 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00,
599 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
601 0x8f, 0x00, 0x00, 0x00, 0x02, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00,
602 0x00, 0x00, 0x43, 0x52, 0x54, 0x20, 0x63, 0x75, 0x72, 0x76, 0x00,
603 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x05,
604 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19, 0x00, 0x1e, 0x00,
605 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37, 0x00, 0x3b,
606 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54, 0x00,
607 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
608 0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00,
609 0x90, 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9,
610 0x00, 0xae, 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00,
611 0xc6, 0x00, 0xcb, 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0,
612 0x00, 0xe5, 0x00, 0xeb, 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01,
613 0x01, 0x01, 0x07, 0x01, 0x0d, 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f,
614 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32, 0x01, 0x38, 0x01, 0x3e, 0x01,
615 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59, 0x01, 0x60, 0x01, 0x67,
616 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83, 0x01, 0x8b, 0x01,
617 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1, 0x01, 0xb9,
618 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1, 0x01,
619 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
620 0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02,
621 0x4b, 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a,
622 0x02, 0x84, 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02,
623 0xb6, 0x02, 0xc1, 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb,
624 0x02, 0xf5, 0x03, 0x00, 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03,
625 0x2d, 0x03, 0x38, 0x03, 0x43, 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66,
626 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a, 0x03, 0x96, 0x03, 0xa2, 0x03,
627 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3, 0x03, 0xe0, 0x03, 0xec,
628 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20, 0x04, 0x2d, 0x04,
629 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71, 0x04, 0x7e,
630 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4, 0x04,
631 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
632 0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05,
633 0x77, 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5,
634 0x05, 0xd5, 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06,
635 0x27, 0x06, 0x37, 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b,
636 0x06, 0x8c, 0x06, 0x9d, 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06,
637 0xe3, 0x06, 0xf5, 0x07, 0x07, 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d,
638 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74, 0x07, 0x86, 0x07, 0x99, 0x07,
639 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5, 0x07, 0xf8, 0x08, 0x0b,
640 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a, 0x08, 0x6e, 0x08,
641 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2, 0x08, 0xe7,
642 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f, 0x09,
643 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
644 0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a,
645 0x54, 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5,
646 0x0a, 0xdc, 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b,
647 0x51, 0x0b, 0x69, 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8,
648 0x0b, 0xe1, 0x0b, 0xf9, 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c,
649 0x5c, 0x0c, 0x75, 0x0c, 0x8e, 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9,
650 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26, 0x0d, 0x40, 0x0d, 0x5a, 0x0d,
651 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3, 0x0d, 0xde, 0x0d, 0xf8,
652 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64, 0x0e, 0x7f, 0x0e,
653 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09, 0x0f, 0x25,
654 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3, 0x0f,
655 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
656 0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11,
657 0x13, 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa,
658 0x11, 0xc9, 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12,
659 0x64, 0x12, 0x84, 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03,
660 0x13, 0x23, 0x13, 0x43, 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13,
661 0xc5, 0x13, 0xe5, 0x14, 0x06, 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a,
662 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce, 0x14, 0xf0, 0x15, 0x12, 0x15,
663 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b, 0x15, 0xbd, 0x15, 0xe0,
664 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c, 0x16, 0x8f, 0x16,
665 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41, 0x17, 0x65,
666 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b, 0x18,
667 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
668 0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19,
669 0xdd, 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e,
670 0x1a, 0xc5, 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b,
671 0x8a, 0x1b, 0xb2, 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52,
672 0x1c, 0x7b, 0x1c, 0xa3, 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d,
673 0x47, 0x1d, 0x70, 0x1d, 0x99, 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16,
674 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94, 0x1e, 0xbe, 0x1e, 0xe9, 0x1f,
675 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94, 0x1f, 0xbf, 0x1f, 0xea,
676 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98, 0x20, 0xc4, 0x20,
677 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1, 0x21, 0xce,
678 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf, 0x22,
679 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
680 0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24,
681 0xda, 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7,
682 0x25, 0xf7, 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26,
683 0xe8, 0x27, 0x18, 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc,
684 0x28, 0x0d, 0x28, 0x3f, 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29,
685 0x06, 0x29, 0x38, 0x29, 0x6b, 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02,
686 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b, 0x2a, 0xcf, 0x2b, 0x02, 0x2b,
687 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1, 0x2c, 0x05, 0x2c, 0x39,
688 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c, 0x2d, 0x41, 0x2d,
689 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c, 0x2e, 0x82,
690 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91, 0x2f,
691 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
692 0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32,
693 0x2a, 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46,
694 0x33, 0x7f, 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34,
695 0x9e, 0x34, 0xd8, 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2,
696 0x35, 0xfd, 0x36, 0x37, 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37,
697 0x24, 0x37, 0x60, 0x37, 0x9c, 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50,
698 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05, 0x39, 0x42, 0x39, 0x7f, 0x39,
699 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74, 0x3a, 0xb2, 0x3a, 0xef,
700 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8, 0x3c, 0x27, 0x3c,
701 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61, 0x3d, 0xa1,
702 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0, 0x3f,
703 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
704 0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41,
705 0xee, 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a,
706 0x43, 0x7d, 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44,
707 0xce, 0x45, 0x12, 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22,
708 0x46, 0x67, 0x46, 0xab, 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47,
709 0xc0, 0x48, 0x05, 0x48, 0x4b, 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d,
710 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0, 0x4a, 0x37, 0x4a, 0x7d, 0x4a,
711 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a, 0x4b, 0xe2, 0x4c, 0x2a,
712 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a, 0x4d, 0x93, 0x4d,
713 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00, 0x4f, 0x49,
714 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb, 0x51,
715 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
716 0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54,
717 0x42, 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2,
718 0x56, 0x0f, 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57,
719 0x92, 0x57, 0xe0, 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a,
720 0x59, 0x69, 0x59, 0xb8, 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a,
721 0xf5, 0x5b, 0x45, 0x5b, 0x95, 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86,
722 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78, 0x5d, 0xc9, 0x5e, 0x1a, 0x5e,
723 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61, 0x5f, 0xb3, 0x60, 0x05,
724 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f, 0x61, 0xa2, 0x61,
725 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43, 0x63, 0x97,
726 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d, 0x65,
727 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
728 0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69,
729 0x43, 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7,
730 0x6b, 0x4f, 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d,
731 0x08, 0x6d, 0x60, 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4,
732 0x6f, 0x1e, 0x6f, 0x78, 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70,
733 0xe0, 0x71, 0x3a, 0x71, 0x95, 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6,
734 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8, 0x74, 0x14, 0x74, 0x70, 0x74,
735 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1, 0x76, 0x3e, 0x76, 0x9b,
736 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11, 0x78, 0x6e, 0x78,
737 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46, 0x7a, 0xa5,
738 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81, 0x7c,
739 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
740 0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81,
741 0x0a, 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4,
742 0x83, 0x57, 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85,
743 0x47, 0x85, 0xab, 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b,
744 0x87, 0x9f, 0x88, 0x04, 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89,
745 0x99, 0x89, 0xfe, 0x8a, 0x64, 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96,
746 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca, 0x8d, 0x31, 0x8d, 0x98, 0x8d,
747 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36, 0x8f, 0x9e, 0x90, 0x06,
748 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8, 0x92, 0x11, 0x92,
749 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20, 0x94, 0x8a,
750 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f, 0x97,
751 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
752 0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b,
753 0xaf, 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2,
754 0x9e, 0x40, 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0,
755 0x69, 0xa0, 0xd8, 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96,
756 0xa3, 0x06, 0xa3, 0x76, 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5,
757 0x38, 0xa5, 0xa9, 0xa6, 0x1a, 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e,
758 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4, 0xa9, 0x37, 0xa9, 0xa9, 0xaa,
759 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75, 0xab, 0xe9, 0xac, 0x5c,
760 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d, 0xae, 0xa1, 0xaf,
761 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea, 0xb1, 0x60,
762 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae, 0xb4,
763 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
764 0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9,
765 0x4a, 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7,
766 0xbc, 0x21, 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe,
767 0x84, 0xbe, 0xff, 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec,
768 0xc1, 0x67, 0xc1, 0xe3, 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3,
769 0xd4, 0xc4, 0x51, 0xc4, 0xce, 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46,
770 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf, 0xc8, 0x3d, 0xc8, 0xbc, 0xc9,
771 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7, 0xcb, 0x36, 0xcb, 0xb6,
772 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5, 0xce, 0x36, 0xce,
773 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba, 0xd1, 0x3c,
774 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6, 0xd4,
775 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
776 0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9,
777 0xf1, 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a,
778 0xdd, 0x10, 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf,
779 0xaf, 0xe0, 0x36, 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53,
780 0xe2, 0xdb, 0xe3, 0x63, 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5,
781 0x84, 0xe6, 0x0d, 0xe6, 0x96, 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32,
782 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0, 0xea, 0x5b, 0xea, 0xe5, 0xeb,
783 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11, 0xed, 0x9c, 0xee, 0x28,
784 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58, 0xf0, 0xe5, 0xf1,
785 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7, 0xf4, 0x34,
786 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb, 0xf7,
787 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
788 0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd,
789 0xba, 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
798 assert(image != (Image *) NULL);
799 assert(image->signature == MagickSignature);
800 if (GetImageProfile(image,"icm") != (const StringInfo *) NULL)
802 profile=AcquireStringInfo(sizeof(sRGBProfile));
803 SetStringInfoDatum(profile,sRGBProfile);
804 status=SetImageProfile(image,"icm",profile);
805 profile=DestroyStringInfo(profile);
808 #if defined(MAGICKCORE_LCMS_DELEGATE)
809 #if defined(LCMS_VERSION) && (LCMS_VERSION >= 2000)
810 static void LCMSErrorHandler(cmsContext context,cmsUInt32Number severity,
814 (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%d, %s",
815 severity,message != (char *) NULL ? message : "no message");
818 #if defined(LCMS_VERSION) && (LCMS_VERSION < 2000)
819 #if defined(LCMS_VERSION) && (LCMS_VERSION > 1010)
820 static int LCMSErrorHandler(int severity,const char *message)
822 (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%d, %s",
823 severity,message != (char *) NULL ? message : "no message");
830 MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
831 const void *datum,const size_t length,
832 const MagickBooleanType magick_unused(clone))
834 #define ProfileImageTag "Profile/Image"
835 #define ThrowProfileException(severity,tag,context) \
837 (void) cmsCloseProfile(source_profile); \
838 if (target_profile != (cmsHPROFILE) NULL) \
839 (void) cmsCloseProfile(target_profile); \
840 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 if ((datum == (const void *) NULL) || (length == 0))
867 Delete image profile(s).
869 names=ConstantString(name);
870 (void) SubstituteString(&names,","," ");
871 arguments=StringToArgv(names,&number_arguments);
872 names=DestroyString(names);
873 if (arguments == (char **) NULL)
875 ResetImageProfileIterator(image);
876 for (name=GetNextImageProfile(image); name != (const char *) NULL; )
878 for (i=1; i < number_arguments; i++)
880 if ((*arguments[i] == '!') &&
881 (LocaleCompare(name,arguments[i]+1) == 0))
883 if (GlobExpression(name,arguments[i],MagickTrue) != MagickFalse)
885 (void) DeleteImageProfile(image,name);
886 ResetImageProfileIterator(image);
890 name=GetNextImageProfile(image);
892 for (i=0; i < number_arguments; i++)
893 arguments[i]=DestroyString(arguments[i]);
894 arguments=(char **) RelinquishMagickMemory(arguments);
898 Add a ICC, IPTC, or generic profile to the image.
901 profile=AcquireStringInfo((size_t) length);
902 SetStringInfoDatum(profile,(unsigned char *) datum);
903 if ((LocaleCompare(name,"icc") != 0) && (LocaleCompare(name,"icm") != 0))
904 status=SetImageProfile(image,name,profile);
910 icc_profile=GetImageProfile(image,"icc");
911 if ((icc_profile != (const StringInfo *) NULL) &&
912 (CompareStringInfo(icc_profile,profile) == 0))
917 value=GetImageProperty(image,"exif:ColorSpace");
918 if (LocaleCompare(value,"1") != 0)
919 (void) SetsRGBImageProfile(image);
920 value=GetImageProperty(image,"exif:InteroperabilityIndex");
921 if (LocaleCompare(value,"R98.") != 0)
922 (void) SetsRGBImageProfile(image);
923 value=GetImageProperty(image,"exif:InteroperabilityIndex");
924 if (LocaleCompare(value,"R03.") != 0)
925 (void) SetAdobeRGB1998ImageProfile(image);
926 icc_profile=GetImageProfile(image,"icc");
928 if ((icc_profile != (const StringInfo *) NULL) &&
929 (CompareStringInfo(icc_profile,profile) == 0))
931 profile=DestroyStringInfo(profile);
934 #if !defined(MAGICKCORE_LCMS_DELEGATE)
935 (void) ThrowMagickException(&image->exception,GetMagickModule(),
936 MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn","`%s' (LCMS)",
947 cmsColorSpaceSignature
981 **restrict source_pixels,
982 **restrict target_pixels;
985 Transform pixel colors as defined by the color profiles.
987 exception=(&image->exception);
988 #if defined(LCMS_VERSION) && (LCMS_VERSION >= 2000)
989 cmsSetLogErrorHandler(LCMSErrorHandler);
991 #if defined(LCMS_VERSION) && (LCMS_VERSION < 2000)
992 #if defined(LCMS_VERSION) && (LCMS_VERSION > 1010)
993 cmsSetErrorHandler(LCMSErrorHandler);
995 (void) cmsErrorAction(LCMS_ERROR_SHOW);
998 source_profile=cmsOpenProfileFromMem(GetStringInfoDatum(profile),
999 (cmsUInt32Number) GetStringInfoLength(profile));
1000 if (source_profile == (cmsHPROFILE) NULL)
1001 ThrowBinaryException(ResourceLimitError,
1002 "ColorspaceColorProfileMismatch",name);
1003 target_profile=(cmsHPROFILE) NULL;
1004 if ((cmsGetDeviceClass(source_profile) != cmsSigLinkClass) &&
1005 (icc_profile != (StringInfo *) NULL))
1007 target_profile=source_profile;
1008 source_profile=cmsOpenProfileFromMem(
1009 GetStringInfoDatum(icc_profile),(cmsUInt32Number)
1010 GetStringInfoLength(icc_profile));
1011 if (source_profile == (cmsHPROFILE) NULL)
1012 ThrowBinaryException(ResourceLimitError,
1013 "ColorspaceColorProfileMismatch",name);
1015 switch (cmsGetColorSpace(source_profile))
1017 case cmsSigCmykData:
1019 source_colorspace=CMYKColorspace;
1020 source_type=(cmsUInt32Number) TYPE_CMYK_16;
1024 case cmsSigGrayData:
1026 source_colorspace=GRAYColorspace;
1027 source_type=(cmsUInt32Number) TYPE_GRAY_16;
1033 source_colorspace=LabColorspace;
1034 source_type=(cmsUInt32Number) TYPE_Lab_16;
1040 source_colorspace=YUVColorspace;
1041 source_type=(cmsUInt32Number) TYPE_YUV_16;
1047 source_colorspace=RGBColorspace;
1048 source_type=(cmsUInt32Number) TYPE_RGB_16;
1054 source_colorspace=XYZColorspace;
1055 source_type=(cmsUInt32Number) TYPE_XYZ_16;
1059 case cmsSigYCbCrData:
1061 source_colorspace=YCbCrColorspace;
1062 source_type=(cmsUInt32Number) TYPE_YCbCr_16;
1068 source_colorspace=UndefinedColorspace;
1069 source_type=(cmsUInt32Number) TYPE_RGB_16;
1074 signature=cmsGetPCS(source_profile);
1075 if (target_profile != (cmsHPROFILE) NULL)
1076 signature=cmsGetColorSpace(target_profile);
1079 case cmsSigCmykData:
1081 target_colorspace=CMYKColorspace;
1082 target_type=(cmsUInt32Number) TYPE_CMYK_16;
1088 target_colorspace=LabColorspace;
1089 target_type=(cmsUInt32Number) TYPE_Lab_16;
1093 case cmsSigGrayData:
1095 target_colorspace=GRAYColorspace;
1096 target_type=(cmsUInt32Number) TYPE_GRAY_16;
1102 target_colorspace=YUVColorspace;
1103 target_type=(cmsUInt32Number) TYPE_YUV_16;
1109 target_colorspace=RGBColorspace;
1110 target_type=(cmsUInt32Number) TYPE_RGB_16;
1116 target_colorspace=XYZColorspace;
1117 target_type=(cmsUInt32Number) TYPE_XYZ_16;
1121 case cmsSigYCbCrData:
1123 target_colorspace=YCbCrColorspace;
1124 target_type=(cmsUInt32Number) TYPE_YCbCr_16;
1130 target_colorspace=UndefinedColorspace;
1131 target_type=(cmsUInt32Number) TYPE_RGB_16;
1136 if ((source_colorspace == UndefinedColorspace) ||
1137 (target_colorspace == UndefinedColorspace))
1138 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1140 if ((source_colorspace == GRAYColorspace) &&
1141 (IsGrayImage(image,exception) == MagickFalse))
1142 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1144 if ((source_colorspace == CMYKColorspace) &&
1145 (image->colorspace != CMYKColorspace))
1146 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1148 if ((source_colorspace == XYZColorspace) &&
1149 (image->colorspace != XYZColorspace))
1150 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1152 if ((source_colorspace == YCbCrColorspace) &&
1153 (image->colorspace != YCbCrColorspace))
1154 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1156 if ((source_colorspace != CMYKColorspace) &&
1157 (source_colorspace != GRAYColorspace) &&
1158 (source_colorspace != LabColorspace) &&
1159 (source_colorspace != XYZColorspace) &&
1160 (source_colorspace != YCbCrColorspace) &&
1161 (image->colorspace != RGBColorspace))
1162 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1164 switch (image->rendering_intent)
1166 case AbsoluteIntent: intent=INTENT_ABSOLUTE_COLORIMETRIC; break;
1167 case PerceptualIntent: intent=INTENT_PERCEPTUAL; break;
1168 case RelativeIntent: intent=INTENT_RELATIVE_COLORIMETRIC; break;
1169 case SaturationIntent: intent=INTENT_SATURATION; break;
1170 default: intent=INTENT_PERCEPTUAL; break;
1172 flags=cmsFLAGS_HIGHRESPRECALC;
1173 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1174 if (image->black_point_compensation != MagickFalse)
1175 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1177 transform=AcquireTransformThreadSet(source_profile,source_type,
1178 target_profile,target_type,intent,flags);
1179 if (transform == (cmsHTRANSFORM *) NULL)
1180 ThrowBinaryException(ImageError,"UnableToCreateColorTransform",name);
1182 Transform image as dictated by the source and target image profiles.
1184 length=(size_t) image->columns;
1185 source_pixels=AcquirePixelThreadSet(image->columns,source_channels);
1186 target_pixels=AcquirePixelThreadSet(image->columns,target_channels);
1187 if ((source_pixels == (unsigned short **) NULL) ||
1188 (target_pixels == (unsigned short **) NULL))
1190 transform=DestroyTransformThreadSet(transform);
1191 if (target_profile != (cmsHPROFILE) NULL)
1192 (void) cmsCloseProfile(target_profile);
1193 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1196 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1198 target_pixels=DestroyPixelThreadSet(target_pixels);
1199 source_pixels=DestroyPixelThreadSet(source_pixels);
1200 transform=DestroyTransformThreadSet(transform);
1201 if (target_profile != (cmsHPROFILE) NULL)
1202 (void) cmsCloseProfile(target_profile);
1203 return(MagickFalse);
1205 if (target_colorspace == CMYKColorspace)
1206 (void) SetImageColorspace(image,target_colorspace);
1209 image_view=AcquireCacheView(image);
1210 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1211 #pragma omp parallel for schedule(dynamic,4) shared(status)
1213 for (y=0; y < (long) image->rows; y++)
1218 register IndexPacket
1225 register PixelPacket
1228 register unsigned short
1231 if (status == MagickFalse)
1233 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1235 if (q == (PixelPacket *) NULL)
1240 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1241 id=GetOpenMPThreadId();
1242 p=source_pixels[id];
1243 for (x=0; x < (long) image->columns; x++)
1245 *p++=ScaleQuantumToShort(q->red);
1246 if (source_channels > 1)
1248 *p++=ScaleQuantumToShort(q->green);
1249 *p++=ScaleQuantumToShort(q->blue);
1251 if (source_channels > 3)
1252 *p++=ScaleQuantumToShort(indexes[x]);
1255 cmsDoTransform(transform[id],source_pixels[id],target_pixels[id],
1256 (unsigned int) image->columns);
1257 p=target_pixels[id];
1259 for (x=0; x < (long) image->columns; x++)
1261 q->red=ScaleShortToQuantum(*p);
1265 if (target_channels > 1)
1267 q->green=ScaleShortToQuantum(*p);
1269 q->blue=ScaleShortToQuantum(*p);
1272 if (target_channels > 3)
1274 indexes[x]=ScaleShortToQuantum(*p);
1279 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1280 if (sync == MagickFalse)
1282 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1287 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1288 #pragma omp critical (MagickCore_ProfileImage)
1290 proceed=SetImageProgress(image,ProfileImageTag,progress++,
1292 if (proceed == MagickFalse)
1296 image_view=DestroyCacheView(image_view);
1297 (void) SetImageColorspace(image,target_colorspace);
1302 image->type=image->matte == MagickFalse ? TrueColorType :
1306 case cmsSigCmykData:
1308 image->type=image->matte == MagickFalse ? ColorSeparationType :
1309 ColorSeparationMatteType;
1312 case cmsSigGrayData:
1314 image->type=image->matte == MagickFalse ? GrayscaleType :
1321 target_pixels=DestroyPixelThreadSet(target_pixels);
1322 source_pixels=DestroyPixelThreadSet(source_pixels);
1323 transform=DestroyTransformThreadSet(transform);
1324 if (cmsGetDeviceClass(source_profile) != cmsSigLinkClass)
1325 status=SetImageProfile(image,name,profile);
1326 if (target_profile != (cmsHPROFILE) NULL)
1327 (void) cmsCloseProfile(target_profile);
1328 (void) cmsCloseProfile(source_profile);
1332 profile=DestroyStringInfo(profile);
1337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1341 % R e m o v e I m a g e P r o f i l e %
1345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1347 % RemoveImageProfile() removes a named profile from the image and returns its
1350 % The format of the RemoveImageProfile method is:
1352 % void *RemoveImageProfile(Image *image,const char *name)
1354 % A description of each parameter follows:
1356 % o image: the image.
1358 % o name: the profile name.
1361 MagickExport StringInfo *RemoveImageProfile(Image *image,const char *name)
1366 assert(image != (Image *) NULL);
1367 assert(image->signature == MagickSignature);
1368 if (image->debug != MagickFalse)
1369 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1370 if (image->profiles == (SplayTreeInfo *) NULL)
1371 return((StringInfo *) NULL);
1372 if (LocaleCompare(name,"icc") == 0)
1375 Continue to support deprecated color profile for now.
1377 image->color_profile.length=0;
1378 image->color_profile.info=(unsigned char *) NULL;
1380 if (LocaleCompare(name,"iptc") == 0)
1383 Continue to support deprecated IPTC profile for now.
1385 image->iptc_profile.length=0;
1386 image->iptc_profile.info=(unsigned char *) NULL;
1388 profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
1389 image->profiles,name);
1394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1398 % R e s e t P r o f i l e I t e r a t o r %
1402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1404 % ResetImageProfileIterator() resets the image profile iterator. Use it in
1405 % conjunction with GetNextImageProfile() to iterate over all the profiles
1406 % associated with an image.
1408 % The format of the ResetImageProfileIterator method is:
1410 % ResetImageProfileIterator(Image *image)
1412 % A description of each parameter follows:
1414 % o image: the image.
1417 MagickExport void ResetImageProfileIterator(const Image *image)
1419 assert(image != (Image *) NULL);
1420 assert(image->signature == MagickSignature);
1421 if (image->debug != MagickFalse)
1422 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1423 if (image->profiles == (SplayTreeInfo *) NULL)
1425 ResetSplayTreeIterator((SplayTreeInfo *) image->profiles);
1429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1433 % S e t I m a g e P r o f i l e %
1437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1439 % SetImageProfile() adds a named profile to the image. If a profile with the
1440 % same name already exists, it is replaced. This method differs from the
1441 % ProfileImage() method in that it does not apply CMS color profiles.
1443 % The format of the SetImageProfile method is:
1445 % MagickBooleanType SetImageProfile(Image *image,const char *name,
1446 % const StringInfo *profile)
1448 % A description of each parameter follows:
1450 % o image: the image.
1452 % o name: the profile name, for example icc, exif, and 8bim (8bim is the
1453 % Photoshop wrapper for iptc profiles).
1455 % o profile: A StringInfo structure that contains the named profile.
1459 static void *DestroyProfile(void *profile)
1461 return((void *) DestroyStringInfo((StringInfo *) profile));
1464 static inline const unsigned char *ReadResourceByte(const unsigned char *p,
1465 unsigned char *quantum)
1471 static inline const unsigned char *ReadResourceBytes(const unsigned char *p,
1472 const ssize_t count,unsigned char *quantum)
1477 for (i=0; i < count; i++)
1482 static inline const unsigned char *ReadResourceLong(const unsigned char *p,
1483 unsigned long *quantum)
1485 *quantum=(unsigned long) (*p++ << 24);
1486 *quantum|=(unsigned long) (*p++ << 16);
1487 *quantum|=(unsigned long) (*p++ << 8);
1488 *quantum|=(unsigned long) (*p++ << 0);
1492 static inline const unsigned char *ReadResourceShort(const unsigned char *p,
1493 unsigned short *quantum)
1495 *quantum=(unsigned short) (*p++ << 8);
1496 *quantum|=(unsigned short) (*p++ << 0);
1500 static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
1501 const StringInfo *resource_block)
1506 register const unsigned char
1524 datum=GetStringInfoDatum(resource_block);
1525 length=GetStringInfoLength(resource_block);
1526 for (p=datum; p < (datum+length-16); )
1528 if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1531 p=ReadResourceShort(p,&id);
1532 p=ReadResourceByte(p,&length_byte);
1534 if (((length_byte+1) & 0x01) != 0)
1536 if (p > (datum+length-4))
1538 p=ReadResourceLong(p,&count);
1539 if ((p > (datum+length-count)) || (count > length))
1551 p=ReadResourceShort(p,&resolution)+6;
1552 image->x_resolution=(double) resolution;
1553 p=ReadResourceShort(p,&resolution)+6;
1554 image->y_resolution=(double) resolution;
1562 profile=AcquireStringInfo(count);
1563 SetStringInfoDatum(profile,p);
1564 (void) SetImageProfile(image,"iptc",profile);
1565 profile=DestroyStringInfo(profile);
1582 profile=AcquireStringInfo(count);
1583 SetStringInfoDatum(profile,p);
1584 (void) SetImageProfile(image,"icc",profile);
1585 profile=DestroyStringInfo(profile);
1594 profile=AcquireStringInfo(count);
1595 SetStringInfoDatum(profile,p);
1596 (void) SetImageProfile(image,"exif",profile);
1597 profile=DestroyStringInfo(profile);
1606 profile=AcquireStringInfo(count);
1607 SetStringInfoDatum(profile,p);
1608 (void) SetImageProfile(image,"xmp",profile);
1609 profile=DestroyStringInfo(profile);
1619 if ((count & 0x01) != 0)
1625 MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name,
1626 const StringInfo *profile)
1630 property[MaxTextExtent];
1635 assert(image != (Image *) NULL);
1636 assert(image->signature == MagickSignature);
1637 if (image->debug != MagickFalse)
1638 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1639 if (image->profiles == (SplayTreeInfo *) NULL)
1640 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
1642 (void) CopyMagickString(key,name,MaxTextExtent);
1643 status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1644 ConstantString(key),CloneStringInfo(profile));
1645 if ((status != MagickFalse) &&
1646 ((LocaleCompare(name,"icc") == 0) || (LocaleCompare(name,"icm") == 0)))
1652 Continue to support deprecated color profile member.
1654 icc_profile=GetImageProfile(image,name);
1655 if (icc_profile != (const StringInfo *) NULL)
1657 image->color_profile.length=GetStringInfoLength(icc_profile);
1658 image->color_profile.info=GetStringInfoDatum(icc_profile);
1661 if ((status != MagickFalse) &&
1662 ((LocaleCompare(name,"iptc") == 0) || (LocaleCompare(name,"8bim") == 0)))
1668 Continue to support deprecated IPTC profile member.
1670 iptc_profile=GetImageProfile(image,name);
1671 if (iptc_profile != (const StringInfo *) NULL)
1673 image->iptc_profile.length=GetStringInfoLength(iptc_profile);
1674 image->iptc_profile.info=GetStringInfoDatum(iptc_profile);
1676 (void) GetProfilesFromResourceBlock(image,profile);
1679 Inject profile into image properties.
1681 (void) FormatMagickString(property,MaxTextExtent,"%s:sans",name);
1682 (void) GetImageProperty(image,property);
1687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1691 % S y n c I m a g e P r o f i l e s %
1695 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1697 % SyncImageProfiles() synchronizes image properties with the image profiles.
1698 % Currently we only support updating the EXIF resolution and orientation.
1700 % The format of the SyncImageProfiles method is:
1702 % MagickBooleanType SyncImageProfiles(Image *image)
1704 % A description of each parameter follows:
1706 % o image: the image.
1710 static inline int ReadProfileByte(unsigned char **p,size_t *length)
1722 static inline unsigned short ReadProfileShort(const EndianType endian,
1723 unsigned char *buffer)
1728 if (endian == MSBEndian)
1730 value=(unsigned short) ((((unsigned char *) buffer)[0] << 8) |
1731 ((unsigned char *) buffer)[1]);
1732 return((unsigned short) (value & 0xffff));
1734 value=(unsigned short) ((buffer[1] << 8) | buffer[0]);
1735 return((unsigned short) (value & 0xffff));
1738 static inline unsigned long ReadProfileLong(const EndianType endian,
1739 unsigned char *buffer)
1744 if (endian == MSBEndian)
1746 value=(unsigned long) ((buffer[0] << 24) | (buffer[1] << 16) |
1747 (buffer[2] << 8) | buffer[3]);
1748 return((unsigned long) (value & 0xffffffff));
1750 value=(unsigned long) ((buffer[3] << 24) | (buffer[2] << 16) |
1751 (buffer[1] << 8 ) | (buffer[0]));
1752 return((unsigned long) (value & 0xffffffff));
1755 static inline void WriteProfileLong(const EndianType endian,
1756 const unsigned long value,unsigned char *p)
1761 if (endian == MSBEndian)
1763 buffer[0]=(unsigned char) (value >> 24);
1764 buffer[1]=(unsigned char) (value >> 16);
1765 buffer[2]=(unsigned char) (value >> 8);
1766 buffer[3]=(unsigned char) value;
1767 (void) CopyMagickMemory(p,buffer,4);
1770 buffer[0]=(unsigned char) value;
1771 buffer[1]=(unsigned char) (value >> 8);
1772 buffer[2]=(unsigned char) (value >> 16);
1773 buffer[3]=(unsigned char) (value >> 24);
1774 (void) CopyMagickMemory(p,buffer,4);
1777 static void WriteProfileShort(const EndianType endian,
1778 const unsigned short value,unsigned char *p)
1783 if (endian == MSBEndian)
1785 buffer[0]=(unsigned char) (value >> 8);
1786 buffer[1]=(unsigned char) value;
1787 (void) CopyMagickMemory(p,buffer,2);
1790 buffer[0]=(unsigned char) value;
1791 buffer[1]=(unsigned char) (value >> 8);
1792 (void) CopyMagickMemory(p,buffer,2);
1795 MagickExport MagickBooleanType SyncImageProfiles(Image *image)
1797 #define MaxDirectoryStack 16
1798 #define EXIF_DELIMITER "\n"
1799 #define EXIF_NUM_FORMATS 12
1800 #define TAG_EXIF_OFFSET 0x8769
1801 #define TAG_INTEROP_OFFSET 0xa005
1803 typedef struct _DirectoryInfo
1813 directory_stack[MaxDirectoryStack];
1829 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
1843 Set EXIF resolution tag.
1845 profile=(StringInfo *) GetImageProfile(image,"EXIF");
1846 if (profile == (StringInfo *) NULL)
1848 length=GetStringInfoLength(profile);
1849 exif=GetStringInfoDatum(profile);
1852 if (ReadProfileByte(&exif,&length) != 0x45)
1854 if (ReadProfileByte(&exif,&length) != 0x78)
1856 if (ReadProfileByte(&exif,&length) != 0x69)
1858 if (ReadProfileByte(&exif,&length) != 0x66)
1860 if (ReadProfileByte(&exif,&length) != 0x00)
1862 if (ReadProfileByte(&exif,&length) != 0x00)
1867 return(MagickFalse);
1868 id=(int) ReadProfileShort(LSBEndian,exif);
1876 return(MagickFalse);
1877 if (ReadProfileShort(endian,exif+2) != 0x002a)
1878 return(MagickFalse);
1880 This the offset to the first IFD.
1882 offset=(ssize_t) ReadProfileLong(endian,exif+4);
1883 if ((size_t) offset >= length)
1884 return(MagickFalse);
1885 directory=exif+offset;
1893 directory=directory_stack[level].directory;
1894 entry=directory_stack[level].entry;
1897 Determine how many entries there are in the current IFD.
1899 number_entries=ReadProfileShort(endian,directory);
1900 for ( ; entry < number_entries; entry++)
1907 register unsigned char
1914 q=(unsigned char *) (directory+2+(12*entry));
1915 tag_value=(long) ReadProfileShort(endian,q);
1916 format=(long) ReadProfileShort(endian,q+2);
1917 if ((format-1) >= EXIF_NUM_FORMATS)
1919 components=(long) ReadProfileLong(endian,q+4);
1920 number_bytes=(size_t) components*format_bytes[format];
1921 if (number_bytes <= 4)
1929 The directory entry contains an offset.
1931 offset=(ssize_t) ReadProfileLong(endian,q+8);
1932 if ((size_t) (offset+number_bytes) > length)
1934 p=(unsigned char *) (exif+offset);
1940 (void) WriteProfileLong(endian,(unsigned long)
1941 (image->x_resolution+0.5),p);
1942 (void) WriteProfileLong(endian,1UL,p+4);
1947 (void) WriteProfileLong(endian,(unsigned long)
1948 (image->y_resolution+0.5),p);
1949 (void) WriteProfileLong(endian,1UL,p+4);
1954 (void) WriteProfileShort(endian,(unsigned short)
1955 image->orientation,p);
1960 (void) WriteProfileShort(endian,(unsigned short)
1961 (image->units+1),p);
1967 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
1972 offset=(size_t) ReadProfileLong(endian,p);
1973 if ((offset < length) && (level < (MaxDirectoryStack-2)))
1975 directory_stack[level].directory=directory;
1977 directory_stack[level].entry=entry;
1979 directory_stack[level].directory=exif+offset;
1980 directory_stack[level].entry=0;
1982 if ((directory+2+(12*number_entries)) > (exif+length))
1984 offset=(size_t) ReadProfileLong(endian,directory+2+(12*
1986 if ((offset != 0) && (offset < length) &&
1987 (level < (MaxDirectoryStack-2)))
1989 directory_stack[level].directory=exif+offset;
1990 directory_stack[level].entry=0;
1997 } while (level > 0);