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 status=SetImageProfile(image,name,profile);
936 (void) ThrowMagickException(&image->exception,GetMagickModule(),
937 MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn","`%s' (LCMS)",
948 cmsColorSpaceSignature
982 **restrict source_pixels,
983 **restrict target_pixels;
986 Transform pixel colors as defined by the color profiles.
988 exception=(&image->exception);
989 #if defined(LCMS_VERSION) && (LCMS_VERSION >= 2000)
990 cmsSetLogErrorHandler(LCMSErrorHandler);
992 #if defined(LCMS_VERSION) && (LCMS_VERSION < 2000)
993 #if defined(LCMS_VERSION) && (LCMS_VERSION > 1010)
994 cmsSetErrorHandler(LCMSErrorHandler);
996 (void) cmsErrorAction(LCMS_ERROR_SHOW);
999 source_profile=cmsOpenProfileFromMem(GetStringInfoDatum(profile),
1000 (cmsUInt32Number) GetStringInfoLength(profile));
1001 if (source_profile == (cmsHPROFILE) NULL)
1002 ThrowBinaryException(ResourceLimitError,
1003 "ColorspaceColorProfileMismatch",name);
1004 target_profile=(cmsHPROFILE) NULL;
1005 if (cmsGetDeviceClass(source_profile) != cmsSigLinkClass)
1007 status=SetImageProfile(image,name,profile);
1008 if (icc_profile != (StringInfo *) NULL)
1010 target_profile=source_profile;
1011 source_profile=cmsOpenProfileFromMem(
1012 GetStringInfoDatum(icc_profile),(cmsUInt32Number)
1013 GetStringInfoLength(icc_profile));
1014 if (source_profile == (cmsHPROFILE) NULL)
1015 ThrowBinaryException(ResourceLimitError,
1016 "ColorspaceColorProfileMismatch",name);
1019 switch (cmsGetColorSpace(source_profile))
1021 case cmsSigCmykData:
1023 source_colorspace=CMYKColorspace;
1024 source_type=(cmsUInt32Number) TYPE_CMYK_16;
1028 case cmsSigGrayData:
1030 source_colorspace=GRAYColorspace;
1031 source_type=(cmsUInt32Number) TYPE_GRAY_16;
1037 source_colorspace=LabColorspace;
1038 source_type=(cmsUInt32Number) TYPE_Lab_16;
1044 source_colorspace=YUVColorspace;
1045 source_type=(cmsUInt32Number) TYPE_YUV_16;
1051 source_colorspace=RGBColorspace;
1052 source_type=(cmsUInt32Number) TYPE_RGB_16;
1058 source_colorspace=XYZColorspace;
1059 source_type=(cmsUInt32Number) TYPE_XYZ_16;
1063 case cmsSigYCbCrData:
1065 source_colorspace=YCbCrColorspace;
1066 source_type=(cmsUInt32Number) TYPE_YCbCr_16;
1072 source_colorspace=UndefinedColorspace;
1073 source_type=(cmsUInt32Number) TYPE_RGB_16;
1078 signature=cmsGetPCS(source_profile);
1079 if (target_profile != (cmsHPROFILE) NULL)
1080 signature=cmsGetColorSpace(target_profile);
1083 case cmsSigCmykData:
1085 target_colorspace=CMYKColorspace;
1086 target_type=(cmsUInt32Number) TYPE_CMYK_16;
1092 target_colorspace=LabColorspace;
1093 target_type=(cmsUInt32Number) TYPE_Lab_16;
1097 case cmsSigGrayData:
1099 target_colorspace=GRAYColorspace;
1100 target_type=(cmsUInt32Number) TYPE_GRAY_16;
1106 target_colorspace=YUVColorspace;
1107 target_type=(cmsUInt32Number) TYPE_YUV_16;
1113 target_colorspace=RGBColorspace;
1114 target_type=(cmsUInt32Number) TYPE_RGB_16;
1120 target_colorspace=XYZColorspace;
1121 target_type=(cmsUInt32Number) TYPE_XYZ_16;
1125 case cmsSigYCbCrData:
1127 target_colorspace=YCbCrColorspace;
1128 target_type=(cmsUInt32Number) TYPE_YCbCr_16;
1134 target_colorspace=UndefinedColorspace;
1135 target_type=(cmsUInt32Number) TYPE_RGB_16;
1140 if ((source_colorspace == UndefinedColorspace) ||
1141 (target_colorspace == UndefinedColorspace))
1142 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1144 if ((source_colorspace == GRAYColorspace) &&
1145 (IsGrayImage(image,exception) == MagickFalse))
1146 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1148 if ((source_colorspace == CMYKColorspace) &&
1149 (image->colorspace != CMYKColorspace))
1150 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1152 if ((source_colorspace == XYZColorspace) &&
1153 (image->colorspace != XYZColorspace))
1154 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1156 if ((source_colorspace == YCbCrColorspace) &&
1157 (image->colorspace != YCbCrColorspace))
1158 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1160 if ((source_colorspace != CMYKColorspace) &&
1161 (source_colorspace != GRAYColorspace) &&
1162 (source_colorspace != LabColorspace) &&
1163 (source_colorspace != XYZColorspace) &&
1164 (source_colorspace != YCbCrColorspace) &&
1165 (image->colorspace != RGBColorspace))
1166 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1168 switch (image->rendering_intent)
1170 case AbsoluteIntent: intent=INTENT_ABSOLUTE_COLORIMETRIC; break;
1171 case PerceptualIntent: intent=INTENT_PERCEPTUAL; break;
1172 case RelativeIntent: intent=INTENT_RELATIVE_COLORIMETRIC; break;
1173 case SaturationIntent: intent=INTENT_SATURATION; break;
1174 default: intent=INTENT_PERCEPTUAL; break;
1176 flags=cmsFLAGS_HIGHRESPRECALC;
1177 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1178 if (image->black_point_compensation != MagickFalse)
1179 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1181 transform=AcquireTransformThreadSet(source_profile,source_type,
1182 target_profile,target_type,intent,flags);
1183 (void) cmsCloseProfile(source_profile);
1184 if (transform == (cmsHTRANSFORM *) NULL)
1185 ThrowBinaryException(ImageError,"UnableToCreateColorTransform",
1188 Transform image as dictated by the source and target image profiles.
1190 length=(size_t) image->columns;
1191 source_pixels=AcquirePixelThreadSet(image->columns,source_channels);
1192 target_pixels=AcquirePixelThreadSet(image->columns,target_channels);
1193 if ((source_pixels == (unsigned short **) NULL) ||
1194 (target_pixels == (unsigned short **) NULL))
1196 transform=DestroyTransformThreadSet(transform);
1197 (void) cmsCloseProfile(target_profile);
1198 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1201 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1203 target_pixels=DestroyPixelThreadSet(target_pixels);
1204 source_pixels=DestroyPixelThreadSet(source_pixels);
1205 transform=DestroyTransformThreadSet(transform);
1206 (void) cmsCloseProfile(target_profile);
1207 return(MagickFalse);
1209 if (target_colorspace == CMYKColorspace)
1210 (void) SetImageColorspace(image,target_colorspace);
1213 image_view=AcquireCacheView(image);
1214 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1215 #pragma omp parallel for schedule(dynamic,4) shared(status)
1217 for (y=0; y < (long) image->rows; y++)
1222 register IndexPacket
1229 register PixelPacket
1232 register unsigned short
1235 if (status == MagickFalse)
1237 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1239 if (q == (PixelPacket *) NULL)
1244 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1245 id=GetOpenMPThreadId();
1246 p=source_pixels[id];
1247 for (x=0; x < (long) image->columns; x++)
1249 *p++=ScaleQuantumToShort(q->red);
1250 if (source_channels > 1)
1252 *p++=ScaleQuantumToShort(q->green);
1253 *p++=ScaleQuantumToShort(q->blue);
1255 if (source_channels > 3)
1256 *p++=ScaleQuantumToShort(indexes[x]);
1259 cmsDoTransform(transform[id],source_pixels[id],target_pixels[id],
1260 (unsigned int) image->columns);
1261 p=target_pixels[id];
1263 for (x=0; x < (long) image->columns; x++)
1265 q->red=ScaleShortToQuantum(*p);
1269 if (target_channels > 1)
1271 q->green=ScaleShortToQuantum(*p);
1273 q->blue=ScaleShortToQuantum(*p);
1276 if (target_channels > 3)
1278 indexes[x]=ScaleShortToQuantum(*p);
1283 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1284 if (sync == MagickFalse)
1286 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1291 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1292 #pragma omp critical (MagickCore_ProfileImage)
1294 proceed=SetImageProgress(image,ProfileImageTag,progress++,
1296 if (proceed == MagickFalse)
1300 image_view=DestroyCacheView(image_view);
1301 (void) SetImageColorspace(image,target_colorspace);
1306 image->type=image->matte == MagickFalse ? TrueColorType :
1310 case cmsSigCmykData:
1312 image->type=image->matte == MagickFalse ? ColorSeparationType :
1313 ColorSeparationMatteType;
1316 case cmsSigGrayData:
1318 image->type=image->matte == MagickFalse ? GrayscaleType :
1325 target_pixels=DestroyPixelThreadSet(target_pixels);
1326 source_pixels=DestroyPixelThreadSet(source_pixels);
1327 transform=DestroyTransformThreadSet(transform);
1328 if (target_profile != (cmsHPROFILE) NULL)
1329 (void) cmsCloseProfile(target_profile);
1333 profile=DestroyStringInfo(profile);
1338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1342 % R e m o v e I m a g e P r o f i l e %
1346 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1348 % RemoveImageProfile() removes a named profile from the image and returns its
1351 % The format of the RemoveImageProfile method is:
1353 % void *RemoveImageProfile(Image *image,const char *name)
1355 % A description of each parameter follows:
1357 % o image: the image.
1359 % o name: the profile name.
1362 MagickExport StringInfo *RemoveImageProfile(Image *image,const char *name)
1367 assert(image != (Image *) NULL);
1368 assert(image->signature == MagickSignature);
1369 if (image->debug != MagickFalse)
1370 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1371 if (image->profiles == (SplayTreeInfo *) NULL)
1372 return((StringInfo *) NULL);
1373 if (LocaleCompare(name,"icc") == 0)
1376 Continue to support deprecated color profile for now.
1378 image->color_profile.length=0;
1379 image->color_profile.info=(unsigned char *) NULL;
1381 if (LocaleCompare(name,"iptc") == 0)
1384 Continue to support deprecated IPTC profile for now.
1386 image->iptc_profile.length=0;
1387 image->iptc_profile.info=(unsigned char *) NULL;
1389 profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
1390 image->profiles,name);
1395 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1399 % R e s e t P r o f i l e I t e r a t o r %
1403 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1405 % ResetImageProfileIterator() resets the image profile iterator. Use it in
1406 % conjunction with GetNextImageProfile() to iterate over all the profiles
1407 % associated with an image.
1409 % The format of the ResetImageProfileIterator method is:
1411 % ResetImageProfileIterator(Image *image)
1413 % A description of each parameter follows:
1415 % o image: the image.
1418 MagickExport void ResetImageProfileIterator(const Image *image)
1420 assert(image != (Image *) NULL);
1421 assert(image->signature == MagickSignature);
1422 if (image->debug != MagickFalse)
1423 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1424 if (image->profiles == (SplayTreeInfo *) NULL)
1426 ResetSplayTreeIterator((SplayTreeInfo *) image->profiles);
1430 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1434 % S e t I m a g e P r o f i l e %
1438 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1440 % SetImageProfile() adds a named profile to the image. If a profile with the
1441 % same name already exists, it is replaced. This method differs from the
1442 % ProfileImage() method in that it does not apply CMS color profiles.
1444 % The format of the SetImageProfile method is:
1446 % MagickBooleanType SetImageProfile(Image *image,const char *name,
1447 % const StringInfo *profile)
1449 % A description of each parameter follows:
1451 % o image: the image.
1453 % o name: the profile name, for example icc, exif, and 8bim (8bim is the
1454 % Photoshop wrapper for iptc profiles).
1456 % o profile: A StringInfo structure that contains the named profile.
1460 static void *DestroyProfile(void *profile)
1462 return((void *) DestroyStringInfo((StringInfo *) profile));
1465 static inline const unsigned char *ReadResourceByte(const unsigned char *p,
1466 unsigned char *quantum)
1472 static inline const unsigned char *ReadResourceBytes(const unsigned char *p,
1473 const ssize_t count,unsigned char *quantum)
1478 for (i=0; i < count; i++)
1483 static inline const unsigned char *ReadResourceLong(const unsigned char *p,
1484 unsigned long *quantum)
1486 *quantum=(unsigned long) (*p++ << 24);
1487 *quantum|=(unsigned long) (*p++ << 16);
1488 *quantum|=(unsigned long) (*p++ << 8);
1489 *quantum|=(unsigned long) (*p++ << 0);
1493 static inline const unsigned char *ReadResourceShort(const unsigned char *p,
1494 unsigned short *quantum)
1496 *quantum=(unsigned short) (*p++ << 8);
1497 *quantum|=(unsigned short) (*p++ << 0);
1501 static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
1502 const StringInfo *resource_block)
1507 register const unsigned char
1525 datum=GetStringInfoDatum(resource_block);
1526 length=GetStringInfoLength(resource_block);
1527 for (p=datum; p < (datum+length-16); )
1529 if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1532 p=ReadResourceShort(p,&id);
1533 p=ReadResourceByte(p,&length_byte);
1535 if (((length_byte+1) & 0x01) != 0)
1537 if (p > (datum+length-4))
1539 p=ReadResourceLong(p,&count);
1540 if ((p > (datum+length-count)) || (count > length))
1552 p=ReadResourceShort(p,&resolution)+6;
1553 image->x_resolution=(double) resolution;
1554 p=ReadResourceShort(p,&resolution)+6;
1555 image->y_resolution=(double) resolution;
1563 profile=AcquireStringInfo(count);
1564 SetStringInfoDatum(profile,p);
1565 (void) SetImageProfile(image,"iptc",profile);
1566 profile=DestroyStringInfo(profile);
1583 profile=AcquireStringInfo(count);
1584 SetStringInfoDatum(profile,p);
1585 (void) SetImageProfile(image,"icc",profile);
1586 profile=DestroyStringInfo(profile);
1595 profile=AcquireStringInfo(count);
1596 SetStringInfoDatum(profile,p);
1597 (void) SetImageProfile(image,"exif",profile);
1598 profile=DestroyStringInfo(profile);
1607 profile=AcquireStringInfo(count);
1608 SetStringInfoDatum(profile,p);
1609 (void) SetImageProfile(image,"xmp",profile);
1610 profile=DestroyStringInfo(profile);
1620 if ((count & 0x01) != 0)
1626 MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name,
1627 const StringInfo *profile)
1631 property[MaxTextExtent];
1636 assert(image != (Image *) NULL);
1637 assert(image->signature == MagickSignature);
1638 if (image->debug != MagickFalse)
1639 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1640 if (image->profiles == (SplayTreeInfo *) NULL)
1641 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
1643 (void) CopyMagickString(key,name,MaxTextExtent);
1644 status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1645 ConstantString(key),CloneStringInfo(profile));
1646 if ((status != MagickFalse) &&
1647 ((LocaleCompare(name,"icc") == 0) || (LocaleCompare(name,"icm") == 0)))
1653 Continue to support deprecated color profile member.
1655 icc_profile=GetImageProfile(image,name);
1656 if (icc_profile != (const StringInfo *) NULL)
1658 image->color_profile.length=GetStringInfoLength(icc_profile);
1659 image->color_profile.info=GetStringInfoDatum(icc_profile);
1662 if ((status != MagickFalse) &&
1663 ((LocaleCompare(name,"iptc") == 0) || (LocaleCompare(name,"8bim") == 0)))
1669 Continue to support deprecated IPTC profile member.
1671 iptc_profile=GetImageProfile(image,name);
1672 if (iptc_profile != (const StringInfo *) NULL)
1674 image->iptc_profile.length=GetStringInfoLength(iptc_profile);
1675 image->iptc_profile.info=GetStringInfoDatum(iptc_profile);
1677 (void) GetProfilesFromResourceBlock(image,profile);
1680 Inject profile into image properties.
1682 (void) FormatMagickString(property,MaxTextExtent,"%s:sans",name);
1683 (void) GetImageProperty(image,property);
1688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1692 % S y n c I m a g e P r o f i l e s %
1696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1698 % SyncImageProfiles() synchronizes image properties with the image profiles.
1699 % Currently we only support updating the EXIF resolution and orientation.
1701 % The format of the SyncImageProfiles method is:
1703 % MagickBooleanType SyncImageProfiles(Image *image)
1705 % A description of each parameter follows:
1707 % o image: the image.
1711 static inline int ReadProfileByte(unsigned char **p,size_t *length)
1723 static inline unsigned short ReadProfileShort(const EndianType endian,
1724 unsigned char *buffer)
1729 if (endian == MSBEndian)
1731 value=(unsigned short) ((((unsigned char *) buffer)[0] << 8) |
1732 ((unsigned char *) buffer)[1]);
1733 return((unsigned short) (value & 0xffff));
1735 value=(unsigned short) ((buffer[1] << 8) | buffer[0]);
1736 return((unsigned short) (value & 0xffff));
1739 static inline unsigned long ReadProfileLong(const EndianType endian,
1740 unsigned char *buffer)
1745 if (endian == MSBEndian)
1747 value=(unsigned long) ((buffer[0] << 24) | (buffer[1] << 16) |
1748 (buffer[2] << 8) | buffer[3]);
1749 return((unsigned long) (value & 0xffffffff));
1751 value=(unsigned long) ((buffer[3] << 24) | (buffer[2] << 16) |
1752 (buffer[1] << 8 ) | (buffer[0]));
1753 return((unsigned long) (value & 0xffffffff));
1756 static inline void WriteProfileLong(const EndianType endian,
1757 const unsigned long value,unsigned char *p)
1762 if (endian == MSBEndian)
1764 buffer[0]=(unsigned char) (value >> 24);
1765 buffer[1]=(unsigned char) (value >> 16);
1766 buffer[2]=(unsigned char) (value >> 8);
1767 buffer[3]=(unsigned char) value;
1768 (void) CopyMagickMemory(p,buffer,4);
1771 buffer[0]=(unsigned char) value;
1772 buffer[1]=(unsigned char) (value >> 8);
1773 buffer[2]=(unsigned char) (value >> 16);
1774 buffer[3]=(unsigned char) (value >> 24);
1775 (void) CopyMagickMemory(p,buffer,4);
1778 static void WriteProfileShort(const EndianType endian,
1779 const unsigned short value,unsigned char *p)
1784 if (endian == MSBEndian)
1786 buffer[0]=(unsigned char) (value >> 8);
1787 buffer[1]=(unsigned char) value;
1788 (void) CopyMagickMemory(p,buffer,2);
1791 buffer[0]=(unsigned char) value;
1792 buffer[1]=(unsigned char) (value >> 8);
1793 (void) CopyMagickMemory(p,buffer,2);
1796 MagickExport MagickBooleanType SyncImageProfiles(Image *image)
1798 #define MaxDirectoryStack 16
1799 #define EXIF_DELIMITER "\n"
1800 #define EXIF_NUM_FORMATS 12
1801 #define TAG_EXIF_OFFSET 0x8769
1802 #define TAG_INTEROP_OFFSET 0xa005
1804 typedef struct _DirectoryInfo
1814 directory_stack[MaxDirectoryStack];
1830 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
1844 Set EXIF resolution tag.
1846 profile=(StringInfo *) GetImageProfile(image,"EXIF");
1847 if (profile == (StringInfo *) NULL)
1849 length=GetStringInfoLength(profile);
1850 exif=GetStringInfoDatum(profile);
1853 if (ReadProfileByte(&exif,&length) != 0x45)
1855 if (ReadProfileByte(&exif,&length) != 0x78)
1857 if (ReadProfileByte(&exif,&length) != 0x69)
1859 if (ReadProfileByte(&exif,&length) != 0x66)
1861 if (ReadProfileByte(&exif,&length) != 0x00)
1863 if (ReadProfileByte(&exif,&length) != 0x00)
1868 return(MagickFalse);
1869 id=(int) ReadProfileShort(LSBEndian,exif);
1877 return(MagickFalse);
1878 if (ReadProfileShort(endian,exif+2) != 0x002a)
1879 return(MagickFalse);
1881 This the offset to the first IFD.
1883 offset=(ssize_t) ReadProfileLong(endian,exif+4);
1884 if ((size_t) offset >= length)
1885 return(MagickFalse);
1886 directory=exif+offset;
1894 directory=directory_stack[level].directory;
1895 entry=directory_stack[level].entry;
1898 Determine how many entries there are in the current IFD.
1900 number_entries=ReadProfileShort(endian,directory);
1901 for ( ; entry < number_entries; entry++)
1908 register unsigned char
1915 q=(unsigned char *) (directory+2+(12*entry));
1916 tag_value=(long) ReadProfileShort(endian,q);
1917 format=(long) ReadProfileShort(endian,q+2);
1918 if ((format-1) >= EXIF_NUM_FORMATS)
1920 components=(long) ReadProfileLong(endian,q+4);
1921 number_bytes=(size_t) components*format_bytes[format];
1922 if (number_bytes <= 4)
1930 The directory entry contains an offset.
1932 offset=(ssize_t) ReadProfileLong(endian,q+8);
1933 if ((size_t) (offset+number_bytes) > length)
1935 p=(unsigned char *) (exif+offset);
1941 (void) WriteProfileLong(endian,(unsigned long)
1942 (image->x_resolution+0.5),p);
1943 (void) WriteProfileLong(endian,1UL,p+4);
1948 (void) WriteProfileLong(endian,(unsigned long)
1949 (image->y_resolution+0.5),p);
1950 (void) WriteProfileLong(endian,1UL,p+4);
1955 (void) WriteProfileShort(endian,(unsigned short)
1956 image->orientation,p);
1961 (void) WriteProfileShort(endian,(unsigned short)
1962 (image->units+1),p);
1968 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
1973 offset=(size_t) ReadProfileLong(endian,p);
1974 if ((offset < length) && (level < (MaxDirectoryStack-2)))
1976 directory_stack[level].directory=directory;
1978 directory_stack[level].entry=entry;
1980 directory_stack[level].directory=exif+offset;
1981 directory_stack[level].entry=0;
1983 if ((directory+2+(12*number_entries)) > (exif+length))
1985 offset=(size_t) ReadProfileLong(endian,directory+2+(12*
1987 if ((offset != 0) && (offset < length) &&
1988 (level < (MaxDirectoryStack-2)))
1990 directory_stack[level].directory=exif+offset;
1991 directory_stack[level].entry=0;
1998 } while (level > 0);