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 if (target_profile != (cmsHPROFILE) NULL) \
837 (void) cmsCloseProfile(target_profile); \
838 ThrowBinaryException(severity,tag,context); \
847 assert(image != (Image *) NULL);
848 assert(image->signature == MagickSignature);
849 if (image->debug != MagickFalse)
850 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
851 assert(name != (const char *) NULL);
852 if ((datum == (const void *) NULL) || (length == 0))
865 Delete image profile(s).
867 names=ConstantString(name);
868 (void) SubstituteString(&names,","," ");
869 arguments=StringToArgv(names,&number_arguments);
870 names=DestroyString(names);
871 if (arguments == (char **) NULL)
873 ResetImageProfileIterator(image);
874 for (name=GetNextImageProfile(image); name != (const char *) NULL; )
876 for (i=1; i < number_arguments; i++)
878 if ((*arguments[i] == '!') &&
879 (LocaleCompare(name,arguments[i]+1) == 0))
881 if (GlobExpression(name,arguments[i],MagickTrue) != MagickFalse)
883 (void) DeleteImageProfile(image,name);
884 ResetImageProfileIterator(image);
888 name=GetNextImageProfile(image);
890 for (i=0; i < number_arguments; i++)
891 arguments[i]=DestroyString(arguments[i]);
892 arguments=(char **) RelinquishMagickMemory(arguments);
896 Add a ICC, IPTC, or generic profile to the image.
899 profile=AcquireStringInfo((size_t) length);
900 SetStringInfoDatum(profile,(unsigned char *) datum);
901 if ((LocaleCompare(name,"icc") != 0) && (LocaleCompare(name,"icm") != 0))
902 status=SetImageProfile(image,name,profile);
908 icc_profile=GetImageProfile(image,"icc");
909 if ((icc_profile != (const StringInfo *) NULL) &&
910 (CompareStringInfo(icc_profile,profile) == 0))
915 value=GetImageProperty(image,"exif:ColorSpace");
916 if (LocaleCompare(value,"1") != 0)
917 (void) SetsRGBImageProfile(image);
918 value=GetImageProperty(image,"exif:InteroperabilityIndex");
919 if (LocaleCompare(value,"R98.") != 0)
920 (void) SetsRGBImageProfile(image);
921 value=GetImageProperty(image,"exif:InteroperabilityIndex");
922 if (LocaleCompare(value,"R03.") != 0)
923 (void) SetAdobeRGB1998ImageProfile(image);
924 icc_profile=GetImageProfile(image,"icc");
926 if ((icc_profile != (const StringInfo *) NULL) &&
927 (CompareStringInfo(icc_profile,profile) == 0))
929 profile=DestroyStringInfo(profile);
932 #if !defined(MAGICKCORE_LCMS_DELEGATE)
933 (void) ThrowMagickException(&image->exception,GetMagickModule(),
934 MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn","`%s' (LCMS)",
937 if ((icc_profile != (StringInfo *) NULL) ||
938 (cmsGetDeviceClass(profile) == cmsSigLinkClass))
978 **restrict source_pixels,
979 **restrict target_pixels;
982 Transform pixel colors as defined by the color profiles.
984 exception=(&image->exception);
985 #if defined(LCMS_VERSION) && (LCMS_VERSION >= 2000)
986 cmsSetLogErrorHandler(LCMSErrorHandler);
988 #if defined(LCMS_VERSION) && (LCMS_VERSION < 2000)
989 #if defined(LCMS_VERSION) && (LCMS_VERSION > 1010)
990 cmsSetErrorHandler(LCMSErrorHandler);
992 (void) cmsErrorAction(LCMS_ERROR_SHOW);
995 if (icc_profile == (StringInfo *) NULL)
998 Device link profile, embeds source and target transforms.
1000 source_profile=cmsOpenProfileFromMem(GetStringInfoDatum(profile),
1001 (cmsUInt32Number) GetStringInfoLength(profile));
1002 if (source_profile == (cmsHPROFILE) NULL)
1003 ThrowBinaryException(ResourceLimitError,
1004 "ColorspaceColorProfileMismatch",name);
1005 target_profile=(cmsHPROFILE) NULL;
1009 source_profile=cmsOpenProfileFromMem(
1010 GetStringInfoDatum(icc_profile),(cmsUInt32Number)
1011 GetStringInfoLength(icc_profile));
1012 target_profile=cmsOpenProfileFromMem(GetStringInfoDatum(profile),
1013 (cmsUInt32Number) GetStringInfoLength(profile));
1014 if ((source_profile == (cmsHPROFILE) NULL) ||
1015 (target_profile == (cmsHPROFILE) NULL))
1016 ThrowBinaryException(ResourceLimitError,
1017 "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 target_colorspace=source_colorspace;
1079 target_type=source_type;
1080 target_channels=source_channels;
1081 if (target_profile != (cmsHPROFILE) NULL)
1083 switch (cmsGetColorSpace(target_profile))
1085 case cmsSigCmykData:
1087 target_colorspace=CMYKColorspace;
1088 target_type=(cmsUInt32Number) TYPE_CMYK_16;
1094 target_colorspace=LabColorspace;
1095 target_type=(cmsUInt32Number) TYPE_Lab_16;
1099 case cmsSigGrayData:
1101 target_colorspace=GRAYColorspace;
1102 target_type=(cmsUInt32Number) TYPE_GRAY_16;
1108 target_colorspace=YUVColorspace;
1109 target_type=(cmsUInt32Number) TYPE_YUV_16;
1115 target_colorspace=RGBColorspace;
1116 target_type=(cmsUInt32Number) TYPE_RGB_16;
1122 target_colorspace=XYZColorspace;
1123 target_type=(cmsUInt32Number) TYPE_XYZ_16;
1127 case cmsSigYCbCrData:
1129 target_colorspace=YCbCrColorspace;
1130 target_type=(cmsUInt32Number) TYPE_YCbCr_16;
1136 target_colorspace=UndefinedColorspace;
1137 target_type=(cmsUInt32Number) TYPE_RGB_16;
1142 if ((source_colorspace == UndefinedColorspace) ||
1143 (target_colorspace == UndefinedColorspace))
1144 ThrowProfileException(ImageError,
1145 "ColorspaceColorProfileMismatch",name);
1146 if ((source_colorspace == GRAYColorspace) &&
1147 (IsGrayImage(image,exception) == MagickFalse))
1148 ThrowProfileException(ImageError,
1149 "ColorspaceColorProfileMismatch",name);
1150 if ((source_colorspace == CMYKColorspace) &&
1151 (image->colorspace != CMYKColorspace))
1152 ThrowProfileException(ImageError,
1153 "ColorspaceColorProfileMismatch",name);
1154 if ((source_colorspace == XYZColorspace) &&
1155 (image->colorspace != XYZColorspace))
1156 ThrowProfileException(ImageError,
1157 "ColorspaceColorProfileMismatch",name);
1158 if ((source_colorspace == YCbCrColorspace) &&
1159 (image->colorspace != YCbCrColorspace))
1160 ThrowProfileException(ImageError,
1161 "ColorspaceColorProfileMismatch",name);
1162 if ((source_colorspace != CMYKColorspace) &&
1163 (source_colorspace != GRAYColorspace) &&
1164 (source_colorspace != LabColorspace) &&
1165 (source_colorspace != XYZColorspace) &&
1166 (source_colorspace != YCbCrColorspace) &&
1167 (image->colorspace != RGBColorspace))
1168 ThrowProfileException(ImageError,
1169 "ColorspaceColorProfileMismatch",name);
1171 switch (image->rendering_intent)
1173 case AbsoluteIntent: intent=INTENT_ABSOLUTE_COLORIMETRIC; break;
1174 case PerceptualIntent: intent=INTENT_PERCEPTUAL; break;
1175 case RelativeIntent: intent=INTENT_RELATIVE_COLORIMETRIC; break;
1176 case SaturationIntent: intent=INTENT_SATURATION; break;
1177 default: intent=INTENT_PERCEPTUAL; break;
1179 flags=cmsFLAGS_HIGHRESPRECALC;
1180 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1181 if (image->black_point_compensation != MagickFalse)
1182 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1184 transform=AcquireTransformThreadSet(source_profile,source_type,
1185 target_profile,target_type,intent,flags);
1186 (void) cmsCloseProfile(source_profile);
1187 if (transform == (cmsHTRANSFORM *) NULL)
1188 ThrowBinaryException(ImageError,"UnableToCreateColorTransform",
1191 Transform image as dictated by the source and target image profiles.
1193 length=(size_t) image->columns;
1194 source_pixels=AcquirePixelThreadSet(image->columns,source_channels);
1195 target_pixels=AcquirePixelThreadSet(image->columns,target_channels);
1196 if ((source_pixels == (unsigned short **) NULL) ||
1197 (target_pixels == (unsigned short **) NULL))
1199 transform=DestroyTransformThreadSet(transform);
1200 (void) cmsCloseProfile(target_profile);
1201 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1204 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1206 target_pixels=DestroyPixelThreadSet(target_pixels);
1207 source_pixels=DestroyPixelThreadSet(source_pixels);
1208 transform=DestroyTransformThreadSet(transform);
1209 (void) cmsCloseProfile(target_profile);
1210 return(MagickFalse);
1212 if (target_colorspace == CMYKColorspace)
1213 (void) SetImageColorspace(image,target_colorspace);
1216 image_view=AcquireCacheView(image);
1217 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1218 #pragma omp parallel for schedule(dynamic,4) shared(status)
1220 for (y=0; y < (long) image->rows; y++)
1225 register IndexPacket
1232 register PixelPacket
1235 register unsigned short
1238 if (status == MagickFalse)
1240 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1242 if (q == (PixelPacket *) NULL)
1247 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1248 id=GetOpenMPThreadId();
1249 p=source_pixels[id];
1250 for (x=0; x < (long) image->columns; x++)
1252 *p++=ScaleQuantumToShort(q->red);
1253 if (source_channels > 1)
1255 *p++=ScaleQuantumToShort(q->green);
1256 *p++=ScaleQuantumToShort(q->blue);
1258 if (source_channels > 3)
1259 *p++=ScaleQuantumToShort(indexes[x]);
1262 cmsDoTransform(transform[id],source_pixels[id],target_pixels[id],
1263 (unsigned int) image->columns);
1264 p=target_pixels[id];
1266 for (x=0; x < (long) image->columns; x++)
1268 q->red=ScaleShortToQuantum(*p);
1272 if (target_channels > 1)
1274 q->green=ScaleShortToQuantum(*p);
1276 q->blue=ScaleShortToQuantum(*p);
1279 if (target_channels > 3)
1281 indexes[x]=ScaleShortToQuantum(*p);
1286 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1287 if (sync == MagickFalse)
1289 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1294 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1295 #pragma omp critical (MagickCore_ProfileImage)
1297 proceed=SetImageProgress(image,ProfileImageTag,progress++,
1299 if (proceed == MagickFalse)
1303 image_view=DestroyCacheView(image_view);
1304 (void) SetImageColorspace(image,target_colorspace);
1305 switch (cmsGetColorSpace(target_profile))
1309 image->type=image->matte == MagickFalse ? TrueColorType :
1313 case cmsSigCmykData:
1315 image->type=image->matte == MagickFalse ? ColorSeparationType :
1316 ColorSeparationMatteType;
1319 case cmsSigGrayData:
1321 image->type=image->matte == MagickFalse ? GrayscaleType :
1328 target_pixels=DestroyPixelThreadSet(target_pixels);
1329 source_pixels=DestroyPixelThreadSet(source_pixels);
1330 transform=DestroyTransformThreadSet(transform);
1331 (void) cmsCloseProfile(target_profile);
1333 if (cmsGetDeviceClass(profile) != cmsSigLinkClass)
1334 status=SetImageProfile(image,name,profile);
1337 profile=DestroyStringInfo(profile);
1342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1346 % R e m o v e I m a g e P r o f i l e %
1350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1352 % RemoveImageProfile() removes a named profile from the image and returns its
1355 % The format of the RemoveImageProfile method is:
1357 % void *RemoveImageProfile(Image *image,const char *name)
1359 % A description of each parameter follows:
1361 % o image: the image.
1363 % o name: the profile name.
1366 MagickExport StringInfo *RemoveImageProfile(Image *image,const char *name)
1371 assert(image != (Image *) NULL);
1372 assert(image->signature == MagickSignature);
1373 if (image->debug != MagickFalse)
1374 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1375 if (image->profiles == (SplayTreeInfo *) NULL)
1376 return((StringInfo *) NULL);
1377 if (LocaleCompare(name,"icc") == 0)
1380 Continue to support deprecated color profile for now.
1382 image->color_profile.length=0;
1383 image->color_profile.info=(unsigned char *) NULL;
1385 if (LocaleCompare(name,"iptc") == 0)
1388 Continue to support deprecated IPTC profile for now.
1390 image->iptc_profile.length=0;
1391 image->iptc_profile.info=(unsigned char *) NULL;
1393 profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
1394 image->profiles,name);
1399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1403 % R e s e t P r o f i l e I t e r a t o r %
1407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1409 % ResetImageProfileIterator() resets the image profile iterator. Use it in
1410 % conjunction with GetNextImageProfile() to iterate over all the profiles
1411 % associated with an image.
1413 % The format of the ResetImageProfileIterator method is:
1415 % ResetImageProfileIterator(Image *image)
1417 % A description of each parameter follows:
1419 % o image: the image.
1422 MagickExport void ResetImageProfileIterator(const Image *image)
1424 assert(image != (Image *) NULL);
1425 assert(image->signature == MagickSignature);
1426 if (image->debug != MagickFalse)
1427 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1428 if (image->profiles == (SplayTreeInfo *) NULL)
1430 ResetSplayTreeIterator((SplayTreeInfo *) image->profiles);
1434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1438 % S e t I m a g e P r o f i l e %
1442 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1444 % SetImageProfile() adds a named profile to the image. If a profile with the
1445 % same name already exists, it is replaced. This method differs from the
1446 % ProfileImage() method in that it does not apply CMS color profiles.
1448 % The format of the SetImageProfile method is:
1450 % MagickBooleanType SetImageProfile(Image *image,const char *name,
1451 % const StringInfo *profile)
1453 % A description of each parameter follows:
1455 % o image: the image.
1457 % o name: the profile name, for example icc, exif, and 8bim (8bim is the
1458 % Photoshop wrapper for iptc profiles).
1460 % o profile: A StringInfo structure that contains the named profile.
1464 static void *DestroyProfile(void *profile)
1466 return((void *) DestroyStringInfo((StringInfo *) profile));
1469 static inline const unsigned char *ReadResourceByte(const unsigned char *p,
1470 unsigned char *quantum)
1476 static inline const unsigned char *ReadResourceBytes(const unsigned char *p,
1477 const ssize_t count,unsigned char *quantum)
1482 for (i=0; i < count; i++)
1487 static inline const unsigned char *ReadResourceLong(const unsigned char *p,
1488 unsigned long *quantum)
1490 *quantum=(unsigned long) (*p++ << 24);
1491 *quantum|=(unsigned long) (*p++ << 16);
1492 *quantum|=(unsigned long) (*p++ << 8);
1493 *quantum|=(unsigned long) (*p++ << 0);
1497 static inline const unsigned char *ReadResourceShort(const unsigned char *p,
1498 unsigned short *quantum)
1500 *quantum=(unsigned short) (*p++ << 8);
1501 *quantum|=(unsigned short) (*p++ << 0);
1505 static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
1506 const StringInfo *resource_block)
1511 register const unsigned char
1529 datum=GetStringInfoDatum(resource_block);
1530 length=GetStringInfoLength(resource_block);
1531 for (p=datum; p < (datum+length-16); )
1533 if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1536 p=ReadResourceShort(p,&id);
1537 p=ReadResourceByte(p,&length_byte);
1539 if (((length_byte+1) & 0x01) != 0)
1541 if (p > (datum+length-4))
1543 p=ReadResourceLong(p,&count);
1544 if ((p > (datum+length-count)) || (count > length))
1556 p=ReadResourceShort(p,&resolution)+6;
1557 image->x_resolution=(double) resolution;
1558 p=ReadResourceShort(p,&resolution)+6;
1559 image->y_resolution=(double) resolution;
1567 profile=AcquireStringInfo(count);
1568 SetStringInfoDatum(profile,p);
1569 (void) SetImageProfile(image,"iptc",profile);
1570 profile=DestroyStringInfo(profile);
1587 profile=AcquireStringInfo(count);
1588 SetStringInfoDatum(profile,p);
1589 (void) SetImageProfile(image,"icc",profile);
1590 profile=DestroyStringInfo(profile);
1599 profile=AcquireStringInfo(count);
1600 SetStringInfoDatum(profile,p);
1601 (void) SetImageProfile(image,"exif",profile);
1602 profile=DestroyStringInfo(profile);
1611 profile=AcquireStringInfo(count);
1612 SetStringInfoDatum(profile,p);
1613 (void) SetImageProfile(image,"xmp",profile);
1614 profile=DestroyStringInfo(profile);
1624 if ((count & 0x01) != 0)
1630 MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name,
1631 const StringInfo *profile)
1635 property[MaxTextExtent];
1640 assert(image != (Image *) NULL);
1641 assert(image->signature == MagickSignature);
1642 if (image->debug != MagickFalse)
1643 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1644 if (image->profiles == (SplayTreeInfo *) NULL)
1645 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
1647 (void) CopyMagickString(key,name,MaxTextExtent);
1648 status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1649 ConstantString(key),CloneStringInfo(profile));
1650 if ((status != MagickFalse) &&
1651 ((LocaleCompare(name,"icc") == 0) || (LocaleCompare(name,"icm") == 0)))
1657 Continue to support deprecated color profile member.
1659 icc_profile=GetImageProfile(image,name);
1660 if (icc_profile != (const StringInfo *) NULL)
1662 image->color_profile.length=GetStringInfoLength(icc_profile);
1663 image->color_profile.info=GetStringInfoDatum(icc_profile);
1666 if ((status != MagickFalse) &&
1667 ((LocaleCompare(name,"iptc") == 0) || (LocaleCompare(name,"8bim") == 0)))
1673 Continue to support deprecated IPTC profile member.
1675 iptc_profile=GetImageProfile(image,name);
1676 if (iptc_profile != (const StringInfo *) NULL)
1678 image->iptc_profile.length=GetStringInfoLength(iptc_profile);
1679 image->iptc_profile.info=GetStringInfoDatum(iptc_profile);
1681 (void) GetProfilesFromResourceBlock(image,profile);
1684 Inject profile into image properties.
1686 (void) FormatMagickString(property,MaxTextExtent,"%s:sans",name);
1687 (void) GetImageProperty(image,property);
1692 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1696 % S y n c I m a g e P r o f i l e s %
1700 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1702 % SyncImageProfiles() synchronizes image properties with the image profiles.
1703 % Currently we only support updating the EXIF resolution and orientation.
1705 % The format of the SyncImageProfiles method is:
1707 % MagickBooleanType SyncImageProfiles(Image *image)
1709 % A description of each parameter follows:
1711 % o image: the image.
1715 static inline int ReadProfileByte(unsigned char **p,size_t *length)
1727 static inline unsigned short ReadProfileShort(const EndianType endian,
1728 unsigned char *buffer)
1733 if (endian == MSBEndian)
1735 value=(unsigned short) ((((unsigned char *) buffer)[0] << 8) |
1736 ((unsigned char *) buffer)[1]);
1737 return((unsigned short) (value & 0xffff));
1739 value=(unsigned short) ((buffer[1] << 8) | buffer[0]);
1740 return((unsigned short) (value & 0xffff));
1743 static inline unsigned long ReadProfileLong(const EndianType endian,
1744 unsigned char *buffer)
1749 if (endian == MSBEndian)
1751 value=(unsigned long) ((buffer[0] << 24) | (buffer[1] << 16) |
1752 (buffer[2] << 8) | buffer[3]);
1753 return((unsigned long) (value & 0xffffffff));
1755 value=(unsigned long) ((buffer[3] << 24) | (buffer[2] << 16) |
1756 (buffer[1] << 8 ) | (buffer[0]));
1757 return((unsigned long) (value & 0xffffffff));
1760 static inline void WriteProfileLong(const EndianType endian,
1761 const unsigned long value,unsigned char *p)
1766 if (endian == MSBEndian)
1768 buffer[0]=(unsigned char) (value >> 24);
1769 buffer[1]=(unsigned char) (value >> 16);
1770 buffer[2]=(unsigned char) (value >> 8);
1771 buffer[3]=(unsigned char) value;
1772 (void) CopyMagickMemory(p,buffer,4);
1775 buffer[0]=(unsigned char) value;
1776 buffer[1]=(unsigned char) (value >> 8);
1777 buffer[2]=(unsigned char) (value >> 16);
1778 buffer[3]=(unsigned char) (value >> 24);
1779 (void) CopyMagickMemory(p,buffer,4);
1782 static void WriteProfileShort(const EndianType endian,
1783 const unsigned short value,unsigned char *p)
1788 if (endian == MSBEndian)
1790 buffer[0]=(unsigned char) (value >> 8);
1791 buffer[1]=(unsigned char) value;
1792 (void) CopyMagickMemory(p,buffer,2);
1795 buffer[0]=(unsigned char) value;
1796 buffer[1]=(unsigned char) (value >> 8);
1797 (void) CopyMagickMemory(p,buffer,2);
1800 MagickExport MagickBooleanType SyncImageProfiles(Image *image)
1802 #define MaxDirectoryStack 16
1803 #define EXIF_DELIMITER "\n"
1804 #define EXIF_NUM_FORMATS 12
1805 #define TAG_EXIF_OFFSET 0x8769
1806 #define TAG_INTEROP_OFFSET 0xa005
1808 typedef struct _DirectoryInfo
1818 directory_stack[MaxDirectoryStack];
1834 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
1848 Set EXIF resolution tag.
1850 profile=(StringInfo *) GetImageProfile(image,"EXIF");
1851 if (profile == (StringInfo *) NULL)
1853 length=GetStringInfoLength(profile);
1854 exif=GetStringInfoDatum(profile);
1857 if (ReadProfileByte(&exif,&length) != 0x45)
1859 if (ReadProfileByte(&exif,&length) != 0x78)
1861 if (ReadProfileByte(&exif,&length) != 0x69)
1863 if (ReadProfileByte(&exif,&length) != 0x66)
1865 if (ReadProfileByte(&exif,&length) != 0x00)
1867 if (ReadProfileByte(&exif,&length) != 0x00)
1872 return(MagickFalse);
1873 id=(int) ReadProfileShort(LSBEndian,exif);
1881 return(MagickFalse);
1882 if (ReadProfileShort(endian,exif+2) != 0x002a)
1883 return(MagickFalse);
1885 This the offset to the first IFD.
1887 offset=(ssize_t) ReadProfileLong(endian,exif+4);
1888 if ((size_t) offset >= length)
1889 return(MagickFalse);
1890 directory=exif+offset;
1898 directory=directory_stack[level].directory;
1899 entry=directory_stack[level].entry;
1902 Determine how many entries there are in the current IFD.
1904 number_entries=ReadProfileShort(endian,directory);
1905 for ( ; entry < number_entries; entry++)
1912 register unsigned char
1919 q=(unsigned char *) (directory+2+(12*entry));
1920 tag_value=(long) ReadProfileShort(endian,q);
1921 format=(long) ReadProfileShort(endian,q+2);
1922 if ((format-1) >= EXIF_NUM_FORMATS)
1924 components=(long) ReadProfileLong(endian,q+4);
1925 number_bytes=(size_t) components*format_bytes[format];
1926 if (number_bytes <= 4)
1934 The directory entry contains an offset.
1936 offset=(ssize_t) ReadProfileLong(endian,q+8);
1937 if ((size_t) (offset+number_bytes) > length)
1939 p=(unsigned char *) (exif+offset);
1945 (void) WriteProfileLong(endian,(unsigned long)
1946 (image->x_resolution+0.5),p);
1947 (void) WriteProfileLong(endian,1UL,p+4);
1952 (void) WriteProfileLong(endian,(unsigned long)
1953 (image->y_resolution+0.5),p);
1954 (void) WriteProfileLong(endian,1UL,p+4);
1959 (void) WriteProfileShort(endian,(unsigned short)
1960 image->orientation,p);
1965 (void) WriteProfileShort(endian,(unsigned short)
1966 (image->units+1),p);
1972 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
1977 offset=(size_t) ReadProfileLong(endian,p);
1978 if ((offset < length) && (level < (MaxDirectoryStack-2)))
1980 directory_stack[level].directory=directory;
1982 directory_stack[level].entry=entry;
1984 directory_stack[level].directory=exif+offset;
1985 directory_stack[level].entry=0;
1987 if ((directory+2+(12*number_entries)) > (exif+length))
1989 offset=(size_t) ReadProfileLong(endian,directory+2+(12*
1991 if ((offset != 0) && (offset < length) &&
1992 (level < (MaxDirectoryStack-2)))
1994 directory_stack[level].directory=exif+offset;
1995 directory_stack[level].entry=0;
2002 } while (level > 0);