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_LCMS_H)
65 #include <lcms/lcms.h>
72 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
76 % C l o n e I m a g e P r o f i l e s %
80 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82 % CloneImageProfiles() clones one or more image profiles.
84 % The format of the CloneImageProfiles method is:
86 % MagickBooleanType CloneImageProfiles(Image *image,
87 % const Image *clone_image)
89 % A description of each parameter follows:
93 % o clone_image: the clone image.
96 MagickExport MagickBooleanType CloneImageProfiles(Image *image,
97 const Image *clone_image)
99 assert(image != (Image *) NULL);
100 assert(image->signature == MagickSignature);
101 if (image->debug != MagickFalse)
102 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
103 assert(clone_image != (const Image *) NULL);
104 assert(clone_image->signature == MagickSignature);
105 image->color_profile.length=clone_image->color_profile.length;
106 image->color_profile.info=clone_image->color_profile.info;
107 image->iptc_profile.length=clone_image->iptc_profile.length;
108 image->iptc_profile.info=clone_image->iptc_profile.info;
109 if (clone_image->profiles != (void *) NULL)
110 image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
111 (void *(*)(void *)) ConstantString,(void *(*)(void *)) CloneStringInfo);
116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120 % D e l e t e I m a g e P r o f i l e %
124 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
126 % DeleteImageProfile() deletes a profile from the image by its name.
128 % The format of the DeleteImageProfile method is:
130 % MagickBooleanTyupe DeleteImageProfile(Image *image,const char *name)
132 % A description of each parameter follows:
134 % o image: the image.
136 % o name: the profile name.
139 MagickExport MagickBooleanType DeleteImageProfile(Image *image,const char *name)
141 assert(image != (Image *) NULL);
142 assert(image->signature == MagickSignature);
143 if (image->debug != MagickFalse)
144 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
145 if (image->profiles == (SplayTreeInfo *) NULL)
147 if (LocaleCompare(name,"icc") == 0)
150 Continue to support deprecated color profile for now.
152 image->color_profile.length=0;
153 image->color_profile.info=(unsigned char *) NULL;
155 if (LocaleCompare(name,"iptc") == 0)
158 Continue to support deprecated IPTC profile for now.
160 image->iptc_profile.length=0;
161 image->iptc_profile.info=(unsigned char *) NULL;
163 return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->profiles,name));
167 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
171 % D e s t r o y I m a g e P r o f i l e s %
175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
177 % DestroyImageProfiles() releases memory associated with an image profile map.
179 % The format of the DestroyProfiles method is:
181 % void DestroyImageProfiles(Image *image)
183 % A description of each parameter follows:
185 % o image: the image.
188 MagickExport void DestroyImageProfiles(Image *image)
190 if (image->profiles != (SplayTreeInfo *) NULL)
191 image->profiles=DestroySplayTree((SplayTreeInfo *) image->profiles);
195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
199 % G e t I m a g e P r o f i l e %
203 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
205 % GetImageProfile() gets a profile associated with an image by name.
207 % The format of the GetImageProfile method is:
209 % const StringInfo *GetImageProfile(const Image *image,const char *name)
211 % A description of each parameter follows:
213 % o image: the image.
215 % o name: the profile name.
218 MagickExport const StringInfo *GetImageProfile(const Image *image,
227 assert(image != (Image *) NULL);
228 assert(image->signature == MagickSignature);
229 if (image->debug != MagickFalse)
230 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
231 if (image->profiles == (SplayTreeInfo *) NULL)
232 return((StringInfo *) NULL);
233 (void) CopyMagickString(key,name,MaxTextExtent);
234 profile=(const StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
235 image->profiles,key);
240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
244 % G e t N e x t I m a g e P r o f i l e %
248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250 % GetNextImageProfile() gets the next profile name for an image.
252 % The format of the GetNextImageProfile method is:
254 % char *GetNextImageProfile(const Image *image)
256 % A description of each parameter follows:
258 % o hash_info: the hash info.
261 MagickExport char *GetNextImageProfile(const Image *image)
263 assert(image != (Image *) NULL);
264 assert(image->signature == MagickSignature);
265 if (image->debug != MagickFalse)
266 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
267 if (image->profiles == (SplayTreeInfo *) NULL)
268 return((char *) NULL);
269 return((char *) GetNextKeyInSplayTree((SplayTreeInfo *) image->profiles));
273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
277 % P r o f i l e I m a g e %
281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
283 % ProfileImage() associates, applies, or removes an ICM, IPTC, or generic
284 % profile with / to / from an image. If the profile is NULL, it is removed
285 % from the image otherwise added or applied. Use a name of '*' and a profile
286 % of NULL to remove all profiles from the image.
288 % ICC and ICM profiles are handled as follows: If the image does not have
289 % an associated color profile, the one you provide is associated with the
290 % image and the image pixels are not transformed. Otherwise, the colorspace
291 % transform defined by the existing and new profile are applied to the image
292 % pixels and the new profile is associated with the image.
294 % The format of the ProfileImage method is:
296 % MagickBooleanType ProfileImage(Image *image,const char *name,
297 % const void *datum,const size_t length,const MagickBooleanType clone)
299 % A description of each parameter follows:
301 % o image: the image.
303 % o name: Name of profile to add or remove: ICC, IPTC, or generic profile.
305 % o datum: the profile data.
307 % o length: the length of the profile.
309 % o clone: should be MagickFalse.
313 #if defined(MAGICKCORE_LCMS_DELEGATE)
315 static unsigned short **DestroyPixelThreadSet(unsigned short **pixels)
320 assert(pixels != (unsigned short **) NULL);
321 for (i=0; i < (long) GetOpenMPMaximumThreads(); i++)
322 if (pixels[i] != (unsigned short *) NULL)
323 pixels[i]=(unsigned short *) RelinquishMagickMemory(pixels[i]);
324 pixels=(unsigned short **) RelinquishAlignedMemory(pixels);
328 static unsigned short **AcquirePixelThreadSet(const size_t columns,
329 const size_t channels)
340 number_threads=GetOpenMPMaximumThreads();
341 pixels=(unsigned short **) AcquireAlignedMemory(number_threads,
343 if (pixels == (unsigned short **) NULL)
344 return((unsigned short **) NULL);
345 (void) ResetMagickMemory(pixels,0,number_threads*sizeof(*pixels));
346 for (i=0; i < (long) number_threads; i++)
348 pixels[i]=(unsigned short *) AcquireQuantumMemory(columns,channels*
350 if (pixels[i] == (unsigned short *) NULL)
351 return(DestroyPixelThreadSet(pixels));
356 static cmsHTRANSFORM *DestroyTransformThreadSet(cmsHTRANSFORM *transform)
361 assert(transform != (cmsHTRANSFORM *) NULL);
362 for (i=0; i < (long) GetOpenMPMaximumThreads(); i++)
363 if (transform[i] != (cmsHTRANSFORM) NULL)
364 cmsDeleteTransform(transform[i]);
365 transform=(cmsHTRANSFORM *) RelinquishAlignedMemory(transform);
369 static cmsHTRANSFORM *AcquireTransformThreadSet(
370 const cmsHPROFILE source_profile,const DWORD source_type,
371 const cmsHPROFILE target_profile,const DWORD target_type,const int intent,
383 number_threads=GetOpenMPMaximumThreads();
384 transform=(cmsHTRANSFORM *) AcquireAlignedMemory(number_threads,
386 if (transform == (cmsHTRANSFORM *) NULL)
387 return((cmsHTRANSFORM *) NULL);
388 (void) ResetMagickMemory(transform,0,number_threads*sizeof(*transform));
389 for (i=0; i < (long) number_threads; i++)
391 transform[i]=cmsCreateTransform(source_profile,source_type,target_profile,
392 target_type,intent,flags);
393 if (transform[i] == (cmsHTRANSFORM) NULL)
394 return(DestroyTransformThreadSet(transform));
400 static MagickBooleanType SetAdobeRGB1998ImageProfile(Image *image)
403 AdobeRGB1998Profile[] =
405 0x00, 0x00, 0x02, 0x30, 0x41, 0x44, 0x42, 0x45, 0x02, 0x10, 0x00,
406 0x00, 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59,
407 0x5a, 0x20, 0x07, 0xd0, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x13, 0x00,
408 0x33, 0x00, 0x3b, 0x61, 0x63, 0x73, 0x70, 0x41, 0x50, 0x50, 0x4c,
409 0x00, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x00,
410 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00,
412 0x00, 0xd3, 0x2d, 0x41, 0x44, 0x42, 0x45, 0x00, 0x00, 0x00, 0x00,
413 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
417 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
418 0x32, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00,
419 0x00, 0x6b, 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x9c, 0x00,
420 0x00, 0x00, 0x14, 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x01, 0xb0,
421 0x00, 0x00, 0x00, 0x14, 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01,
422 0xc4, 0x00, 0x00, 0x00, 0x0e, 0x67, 0x54, 0x52, 0x43, 0x00, 0x00,
423 0x01, 0xd4, 0x00, 0x00, 0x00, 0x0e, 0x62, 0x54, 0x52, 0x43, 0x00,
424 0x00, 0x01, 0xe4, 0x00, 0x00, 0x00, 0x0e, 0x72, 0x58, 0x59, 0x5a,
425 0x00, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x00, 0x14, 0x67, 0x58, 0x59,
426 0x5a, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x14, 0x62, 0x58,
427 0x59, 0x5a, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x14, 0x74,
428 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x70, 0x79,
429 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x32, 0x30, 0x30, 0x30, 0x20,
430 0x41, 0x64, 0x6f, 0x62, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65,
431 0x6d, 0x73, 0x20, 0x49, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72,
432 0x61, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x41, 0x64, 0x6f,
434 0x62, 0x65, 0x20, 0x52, 0x47, 0x42, 0x20, 0x28, 0x31, 0x39, 0x39,
435 0x38, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00,
440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
441 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
442 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00,
443 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00,
444 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
445 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
446 0x00, 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447 0x00, 0x01, 0x02, 0x33, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76, 0x00,
448 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x33, 0x00, 0x00,
449 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450 0x01, 0x02, 0x33, 0x00, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00,
451 0x00, 0x00, 0x00, 0x00, 0x9c, 0x18, 0x00, 0x00, 0x4f, 0xa5, 0x00,
452 0x00, 0x04, 0xfc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
453 0x00, 0x00, 0x34, 0x8d, 0x00, 0x00, 0xa0, 0x2c, 0x00, 0x00, 0x0f,
454 0x95, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
455 0x26, 0x31, 0x00, 0x00, 0x10, 0x2f, 0x00, 0x00, 0xbe, 0x9c
464 assert(image != (Image *) NULL);
465 assert(image->signature == MagickSignature);
466 if (GetImageProfile(image,"icm") != (const StringInfo *) NULL)
468 profile=AcquireStringInfo(sizeof(AdobeRGB1998Profile));
469 SetStringInfoDatum(profile,AdobeRGB1998Profile);
470 status=SetImageProfile(image,"icm",profile);
471 profile=DestroyStringInfo(profile);
475 static MagickBooleanType SetsRGBImageProfile(Image *image)
480 0x00, 0x00, 0x0c, 0x48, 0x4c, 0x69, 0x6e, 0x6f, 0x02, 0x10, 0x00,
481 0x00, 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59,
482 0x5a, 0x20, 0x07, 0xce, 0x00, 0x02, 0x00, 0x09, 0x00, 0x06, 0x00,
483 0x31, 0x00, 0x00, 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54,
484 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47,
485 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
486 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00,
487 0x00, 0xd3, 0x2d, 0x48, 0x50, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
488 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
492 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00,
493 0x33, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00,
494 0x00, 0x6c, 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0xf0, 0x00,
495 0x00, 0x00, 0x14, 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x02, 0x04,
496 0x00, 0x00, 0x00, 0x14, 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x02,
497 0x18, 0x00, 0x00, 0x00, 0x14, 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00,
498 0x02, 0x2c, 0x00, 0x00, 0x00, 0x14, 0x62, 0x58, 0x59, 0x5a, 0x00,
499 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x14, 0x64, 0x6d, 0x6e, 0x64,
500 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70, 0x64, 0x6d, 0x64,
501 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88, 0x76, 0x75,
502 0x65, 0x64, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x86, 0x76,
503 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xd4, 0x00, 0x00, 0x00, 0x24,
504 0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00,
505 0x14, 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x04, 0x0c, 0x00, 0x00,
506 0x00, 0x24, 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x04, 0x30, 0x00,
507 0x00, 0x00, 0x0c, 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x3c,
508 0x00, 0x00, 0x08, 0x0c, 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04,
509 0x3c, 0x00, 0x00, 0x08, 0x0c, 0x62, 0x54, 0x52, 0x43, 0x00, 0x00,
510 0x04, 0x3c, 0x00, 0x00, 0x08, 0x0c, 0x74, 0x65, 0x78, 0x74, 0x00,
511 0x00, 0x00, 0x00, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
512 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, 0x39, 0x38, 0x20,
513 0x48, 0x65, 0x77, 0x6c, 0x65, 0x74, 0x74, 0x2d, 0x50, 0x61, 0x63,
514 0x6b, 0x61, 0x72, 0x64, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e,
515 0x79, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
516 0x00, 0x00, 0x00, 0x12, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45,
517 0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00,
518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
519 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39,
520 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00,
521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
523 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
525 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xcc, 0x58,
527 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5a,
529 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa2, 0x00, 0x00,
530 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20, 0x00,
531 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x99, 0x00, 0x00, 0xb7, 0x85,
532 0x00, 0x00, 0x18, 0xda, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00,
533 0x00, 0x00, 0x00, 0x24, 0xa0, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00,
534 0xb6, 0xcf, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00,
535 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74, 0x70,
536 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
537 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74, 0x70,
539 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
540 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43, 0x20, 0x36, 0x31,
546 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44, 0x65, 0x66,
547 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63, 0x6f,
548 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
549 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00,
550 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43, 0x20,
551 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
552 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20,
553 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63,
554 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73,
557 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x52, 0x65,
558 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65,
559 0x77, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74,
560 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 0x43, 0x36,
561 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00,
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x52, 0x65,
563 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65,
564 0x77, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74,
565 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 0x43, 0x36,
566 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569 0x00, 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
570 0xa4, 0xfe, 0x00, 0x14, 0x5f, 0x2e, 0x00, 0x10, 0xcf, 0x14, 0x00,
571 0x03, 0xed, 0xcc, 0x00, 0x04, 0x13, 0x0b, 0x00, 0x03, 0x5c, 0x9e,
572 0x00, 0x00, 0x00, 0x01, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00,
573 0x00, 0x00, 0x4c, 0x09, 0x56, 0x00, 0x50, 0x00, 0x00, 0x00, 0x57,
574 0x1f, 0xe7, 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
577 0x8f, 0x00, 0x00, 0x00, 0x02, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00,
578 0x00, 0x00, 0x43, 0x52, 0x54, 0x20, 0x63, 0x75, 0x72, 0x76, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x05,
580 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19, 0x00, 0x1e, 0x00,
581 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37, 0x00, 0x3b,
582 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54, 0x00,
583 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
584 0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00,
585 0x90, 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9,
586 0x00, 0xae, 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00,
587 0xc6, 0x00, 0xcb, 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0,
588 0x00, 0xe5, 0x00, 0xeb, 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01,
589 0x01, 0x01, 0x07, 0x01, 0x0d, 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f,
590 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32, 0x01, 0x38, 0x01, 0x3e, 0x01,
591 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59, 0x01, 0x60, 0x01, 0x67,
592 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83, 0x01, 0x8b, 0x01,
593 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1, 0x01, 0xb9,
594 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1, 0x01,
595 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
596 0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02,
597 0x4b, 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a,
598 0x02, 0x84, 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02,
599 0xb6, 0x02, 0xc1, 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb,
600 0x02, 0xf5, 0x03, 0x00, 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03,
601 0x2d, 0x03, 0x38, 0x03, 0x43, 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66,
602 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a, 0x03, 0x96, 0x03, 0xa2, 0x03,
603 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3, 0x03, 0xe0, 0x03, 0xec,
604 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20, 0x04, 0x2d, 0x04,
605 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71, 0x04, 0x7e,
606 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4, 0x04,
607 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
608 0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05,
609 0x77, 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5,
610 0x05, 0xd5, 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06,
611 0x27, 0x06, 0x37, 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b,
612 0x06, 0x8c, 0x06, 0x9d, 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06,
613 0xe3, 0x06, 0xf5, 0x07, 0x07, 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d,
614 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74, 0x07, 0x86, 0x07, 0x99, 0x07,
615 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5, 0x07, 0xf8, 0x08, 0x0b,
616 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a, 0x08, 0x6e, 0x08,
617 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2, 0x08, 0xe7,
618 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f, 0x09,
619 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
620 0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a,
621 0x54, 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5,
622 0x0a, 0xdc, 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b,
623 0x51, 0x0b, 0x69, 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8,
624 0x0b, 0xe1, 0x0b, 0xf9, 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c,
625 0x5c, 0x0c, 0x75, 0x0c, 0x8e, 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9,
626 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26, 0x0d, 0x40, 0x0d, 0x5a, 0x0d,
627 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3, 0x0d, 0xde, 0x0d, 0xf8,
628 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64, 0x0e, 0x7f, 0x0e,
629 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09, 0x0f, 0x25,
630 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3, 0x0f,
631 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
632 0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11,
633 0x13, 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa,
634 0x11, 0xc9, 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12,
635 0x64, 0x12, 0x84, 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03,
636 0x13, 0x23, 0x13, 0x43, 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13,
637 0xc5, 0x13, 0xe5, 0x14, 0x06, 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a,
638 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce, 0x14, 0xf0, 0x15, 0x12, 0x15,
639 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b, 0x15, 0xbd, 0x15, 0xe0,
640 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c, 0x16, 0x8f, 0x16,
641 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41, 0x17, 0x65,
642 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b, 0x18,
643 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
644 0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19,
645 0xdd, 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e,
646 0x1a, 0xc5, 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b,
647 0x8a, 0x1b, 0xb2, 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52,
648 0x1c, 0x7b, 0x1c, 0xa3, 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d,
649 0x47, 0x1d, 0x70, 0x1d, 0x99, 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16,
650 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94, 0x1e, 0xbe, 0x1e, 0xe9, 0x1f,
651 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94, 0x1f, 0xbf, 0x1f, 0xea,
652 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98, 0x20, 0xc4, 0x20,
653 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1, 0x21, 0xce,
654 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf, 0x22,
655 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
656 0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24,
657 0xda, 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7,
658 0x25, 0xf7, 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26,
659 0xe8, 0x27, 0x18, 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc,
660 0x28, 0x0d, 0x28, 0x3f, 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29,
661 0x06, 0x29, 0x38, 0x29, 0x6b, 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02,
662 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b, 0x2a, 0xcf, 0x2b, 0x02, 0x2b,
663 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1, 0x2c, 0x05, 0x2c, 0x39,
664 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c, 0x2d, 0x41, 0x2d,
665 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c, 0x2e, 0x82,
666 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91, 0x2f,
667 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
668 0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32,
669 0x2a, 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46,
670 0x33, 0x7f, 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34,
671 0x9e, 0x34, 0xd8, 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2,
672 0x35, 0xfd, 0x36, 0x37, 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37,
673 0x24, 0x37, 0x60, 0x37, 0x9c, 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50,
674 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05, 0x39, 0x42, 0x39, 0x7f, 0x39,
675 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74, 0x3a, 0xb2, 0x3a, 0xef,
676 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8, 0x3c, 0x27, 0x3c,
677 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61, 0x3d, 0xa1,
678 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0, 0x3f,
679 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
680 0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41,
681 0xee, 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a,
682 0x43, 0x7d, 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44,
683 0xce, 0x45, 0x12, 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22,
684 0x46, 0x67, 0x46, 0xab, 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47,
685 0xc0, 0x48, 0x05, 0x48, 0x4b, 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d,
686 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0, 0x4a, 0x37, 0x4a, 0x7d, 0x4a,
687 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a, 0x4b, 0xe2, 0x4c, 0x2a,
688 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a, 0x4d, 0x93, 0x4d,
689 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00, 0x4f, 0x49,
690 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb, 0x51,
691 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
692 0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54,
693 0x42, 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2,
694 0x56, 0x0f, 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57,
695 0x92, 0x57, 0xe0, 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a,
696 0x59, 0x69, 0x59, 0xb8, 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a,
697 0xf5, 0x5b, 0x45, 0x5b, 0x95, 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86,
698 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78, 0x5d, 0xc9, 0x5e, 0x1a, 0x5e,
699 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61, 0x5f, 0xb3, 0x60, 0x05,
700 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f, 0x61, 0xa2, 0x61,
701 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43, 0x63, 0x97,
702 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d, 0x65,
703 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
704 0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69,
705 0x43, 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7,
706 0x6b, 0x4f, 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d,
707 0x08, 0x6d, 0x60, 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4,
708 0x6f, 0x1e, 0x6f, 0x78, 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70,
709 0xe0, 0x71, 0x3a, 0x71, 0x95, 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6,
710 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8, 0x74, 0x14, 0x74, 0x70, 0x74,
711 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1, 0x76, 0x3e, 0x76, 0x9b,
712 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11, 0x78, 0x6e, 0x78,
713 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46, 0x7a, 0xa5,
714 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81, 0x7c,
715 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
716 0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81,
717 0x0a, 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4,
718 0x83, 0x57, 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85,
719 0x47, 0x85, 0xab, 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b,
720 0x87, 0x9f, 0x88, 0x04, 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89,
721 0x99, 0x89, 0xfe, 0x8a, 0x64, 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96,
722 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca, 0x8d, 0x31, 0x8d, 0x98, 0x8d,
723 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36, 0x8f, 0x9e, 0x90, 0x06,
724 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8, 0x92, 0x11, 0x92,
725 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20, 0x94, 0x8a,
726 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f, 0x97,
727 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
728 0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b,
729 0xaf, 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2,
730 0x9e, 0x40, 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0,
731 0x69, 0xa0, 0xd8, 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96,
732 0xa3, 0x06, 0xa3, 0x76, 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5,
733 0x38, 0xa5, 0xa9, 0xa6, 0x1a, 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e,
734 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4, 0xa9, 0x37, 0xa9, 0xa9, 0xaa,
735 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75, 0xab, 0xe9, 0xac, 0x5c,
736 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d, 0xae, 0xa1, 0xaf,
737 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea, 0xb1, 0x60,
738 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae, 0xb4,
739 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
740 0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9,
741 0x4a, 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7,
742 0xbc, 0x21, 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe,
743 0x84, 0xbe, 0xff, 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec,
744 0xc1, 0x67, 0xc1, 0xe3, 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3,
745 0xd4, 0xc4, 0x51, 0xc4, 0xce, 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46,
746 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf, 0xc8, 0x3d, 0xc8, 0xbc, 0xc9,
747 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7, 0xcb, 0x36, 0xcb, 0xb6,
748 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5, 0xce, 0x36, 0xce,
749 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba, 0xd1, 0x3c,
750 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6, 0xd4,
751 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
752 0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9,
753 0xf1, 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a,
754 0xdd, 0x10, 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf,
755 0xaf, 0xe0, 0x36, 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53,
756 0xe2, 0xdb, 0xe3, 0x63, 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5,
757 0x84, 0xe6, 0x0d, 0xe6, 0x96, 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32,
758 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0, 0xea, 0x5b, 0xea, 0xe5, 0xeb,
759 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11, 0xed, 0x9c, 0xee, 0x28,
760 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58, 0xf0, 0xe5, 0xf1,
761 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7, 0xf4, 0x34,
762 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb, 0xf7,
763 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
764 0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd,
765 0xba, 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
774 assert(image != (Image *) NULL);
775 assert(image->signature == MagickSignature);
776 if (GetImageProfile(image,"icm") != (const StringInfo *) NULL)
778 profile=AcquireStringInfo(sizeof(sRGBProfile));
779 SetStringInfoDatum(profile,sRGBProfile);
780 status=SetImageProfile(image,"icm",profile);
781 profile=DestroyStringInfo(profile);
784 #if defined(MAGICKCORE_LCMS_DELEGATE)
785 #if defined(LCMS_VERSION) && (LCMS_VERSION > 1010)
786 static int LCMSErrorHandler(int severity,const char *message)
788 (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%d, %s",
789 severity,message != (char *) NULL ? message : "no message");
795 MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
796 const void *datum,const size_t length,
797 const MagickBooleanType magick_unused(clone))
799 #define ProfileImageTag "Profile/Image"
800 #define ThrowProfileException(severity,tag,context) \
802 (void) cmsCloseProfile(source_profile); \
803 (void) cmsCloseProfile(target_profile); \
804 ThrowBinaryException(severity,tag,context); \
813 assert(image != (Image *) NULL);
814 assert(image->signature == MagickSignature);
815 if (image->debug != MagickFalse)
816 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
817 assert(name != (const char *) NULL);
818 if ((datum == (const void *) NULL) || (length == 0))
831 Delete image profile(s).
833 names=ConstantString(name);
834 (void) SubstituteString(&names,","," ");
835 arguments=StringToArgv(names,&number_arguments);
836 names=DestroyString(names);
837 if (arguments == (char **) NULL)
839 ResetImageProfileIterator(image);
840 for (name=GetNextImageProfile(image); name != (const char *) NULL; )
842 for (i=1; i < number_arguments; i++)
844 if ((*arguments[i] == '!') &&
845 (LocaleCompare(name,arguments[i]+1) == 0))
847 if (GlobExpression(name,arguments[i],MagickTrue) != MagickFalse)
849 (void) DeleteImageProfile(image,name);
850 ResetImageProfileIterator(image);
854 name=GetNextImageProfile(image);
856 for (i=0; i < number_arguments; i++)
857 arguments[i]=DestroyString(arguments[i]);
858 arguments=(char **) RelinquishMagickMemory(arguments);
862 Add a ICC, IPTC, or generic profile to the image.
864 profile=AcquireStringInfo((size_t) length);
865 SetStringInfoDatum(profile,(unsigned char *) datum);
866 if ((LocaleCompare(name,"icc") == 0) || (LocaleCompare(name,"icm") == 0))
871 icc_profile=GetImageProfile(image,"icc");
872 if ((icc_profile != (const StringInfo *) NULL) &&
873 (CompareStringInfo(icc_profile,profile) == 0))
878 value=GetImageProperty(image,"exif:ColorSpace");
879 if (LocaleCompare(value,"1") != 0)
880 (void) SetsRGBImageProfile(image);
881 value=GetImageProperty(image,"exif:InteroperabilityIndex");
882 if (LocaleCompare(value,"R98.") != 0)
883 (void) SetsRGBImageProfile(image);
884 value=GetImageProperty(image,"exif:InteroperabilityIndex");
885 if (LocaleCompare(value,"R03.") != 0)
886 (void) SetAdobeRGB1998ImageProfile(image);
887 icc_profile=GetImageProfile(image,"icc");
889 if ((icc_profile != (const StringInfo *) NULL) &&
890 (CompareStringInfo(icc_profile,profile) == 0))
892 profile=DestroyStringInfo(profile);
895 #if !defined(MAGICKCORE_LCMS_DELEGATE)
896 (void) ThrowMagickException(&image->exception,GetMagickModule(),
897 MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn","`%s' (LCMS)",
900 if (icc_profile != (StringInfo *) NULL)
940 **restrict source_pixels,
941 **restrict target_pixels;
944 Transform pixel colors as defined by the color profiles.
946 #if defined(LCMS_VERSION) && (LCMS_VERSION > 1010)
947 cmsSetErrorHandler(LCMSErrorHandler);
949 (void) cmsErrorAction(LCMS_ERROR_SHOW);
951 source_profile=cmsOpenProfileFromMem(GetStringInfoDatum(icc_profile),
952 (DWORD) GetStringInfoLength(icc_profile));
953 target_profile=cmsOpenProfileFromMem(GetStringInfoDatum(profile),
954 (DWORD) GetStringInfoLength(profile));
955 if ((source_profile == (cmsHPROFILE) NULL) ||
956 (target_profile == (cmsHPROFILE) NULL))
957 ThrowBinaryException(ResourceLimitError,
958 "ColorspaceColorProfileMismatch",name);
959 switch (cmsGetColorSpace(source_profile))
963 source_colorspace=CMYKColorspace;
964 source_type=(DWORD) TYPE_CMYK_16;
970 source_colorspace=GRAYColorspace;
971 source_type=(DWORD) TYPE_GRAY_16;
977 source_colorspace=LabColorspace;
978 source_type=(DWORD) TYPE_Lab_16;
984 source_colorspace=YUVColorspace;
985 source_type=(DWORD) TYPE_YUV_16;
991 source_colorspace=RGBColorspace;
992 source_type=(DWORD) TYPE_RGB_16;
998 source_colorspace=XYZColorspace;
999 source_type=(DWORD) TYPE_XYZ_16;
1003 case icSigYCbCrData:
1005 source_colorspace=YCbCrColorspace;
1006 source_type=(DWORD) TYPE_YCbCr_16;
1012 source_colorspace=UndefinedColorspace;
1013 source_type=(DWORD) TYPE_RGB_16;
1018 switch (cmsGetColorSpace(target_profile))
1022 target_colorspace=CMYKColorspace;
1023 target_type=(DWORD) TYPE_CMYK_16;
1029 target_colorspace=LabColorspace;
1030 target_type=(DWORD) TYPE_Lab_16;
1036 target_colorspace=GRAYColorspace;
1037 target_type=(DWORD) TYPE_GRAY_16;
1043 target_colorspace=YUVColorspace;
1044 target_type=(DWORD) TYPE_YUV_16;
1050 target_colorspace=RGBColorspace;
1051 target_type=(DWORD) TYPE_RGB_16;
1057 target_colorspace=XYZColorspace;
1058 target_type=(DWORD) TYPE_XYZ_16;
1062 case icSigYCbCrData:
1064 target_colorspace=YCbCrColorspace;
1065 target_type=(DWORD) TYPE_YCbCr_16;
1071 target_colorspace=UndefinedColorspace;
1072 target_type=(DWORD) TYPE_RGB_16;
1077 exception=(&image->exception);
1078 if ((source_colorspace == UndefinedColorspace) ||
1079 (target_colorspace == UndefinedColorspace))
1080 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1082 if ((source_colorspace == GRAYColorspace) &&
1083 (IsGrayImage(image,exception) == MagickFalse))
1084 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1086 if ((source_colorspace == CMYKColorspace) &&
1087 (image->colorspace != CMYKColorspace))
1088 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1090 if ((source_colorspace == XYZColorspace) &&
1091 (image->colorspace != XYZColorspace))
1092 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1094 if ((source_colorspace == YCbCrColorspace) &&
1095 (image->colorspace != YCbCrColorspace))
1096 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1098 if ((source_colorspace != CMYKColorspace) &&
1099 (source_colorspace != GRAYColorspace) &&
1100 (source_colorspace != LabColorspace) &&
1101 (source_colorspace != XYZColorspace) &&
1102 (source_colorspace != YCbCrColorspace) &&
1103 (image->colorspace != RGBColorspace))
1104 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1106 switch (image->rendering_intent)
1108 case AbsoluteIntent: intent=INTENT_ABSOLUTE_COLORIMETRIC; break;
1109 case PerceptualIntent: intent=INTENT_PERCEPTUAL; break;
1110 case RelativeIntent: intent=INTENT_RELATIVE_COLORIMETRIC; break;
1111 case SaturationIntent: intent=INTENT_SATURATION; break;
1112 default: intent=INTENT_PERCEPTUAL; break;
1114 flags=cmsFLAGS_HIGHRESPRECALC;
1115 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1116 if (image->black_point_compensation != MagickFalse)
1117 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1119 transform=AcquireTransformThreadSet(source_profile,source_type,
1120 target_profile,target_type,intent,flags);
1121 (void) cmsCloseProfile(source_profile);
1122 if (transform == (cmsHTRANSFORM *) NULL)
1123 ThrowBinaryException(ImageError,"UnableToCreateColorTransform",
1126 Transform image as dictated by the source and target image profiles.
1128 length=(size_t) image->columns;
1129 source_pixels=AcquirePixelThreadSet(image->columns,source_channels);
1130 target_pixels=AcquirePixelThreadSet(image->columns,target_channels);
1131 if ((source_pixels == (unsigned short **) NULL) ||
1132 (target_pixels == (unsigned short **) NULL))
1134 transform=DestroyTransformThreadSet(transform);
1135 (void) cmsCloseProfile(target_profile);
1136 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1139 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1141 target_pixels=DestroyPixelThreadSet(target_pixels);
1142 source_pixels=DestroyPixelThreadSet(source_pixels);
1143 transform=DestroyTransformThreadSet(transform);
1144 (void) cmsCloseProfile(target_profile);
1145 return(MagickFalse);
1147 if (target_colorspace == CMYKColorspace)
1148 (void) SetImageColorspace(image,target_colorspace);
1151 image_view=AcquireCacheView(image);
1152 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1153 #pragma omp parallel for schedule(dynamic,4) shared(status)
1155 for (y=0; y < (long) image->rows; y++)
1160 register IndexPacket
1167 register PixelPacket
1170 register unsigned short
1173 if (status == MagickFalse)
1175 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1177 if (q == (PixelPacket *) NULL)
1182 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1183 id=GetOpenMPThreadId();
1184 p=source_pixels[id];
1185 for (x=0; x < (long) image->columns; x++)
1187 *p++=ScaleQuantumToShort(q->red);
1188 if (source_channels > 1)
1190 *p++=ScaleQuantumToShort(q->green);
1191 *p++=ScaleQuantumToShort(q->blue);
1193 if (source_channels > 3)
1194 *p++=ScaleQuantumToShort(indexes[x]);
1197 cmsDoTransform(transform[id],source_pixels[id],target_pixels[id],
1198 (unsigned int) image->columns);
1199 p=target_pixels[id];
1201 for (x=0; x < (long) image->columns; x++)
1203 q->red=ScaleShortToQuantum(*p);
1207 if (target_channels > 1)
1209 q->green=ScaleShortToQuantum(*p);
1211 q->blue=ScaleShortToQuantum(*p);
1214 if (target_channels > 3)
1216 indexes[x]=ScaleShortToQuantum(*p);
1221 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1222 if (sync == MagickFalse)
1224 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1229 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1230 #pragma omp critical (MagickCore_ProfileImage)
1232 proceed=SetImageProgress(image,ProfileImageTag,progress++,
1234 if (proceed == MagickFalse)
1238 image_view=DestroyCacheView(image_view);
1239 (void) SetImageColorspace(image,target_colorspace);
1240 switch (cmsGetColorSpace(target_profile))
1244 image->type=image->matte == MagickFalse ? TrueColorType :
1250 image->type=image->matte == MagickFalse ? ColorSeparationType :
1251 ColorSeparationMatteType;
1256 image->type=image->matte == MagickFalse ? GrayscaleType :
1263 target_pixels=DestroyPixelThreadSet(target_pixels);
1264 source_pixels=DestroyPixelThreadSet(source_pixels);
1265 transform=DestroyTransformThreadSet(transform);
1266 (void) cmsCloseProfile(target_profile);
1270 status=SetImageProfile(image,name,profile);
1271 profile=DestroyStringInfo(profile);
1276 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1280 % R e m o v e I m a g e P r o f i l e %
1284 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1286 % RemoveImageProfile() removes a named profile from the image and returns its
1289 % The format of the RemoveImageProfile method is:
1291 % void *RemoveImageProfile(Image *image,const char *name)
1293 % A description of each parameter follows:
1295 % o image: the image.
1297 % o name: the profile name.
1300 MagickExport StringInfo *RemoveImageProfile(Image *image,const char *name)
1305 assert(image != (Image *) NULL);
1306 assert(image->signature == MagickSignature);
1307 if (image->debug != MagickFalse)
1308 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1309 if (image->profiles == (SplayTreeInfo *) NULL)
1310 return((StringInfo *) NULL);
1311 if (LocaleCompare(name,"icc") == 0)
1314 Continue to support deprecated color profile for now.
1316 image->color_profile.length=0;
1317 image->color_profile.info=(unsigned char *) NULL;
1319 if (LocaleCompare(name,"iptc") == 0)
1322 Continue to support deprecated IPTC profile for now.
1324 image->iptc_profile.length=0;
1325 image->iptc_profile.info=(unsigned char *) NULL;
1327 profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
1328 image->profiles,name);
1333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1337 % R e s e t P r o f i l e I t e r a t o r %
1341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1343 % ResetImageProfileIterator() resets the image profile iterator. Use it in
1344 % conjunction with GetNextImageProfile() to iterate over all the profiles
1345 % associated with an image.
1347 % The format of the ResetImageProfileIterator method is:
1349 % ResetImageProfileIterator(Image *image)
1351 % A description of each parameter follows:
1353 % o image: the image.
1356 MagickExport void ResetImageProfileIterator(const Image *image)
1358 assert(image != (Image *) NULL);
1359 assert(image->signature == MagickSignature);
1360 if (image->debug != MagickFalse)
1361 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1362 if (image->profiles == (SplayTreeInfo *) NULL)
1364 ResetSplayTreeIterator((SplayTreeInfo *) image->profiles);
1368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1372 % S e t I m a g e P r o f i l e %
1376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1378 % SetImageProfile() adds a named profile to the image. If a profile with the
1379 % same name already exists, it is replaced. This method differs from the
1380 % ProfileImage() method in that it does not apply CMS color profiles.
1382 % The format of the SetImageProfile method is:
1384 % MagickBooleanType SetImageProfile(Image *image,const char *name,
1385 % const StringInfo *profile)
1387 % A description of each parameter follows:
1389 % o image: the image.
1391 % o name: the profile name, for example icc, exif, and 8bim (8bim is the
1392 % Photoshop wrapper for iptc profiles).
1394 % o profile: A StringInfo structure that contains the named profile.
1398 static void *DestroyProfile(void *profile)
1400 return((void *) DestroyStringInfo((StringInfo *) profile));
1403 static inline const unsigned char *ReadResourceByte(const unsigned char *p,
1404 unsigned char *quantum)
1410 static inline const unsigned char *ReadResourceBytes(const unsigned char *p,
1411 const ssize_t count,unsigned char *quantum)
1416 for (i=0; i < count; i++)
1421 static inline const unsigned char *ReadResourceLong(const unsigned char *p,
1422 unsigned long *quantum)
1424 *quantum=(unsigned long) (*p++ << 24);
1425 *quantum|=(unsigned long) (*p++ << 16);
1426 *quantum|=(unsigned long) (*p++ << 8);
1427 *quantum|=(unsigned long) (*p++ << 0);
1431 static inline const unsigned char *ReadResourceShort(const unsigned char *p,
1432 unsigned short *quantum)
1434 *quantum=(unsigned short) (*p++ << 8);
1435 *quantum|=(unsigned short) (*p++ << 0);
1439 static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
1440 const StringInfo *resource_block)
1445 register const unsigned char
1463 datum=GetStringInfoDatum(resource_block);
1464 length=GetStringInfoLength(resource_block);
1465 for (p=datum; p < (datum+length-16); )
1467 if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1470 p=ReadResourceShort(p,&id);
1471 p=ReadResourceByte(p,&length_byte);
1473 if (((length_byte+1) & 0x01) != 0)
1475 if (p > (datum+length-4))
1477 p=ReadResourceLong(p,&count);
1478 if ((p > (datum+length-count)) || (count > length))
1490 p=ReadResourceShort(p,&resolution)+6;
1491 image->x_resolution=(double) resolution;
1492 p=ReadResourceShort(p,&resolution)+6;
1493 image->y_resolution=(double) resolution;
1501 profile=AcquireStringInfo(count);
1502 SetStringInfoDatum(profile,p);
1503 (void) SetImageProfile(image,"iptc",profile);
1504 profile=DestroyStringInfo(profile);
1521 profile=AcquireStringInfo(count);
1522 SetStringInfoDatum(profile,p);
1523 (void) SetImageProfile(image,"icc",profile);
1524 profile=DestroyStringInfo(profile);
1533 profile=AcquireStringInfo(count);
1534 SetStringInfoDatum(profile,p);
1535 (void) SetImageProfile(image,"exif",profile);
1536 profile=DestroyStringInfo(profile);
1545 profile=AcquireStringInfo(count);
1546 SetStringInfoDatum(profile,p);
1547 (void) SetImageProfile(image,"xmp",profile);
1548 profile=DestroyStringInfo(profile);
1558 if ((count & 0x01) != 0)
1564 MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name,
1565 const StringInfo *profile)
1569 property[MaxTextExtent];
1574 assert(image != (Image *) NULL);
1575 assert(image->signature == MagickSignature);
1576 if (image->debug != MagickFalse)
1577 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1578 if (image->profiles == (SplayTreeInfo *) NULL)
1579 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
1581 (void) CopyMagickString(key,name,MaxTextExtent);
1582 status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1583 ConstantString(key),CloneStringInfo(profile));
1584 if ((status != MagickFalse) &&
1585 ((LocaleCompare(name,"icc") == 0) || (LocaleCompare(name,"icm") == 0)))
1591 Continue to support deprecated color profile member.
1593 icc_profile=GetImageProfile(image,name);
1594 if (icc_profile != (const StringInfo *) NULL)
1596 image->color_profile.length=GetStringInfoLength(icc_profile);
1597 image->color_profile.info=GetStringInfoDatum(icc_profile);
1600 if ((status != MagickFalse) &&
1601 ((LocaleCompare(name,"iptc") == 0) || (LocaleCompare(name,"8bim") == 0)))
1607 Continue to support deprecated IPTC profile member.
1609 iptc_profile=GetImageProfile(image,name);
1610 if (iptc_profile != (const StringInfo *) NULL)
1612 image->iptc_profile.length=GetStringInfoLength(iptc_profile);
1613 image->iptc_profile.info=GetStringInfoDatum(iptc_profile);
1615 (void) GetProfilesFromResourceBlock(image,profile);
1618 Inject profile into image properties.
1620 (void) FormatMagickString(property,MaxTextExtent,"%s:sans",name);
1621 (void) GetImageProperty(image,property);
1626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1630 % S y n c I m a g e P r o f i l e s %
1634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1636 % SyncImageProfiles() synchronizes image properties with the image profiles.
1637 % Currently we only support updating the EXIF resolution and orientation.
1639 % The format of the SyncImageProfiles method is:
1641 % MagickBooleanType SyncImageProfiles(Image *image)
1643 % A description of each parameter follows:
1645 % o image: the image.
1649 static inline int ReadProfileByte(unsigned char **p,size_t *length)
1661 static inline unsigned short ReadProfileShort(const EndianType endian,
1662 unsigned char *buffer)
1667 if (endian == MSBEndian)
1669 value=(unsigned short) ((((unsigned char *) buffer)[0] << 8) |
1670 ((unsigned char *) buffer)[1]);
1671 return((unsigned short) (value & 0xffff));
1673 value=(unsigned short) ((buffer[1] << 8) | buffer[0]);
1674 return((unsigned short) (value & 0xffff));
1677 static inline unsigned long ReadProfileLong(const EndianType endian,
1678 unsigned char *buffer)
1683 if (endian == MSBEndian)
1685 value=(unsigned long) ((buffer[0] << 24) | (buffer[1] << 16) |
1686 (buffer[2] << 8) | buffer[3]);
1687 return((unsigned long) (value & 0xffffffff));
1689 value=(unsigned long) ((buffer[3] << 24) | (buffer[2] << 16) |
1690 (buffer[1] << 8 ) | (buffer[0]));
1691 return((unsigned long) (value & 0xffffffff));
1694 static inline void WriteProfileLong(const EndianType endian,
1695 const unsigned long value,unsigned char *p)
1700 if (endian == MSBEndian)
1702 buffer[0]=(unsigned char) (value >> 24);
1703 buffer[1]=(unsigned char) (value >> 16);
1704 buffer[2]=(unsigned char) (value >> 8);
1705 buffer[3]=(unsigned char) value;
1706 (void) CopyMagickMemory(p,buffer,4);
1709 buffer[0]=(unsigned char) value;
1710 buffer[1]=(unsigned char) (value >> 8);
1711 buffer[2]=(unsigned char) (value >> 16);
1712 buffer[3]=(unsigned char) (value >> 24);
1713 (void) CopyMagickMemory(p,buffer,4);
1716 static void WriteProfileShort(const EndianType endian,
1717 const unsigned short value,unsigned char *p)
1722 if (endian == MSBEndian)
1724 buffer[0]=(unsigned char) (value >> 8);
1725 buffer[1]=(unsigned char) value;
1726 (void) CopyMagickMemory(p,buffer,2);
1729 buffer[0]=(unsigned char) value;
1730 buffer[1]=(unsigned char) (value >> 8);
1731 (void) CopyMagickMemory(p,buffer,2);
1734 MagickExport MagickBooleanType SyncImageProfiles(Image *image)
1736 #define MaxDirectoryStack 16
1737 #define EXIF_DELIMITER "\n"
1738 #define EXIF_NUM_FORMATS 12
1739 #define TAG_EXIF_OFFSET 0x8769
1740 #define TAG_INTEROP_OFFSET 0xa005
1742 typedef struct _DirectoryInfo
1752 directory_stack[MaxDirectoryStack];
1768 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
1782 Set EXIF resolution tag.
1784 profile=(StringInfo *) GetImageProfile(image,"EXIF");
1785 if (profile == (StringInfo *) NULL)
1787 length=GetStringInfoLength(profile);
1788 exif=GetStringInfoDatum(profile);
1791 if (ReadProfileByte(&exif,&length) != 0x45)
1793 if (ReadProfileByte(&exif,&length) != 0x78)
1795 if (ReadProfileByte(&exif,&length) != 0x69)
1797 if (ReadProfileByte(&exif,&length) != 0x66)
1799 if (ReadProfileByte(&exif,&length) != 0x00)
1801 if (ReadProfileByte(&exif,&length) != 0x00)
1806 return(MagickFalse);
1807 id=(int) ReadProfileShort(LSBEndian,exif);
1815 return(MagickFalse);
1816 if (ReadProfileShort(endian,exif+2) != 0x002a)
1817 return(MagickFalse);
1819 This the offset to the first IFD.
1821 offset=(ssize_t) ReadProfileLong(endian,exif+4);
1822 if ((size_t) offset >= length)
1823 return(MagickFalse);
1824 directory=exif+offset;
1832 directory=directory_stack[level].directory;
1833 entry=directory_stack[level].entry;
1836 Determine how many entries there are in the current IFD.
1838 number_entries=ReadProfileShort(endian,directory);
1839 for ( ; entry < number_entries; entry++)
1846 register unsigned char
1853 q=(unsigned char *) (directory+2+(12*entry));
1854 tag_value=(long) ReadProfileShort(endian,q);
1855 format=(long) ReadProfileShort(endian,q+2);
1856 if ((format-1) >= EXIF_NUM_FORMATS)
1858 components=(long) ReadProfileLong(endian,q+4);
1859 number_bytes=(size_t) components*format_bytes[format];
1860 if (number_bytes <= 4)
1868 The directory entry contains an offset.
1870 offset=(ssize_t) ReadProfileLong(endian,q+8);
1871 if ((size_t) (offset+number_bytes) > length)
1873 p=(unsigned char *) (exif+offset);
1879 (void) WriteProfileLong(endian,(unsigned long)
1880 (image->x_resolution+0.5),p);
1881 (void) WriteProfileLong(endian,1UL,p+4);
1886 (void) WriteProfileLong(endian,(unsigned long)
1887 (image->y_resolution+0.5),p);
1888 (void) WriteProfileLong(endian,1UL,p+4);
1893 (void) WriteProfileShort(endian,(unsigned short)
1894 image->orientation,p);
1899 (void) WriteProfileShort(endian,(unsigned short)
1900 (image->units+1),p);
1906 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
1911 offset=(size_t) ReadProfileLong(endian,p);
1912 if ((offset < length) && (level < (MaxDirectoryStack-2)))
1914 directory_stack[level].directory=directory;
1916 directory_stack[level].entry=entry;
1918 directory_stack[level].directory=exif+offset;
1919 directory_stack[level].entry=0;
1921 if ((directory+2+(12*number_entries)) > (exif+length))
1923 offset=(size_t) ReadProfileLong(endian,directory+2+(12*
1925 if ((offset != 0) && (offset < length) &&
1926 (level < (MaxDirectoryStack-2)))
1928 directory_stack[level].directory=exif+offset;
1929 directory_stack[level].entry=0;
1936 } while (level > 0);