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
95 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
99 % C l o n e I m a g e P r o f i l e s %
103 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
105 % CloneImageProfiles() clones one or more image profiles.
107 % The format of the CloneImageProfiles method is:
109 % MagickBooleanType CloneImageProfiles(Image *image,
110 % const Image *clone_image)
112 % A description of each parameter follows:
114 % o image: the image.
116 % o clone_image: the clone image.
119 MagickExport MagickBooleanType CloneImageProfiles(Image *image,
120 const Image *clone_image)
122 assert(image != (Image *) NULL);
123 assert(image->signature == MagickSignature);
124 if (image->debug != MagickFalse)
125 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
126 assert(clone_image != (const Image *) NULL);
127 assert(clone_image->signature == MagickSignature);
128 image->color_profile.length=clone_image->color_profile.length;
129 image->color_profile.info=clone_image->color_profile.info;
130 image->iptc_profile.length=clone_image->iptc_profile.length;
131 image->iptc_profile.info=clone_image->iptc_profile.info;
132 if (clone_image->profiles != (void *) NULL)
133 image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
134 (void *(*)(void *)) ConstantString,(void *(*)(void *)) CloneStringInfo);
139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
143 % D e l e t e I m a g e P r o f i l e %
147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149 % DeleteImageProfile() deletes a profile from the image by its name.
151 % The format of the DeleteImageProfile method is:
153 % MagickBooleanTyupe DeleteImageProfile(Image *image,const char *name)
155 % A description of each parameter follows:
157 % o image: the image.
159 % o name: the profile name.
162 MagickExport MagickBooleanType DeleteImageProfile(Image *image,const char *name)
164 assert(image != (Image *) NULL);
165 assert(image->signature == MagickSignature);
166 if (image->debug != MagickFalse)
167 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
168 if (image->profiles == (SplayTreeInfo *) NULL)
170 if (LocaleCompare(name,"icc") == 0)
173 Continue to support deprecated color profile for now.
175 image->color_profile.length=0;
176 image->color_profile.info=(unsigned char *) NULL;
178 if (LocaleCompare(name,"iptc") == 0)
181 Continue to support deprecated IPTC profile for now.
183 image->iptc_profile.length=0;
184 image->iptc_profile.info=(unsigned char *) NULL;
186 return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->profiles,name));
190 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
194 % D e s t r o y I m a g e P r o f i l e s %
198 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
200 % DestroyImageProfiles() releases memory associated with an image profile map.
202 % The format of the DestroyProfiles method is:
204 % void DestroyImageProfiles(Image *image)
206 % A description of each parameter follows:
208 % o image: the image.
211 MagickExport void DestroyImageProfiles(Image *image)
213 if (image->profiles != (SplayTreeInfo *) NULL)
214 image->profiles=DestroySplayTree((SplayTreeInfo *) image->profiles);
218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222 % G e t I m a g e P r o f i l e %
226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228 % GetImageProfile() gets a profile associated with an image by name.
230 % The format of the GetImageProfile method is:
232 % const StringInfo *GetImageProfile(const Image *image,const char *name)
234 % A description of each parameter follows:
236 % o image: the image.
238 % o name: the profile name.
241 MagickExport const StringInfo *GetImageProfile(const Image *image,
250 assert(image != (Image *) NULL);
251 assert(image->signature == MagickSignature);
252 if (image->debug != MagickFalse)
253 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
254 if (image->profiles == (SplayTreeInfo *) NULL)
255 return((StringInfo *) NULL);
256 (void) CopyMagickString(key,name,MaxTextExtent);
257 profile=(const StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
258 image->profiles,key);
263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
267 % G e t N e x t I m a g e P r o f i l e %
271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
273 % GetNextImageProfile() gets the next profile name for an image.
275 % The format of the GetNextImageProfile method is:
277 % char *GetNextImageProfile(const Image *image)
279 % A description of each parameter follows:
281 % o hash_info: the hash info.
284 MagickExport char *GetNextImageProfile(const Image *image)
286 assert(image != (Image *) NULL);
287 assert(image->signature == MagickSignature);
288 if (image->debug != MagickFalse)
289 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
290 if (image->profiles == (SplayTreeInfo *) NULL)
291 return((char *) NULL);
292 return((char *) GetNextKeyInSplayTree((SplayTreeInfo *) image->profiles));
296 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
300 % P r o f i l e I m a g e %
304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
306 % ProfileImage() associates, applies, or removes an ICM, IPTC, or generic
307 % profile with / to / from an image. If the profile is NULL, it is removed
308 % from the image otherwise added or applied. Use a name of '*' and a profile
309 % of NULL to remove all profiles from the image.
311 % ICC and ICM profiles are handled as follows: If the image does not have
312 % an associated color profile, the one you provide is associated with the
313 % image and the image pixels are not transformed. Otherwise, the colorspace
314 % transform defined by the existing and new profile are applied to the image
315 % pixels and the new profile is associated with the image.
317 % The format of the ProfileImage method is:
319 % MagickBooleanType ProfileImage(Image *image,const char *name,
320 % const void *datum,const size_t length,const MagickBooleanType clone)
322 % A description of each parameter follows:
324 % o image: the image.
326 % o name: Name of profile to add or remove: ICC, IPTC, or generic profile.
328 % o datum: the profile data.
330 % o length: the length of the profile.
332 % o clone: should be MagickFalse.
336 #if defined(MAGICKCORE_LCMS_DELEGATE)
338 static unsigned short **DestroyPixelThreadSet(unsigned short **pixels)
343 assert(pixels != (unsigned short **) NULL);
344 for (i=0; i < (long) GetOpenMPMaximumThreads(); i++)
345 if (pixels[i] != (unsigned short *) NULL)
346 pixels[i]=(unsigned short *) RelinquishMagickMemory(pixels[i]);
347 pixels=(unsigned short **) RelinquishAlignedMemory(pixels);
351 static unsigned short **AcquirePixelThreadSet(const size_t columns,
352 const size_t channels)
363 number_threads=GetOpenMPMaximumThreads();
364 pixels=(unsigned short **) AcquireAlignedMemory(number_threads,
366 if (pixels == (unsigned short **) NULL)
367 return((unsigned short **) NULL);
368 (void) ResetMagickMemory(pixels,0,number_threads*sizeof(*pixels));
369 for (i=0; i < (long) number_threads; i++)
371 pixels[i]=(unsigned short *) AcquireQuantumMemory(columns,channels*
373 if (pixels[i] == (unsigned short *) NULL)
374 return(DestroyPixelThreadSet(pixels));
379 static cmsHTRANSFORM *DestroyTransformThreadSet(cmsHTRANSFORM *transform)
384 assert(transform != (cmsHTRANSFORM *) NULL);
385 for (i=0; i < (long) GetOpenMPMaximumThreads(); i++)
386 if (transform[i] != (cmsHTRANSFORM) NULL)
387 cmsDeleteTransform(transform[i]);
388 transform=(cmsHTRANSFORM *) RelinquishAlignedMemory(transform);
392 static cmsHTRANSFORM *AcquireTransformThreadSet(
393 const cmsHPROFILE source_profile,const cmsUInt32Number source_type,
394 const cmsHPROFILE target_profile,const cmsUInt32Number target_type,
395 const int intent,const cmsUInt32Number flags)
406 number_threads=GetOpenMPMaximumThreads();
407 transform=(cmsHTRANSFORM *) AcquireAlignedMemory(number_threads,
409 if (transform == (cmsHTRANSFORM *) NULL)
410 return((cmsHTRANSFORM *) NULL);
411 (void) ResetMagickMemory(transform,0,number_threads*sizeof(*transform));
412 for (i=0; i < (long) number_threads; i++)
414 transform[i]=cmsCreateTransform(source_profile,source_type,target_profile,
415 target_type,intent,flags);
416 if (transform[i] == (cmsHTRANSFORM) NULL)
417 return(DestroyTransformThreadSet(transform));
423 static MagickBooleanType SetAdobeRGB1998ImageProfile(Image *image)
426 AdobeRGB1998Profile[] =
428 0x00, 0x00, 0x02, 0x30, 0x41, 0x44, 0x42, 0x45, 0x02, 0x10, 0x00,
429 0x00, 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59,
430 0x5a, 0x20, 0x07, 0xd0, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x13, 0x00,
431 0x33, 0x00, 0x3b, 0x61, 0x63, 0x73, 0x70, 0x41, 0x50, 0x50, 0x4c,
432 0x00, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x00,
433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
434 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00,
435 0x00, 0xd3, 0x2d, 0x41, 0x44, 0x42, 0x45, 0x00, 0x00, 0x00, 0x00,
436 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x0a,
440 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
441 0x32, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00,
442 0x00, 0x6b, 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x9c, 0x00,
443 0x00, 0x00, 0x14, 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x01, 0xb0,
444 0x00, 0x00, 0x00, 0x14, 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01,
445 0xc4, 0x00, 0x00, 0x00, 0x0e, 0x67, 0x54, 0x52, 0x43, 0x00, 0x00,
446 0x01, 0xd4, 0x00, 0x00, 0x00, 0x0e, 0x62, 0x54, 0x52, 0x43, 0x00,
447 0x00, 0x01, 0xe4, 0x00, 0x00, 0x00, 0x0e, 0x72, 0x58, 0x59, 0x5a,
448 0x00, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x00, 0x14, 0x67, 0x58, 0x59,
449 0x5a, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x14, 0x62, 0x58,
450 0x59, 0x5a, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x14, 0x74,
451 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x70, 0x79,
452 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x32, 0x30, 0x30, 0x30, 0x20,
453 0x41, 0x64, 0x6f, 0x62, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65,
454 0x6d, 0x73, 0x20, 0x49, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72,
455 0x61, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x41, 0x64, 0x6f,
457 0x62, 0x65, 0x20, 0x52, 0x47, 0x42, 0x20, 0x28, 0x31, 0x39, 0x39,
458 0x38, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
459 0x00, 0x00, 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, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00,
466 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00,
467 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
469 0x00, 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
470 0x00, 0x01, 0x02, 0x33, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76, 0x00,
471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x33, 0x00, 0x00,
472 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473 0x01, 0x02, 0x33, 0x00, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00,
474 0x00, 0x00, 0x00, 0x00, 0x9c, 0x18, 0x00, 0x00, 0x4f, 0xa5, 0x00,
475 0x00, 0x04, 0xfc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
476 0x00, 0x00, 0x34, 0x8d, 0x00, 0x00, 0xa0, 0x2c, 0x00, 0x00, 0x0f,
477 0x95, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
478 0x26, 0x31, 0x00, 0x00, 0x10, 0x2f, 0x00, 0x00, 0xbe, 0x9c
487 assert(image != (Image *) NULL);
488 assert(image->signature == MagickSignature);
489 if (GetImageProfile(image,"icm") != (const StringInfo *) NULL)
491 profile=AcquireStringInfo(sizeof(AdobeRGB1998Profile));
492 SetStringInfoDatum(profile,AdobeRGB1998Profile);
493 status=SetImageProfile(image,"icm",profile);
494 profile=DestroyStringInfo(profile);
498 static MagickBooleanType SetsRGBImageProfile(Image *image)
503 0x00, 0x00, 0x0c, 0x48, 0x4c, 0x69, 0x6e, 0x6f, 0x02, 0x10, 0x00,
504 0x00, 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59,
505 0x5a, 0x20, 0x07, 0xce, 0x00, 0x02, 0x00, 0x09, 0x00, 0x06, 0x00,
506 0x31, 0x00, 0x00, 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54,
507 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47,
508 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
509 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00,
510 0x00, 0xd3, 0x2d, 0x48, 0x50, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x11,
515 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00,
516 0x33, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00,
517 0x00, 0x6c, 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0xf0, 0x00,
518 0x00, 0x00, 0x14, 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x02, 0x04,
519 0x00, 0x00, 0x00, 0x14, 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x02,
520 0x18, 0x00, 0x00, 0x00, 0x14, 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00,
521 0x02, 0x2c, 0x00, 0x00, 0x00, 0x14, 0x62, 0x58, 0x59, 0x5a, 0x00,
522 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x14, 0x64, 0x6d, 0x6e, 0x64,
523 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70, 0x64, 0x6d, 0x64,
524 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88, 0x76, 0x75,
525 0x65, 0x64, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x86, 0x76,
526 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xd4, 0x00, 0x00, 0x00, 0x24,
527 0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00,
528 0x14, 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x04, 0x0c, 0x00, 0x00,
529 0x00, 0x24, 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x04, 0x30, 0x00,
530 0x00, 0x00, 0x0c, 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x3c,
531 0x00, 0x00, 0x08, 0x0c, 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04,
532 0x3c, 0x00, 0x00, 0x08, 0x0c, 0x62, 0x54, 0x52, 0x43, 0x00, 0x00,
533 0x04, 0x3c, 0x00, 0x00, 0x08, 0x0c, 0x74, 0x65, 0x78, 0x74, 0x00,
534 0x00, 0x00, 0x00, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
535 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, 0x39, 0x38, 0x20,
536 0x48, 0x65, 0x77, 0x6c, 0x65, 0x74, 0x74, 0x2d, 0x50, 0x61, 0x63,
537 0x6b, 0x61, 0x72, 0x64, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e,
538 0x79, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
539 0x00, 0x00, 0x00, 0x12, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45,
540 0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00,
541 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
542 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39,
543 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
549 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xcc, 0x58,
550 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
551 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5a,
552 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa2, 0x00, 0x00,
553 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20, 0x00,
554 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x99, 0x00, 0x00, 0xb7, 0x85,
555 0x00, 0x00, 0x18, 0xda, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00,
556 0x00, 0x00, 0x00, 0x24, 0xa0, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00,
557 0xb6, 0xcf, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74, 0x70,
559 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
560 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74, 0x70,
562 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
563 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 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, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43, 0x20, 0x36, 0x31,
569 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44, 0x65, 0x66,
570 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63, 0x6f,
571 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
572 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00,
573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43, 0x20,
574 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
575 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20,
576 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63,
577 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73,
580 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x52, 0x65,
581 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65,
582 0x77, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74,
583 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 0x43, 0x36,
584 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00,
585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x52, 0x65,
586 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65,
587 0x77, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74,
588 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 0x43, 0x36,
589 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00,
590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592 0x00, 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
593 0xa4, 0xfe, 0x00, 0x14, 0x5f, 0x2e, 0x00, 0x10, 0xcf, 0x14, 0x00,
594 0x03, 0xed, 0xcc, 0x00, 0x04, 0x13, 0x0b, 0x00, 0x03, 0x5c, 0x9e,
595 0x00, 0x00, 0x00, 0x01, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00,
596 0x00, 0x00, 0x4c, 0x09, 0x56, 0x00, 0x50, 0x00, 0x00, 0x00, 0x57,
597 0x1f, 0xe7, 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00,
598 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
600 0x8f, 0x00, 0x00, 0x00, 0x02, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00,
601 0x00, 0x00, 0x43, 0x52, 0x54, 0x20, 0x63, 0x75, 0x72, 0x76, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x05,
603 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19, 0x00, 0x1e, 0x00,
604 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37, 0x00, 0x3b,
605 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54, 0x00,
606 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
607 0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00,
608 0x90, 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9,
609 0x00, 0xae, 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00,
610 0xc6, 0x00, 0xcb, 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0,
611 0x00, 0xe5, 0x00, 0xeb, 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01,
612 0x01, 0x01, 0x07, 0x01, 0x0d, 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f,
613 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32, 0x01, 0x38, 0x01, 0x3e, 0x01,
614 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59, 0x01, 0x60, 0x01, 0x67,
615 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83, 0x01, 0x8b, 0x01,
616 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1, 0x01, 0xb9,
617 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1, 0x01,
618 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
619 0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02,
620 0x4b, 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a,
621 0x02, 0x84, 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02,
622 0xb6, 0x02, 0xc1, 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb,
623 0x02, 0xf5, 0x03, 0x00, 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03,
624 0x2d, 0x03, 0x38, 0x03, 0x43, 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66,
625 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a, 0x03, 0x96, 0x03, 0xa2, 0x03,
626 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3, 0x03, 0xe0, 0x03, 0xec,
627 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20, 0x04, 0x2d, 0x04,
628 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71, 0x04, 0x7e,
629 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4, 0x04,
630 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
631 0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05,
632 0x77, 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5,
633 0x05, 0xd5, 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06,
634 0x27, 0x06, 0x37, 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b,
635 0x06, 0x8c, 0x06, 0x9d, 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06,
636 0xe3, 0x06, 0xf5, 0x07, 0x07, 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d,
637 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74, 0x07, 0x86, 0x07, 0x99, 0x07,
638 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5, 0x07, 0xf8, 0x08, 0x0b,
639 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a, 0x08, 0x6e, 0x08,
640 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2, 0x08, 0xe7,
641 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f, 0x09,
642 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
643 0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a,
644 0x54, 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5,
645 0x0a, 0xdc, 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b,
646 0x51, 0x0b, 0x69, 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8,
647 0x0b, 0xe1, 0x0b, 0xf9, 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c,
648 0x5c, 0x0c, 0x75, 0x0c, 0x8e, 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9,
649 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26, 0x0d, 0x40, 0x0d, 0x5a, 0x0d,
650 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3, 0x0d, 0xde, 0x0d, 0xf8,
651 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64, 0x0e, 0x7f, 0x0e,
652 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09, 0x0f, 0x25,
653 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3, 0x0f,
654 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
655 0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11,
656 0x13, 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa,
657 0x11, 0xc9, 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12,
658 0x64, 0x12, 0x84, 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03,
659 0x13, 0x23, 0x13, 0x43, 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13,
660 0xc5, 0x13, 0xe5, 0x14, 0x06, 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a,
661 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce, 0x14, 0xf0, 0x15, 0x12, 0x15,
662 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b, 0x15, 0xbd, 0x15, 0xe0,
663 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c, 0x16, 0x8f, 0x16,
664 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41, 0x17, 0x65,
665 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b, 0x18,
666 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
667 0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19,
668 0xdd, 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e,
669 0x1a, 0xc5, 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b,
670 0x8a, 0x1b, 0xb2, 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52,
671 0x1c, 0x7b, 0x1c, 0xa3, 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d,
672 0x47, 0x1d, 0x70, 0x1d, 0x99, 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16,
673 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94, 0x1e, 0xbe, 0x1e, 0xe9, 0x1f,
674 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94, 0x1f, 0xbf, 0x1f, 0xea,
675 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98, 0x20, 0xc4, 0x20,
676 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1, 0x21, 0xce,
677 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf, 0x22,
678 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
679 0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24,
680 0xda, 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7,
681 0x25, 0xf7, 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26,
682 0xe8, 0x27, 0x18, 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc,
683 0x28, 0x0d, 0x28, 0x3f, 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29,
684 0x06, 0x29, 0x38, 0x29, 0x6b, 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02,
685 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b, 0x2a, 0xcf, 0x2b, 0x02, 0x2b,
686 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1, 0x2c, 0x05, 0x2c, 0x39,
687 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c, 0x2d, 0x41, 0x2d,
688 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c, 0x2e, 0x82,
689 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91, 0x2f,
690 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
691 0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32,
692 0x2a, 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46,
693 0x33, 0x7f, 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34,
694 0x9e, 0x34, 0xd8, 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2,
695 0x35, 0xfd, 0x36, 0x37, 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37,
696 0x24, 0x37, 0x60, 0x37, 0x9c, 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50,
697 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05, 0x39, 0x42, 0x39, 0x7f, 0x39,
698 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74, 0x3a, 0xb2, 0x3a, 0xef,
699 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8, 0x3c, 0x27, 0x3c,
700 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61, 0x3d, 0xa1,
701 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0, 0x3f,
702 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
703 0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41,
704 0xee, 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a,
705 0x43, 0x7d, 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44,
706 0xce, 0x45, 0x12, 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22,
707 0x46, 0x67, 0x46, 0xab, 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47,
708 0xc0, 0x48, 0x05, 0x48, 0x4b, 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d,
709 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0, 0x4a, 0x37, 0x4a, 0x7d, 0x4a,
710 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a, 0x4b, 0xe2, 0x4c, 0x2a,
711 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a, 0x4d, 0x93, 0x4d,
712 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00, 0x4f, 0x49,
713 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb, 0x51,
714 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
715 0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54,
716 0x42, 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2,
717 0x56, 0x0f, 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57,
718 0x92, 0x57, 0xe0, 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a,
719 0x59, 0x69, 0x59, 0xb8, 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a,
720 0xf5, 0x5b, 0x45, 0x5b, 0x95, 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86,
721 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78, 0x5d, 0xc9, 0x5e, 0x1a, 0x5e,
722 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61, 0x5f, 0xb3, 0x60, 0x05,
723 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f, 0x61, 0xa2, 0x61,
724 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43, 0x63, 0x97,
725 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d, 0x65,
726 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
727 0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69,
728 0x43, 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7,
729 0x6b, 0x4f, 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d,
730 0x08, 0x6d, 0x60, 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4,
731 0x6f, 0x1e, 0x6f, 0x78, 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70,
732 0xe0, 0x71, 0x3a, 0x71, 0x95, 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6,
733 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8, 0x74, 0x14, 0x74, 0x70, 0x74,
734 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1, 0x76, 0x3e, 0x76, 0x9b,
735 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11, 0x78, 0x6e, 0x78,
736 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46, 0x7a, 0xa5,
737 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81, 0x7c,
738 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
739 0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81,
740 0x0a, 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4,
741 0x83, 0x57, 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85,
742 0x47, 0x85, 0xab, 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b,
743 0x87, 0x9f, 0x88, 0x04, 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89,
744 0x99, 0x89, 0xfe, 0x8a, 0x64, 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96,
745 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca, 0x8d, 0x31, 0x8d, 0x98, 0x8d,
746 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36, 0x8f, 0x9e, 0x90, 0x06,
747 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8, 0x92, 0x11, 0x92,
748 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20, 0x94, 0x8a,
749 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f, 0x97,
750 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
751 0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b,
752 0xaf, 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2,
753 0x9e, 0x40, 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0,
754 0x69, 0xa0, 0xd8, 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96,
755 0xa3, 0x06, 0xa3, 0x76, 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5,
756 0x38, 0xa5, 0xa9, 0xa6, 0x1a, 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e,
757 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4, 0xa9, 0x37, 0xa9, 0xa9, 0xaa,
758 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75, 0xab, 0xe9, 0xac, 0x5c,
759 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d, 0xae, 0xa1, 0xaf,
760 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea, 0xb1, 0x60,
761 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae, 0xb4,
762 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
763 0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9,
764 0x4a, 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7,
765 0xbc, 0x21, 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe,
766 0x84, 0xbe, 0xff, 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec,
767 0xc1, 0x67, 0xc1, 0xe3, 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3,
768 0xd4, 0xc4, 0x51, 0xc4, 0xce, 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46,
769 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf, 0xc8, 0x3d, 0xc8, 0xbc, 0xc9,
770 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7, 0xcb, 0x36, 0xcb, 0xb6,
771 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5, 0xce, 0x36, 0xce,
772 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba, 0xd1, 0x3c,
773 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6, 0xd4,
774 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
775 0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9,
776 0xf1, 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a,
777 0xdd, 0x10, 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf,
778 0xaf, 0xe0, 0x36, 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53,
779 0xe2, 0xdb, 0xe3, 0x63, 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5,
780 0x84, 0xe6, 0x0d, 0xe6, 0x96, 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32,
781 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0, 0xea, 0x5b, 0xea, 0xe5, 0xeb,
782 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11, 0xed, 0x9c, 0xee, 0x28,
783 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58, 0xf0, 0xe5, 0xf1,
784 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7, 0xf4, 0x34,
785 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb, 0xf7,
786 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
787 0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd,
788 0xba, 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
797 assert(image != (Image *) NULL);
798 assert(image->signature == MagickSignature);
799 if (GetImageProfile(image,"icm") != (const StringInfo *) NULL)
801 profile=AcquireStringInfo(sizeof(sRGBProfile));
802 SetStringInfoDatum(profile,sRGBProfile);
803 status=SetImageProfile(image,"icm",profile);
804 profile=DestroyStringInfo(profile);
807 #if defined(MAGICKCORE_LCMS_DELEGATE)
808 #if defined(LCMS_VERSION) && (LCMS_VERSION >= 2000)
809 static void LCMSErrorHandler(cmsContext context,int severity,
812 (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%d, %s",
813 severity,message != (char *) NULL ? message : "no message");
816 #if defined(LCMS_VERSION) && (LCMS_VERSION < 2000)
817 #if defined(LCMS_VERSION) && (LCMS_VERSION > 1010)
818 static int LCMSErrorHandler(int severity,const char *message)
820 (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%d, %s",
821 severity,message != (char *) NULL ? message : "no message");
828 MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
829 const void *datum,const size_t length,
830 const MagickBooleanType magick_unused(clone))
832 #define ProfileImageTag "Profile/Image"
833 #define ThrowProfileException(severity,tag,context) \
835 (void) cmsCloseProfile(source_profile); \
836 (void) cmsCloseProfile(target_profile); \
837 ThrowBinaryException(severity,tag,context); \
846 assert(image != (Image *) NULL);
847 assert(image->signature == MagickSignature);
848 if (image->debug != MagickFalse)
849 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
850 assert(name != (const char *) NULL);
851 if ((datum == (const void *) NULL) || (length == 0))
864 Delete image profile(s).
866 names=ConstantString(name);
867 (void) SubstituteString(&names,","," ");
868 arguments=StringToArgv(names,&number_arguments);
869 names=DestroyString(names);
870 if (arguments == (char **) NULL)
872 ResetImageProfileIterator(image);
873 for (name=GetNextImageProfile(image); name != (const char *) NULL; )
875 for (i=1; i < number_arguments; i++)
877 if ((*arguments[i] == '!') &&
878 (LocaleCompare(name,arguments[i]+1) == 0))
880 if (GlobExpression(name,arguments[i],MagickTrue) != MagickFalse)
882 (void) DeleteImageProfile(image,name);
883 ResetImageProfileIterator(image);
887 name=GetNextImageProfile(image);
889 for (i=0; i < number_arguments; i++)
890 arguments[i]=DestroyString(arguments[i]);
891 arguments=(char **) RelinquishMagickMemory(arguments);
895 Add a ICC, IPTC, or generic profile to the image.
898 profile=AcquireStringInfo((size_t) length);
899 SetStringInfoDatum(profile,(unsigned char *) datum);
900 if ((LocaleCompare(name,"icc") != 0) && (LocaleCompare(name,"icm") != 0))
901 status=SetImageProfile(image,name,profile);
907 icc_profile=GetImageProfile(image,"icc");
908 if ((icc_profile != (const StringInfo *) NULL) &&
909 (CompareStringInfo(icc_profile,profile) == 0))
914 value=GetImageProperty(image,"exif:ColorSpace");
915 if (LocaleCompare(value,"1") != 0)
916 (void) SetsRGBImageProfile(image);
917 value=GetImageProperty(image,"exif:InteroperabilityIndex");
918 if (LocaleCompare(value,"R98.") != 0)
919 (void) SetsRGBImageProfile(image);
920 value=GetImageProperty(image,"exif:InteroperabilityIndex");
921 if (LocaleCompare(value,"R03.") != 0)
922 (void) SetAdobeRGB1998ImageProfile(image);
923 icc_profile=GetImageProfile(image,"icc");
925 if ((icc_profile != (const StringInfo *) NULL) &&
926 (CompareStringInfo(icc_profile,profile) == 0))
928 profile=DestroyStringInfo(profile);
931 #if !defined(MAGICKCORE_LCMS_DELEGATE)
932 (void) ThrowMagickException(&image->exception,GetMagickModule(),
933 MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn","`%s' (LCMS)",
936 if ((icc_profile != (StringInfo *) NULL) ||
937 (cmsGetDeviceClass(profile) == cmsSigLinkClass))
977 **restrict source_pixels,
978 **restrict target_pixels;
981 Transform pixel colors as defined by the color profiles.
983 exception=(&image->exception);
984 #if defined(LCMS_VERSION) && (LCMS_VERSION >= 2000)
985 cmsSetLogErrorHandler(LCMSErrorHandler);
987 #if defined(LCMS_VERSION) && (LCMS_VERSION < 2000)
988 #if defined(LCMS_VERSION) && (LCMS_VERSION > 1010)
989 cmsSetErrorHandler(LCMSErrorHandler);
991 (void) cmsErrorAction(LCMS_ERROR_SHOW);
994 if (icc_profile == (StringInfo *) NULL)
997 Device link profile, embeds source and target transforms.
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;
1008 source_profile=cmsOpenProfileFromMem(
1009 GetStringInfoDatum(icc_profile),(cmsUInt32Number)
1010 GetStringInfoLength(icc_profile));
1011 target_profile=cmsOpenProfileFromMem(GetStringInfoDatum(profile),
1012 (cmsUInt32Number) GetStringInfoLength(profile));
1013 if ((source_profile == (cmsHPROFILE) NULL) ||
1014 (target_profile == (cmsHPROFILE) NULL))
1015 ThrowBinaryException(ResourceLimitError,
1016 "ColorspaceColorProfileMismatch",name);
1018 switch (cmsGetColorSpace(source_profile))
1020 case cmsSigCmykData:
1022 source_colorspace=CMYKColorspace;
1023 source_type=(cmsUInt32Number) TYPE_CMYK_16;
1027 case cmsSigGrayData:
1029 source_colorspace=GRAYColorspace;
1030 source_type=(cmsUInt32Number) TYPE_GRAY_16;
1036 source_colorspace=LabColorspace;
1037 source_type=(cmsUInt32Number) TYPE_Lab_16;
1043 source_colorspace=YUVColorspace;
1044 source_type=(cmsUInt32Number) TYPE_YUV_16;
1050 source_colorspace=RGBColorspace;
1051 source_type=(cmsUInt32Number) TYPE_RGB_16;
1057 source_colorspace=XYZColorspace;
1058 source_type=(cmsUInt32Number) TYPE_XYZ_16;
1062 case cmsSigYCbCrData:
1064 source_colorspace=YCbCrColorspace;
1065 source_type=(cmsUInt32Number) TYPE_YCbCr_16;
1071 source_colorspace=UndefinedColorspace;
1072 source_type=(cmsUInt32Number) TYPE_RGB_16;
1077 target_colorspace=source_colorspace;
1078 target_type=source_type;
1079 target_channels=source_channels;
1080 if (target_profile != (cmsHPROFILE) NULL)
1082 switch (cmsGetColorSpace(target_profile))
1084 case cmsSigCmykData:
1086 target_colorspace=CMYKColorspace;
1087 target_type=(cmsUInt32Number) TYPE_CMYK_16;
1093 target_colorspace=LabColorspace;
1094 target_type=(cmsUInt32Number) TYPE_Lab_16;
1098 case cmsSigGrayData:
1100 target_colorspace=GRAYColorspace;
1101 target_type=(cmsUInt32Number) TYPE_GRAY_16;
1107 target_colorspace=YUVColorspace;
1108 target_type=(cmsUInt32Number) TYPE_YUV_16;
1114 target_colorspace=RGBColorspace;
1115 target_type=(cmsUInt32Number) TYPE_RGB_16;
1121 target_colorspace=XYZColorspace;
1122 target_type=(cmsUInt32Number) TYPE_XYZ_16;
1126 case cmsSigYCbCrData:
1128 target_colorspace=YCbCrColorspace;
1129 target_type=(cmsUInt32Number) TYPE_YCbCr_16;
1135 target_colorspace=UndefinedColorspace;
1136 target_type=(cmsUInt32Number) TYPE_RGB_16;
1141 if ((source_colorspace == UndefinedColorspace) ||
1142 (target_colorspace == UndefinedColorspace))
1143 ThrowProfileException(ImageError,
1144 "ColorspaceColorProfileMismatch",name);
1145 if ((source_colorspace == GRAYColorspace) &&
1146 (IsGrayImage(image,exception) == MagickFalse))
1147 ThrowProfileException(ImageError,
1148 "ColorspaceColorProfileMismatch",name);
1149 if ((source_colorspace == CMYKColorspace) &&
1150 (image->colorspace != CMYKColorspace))
1151 ThrowProfileException(ImageError,
1152 "ColorspaceColorProfileMismatch",name);
1153 if ((source_colorspace == XYZColorspace) &&
1154 (image->colorspace != XYZColorspace))
1155 ThrowProfileException(ImageError,
1156 "ColorspaceColorProfileMismatch",name);
1157 if ((source_colorspace == YCbCrColorspace) &&
1158 (image->colorspace != YCbCrColorspace))
1159 ThrowProfileException(ImageError,
1160 "ColorspaceColorProfileMismatch",name);
1161 if ((source_colorspace != CMYKColorspace) &&
1162 (source_colorspace != GRAYColorspace) &&
1163 (source_colorspace != LabColorspace) &&
1164 (source_colorspace != XYZColorspace) &&
1165 (source_colorspace != YCbCrColorspace) &&
1166 (image->colorspace != RGBColorspace))
1167 ThrowProfileException(ImageError,
1168 "ColorspaceColorProfileMismatch",name);
1170 switch (image->rendering_intent)
1172 case AbsoluteIntent: intent=INTENT_ABSOLUTE_COLORIMETRIC; break;
1173 case PerceptualIntent: intent=INTENT_PERCEPTUAL; break;
1174 case RelativeIntent: intent=INTENT_RELATIVE_COLORIMETRIC; break;
1175 case SaturationIntent: intent=INTENT_SATURATION; break;
1176 default: intent=INTENT_PERCEPTUAL; break;
1178 flags=cmsFLAGS_HIGHRESPRECALC;
1179 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1180 if (image->black_point_compensation != MagickFalse)
1181 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1183 transform=AcquireTransformThreadSet(source_profile,source_type,
1184 target_profile,target_type,intent,flags);
1185 (void) cmsCloseProfile(source_profile);
1186 if (transform == (cmsHTRANSFORM *) NULL)
1187 ThrowBinaryException(ImageError,"UnableToCreateColorTransform",
1190 Transform image as dictated by the source and target image profiles.
1192 length=(size_t) image->columns;
1193 source_pixels=AcquirePixelThreadSet(image->columns,source_channels);
1194 target_pixels=AcquirePixelThreadSet(image->columns,target_channels);
1195 if ((source_pixels == (unsigned short **) NULL) ||
1196 (target_pixels == (unsigned short **) NULL))
1198 transform=DestroyTransformThreadSet(transform);
1199 (void) cmsCloseProfile(target_profile);
1200 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1203 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1205 target_pixels=DestroyPixelThreadSet(target_pixels);
1206 source_pixels=DestroyPixelThreadSet(source_pixels);
1207 transform=DestroyTransformThreadSet(transform);
1208 (void) cmsCloseProfile(target_profile);
1209 return(MagickFalse);
1211 if (target_colorspace == CMYKColorspace)
1212 (void) SetImageColorspace(image,target_colorspace);
1215 image_view=AcquireCacheView(image);
1216 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1217 #pragma omp parallel for schedule(dynamic,4) shared(status)
1219 for (y=0; y < (long) image->rows; y++)
1224 register IndexPacket
1231 register PixelPacket
1234 register unsigned short
1237 if (status == MagickFalse)
1239 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1241 if (q == (PixelPacket *) NULL)
1246 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1247 id=GetOpenMPThreadId();
1248 p=source_pixels[id];
1249 for (x=0; x < (long) image->columns; x++)
1251 *p++=ScaleQuantumToShort(q->red);
1252 if (source_channels > 1)
1254 *p++=ScaleQuantumToShort(q->green);
1255 *p++=ScaleQuantumToShort(q->blue);
1257 if (source_channels > 3)
1258 *p++=ScaleQuantumToShort(indexes[x]);
1261 cmsDoTransform(transform[id],source_pixels[id],target_pixels[id],
1262 (unsigned int) image->columns);
1263 p=target_pixels[id];
1265 for (x=0; x < (long) image->columns; x++)
1267 q->red=ScaleShortToQuantum(*p);
1271 if (target_channels > 1)
1273 q->green=ScaleShortToQuantum(*p);
1275 q->blue=ScaleShortToQuantum(*p);
1278 if (target_channels > 3)
1280 indexes[x]=ScaleShortToQuantum(*p);
1285 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1286 if (sync == MagickFalse)
1288 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1293 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1294 #pragma omp critical (MagickCore_ProfileImage)
1296 proceed=SetImageProgress(image,ProfileImageTag,progress++,
1298 if (proceed == MagickFalse)
1302 image_view=DestroyCacheView(image_view);
1303 (void) SetImageColorspace(image,target_colorspace);
1304 switch (cmsGetColorSpace(target_profile))
1308 image->type=image->matte == MagickFalse ? TrueColorType :
1312 case cmsSigCmykData:
1314 image->type=image->matte == MagickFalse ? ColorSeparationType :
1315 ColorSeparationMatteType;
1318 case cmsSigGrayData:
1320 image->type=image->matte == MagickFalse ? GrayscaleType :
1327 target_pixels=DestroyPixelThreadSet(target_pixels);
1328 source_pixels=DestroyPixelThreadSet(source_pixels);
1329 transform=DestroyTransformThreadSet(transform);
1330 (void) cmsCloseProfile(target_profile);
1332 if (cmsGetDeviceClass(profile) != cmsSigLinkClass)
1333 status=SetImageProfile(image,name,profile);
1336 profile=DestroyStringInfo(profile);
1341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1345 % R e m o v e I m a g e P r o f i l e %
1349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1351 % RemoveImageProfile() removes a named profile from the image and returns its
1354 % The format of the RemoveImageProfile method is:
1356 % void *RemoveImageProfile(Image *image,const char *name)
1358 % A description of each parameter follows:
1360 % o image: the image.
1362 % o name: the profile name.
1365 MagickExport StringInfo *RemoveImageProfile(Image *image,const char *name)
1370 assert(image != (Image *) NULL);
1371 assert(image->signature == MagickSignature);
1372 if (image->debug != MagickFalse)
1373 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1374 if (image->profiles == (SplayTreeInfo *) NULL)
1375 return((StringInfo *) NULL);
1376 if (LocaleCompare(name,"icc") == 0)
1379 Continue to support deprecated color profile for now.
1381 image->color_profile.length=0;
1382 image->color_profile.info=(unsigned char *) NULL;
1384 if (LocaleCompare(name,"iptc") == 0)
1387 Continue to support deprecated IPTC profile for now.
1389 image->iptc_profile.length=0;
1390 image->iptc_profile.info=(unsigned char *) NULL;
1392 profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
1393 image->profiles,name);
1398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1402 % R e s e t P r o f i l e I t e r a t o r %
1406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1408 % ResetImageProfileIterator() resets the image profile iterator. Use it in
1409 % conjunction with GetNextImageProfile() to iterate over all the profiles
1410 % associated with an image.
1412 % The format of the ResetImageProfileIterator method is:
1414 % ResetImageProfileIterator(Image *image)
1416 % A description of each parameter follows:
1418 % o image: the image.
1421 MagickExport void ResetImageProfileIterator(const Image *image)
1423 assert(image != (Image *) NULL);
1424 assert(image->signature == MagickSignature);
1425 if (image->debug != MagickFalse)
1426 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1427 if (image->profiles == (SplayTreeInfo *) NULL)
1429 ResetSplayTreeIterator((SplayTreeInfo *) image->profiles);
1433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1437 % S e t I m a g e P r o f i l e %
1441 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1443 % SetImageProfile() adds a named profile to the image. If a profile with the
1444 % same name already exists, it is replaced. This method differs from the
1445 % ProfileImage() method in that it does not apply CMS color profiles.
1447 % The format of the SetImageProfile method is:
1449 % MagickBooleanType SetImageProfile(Image *image,const char *name,
1450 % const StringInfo *profile)
1452 % A description of each parameter follows:
1454 % o image: the image.
1456 % o name: the profile name, for example icc, exif, and 8bim (8bim is the
1457 % Photoshop wrapper for iptc profiles).
1459 % o profile: A StringInfo structure that contains the named profile.
1463 static void *DestroyProfile(void *profile)
1465 return((void *) DestroyStringInfo((StringInfo *) profile));
1468 static inline const unsigned char *ReadResourceByte(const unsigned char *p,
1469 unsigned char *quantum)
1475 static inline const unsigned char *ReadResourceBytes(const unsigned char *p,
1476 const ssize_t count,unsigned char *quantum)
1481 for (i=0; i < count; i++)
1486 static inline const unsigned char *ReadResourceLong(const unsigned char *p,
1487 unsigned long *quantum)
1489 *quantum=(unsigned long) (*p++ << 24);
1490 *quantum|=(unsigned long) (*p++ << 16);
1491 *quantum|=(unsigned long) (*p++ << 8);
1492 *quantum|=(unsigned long) (*p++ << 0);
1496 static inline const unsigned char *ReadResourceShort(const unsigned char *p,
1497 unsigned short *quantum)
1499 *quantum=(unsigned short) (*p++ << 8);
1500 *quantum|=(unsigned short) (*p++ << 0);
1504 static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
1505 const StringInfo *resource_block)
1510 register const unsigned char
1528 datum=GetStringInfoDatum(resource_block);
1529 length=GetStringInfoLength(resource_block);
1530 for (p=datum; p < (datum+length-16); )
1532 if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1535 p=ReadResourceShort(p,&id);
1536 p=ReadResourceByte(p,&length_byte);
1538 if (((length_byte+1) & 0x01) != 0)
1540 if (p > (datum+length-4))
1542 p=ReadResourceLong(p,&count);
1543 if ((p > (datum+length-count)) || (count > length))
1555 p=ReadResourceShort(p,&resolution)+6;
1556 image->x_resolution=(double) resolution;
1557 p=ReadResourceShort(p,&resolution)+6;
1558 image->y_resolution=(double) resolution;
1566 profile=AcquireStringInfo(count);
1567 SetStringInfoDatum(profile,p);
1568 (void) SetImageProfile(image,"iptc",profile);
1569 profile=DestroyStringInfo(profile);
1586 profile=AcquireStringInfo(count);
1587 SetStringInfoDatum(profile,p);
1588 (void) SetImageProfile(image,"icc",profile);
1589 profile=DestroyStringInfo(profile);
1598 profile=AcquireStringInfo(count);
1599 SetStringInfoDatum(profile,p);
1600 (void) SetImageProfile(image,"exif",profile);
1601 profile=DestroyStringInfo(profile);
1610 profile=AcquireStringInfo(count);
1611 SetStringInfoDatum(profile,p);
1612 (void) SetImageProfile(image,"xmp",profile);
1613 profile=DestroyStringInfo(profile);
1623 if ((count & 0x01) != 0)
1629 MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name,
1630 const StringInfo *profile)
1634 property[MaxTextExtent];
1639 assert(image != (Image *) NULL);
1640 assert(image->signature == MagickSignature);
1641 if (image->debug != MagickFalse)
1642 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1643 if (image->profiles == (SplayTreeInfo *) NULL)
1644 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
1646 (void) CopyMagickString(key,name,MaxTextExtent);
1647 status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1648 ConstantString(key),CloneStringInfo(profile));
1649 if ((status != MagickFalse) &&
1650 ((LocaleCompare(name,"icc") == 0) || (LocaleCompare(name,"icm") == 0)))
1656 Continue to support deprecated color profile member.
1658 icc_profile=GetImageProfile(image,name);
1659 if (icc_profile != (const StringInfo *) NULL)
1661 image->color_profile.length=GetStringInfoLength(icc_profile);
1662 image->color_profile.info=GetStringInfoDatum(icc_profile);
1665 if ((status != MagickFalse) &&
1666 ((LocaleCompare(name,"iptc") == 0) || (LocaleCompare(name,"8bim") == 0)))
1672 Continue to support deprecated IPTC profile member.
1674 iptc_profile=GetImageProfile(image,name);
1675 if (iptc_profile != (const StringInfo *) NULL)
1677 image->iptc_profile.length=GetStringInfoLength(iptc_profile);
1678 image->iptc_profile.info=GetStringInfoDatum(iptc_profile);
1680 (void) GetProfilesFromResourceBlock(image,profile);
1683 Inject profile into image properties.
1685 (void) FormatMagickString(property,MaxTextExtent,"%s:sans",name);
1686 (void) GetImageProperty(image,property);
1691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1695 % S y n c I m a g e P r o f i l e s %
1699 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1701 % SyncImageProfiles() synchronizes image properties with the image profiles.
1702 % Currently we only support updating the EXIF resolution and orientation.
1704 % The format of the SyncImageProfiles method is:
1706 % MagickBooleanType SyncImageProfiles(Image *image)
1708 % A description of each parameter follows:
1710 % o image: the image.
1714 static inline int ReadProfileByte(unsigned char **p,size_t *length)
1726 static inline unsigned short ReadProfileShort(const EndianType endian,
1727 unsigned char *buffer)
1732 if (endian == MSBEndian)
1734 value=(unsigned short) ((((unsigned char *) buffer)[0] << 8) |
1735 ((unsigned char *) buffer)[1]);
1736 return((unsigned short) (value & 0xffff));
1738 value=(unsigned short) ((buffer[1] << 8) | buffer[0]);
1739 return((unsigned short) (value & 0xffff));
1742 static inline unsigned long ReadProfileLong(const EndianType endian,
1743 unsigned char *buffer)
1748 if (endian == MSBEndian)
1750 value=(unsigned long) ((buffer[0] << 24) | (buffer[1] << 16) |
1751 (buffer[2] << 8) | buffer[3]);
1752 return((unsigned long) (value & 0xffffffff));
1754 value=(unsigned long) ((buffer[3] << 24) | (buffer[2] << 16) |
1755 (buffer[1] << 8 ) | (buffer[0]));
1756 return((unsigned long) (value & 0xffffffff));
1759 static inline void WriteProfileLong(const EndianType endian,
1760 const unsigned long value,unsigned char *p)
1765 if (endian == MSBEndian)
1767 buffer[0]=(unsigned char) (value >> 24);
1768 buffer[1]=(unsigned char) (value >> 16);
1769 buffer[2]=(unsigned char) (value >> 8);
1770 buffer[3]=(unsigned char) value;
1771 (void) CopyMagickMemory(p,buffer,4);
1774 buffer[0]=(unsigned char) value;
1775 buffer[1]=(unsigned char) (value >> 8);
1776 buffer[2]=(unsigned char) (value >> 16);
1777 buffer[3]=(unsigned char) (value >> 24);
1778 (void) CopyMagickMemory(p,buffer,4);
1781 static void WriteProfileShort(const EndianType endian,
1782 const unsigned short value,unsigned char *p)
1787 if (endian == MSBEndian)
1789 buffer[0]=(unsigned char) (value >> 8);
1790 buffer[1]=(unsigned char) value;
1791 (void) CopyMagickMemory(p,buffer,2);
1794 buffer[0]=(unsigned char) value;
1795 buffer[1]=(unsigned char) (value >> 8);
1796 (void) CopyMagickMemory(p,buffer,2);
1799 MagickExport MagickBooleanType SyncImageProfiles(Image *image)
1801 #define MaxDirectoryStack 16
1802 #define EXIF_DELIMITER "\n"
1803 #define EXIF_NUM_FORMATS 12
1804 #define TAG_EXIF_OFFSET 0x8769
1805 #define TAG_INTEROP_OFFSET 0xa005
1807 typedef struct _DirectoryInfo
1817 directory_stack[MaxDirectoryStack];
1833 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
1847 Set EXIF resolution tag.
1849 profile=(StringInfo *) GetImageProfile(image,"EXIF");
1850 if (profile == (StringInfo *) NULL)
1852 length=GetStringInfoLength(profile);
1853 exif=GetStringInfoDatum(profile);
1856 if (ReadProfileByte(&exif,&length) != 0x45)
1858 if (ReadProfileByte(&exif,&length) != 0x78)
1860 if (ReadProfileByte(&exif,&length) != 0x69)
1862 if (ReadProfileByte(&exif,&length) != 0x66)
1864 if (ReadProfileByte(&exif,&length) != 0x00)
1866 if (ReadProfileByte(&exif,&length) != 0x00)
1871 return(MagickFalse);
1872 id=(int) ReadProfileShort(LSBEndian,exif);
1880 return(MagickFalse);
1881 if (ReadProfileShort(endian,exif+2) != 0x002a)
1882 return(MagickFalse);
1884 This the offset to the first IFD.
1886 offset=(ssize_t) ReadProfileLong(endian,exif+4);
1887 if ((size_t) offset >= length)
1888 return(MagickFalse);
1889 directory=exif+offset;
1897 directory=directory_stack[level].directory;
1898 entry=directory_stack[level].entry;
1901 Determine how many entries there are in the current IFD.
1903 number_entries=ReadProfileShort(endian,directory);
1904 for ( ; entry < number_entries; entry++)
1911 register unsigned char
1918 q=(unsigned char *) (directory+2+(12*entry));
1919 tag_value=(long) ReadProfileShort(endian,q);
1920 format=(long) ReadProfileShort(endian,q+2);
1921 if ((format-1) >= EXIF_NUM_FORMATS)
1923 components=(long) ReadProfileLong(endian,q+4);
1924 number_bytes=(size_t) components*format_bytes[format];
1925 if (number_bytes <= 4)
1933 The directory entry contains an offset.
1935 offset=(ssize_t) ReadProfileLong(endian,q+8);
1936 if ((size_t) (offset+number_bytes) > length)
1938 p=(unsigned char *) (exif+offset);
1944 (void) WriteProfileLong(endian,(unsigned long)
1945 (image->x_resolution+0.5),p);
1946 (void) WriteProfileLong(endian,1UL,p+4);
1951 (void) WriteProfileLong(endian,(unsigned long)
1952 (image->y_resolution+0.5),p);
1953 (void) WriteProfileLong(endian,1UL,p+4);
1958 (void) WriteProfileShort(endian,(unsigned short)
1959 image->orientation,p);
1964 (void) WriteProfileShort(endian,(unsigned short)
1965 (image->units+1),p);
1971 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
1976 offset=(size_t) ReadProfileLong(endian,p);
1977 if ((offset < length) && (level < (MaxDirectoryStack-2)))
1979 directory_stack[level].directory=directory;
1981 directory_stack[level].entry=entry;
1983 directory_stack[level].directory=exif+offset;
1984 directory_stack[level].entry=0;
1986 if ((directory+2+(12*number_entries)) > (exif+length))
1988 offset=(size_t) ReadProfileLong(endian,directory+2+(12*
1990 if ((offset != 0) && (offset < length) &&
1991 (level < (MaxDirectoryStack-2)))
1993 directory_stack[level].directory=exif+offset;
1994 directory_stack[level].entry=0;
2001 } while (level > 0);