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);
1007 source_profile=cmsOpenProfileFromMem(
1008 GetStringInfoDatum(icc_profile),(cmsUInt32Number)
1009 GetStringInfoLength(icc_profile));
1010 target_profile=cmsOpenProfileFromMem(GetStringInfoDatum(profile),
1011 (cmsUInt32Number) GetStringInfoLength(profile));
1012 if ((source_profile == (cmsHPROFILE) NULL) ||
1013 (target_profile == (cmsHPROFILE) NULL))
1014 ThrowBinaryException(ResourceLimitError,
1015 "ColorspaceColorProfileMismatch",name);
1017 switch (cmsGetColorSpace(source_profile))
1019 case cmsSigCmykData:
1021 source_colorspace=CMYKColorspace;
1022 source_type=(cmsUInt32Number) TYPE_CMYK_16;
1026 case cmsSigGrayData:
1028 source_colorspace=GRAYColorspace;
1029 source_type=(cmsUInt32Number) TYPE_GRAY_16;
1035 source_colorspace=LabColorspace;
1036 source_type=(cmsUInt32Number) TYPE_Lab_16;
1042 source_colorspace=YUVColorspace;
1043 source_type=(cmsUInt32Number) TYPE_YUV_16;
1049 source_colorspace=RGBColorspace;
1050 source_type=(cmsUInt32Number) TYPE_RGB_16;
1056 source_colorspace=XYZColorspace;
1057 source_type=(cmsUInt32Number) TYPE_XYZ_16;
1061 case cmsSigYCbCrData:
1063 source_colorspace=YCbCrColorspace;
1064 source_type=(cmsUInt32Number) TYPE_YCbCr_16;
1070 source_colorspace=UndefinedColorspace;
1071 source_type=(cmsUInt32Number) TYPE_RGB_16;
1076 target_colorspace=source_colorspace;
1077 target_type=source_type;
1078 target_channels=source_channels;
1079 if (target_profile != (cmsHPROFILE) NULL)
1081 switch (cmsGetColorSpace(target_profile))
1083 case cmsSigCmykData:
1085 target_colorspace=CMYKColorspace;
1086 target_type=(cmsUInt32Number) TYPE_CMYK_16;
1092 target_colorspace=LabColorspace;
1093 target_type=(cmsUInt32Number) TYPE_Lab_16;
1097 case cmsSigGrayData:
1099 target_colorspace=GRAYColorspace;
1100 target_type=(cmsUInt32Number) TYPE_GRAY_16;
1106 target_colorspace=YUVColorspace;
1107 target_type=(cmsUInt32Number) TYPE_YUV_16;
1113 target_colorspace=RGBColorspace;
1114 target_type=(cmsUInt32Number) TYPE_RGB_16;
1120 target_colorspace=XYZColorspace;
1121 target_type=(cmsUInt32Number) TYPE_XYZ_16;
1125 case cmsSigYCbCrData:
1127 target_colorspace=YCbCrColorspace;
1128 target_type=(cmsUInt32Number) TYPE_YCbCr_16;
1134 target_colorspace=UndefinedColorspace;
1135 target_type=(cmsUInt32Number) TYPE_RGB_16;
1140 if ((source_colorspace == UndefinedColorspace) ||
1141 (target_colorspace == UndefinedColorspace))
1142 ThrowProfileException(ImageError,
1143 "ColorspaceColorProfileMismatch",name);
1144 if ((source_colorspace == GRAYColorspace) &&
1145 (IsGrayImage(image,exception) == MagickFalse))
1146 ThrowProfileException(ImageError,
1147 "ColorspaceColorProfileMismatch",name);
1148 if ((source_colorspace == CMYKColorspace) &&
1149 (image->colorspace != CMYKColorspace))
1150 ThrowProfileException(ImageError,
1151 "ColorspaceColorProfileMismatch",name);
1152 if ((source_colorspace == XYZColorspace) &&
1153 (image->colorspace != XYZColorspace))
1154 ThrowProfileException(ImageError,
1155 "ColorspaceColorProfileMismatch",name);
1156 if ((source_colorspace == YCbCrColorspace) &&
1157 (image->colorspace != YCbCrColorspace))
1158 ThrowProfileException(ImageError,
1159 "ColorspaceColorProfileMismatch",name);
1160 if ((source_colorspace != CMYKColorspace) &&
1161 (source_colorspace != GRAYColorspace) &&
1162 (source_colorspace != LabColorspace) &&
1163 (source_colorspace != XYZColorspace) &&
1164 (source_colorspace != YCbCrColorspace) &&
1165 (image->colorspace != RGBColorspace))
1166 ThrowProfileException(ImageError,
1167 "ColorspaceColorProfileMismatch",name);
1169 switch (image->rendering_intent)
1171 case AbsoluteIntent: intent=INTENT_ABSOLUTE_COLORIMETRIC; break;
1172 case PerceptualIntent: intent=INTENT_PERCEPTUAL; break;
1173 case RelativeIntent: intent=INTENT_RELATIVE_COLORIMETRIC; break;
1174 case SaturationIntent: intent=INTENT_SATURATION; break;
1175 default: intent=INTENT_PERCEPTUAL; break;
1177 flags=cmsFLAGS_HIGHRESPRECALC;
1178 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1179 if (image->black_point_compensation != MagickFalse)
1180 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1182 transform=AcquireTransformThreadSet(source_profile,source_type,
1183 target_profile,target_type,intent,flags);
1184 (void) cmsCloseProfile(source_profile);
1185 if (transform == (cmsHTRANSFORM *) NULL)
1186 ThrowBinaryException(ImageError,"UnableToCreateColorTransform",
1189 Transform image as dictated by the source and target image profiles.
1191 length=(size_t) image->columns;
1192 source_pixels=AcquirePixelThreadSet(image->columns,source_channels);
1193 target_pixels=AcquirePixelThreadSet(image->columns,target_channels);
1194 if ((source_pixels == (unsigned short **) NULL) ||
1195 (target_pixels == (unsigned short **) NULL))
1197 transform=DestroyTransformThreadSet(transform);
1198 (void) cmsCloseProfile(target_profile);
1199 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1202 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1204 target_pixels=DestroyPixelThreadSet(target_pixels);
1205 source_pixels=DestroyPixelThreadSet(source_pixels);
1206 transform=DestroyTransformThreadSet(transform);
1207 (void) cmsCloseProfile(target_profile);
1208 return(MagickFalse);
1210 if (target_colorspace == CMYKColorspace)
1211 (void) SetImageColorspace(image,target_colorspace);
1214 image_view=AcquireCacheView(image);
1215 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1216 #pragma omp parallel for schedule(dynamic,4) shared(status)
1218 for (y=0; y < (long) image->rows; y++)
1223 register IndexPacket
1230 register PixelPacket
1233 register unsigned short
1236 if (status == MagickFalse)
1238 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1240 if (q == (PixelPacket *) NULL)
1245 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1246 id=GetOpenMPThreadId();
1247 p=source_pixels[id];
1248 for (x=0; x < (long) image->columns; x++)
1250 *p++=ScaleQuantumToShort(q->red);
1251 if (source_channels > 1)
1253 *p++=ScaleQuantumToShort(q->green);
1254 *p++=ScaleQuantumToShort(q->blue);
1256 if (source_channels > 3)
1257 *p++=ScaleQuantumToShort(indexes[x]);
1260 cmsDoTransform(transform[id],source_pixels[id],target_pixels[id],
1261 (unsigned int) image->columns);
1262 p=target_pixels[id];
1264 for (x=0; x < (long) image->columns; x++)
1266 q->red=ScaleShortToQuantum(*p);
1270 if (target_channels > 1)
1272 q->green=ScaleShortToQuantum(*p);
1274 q->blue=ScaleShortToQuantum(*p);
1277 if (target_channels > 3)
1279 indexes[x]=ScaleShortToQuantum(*p);
1284 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1285 if (sync == MagickFalse)
1287 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1292 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1293 #pragma omp critical (MagickCore_ProfileImage)
1295 proceed=SetImageProgress(image,ProfileImageTag,progress++,
1297 if (proceed == MagickFalse)
1301 image_view=DestroyCacheView(image_view);
1302 (void) SetImageColorspace(image,target_colorspace);
1303 switch (cmsGetColorSpace(target_profile))
1307 image->type=image->matte == MagickFalse ? TrueColorType :
1311 case cmsSigCmykData:
1313 image->type=image->matte == MagickFalse ? ColorSeparationType :
1314 ColorSeparationMatteType;
1317 case cmsSigGrayData:
1319 image->type=image->matte == MagickFalse ? GrayscaleType :
1326 target_pixels=DestroyPixelThreadSet(target_pixels);
1327 source_pixels=DestroyPixelThreadSet(source_pixels);
1328 transform=DestroyTransformThreadSet(transform);
1329 (void) cmsCloseProfile(target_profile);
1331 if (cmsGetDeviceClass(profile) != cmsSigLinkClass)
1332 status=SetImageProfile(image,name,profile);
1335 profile=DestroyStringInfo(profile);
1340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1344 % R e m o v e I m a g e P r o f i l e %
1348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1350 % RemoveImageProfile() removes a named profile from the image and returns its
1353 % The format of the RemoveImageProfile method is:
1355 % void *RemoveImageProfile(Image *image,const char *name)
1357 % A description of each parameter follows:
1359 % o image: the image.
1361 % o name: the profile name.
1364 MagickExport StringInfo *RemoveImageProfile(Image *image,const char *name)
1369 assert(image != (Image *) NULL);
1370 assert(image->signature == MagickSignature);
1371 if (image->debug != MagickFalse)
1372 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1373 if (image->profiles == (SplayTreeInfo *) NULL)
1374 return((StringInfo *) NULL);
1375 if (LocaleCompare(name,"icc") == 0)
1378 Continue to support deprecated color profile for now.
1380 image->color_profile.length=0;
1381 image->color_profile.info=(unsigned char *) NULL;
1383 if (LocaleCompare(name,"iptc") == 0)
1386 Continue to support deprecated IPTC profile for now.
1388 image->iptc_profile.length=0;
1389 image->iptc_profile.info=(unsigned char *) NULL;
1391 profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
1392 image->profiles,name);
1397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1401 % R e s e t P r o f i l e I t e r a t o r %
1405 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1407 % ResetImageProfileIterator() resets the image profile iterator. Use it in
1408 % conjunction with GetNextImageProfile() to iterate over all the profiles
1409 % associated with an image.
1411 % The format of the ResetImageProfileIterator method is:
1413 % ResetImageProfileIterator(Image *image)
1415 % A description of each parameter follows:
1417 % o image: the image.
1420 MagickExport void ResetImageProfileIterator(const Image *image)
1422 assert(image != (Image *) NULL);
1423 assert(image->signature == MagickSignature);
1424 if (image->debug != MagickFalse)
1425 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1426 if (image->profiles == (SplayTreeInfo *) NULL)
1428 ResetSplayTreeIterator((SplayTreeInfo *) image->profiles);
1432 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1436 % S e t I m a g e P r o f i l e %
1440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1442 % SetImageProfile() adds a named profile to the image. If a profile with the
1443 % same name already exists, it is replaced. This method differs from the
1444 % ProfileImage() method in that it does not apply CMS color profiles.
1446 % The format of the SetImageProfile method is:
1448 % MagickBooleanType SetImageProfile(Image *image,const char *name,
1449 % const StringInfo *profile)
1451 % A description of each parameter follows:
1453 % o image: the image.
1455 % o name: the profile name, for example icc, exif, and 8bim (8bim is the
1456 % Photoshop wrapper for iptc profiles).
1458 % o profile: A StringInfo structure that contains the named profile.
1462 static void *DestroyProfile(void *profile)
1464 return((void *) DestroyStringInfo((StringInfo *) profile));
1467 static inline const unsigned char *ReadResourceByte(const unsigned char *p,
1468 unsigned char *quantum)
1474 static inline const unsigned char *ReadResourceBytes(const unsigned char *p,
1475 const ssize_t count,unsigned char *quantum)
1480 for (i=0; i < count; i++)
1485 static inline const unsigned char *ReadResourceLong(const unsigned char *p,
1486 unsigned long *quantum)
1488 *quantum=(unsigned long) (*p++ << 24);
1489 *quantum|=(unsigned long) (*p++ << 16);
1490 *quantum|=(unsigned long) (*p++ << 8);
1491 *quantum|=(unsigned long) (*p++ << 0);
1495 static inline const unsigned char *ReadResourceShort(const unsigned char *p,
1496 unsigned short *quantum)
1498 *quantum=(unsigned short) (*p++ << 8);
1499 *quantum|=(unsigned short) (*p++ << 0);
1503 static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
1504 const StringInfo *resource_block)
1509 register const unsigned char
1527 datum=GetStringInfoDatum(resource_block);
1528 length=GetStringInfoLength(resource_block);
1529 for (p=datum; p < (datum+length-16); )
1531 if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1534 p=ReadResourceShort(p,&id);
1535 p=ReadResourceByte(p,&length_byte);
1537 if (((length_byte+1) & 0x01) != 0)
1539 if (p > (datum+length-4))
1541 p=ReadResourceLong(p,&count);
1542 if ((p > (datum+length-count)) || (count > length))
1554 p=ReadResourceShort(p,&resolution)+6;
1555 image->x_resolution=(double) resolution;
1556 p=ReadResourceShort(p,&resolution)+6;
1557 image->y_resolution=(double) resolution;
1565 profile=AcquireStringInfo(count);
1566 SetStringInfoDatum(profile,p);
1567 (void) SetImageProfile(image,"iptc",profile);
1568 profile=DestroyStringInfo(profile);
1585 profile=AcquireStringInfo(count);
1586 SetStringInfoDatum(profile,p);
1587 (void) SetImageProfile(image,"icc",profile);
1588 profile=DestroyStringInfo(profile);
1597 profile=AcquireStringInfo(count);
1598 SetStringInfoDatum(profile,p);
1599 (void) SetImageProfile(image,"exif",profile);
1600 profile=DestroyStringInfo(profile);
1609 profile=AcquireStringInfo(count);
1610 SetStringInfoDatum(profile,p);
1611 (void) SetImageProfile(image,"xmp",profile);
1612 profile=DestroyStringInfo(profile);
1622 if ((count & 0x01) != 0)
1628 MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name,
1629 const StringInfo *profile)
1633 property[MaxTextExtent];
1638 assert(image != (Image *) NULL);
1639 assert(image->signature == MagickSignature);
1640 if (image->debug != MagickFalse)
1641 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1642 if (image->profiles == (SplayTreeInfo *) NULL)
1643 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
1645 (void) CopyMagickString(key,name,MaxTextExtent);
1646 status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1647 ConstantString(key),CloneStringInfo(profile));
1648 if ((status != MagickFalse) &&
1649 ((LocaleCompare(name,"icc") == 0) || (LocaleCompare(name,"icm") == 0)))
1655 Continue to support deprecated color profile member.
1657 icc_profile=GetImageProfile(image,name);
1658 if (icc_profile != (const StringInfo *) NULL)
1660 image->color_profile.length=GetStringInfoLength(icc_profile);
1661 image->color_profile.info=GetStringInfoDatum(icc_profile);
1664 if ((status != MagickFalse) &&
1665 ((LocaleCompare(name,"iptc") == 0) || (LocaleCompare(name,"8bim") == 0)))
1671 Continue to support deprecated IPTC profile member.
1673 iptc_profile=GetImageProfile(image,name);
1674 if (iptc_profile != (const StringInfo *) NULL)
1676 image->iptc_profile.length=GetStringInfoLength(iptc_profile);
1677 image->iptc_profile.info=GetStringInfoDatum(iptc_profile);
1679 (void) GetProfilesFromResourceBlock(image,profile);
1682 Inject profile into image properties.
1684 (void) FormatMagickString(property,MaxTextExtent,"%s:sans",name);
1685 (void) GetImageProperty(image,property);
1690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1694 % S y n c I m a g e P r o f i l e s %
1698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1700 % SyncImageProfiles() synchronizes image properties with the image profiles.
1701 % Currently we only support updating the EXIF resolution and orientation.
1703 % The format of the SyncImageProfiles method is:
1705 % MagickBooleanType SyncImageProfiles(Image *image)
1707 % A description of each parameter follows:
1709 % o image: the image.
1713 static inline int ReadProfileByte(unsigned char **p,size_t *length)
1725 static inline unsigned short ReadProfileShort(const EndianType endian,
1726 unsigned char *buffer)
1731 if (endian == MSBEndian)
1733 value=(unsigned short) ((((unsigned char *) buffer)[0] << 8) |
1734 ((unsigned char *) buffer)[1]);
1735 return((unsigned short) (value & 0xffff));
1737 value=(unsigned short) ((buffer[1] << 8) | buffer[0]);
1738 return((unsigned short) (value & 0xffff));
1741 static inline unsigned long ReadProfileLong(const EndianType endian,
1742 unsigned char *buffer)
1747 if (endian == MSBEndian)
1749 value=(unsigned long) ((buffer[0] << 24) | (buffer[1] << 16) |
1750 (buffer[2] << 8) | buffer[3]);
1751 return((unsigned long) (value & 0xffffffff));
1753 value=(unsigned long) ((buffer[3] << 24) | (buffer[2] << 16) |
1754 (buffer[1] << 8 ) | (buffer[0]));
1755 return((unsigned long) (value & 0xffffffff));
1758 static inline void WriteProfileLong(const EndianType endian,
1759 const unsigned long value,unsigned char *p)
1764 if (endian == MSBEndian)
1766 buffer[0]=(unsigned char) (value >> 24);
1767 buffer[1]=(unsigned char) (value >> 16);
1768 buffer[2]=(unsigned char) (value >> 8);
1769 buffer[3]=(unsigned char) value;
1770 (void) CopyMagickMemory(p,buffer,4);
1773 buffer[0]=(unsigned char) value;
1774 buffer[1]=(unsigned char) (value >> 8);
1775 buffer[2]=(unsigned char) (value >> 16);
1776 buffer[3]=(unsigned char) (value >> 24);
1777 (void) CopyMagickMemory(p,buffer,4);
1780 static void WriteProfileShort(const EndianType endian,
1781 const unsigned short value,unsigned char *p)
1786 if (endian == MSBEndian)
1788 buffer[0]=(unsigned char) (value >> 8);
1789 buffer[1]=(unsigned char) value;
1790 (void) CopyMagickMemory(p,buffer,2);
1793 buffer[0]=(unsigned char) value;
1794 buffer[1]=(unsigned char) (value >> 8);
1795 (void) CopyMagickMemory(p,buffer,2);
1798 MagickExport MagickBooleanType SyncImageProfiles(Image *image)
1800 #define MaxDirectoryStack 16
1801 #define EXIF_DELIMITER "\n"
1802 #define EXIF_NUM_FORMATS 12
1803 #define TAG_EXIF_OFFSET 0x8769
1804 #define TAG_INTEROP_OFFSET 0xa005
1806 typedef struct _DirectoryInfo
1816 directory_stack[MaxDirectoryStack];
1832 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
1846 Set EXIF resolution tag.
1848 profile=(StringInfo *) GetImageProfile(image,"EXIF");
1849 if (profile == (StringInfo *) NULL)
1851 length=GetStringInfoLength(profile);
1852 exif=GetStringInfoDatum(profile);
1855 if (ReadProfileByte(&exif,&length) != 0x45)
1857 if (ReadProfileByte(&exif,&length) != 0x78)
1859 if (ReadProfileByte(&exif,&length) != 0x69)
1861 if (ReadProfileByte(&exif,&length) != 0x66)
1863 if (ReadProfileByte(&exif,&length) != 0x00)
1865 if (ReadProfileByte(&exif,&length) != 0x00)
1870 return(MagickFalse);
1871 id=(int) ReadProfileShort(LSBEndian,exif);
1879 return(MagickFalse);
1880 if (ReadProfileShort(endian,exif+2) != 0x002a)
1881 return(MagickFalse);
1883 This the offset to the first IFD.
1885 offset=(ssize_t) ReadProfileLong(endian,exif+4);
1886 if ((size_t) offset >= length)
1887 return(MagickFalse);
1888 directory=exif+offset;
1896 directory=directory_stack[level].directory;
1897 entry=directory_stack[level].entry;
1900 Determine how many entries there are in the current IFD.
1902 number_entries=ReadProfileShort(endian,directory);
1903 for ( ; entry < number_entries; entry++)
1910 register unsigned char
1917 q=(unsigned char *) (directory+2+(12*entry));
1918 tag_value=(long) ReadProfileShort(endian,q);
1919 format=(long) ReadProfileShort(endian,q+2);
1920 if ((format-1) >= EXIF_NUM_FORMATS)
1922 components=(long) ReadProfileLong(endian,q+4);
1923 number_bytes=(size_t) components*format_bytes[format];
1924 if (number_bytes <= 4)
1932 The directory entry contains an offset.
1934 offset=(ssize_t) ReadProfileLong(endian,q+8);
1935 if ((size_t) (offset+number_bytes) > length)
1937 p=(unsigned char *) (exif+offset);
1943 (void) WriteProfileLong(endian,(unsigned long)
1944 (image->x_resolution+0.5),p);
1945 (void) WriteProfileLong(endian,1UL,p+4);
1950 (void) WriteProfileLong(endian,(unsigned long)
1951 (image->y_resolution+0.5),p);
1952 (void) WriteProfileLong(endian,1UL,p+4);
1957 (void) WriteProfileShort(endian,(unsigned short)
1958 image->orientation,p);
1963 (void) WriteProfileShort(endian,(unsigned short)
1964 (image->units+1),p);
1970 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
1975 offset=(size_t) ReadProfileLong(endian,p);
1976 if ((offset < length) && (level < (MaxDirectoryStack-2)))
1978 directory_stack[level].directory=directory;
1980 directory_stack[level].entry=entry;
1982 directory_stack[level].directory=exif+offset;
1983 directory_stack[level].entry=0;
1985 if ((directory+2+(12*number_entries)) > (exif+length))
1987 offset=(size_t) ReadProfileLong(endian,directory+2+(12*
1989 if ((offset != 0) && (offset < length) &&
1990 (level < (MaxDirectoryStack-2)))
1992 directory_stack[level].directory=exif+offset;
1993 directory_stack[level].entry=0;
2000 } while (level > 0);