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-2009 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,
142 assert(image != (Image *) NULL);
143 assert(image->signature == MagickSignature);
144 if (image->debug != MagickFalse)
145 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
146 if (image->profiles == (SplayTreeInfo *) NULL)
148 if (LocaleCompare(name,"icc") == 0)
151 Continue to support deprecated color profile for now.
153 image->color_profile.length=0;
154 image->color_profile.info=(unsigned char *) NULL;
156 if (LocaleCompare(name,"iptc") == 0)
159 Continue to support deprecated IPTC profile for now.
161 image->iptc_profile.length=0;
162 image->iptc_profile.info=(unsigned char *) NULL;
164 return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->profiles,name));
168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172 % D e s t r o y I m a g e P r o f i l e s %
176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
178 % DestroyImageProfiles() releases memory associated with an image profile map.
180 % The format of the DestroyProfiles method is:
182 % void DestroyImageProfiles(Image *image)
184 % A description of each parameter follows:
186 % o image: the image.
189 MagickExport void DestroyImageProfiles(Image *image)
191 if (image->profiles != (SplayTreeInfo *) NULL)
192 image->profiles=DestroySplayTree((SplayTreeInfo *) image->profiles);
196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
200 % G e t I m a g e P r o f i l e %
204 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
206 % GetImageProfile() gets a profile associated with an image by name.
208 % The format of the GetImageProfile method is:
210 % const StringInfo *GetImageProfile(const Image *image,const char *name)
212 % A description of each parameter follows:
214 % o image: the image.
216 % o name: the profile name.
219 MagickExport const StringInfo *GetImageProfile(const Image *image,
228 assert(image != (Image *) NULL);
229 assert(image->signature == MagickSignature);
230 if (image->debug != MagickFalse)
231 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
232 if (image->profiles == (SplayTreeInfo *) NULL)
233 return((StringInfo *) NULL);
234 (void) CopyMagickString(key,name,MaxTextExtent);
235 profile=(const StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
236 image->profiles,key);
241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
245 % G e t N e x t I m a g e P r o f i l e %
249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
251 % GetNextImageProfile() gets the next profile name for an image.
253 % The format of the GetNextImageProfile method is:
255 % char *GetNextImageProfile(const Image *image)
257 % A description of each parameter follows:
259 % o hash_info: the hash info.
262 MagickExport char *GetNextImageProfile(const Image *image)
264 assert(image != (Image *) NULL);
265 assert(image->signature == MagickSignature);
266 if (image->debug != MagickFalse)
267 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
268 if (image->profiles == (SplayTreeInfo *) NULL)
269 return((char *) NULL);
270 return((char *) GetNextKeyInSplayTree((SplayTreeInfo *) image->profiles));
274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
278 % P r o f i l e I m a g e %
282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
284 % ProfileImage() associates, applies, or removes an ICM, IPTC, or generic
285 % profile with / to / from an image. If the profile is NULL, it is removed
286 % from the image otherwise added or applied. Use a name of '*' and a profile
287 % of NULL to remove all profiles from the image.
289 % ICC and ICM profiles are handled as follows: If the image does not have
290 % an associated color profile, the one you provide is associated with the
291 % image and the image pixels are not transformed. Otherwise, the colorspace
292 % transform defined by the existing and new profile are applied to the image
293 % pixels and the new profile is associated with the image.
295 % The format of the ProfileImage method is:
297 % MagickBooleanType ProfileImage(Image *image,const char *name,
298 % const void *datum,const size_t length,const MagickBooleanType clone)
300 % A description of each parameter follows:
302 % o image: the image.
304 % o name: Name of profile to add or remove: ICC, IPTC, or generic profile.
306 % o datum: the profile data.
308 % o length: the length of the profile.
310 % o clone: should be MagickFalse.
314 #if defined(MAGICKCORE_LCMS_DELEGATE)
316 static unsigned short **DestroyPixelThreadSet(unsigned short **pixels)
321 assert(pixels != (unsigned short **) NULL);
322 for (i=0; i < (long) GetOpenMPMaximumThreads(); i++)
323 if (pixels[i] != (unsigned short *) NULL)
324 pixels[i]=(unsigned short *) RelinquishMagickMemory(pixels[i]);
325 pixels=(unsigned short **) RelinquishAlignedMemory(pixels);
329 static unsigned short **AcquirePixelThreadSet(const size_t columns,
330 const size_t channels)
341 number_threads=GetOpenMPMaximumThreads();
342 pixels=(unsigned short **) AcquireAlignedMemory(number_threads,
344 if (pixels == (unsigned short **) NULL)
345 return((unsigned short **) NULL);
346 (void) ResetMagickMemory(pixels,0,number_threads*sizeof(*pixels));
347 for (i=0; i < (long) number_threads; i++)
349 pixels[i]=(unsigned short *) AcquireQuantumMemory(columns,channels*
351 if (pixels[i] == (unsigned short *) NULL)
352 return(DestroyPixelThreadSet(pixels));
357 static cmsHTRANSFORM *DestroyTransformThreadSet(cmsHTRANSFORM *transform)
362 assert(transform != (cmsHTRANSFORM *) NULL);
363 for (i=0; i < (long) GetOpenMPMaximumThreads(); i++)
364 if (transform[i] != (cmsHTRANSFORM) NULL)
365 cmsDeleteTransform(transform[i]);
366 transform=(cmsHTRANSFORM *) RelinquishAlignedMemory(transform);
370 static cmsHTRANSFORM *AcquireTransformThreadSet(
371 const cmsHPROFILE source_profile,const DWORD source_type,
372 const cmsHPROFILE target_profile,const DWORD target_type,const int intent,
384 number_threads=GetOpenMPMaximumThreads();
385 transform=(cmsHTRANSFORM *) AcquireAlignedMemory(number_threads,
387 if (transform == (cmsHTRANSFORM *) NULL)
388 return((cmsHTRANSFORM *) NULL);
389 (void) ResetMagickMemory(transform,0,number_threads*sizeof(*transform));
390 for (i=0; i < (long) number_threads; i++)
392 transform[i]=cmsCreateTransform(source_profile,source_type,target_profile,
393 target_type,intent,flags);
394 if (transform[i] == (cmsHTRANSFORM) NULL)
395 return(DestroyTransformThreadSet(transform));
401 static MagickBooleanType SetAdobeRGB1998ImageProfile(Image *image)
404 AdobeRGB1998Profile[] =
406 0x00, 0x00, 0x02, 0x30, 0x41, 0x44, 0x42, 0x45, 0x02, 0x10, 0x00,
407 0x00, 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59,
408 0x5a, 0x20, 0x07, 0xd0, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x13, 0x00,
409 0x33, 0x00, 0x3b, 0x61, 0x63, 0x73, 0x70, 0x41, 0x50, 0x50, 0x4c,
410 0x00, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x00,
411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
412 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00,
413 0x00, 0xd3, 0x2d, 0x41, 0x44, 0x42, 0x45, 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, 0x00,
417 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
418 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
419 0x32, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00,
420 0x00, 0x6b, 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x9c, 0x00,
421 0x00, 0x00, 0x14, 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x01, 0xb0,
422 0x00, 0x00, 0x00, 0x14, 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01,
423 0xc4, 0x00, 0x00, 0x00, 0x0e, 0x67, 0x54, 0x52, 0x43, 0x00, 0x00,
424 0x01, 0xd4, 0x00, 0x00, 0x00, 0x0e, 0x62, 0x54, 0x52, 0x43, 0x00,
425 0x00, 0x01, 0xe4, 0x00, 0x00, 0x00, 0x0e, 0x72, 0x58, 0x59, 0x5a,
426 0x00, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x00, 0x14, 0x67, 0x58, 0x59,
427 0x5a, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x14, 0x62, 0x58,
428 0x59, 0x5a, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x14, 0x74,
429 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x70, 0x79,
430 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x32, 0x30, 0x30, 0x30, 0x20,
431 0x41, 0x64, 0x6f, 0x62, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65,
432 0x6d, 0x73, 0x20, 0x49, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72,
433 0x61, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x41, 0x64, 0x6f,
435 0x62, 0x65, 0x20, 0x52, 0x47, 0x42, 0x20, 0x28, 0x31, 0x39, 0x39,
436 0x38, 0x29, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
443 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00,
444 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00,
445 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447 0x00, 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
448 0x00, 0x01, 0x02, 0x33, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76, 0x00,
449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x33, 0x00, 0x00,
450 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
451 0x01, 0x02, 0x33, 0x00, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00,
452 0x00, 0x00, 0x00, 0x00, 0x9c, 0x18, 0x00, 0x00, 0x4f, 0xa5, 0x00,
453 0x00, 0x04, 0xfc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
454 0x00, 0x00, 0x34, 0x8d, 0x00, 0x00, 0xa0, 0x2c, 0x00, 0x00, 0x0f,
455 0x95, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
456 0x26, 0x31, 0x00, 0x00, 0x10, 0x2f, 0x00, 0x00, 0xbe, 0x9c
465 assert(image != (Image *) NULL);
466 assert(image->signature == MagickSignature);
467 if (GetImageProfile(image,"icm") != (const StringInfo *) NULL)
469 profile=AcquireStringInfo(sizeof(AdobeRGB1998Profile));
470 SetStringInfoDatum(profile,AdobeRGB1998Profile);
471 status=SetImageProfile(image,"icm",profile);
472 profile=DestroyStringInfo(profile);
476 static MagickBooleanType SetsRGBImageProfile(Image *image)
481 0x00, 0x00, 0x0c, 0x48, 0x4c, 0x69, 0x6e, 0x6f, 0x02, 0x10, 0x00,
482 0x00, 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59,
483 0x5a, 0x20, 0x07, 0xce, 0x00, 0x02, 0x00, 0x09, 0x00, 0x06, 0x00,
484 0x31, 0x00, 0x00, 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54,
485 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47,
486 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
487 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00,
488 0x00, 0xd3, 0x2d, 0x48, 0x50, 0x20, 0x20, 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, 0x00,
492 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
493 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00,
494 0x33, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00,
495 0x00, 0x6c, 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0xf0, 0x00,
496 0x00, 0x00, 0x14, 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x02, 0x04,
497 0x00, 0x00, 0x00, 0x14, 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x02,
498 0x18, 0x00, 0x00, 0x00, 0x14, 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00,
499 0x02, 0x2c, 0x00, 0x00, 0x00, 0x14, 0x62, 0x58, 0x59, 0x5a, 0x00,
500 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x14, 0x64, 0x6d, 0x6e, 0x64,
501 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70, 0x64, 0x6d, 0x64,
502 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88, 0x76, 0x75,
503 0x65, 0x64, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x86, 0x76,
504 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xd4, 0x00, 0x00, 0x00, 0x24,
505 0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00,
506 0x14, 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x04, 0x0c, 0x00, 0x00,
507 0x00, 0x24, 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x04, 0x30, 0x00,
508 0x00, 0x00, 0x0c, 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x3c,
509 0x00, 0x00, 0x08, 0x0c, 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04,
510 0x3c, 0x00, 0x00, 0x08, 0x0c, 0x62, 0x54, 0x52, 0x43, 0x00, 0x00,
511 0x04, 0x3c, 0x00, 0x00, 0x08, 0x0c, 0x74, 0x65, 0x78, 0x74, 0x00,
512 0x00, 0x00, 0x00, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
513 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, 0x39, 0x38, 0x20,
514 0x48, 0x65, 0x77, 0x6c, 0x65, 0x74, 0x74, 0x2d, 0x50, 0x61, 0x63,
515 0x6b, 0x61, 0x72, 0x64, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e,
516 0x79, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
517 0x00, 0x00, 0x00, 0x12, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45,
518 0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00,
519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
520 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39,
521 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
527 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xcc, 0x58,
528 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5a,
530 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa2, 0x00, 0x00,
531 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20, 0x00,
532 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x99, 0x00, 0x00, 0xb7, 0x85,
533 0x00, 0x00, 0x18, 0xda, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00,
534 0x00, 0x00, 0x00, 0x24, 0xa0, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00,
535 0xb6, 0xcf, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00,
536 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74, 0x70,
537 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
538 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74, 0x70,
540 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
541 0x63, 0x68, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00,
546 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43, 0x20, 0x36, 0x31,
547 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44, 0x65, 0x66,
548 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63, 0x6f,
549 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
550 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00,
551 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43, 0x20,
552 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
553 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20,
554 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63,
555 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73,
558 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x52, 0x65,
559 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65,
560 0x77, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74,
561 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 0x43, 0x36,
562 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x52, 0x65,
564 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65,
565 0x77, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74,
566 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 0x43, 0x36,
567 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570 0x00, 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
571 0xa4, 0xfe, 0x00, 0x14, 0x5f, 0x2e, 0x00, 0x10, 0xcf, 0x14, 0x00,
572 0x03, 0xed, 0xcc, 0x00, 0x04, 0x13, 0x0b, 0x00, 0x03, 0x5c, 0x9e,
573 0x00, 0x00, 0x00, 0x01, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00,
574 0x00, 0x00, 0x4c, 0x09, 0x56, 0x00, 0x50, 0x00, 0x00, 0x00, 0x57,
575 0x1f, 0xe7, 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
578 0x8f, 0x00, 0x00, 0x00, 0x02, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00,
579 0x00, 0x00, 0x43, 0x52, 0x54, 0x20, 0x63, 0x75, 0x72, 0x76, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x05,
581 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19, 0x00, 0x1e, 0x00,
582 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37, 0x00, 0x3b,
583 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54, 0x00,
584 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
585 0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00,
586 0x90, 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9,
587 0x00, 0xae, 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00,
588 0xc6, 0x00, 0xcb, 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0,
589 0x00, 0xe5, 0x00, 0xeb, 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01,
590 0x01, 0x01, 0x07, 0x01, 0x0d, 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f,
591 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32, 0x01, 0x38, 0x01, 0x3e, 0x01,
592 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59, 0x01, 0x60, 0x01, 0x67,
593 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83, 0x01, 0x8b, 0x01,
594 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1, 0x01, 0xb9,
595 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1, 0x01,
596 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
597 0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02,
598 0x4b, 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a,
599 0x02, 0x84, 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02,
600 0xb6, 0x02, 0xc1, 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb,
601 0x02, 0xf5, 0x03, 0x00, 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03,
602 0x2d, 0x03, 0x38, 0x03, 0x43, 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66,
603 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a, 0x03, 0x96, 0x03, 0xa2, 0x03,
604 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3, 0x03, 0xe0, 0x03, 0xec,
605 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20, 0x04, 0x2d, 0x04,
606 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71, 0x04, 0x7e,
607 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4, 0x04,
608 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
609 0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05,
610 0x77, 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5,
611 0x05, 0xd5, 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06,
612 0x27, 0x06, 0x37, 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b,
613 0x06, 0x8c, 0x06, 0x9d, 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06,
614 0xe3, 0x06, 0xf5, 0x07, 0x07, 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d,
615 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74, 0x07, 0x86, 0x07, 0x99, 0x07,
616 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5, 0x07, 0xf8, 0x08, 0x0b,
617 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a, 0x08, 0x6e, 0x08,
618 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2, 0x08, 0xe7,
619 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f, 0x09,
620 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
621 0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a,
622 0x54, 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5,
623 0x0a, 0xdc, 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b,
624 0x51, 0x0b, 0x69, 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8,
625 0x0b, 0xe1, 0x0b, 0xf9, 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c,
626 0x5c, 0x0c, 0x75, 0x0c, 0x8e, 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9,
627 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26, 0x0d, 0x40, 0x0d, 0x5a, 0x0d,
628 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3, 0x0d, 0xde, 0x0d, 0xf8,
629 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64, 0x0e, 0x7f, 0x0e,
630 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09, 0x0f, 0x25,
631 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3, 0x0f,
632 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
633 0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11,
634 0x13, 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa,
635 0x11, 0xc9, 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12,
636 0x64, 0x12, 0x84, 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03,
637 0x13, 0x23, 0x13, 0x43, 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13,
638 0xc5, 0x13, 0xe5, 0x14, 0x06, 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a,
639 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce, 0x14, 0xf0, 0x15, 0x12, 0x15,
640 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b, 0x15, 0xbd, 0x15, 0xe0,
641 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c, 0x16, 0x8f, 0x16,
642 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41, 0x17, 0x65,
643 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b, 0x18,
644 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
645 0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19,
646 0xdd, 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e,
647 0x1a, 0xc5, 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b,
648 0x8a, 0x1b, 0xb2, 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52,
649 0x1c, 0x7b, 0x1c, 0xa3, 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d,
650 0x47, 0x1d, 0x70, 0x1d, 0x99, 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16,
651 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94, 0x1e, 0xbe, 0x1e, 0xe9, 0x1f,
652 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94, 0x1f, 0xbf, 0x1f, 0xea,
653 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98, 0x20, 0xc4, 0x20,
654 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1, 0x21, 0xce,
655 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf, 0x22,
656 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
657 0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24,
658 0xda, 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7,
659 0x25, 0xf7, 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26,
660 0xe8, 0x27, 0x18, 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc,
661 0x28, 0x0d, 0x28, 0x3f, 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29,
662 0x06, 0x29, 0x38, 0x29, 0x6b, 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02,
663 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b, 0x2a, 0xcf, 0x2b, 0x02, 0x2b,
664 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1, 0x2c, 0x05, 0x2c, 0x39,
665 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c, 0x2d, 0x41, 0x2d,
666 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c, 0x2e, 0x82,
667 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91, 0x2f,
668 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
669 0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32,
670 0x2a, 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46,
671 0x33, 0x7f, 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34,
672 0x9e, 0x34, 0xd8, 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2,
673 0x35, 0xfd, 0x36, 0x37, 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37,
674 0x24, 0x37, 0x60, 0x37, 0x9c, 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50,
675 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05, 0x39, 0x42, 0x39, 0x7f, 0x39,
676 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74, 0x3a, 0xb2, 0x3a, 0xef,
677 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8, 0x3c, 0x27, 0x3c,
678 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61, 0x3d, 0xa1,
679 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0, 0x3f,
680 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
681 0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41,
682 0xee, 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a,
683 0x43, 0x7d, 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44,
684 0xce, 0x45, 0x12, 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22,
685 0x46, 0x67, 0x46, 0xab, 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47,
686 0xc0, 0x48, 0x05, 0x48, 0x4b, 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d,
687 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0, 0x4a, 0x37, 0x4a, 0x7d, 0x4a,
688 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a, 0x4b, 0xe2, 0x4c, 0x2a,
689 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a, 0x4d, 0x93, 0x4d,
690 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00, 0x4f, 0x49,
691 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb, 0x51,
692 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
693 0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54,
694 0x42, 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2,
695 0x56, 0x0f, 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57,
696 0x92, 0x57, 0xe0, 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a,
697 0x59, 0x69, 0x59, 0xb8, 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a,
698 0xf5, 0x5b, 0x45, 0x5b, 0x95, 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86,
699 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78, 0x5d, 0xc9, 0x5e, 0x1a, 0x5e,
700 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61, 0x5f, 0xb3, 0x60, 0x05,
701 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f, 0x61, 0xa2, 0x61,
702 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43, 0x63, 0x97,
703 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d, 0x65,
704 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
705 0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69,
706 0x43, 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7,
707 0x6b, 0x4f, 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d,
708 0x08, 0x6d, 0x60, 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4,
709 0x6f, 0x1e, 0x6f, 0x78, 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70,
710 0xe0, 0x71, 0x3a, 0x71, 0x95, 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6,
711 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8, 0x74, 0x14, 0x74, 0x70, 0x74,
712 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1, 0x76, 0x3e, 0x76, 0x9b,
713 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11, 0x78, 0x6e, 0x78,
714 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46, 0x7a, 0xa5,
715 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81, 0x7c,
716 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
717 0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81,
718 0x0a, 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4,
719 0x83, 0x57, 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85,
720 0x47, 0x85, 0xab, 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b,
721 0x87, 0x9f, 0x88, 0x04, 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89,
722 0x99, 0x89, 0xfe, 0x8a, 0x64, 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96,
723 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca, 0x8d, 0x31, 0x8d, 0x98, 0x8d,
724 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36, 0x8f, 0x9e, 0x90, 0x06,
725 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8, 0x92, 0x11, 0x92,
726 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20, 0x94, 0x8a,
727 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f, 0x97,
728 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
729 0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b,
730 0xaf, 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2,
731 0x9e, 0x40, 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0,
732 0x69, 0xa0, 0xd8, 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96,
733 0xa3, 0x06, 0xa3, 0x76, 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5,
734 0x38, 0xa5, 0xa9, 0xa6, 0x1a, 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e,
735 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4, 0xa9, 0x37, 0xa9, 0xa9, 0xaa,
736 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75, 0xab, 0xe9, 0xac, 0x5c,
737 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d, 0xae, 0xa1, 0xaf,
738 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea, 0xb1, 0x60,
739 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae, 0xb4,
740 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
741 0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9,
742 0x4a, 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7,
743 0xbc, 0x21, 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe,
744 0x84, 0xbe, 0xff, 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec,
745 0xc1, 0x67, 0xc1, 0xe3, 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3,
746 0xd4, 0xc4, 0x51, 0xc4, 0xce, 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46,
747 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf, 0xc8, 0x3d, 0xc8, 0xbc, 0xc9,
748 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7, 0xcb, 0x36, 0xcb, 0xb6,
749 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5, 0xce, 0x36, 0xce,
750 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba, 0xd1, 0x3c,
751 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6, 0xd4,
752 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
753 0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9,
754 0xf1, 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a,
755 0xdd, 0x10, 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf,
756 0xaf, 0xe0, 0x36, 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53,
757 0xe2, 0xdb, 0xe3, 0x63, 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5,
758 0x84, 0xe6, 0x0d, 0xe6, 0x96, 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32,
759 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0, 0xea, 0x5b, 0xea, 0xe5, 0xeb,
760 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11, 0xed, 0x9c, 0xee, 0x28,
761 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58, 0xf0, 0xe5, 0xf1,
762 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7, 0xf4, 0x34,
763 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb, 0xf7,
764 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
765 0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd,
766 0xba, 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
775 assert(image != (Image *) NULL);
776 assert(image->signature == MagickSignature);
777 if (GetImageProfile(image,"icm") != (const StringInfo *) NULL)
779 profile=AcquireStringInfo(sizeof(sRGBProfile));
780 SetStringInfoDatum(profile,sRGBProfile);
781 status=SetImageProfile(image,"icm",profile);
782 profile=DestroyStringInfo(profile);
785 #if defined(MAGICKCORE_LCMS_DELEGATE)
786 #if defined(LCMS_VERSION) && (LCMS_VERSION > 1010)
787 static int LCMSErrorHandler(int severity,const char *message)
789 (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%d, %s",
790 severity,message != (char *) NULL ? message : "no message");
796 MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
797 const void *datum,const size_t length,
798 const MagickBooleanType magick_unused(clone))
800 #define ProfileImageTag "Profile/Image"
801 #define ThrowProfileException(severity,tag,context) \
803 (void) cmsCloseProfile(source_profile); \
804 (void) cmsCloseProfile(target_profile); \
805 ThrowBinaryException(severity,tag,context); \
814 assert(image != (Image *) NULL);
815 assert(image->signature == MagickSignature);
816 if (image->debug != MagickFalse)
817 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
818 assert(name != (const char *) NULL);
819 if ((datum == (const void *) NULL) || (length == 0))
832 Delete image profile(s).
834 names=ConstantString(name);
835 (void) SubstituteString(&names,","," ");
836 arguments=StringToArgv(names,&number_arguments);
837 names=DestroyString(names);
838 if (arguments == (char **) NULL)
840 ResetImageProfileIterator(image);
841 for (name=GetNextImageProfile(image); name != (const char *) NULL; )
843 for (i=1; i < number_arguments; i++)
845 if ((*arguments[i] == '!') &&
846 (LocaleCompare(name,arguments[i]+1) == 0))
848 if (GlobExpression(name,arguments[i],MagickTrue) != MagickFalse)
850 (void) DeleteImageProfile(image,name);
851 ResetImageProfileIterator(image);
855 name=GetNextImageProfile(image);
857 for (i=0; i < number_arguments; i++)
858 arguments[i]=DestroyString(arguments[i]);
859 arguments=(char **) RelinquishMagickMemory(arguments);
863 Add a ICC, IPTC, or generic profile to the image.
865 profile=AcquireStringInfo((size_t) length);
866 SetStringInfoDatum(profile,(unsigned char *) datum);
867 if ((LocaleCompare(name,"icc") == 0) || (LocaleCompare(name,"icm") == 0))
872 icc_profile=GetImageProfile(image,"icc");
873 if ((icc_profile != (const StringInfo *) NULL) &&
874 (CompareStringInfo(icc_profile,profile) == 0))
879 value=GetImageProperty(image,"exif:ColorSpace");
880 if (LocaleCompare(value,"1") != 0)
881 (void) SetsRGBImageProfile(image);
882 value=GetImageProperty(image,"exif:InteroperabilityIndex");
883 if (LocaleCompare(value,"R98.") != 0)
884 (void) SetsRGBImageProfile(image);
885 value=GetImageProperty(image,"exif:InteroperabilityIndex");
886 if (LocaleCompare(value,"R03.") != 0)
887 (void) SetAdobeRGB1998ImageProfile(image);
888 icc_profile=GetImageProfile(image,"icc");
890 if ((icc_profile != (const StringInfo *) NULL) &&
891 (CompareStringInfo(icc_profile,profile) == 0))
893 profile=DestroyStringInfo(profile);
896 #if !defined(MAGICKCORE_LCMS_DELEGATE)
897 (void) ThrowMagickException(&image->exception,GetMagickModule(),
898 MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn","`%s' (LCMS)",
901 if (icc_profile == (StringInfo *) NULL)
902 (void) ThrowMagickException(&image->exception,GetMagickModule(),
903 ImageWarning,"AssociateProfile","`%s'",name);
948 Transform pixel colors as defined by the color profiles.
950 #if defined(LCMS_VERSION) && (LCMS_VERSION > 1010)
951 cmsSetErrorHandler(LCMSErrorHandler);
953 (void) cmsErrorAction(LCMS_ERROR_SHOW);
955 source_profile=cmsOpenProfileFromMem(GetStringInfoDatum(icc_profile),
956 (DWORD) GetStringInfoLength(icc_profile));
957 target_profile=cmsOpenProfileFromMem(GetStringInfoDatum(profile),
958 (DWORD) GetStringInfoLength(profile));
959 if ((source_profile == (cmsHPROFILE) NULL) ||
960 (target_profile == (cmsHPROFILE) NULL))
961 ThrowBinaryException(ResourceLimitError,
962 "ColorspaceColorProfileMismatch",name);
963 switch (cmsGetColorSpace(source_profile))
967 source_colorspace=CMYKColorspace;
968 source_type=(DWORD) TYPE_CMYK_16;
974 source_colorspace=GRAYColorspace;
975 source_type=(DWORD) TYPE_GRAY_16;
981 source_colorspace=LabColorspace;
982 source_type=(DWORD) TYPE_Lab_16;
988 source_colorspace=YUVColorspace;
989 source_type=(DWORD) TYPE_YUV_16;
995 source_colorspace=RGBColorspace;
996 source_type=(DWORD) TYPE_RGB_16;
1002 source_colorspace=XYZColorspace;
1003 source_type=(DWORD) TYPE_XYZ_16;
1007 case icSigYCbCrData:
1009 source_colorspace=YCbCrColorspace;
1010 source_type=(DWORD) TYPE_YCbCr_16;
1016 source_colorspace=UndefinedColorspace;
1017 source_type=(DWORD) TYPE_RGB_16;
1022 switch (cmsGetColorSpace(target_profile))
1026 target_colorspace=CMYKColorspace;
1027 target_type=(DWORD) TYPE_CMYK_16;
1033 target_colorspace=LabColorspace;
1034 target_type=(DWORD) TYPE_Lab_16;
1040 target_colorspace=GRAYColorspace;
1041 target_type=(DWORD) TYPE_GRAY_16;
1047 target_colorspace=YUVColorspace;
1048 target_type=(DWORD) TYPE_YUV_16;
1054 target_colorspace=RGBColorspace;
1055 target_type=(DWORD) TYPE_RGB_16;
1061 target_colorspace=XYZColorspace;
1062 target_type=(DWORD) TYPE_XYZ_16;
1066 case icSigYCbCrData:
1068 target_colorspace=YCbCrColorspace;
1069 target_type=(DWORD) TYPE_YCbCr_16;
1075 target_colorspace=UndefinedColorspace;
1076 target_type=(DWORD) TYPE_RGB_16;
1081 exception=(&image->exception);
1082 if ((source_colorspace == UndefinedColorspace) ||
1083 (target_colorspace == UndefinedColorspace))
1084 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1086 if ((source_colorspace == GRAYColorspace) &&
1087 (IsGrayImage(image,exception) == MagickFalse))
1088 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1090 if ((source_colorspace == CMYKColorspace) &&
1091 (image->colorspace != CMYKColorspace))
1092 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1094 if ((source_colorspace == XYZColorspace) &&
1095 (image->colorspace != XYZColorspace))
1096 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1098 if ((source_colorspace == YCbCrColorspace) &&
1099 (image->colorspace != YCbCrColorspace))
1100 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1102 if ((source_colorspace != CMYKColorspace) &&
1103 (source_colorspace != GRAYColorspace) &&
1104 (source_colorspace != LabColorspace) &&
1105 (source_colorspace != XYZColorspace) &&
1106 (source_colorspace != YCbCrColorspace) &&
1107 (image->colorspace != RGBColorspace))
1108 ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
1110 switch (image->rendering_intent)
1112 case AbsoluteIntent: intent=INTENT_ABSOLUTE_COLORIMETRIC; break;
1113 case PerceptualIntent: intent=INTENT_PERCEPTUAL; break;
1114 case RelativeIntent: intent=INTENT_RELATIVE_COLORIMETRIC; break;
1115 case SaturationIntent: intent=INTENT_SATURATION; break;
1116 default: intent=INTENT_PERCEPTUAL; break;
1118 flags=cmsFLAGS_HIGHRESPRECALC;
1119 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1120 if (image->black_point_compensation != MagickFalse)
1121 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1123 transform=AcquireTransformThreadSet(source_profile,source_type,
1124 target_profile,target_type,intent,flags);
1125 (void) cmsCloseProfile(source_profile);
1126 if (transform == (cmsHTRANSFORM *) NULL)
1127 ThrowBinaryException(ImageError,"UnableToCreateColorTransform",
1130 Transform image as dictated by the source and target image profiles.
1132 length=(size_t) image->columns;
1133 source_pixels=AcquirePixelThreadSet(image->columns,source_channels);
1134 target_pixels=AcquirePixelThreadSet(image->columns,target_channels);
1135 if ((source_pixels == (unsigned short **) NULL) ||
1136 (target_pixels == (unsigned short **) NULL))
1138 transform=DestroyTransformThreadSet(transform);
1139 (void) cmsCloseProfile(target_profile);
1140 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1143 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1145 target_pixels=DestroyPixelThreadSet(target_pixels);
1146 source_pixels=DestroyPixelThreadSet(source_pixels);
1147 transform=DestroyTransformThreadSet(transform);
1148 (void) cmsCloseProfile(target_profile);
1149 return(MagickFalse);
1151 if (target_colorspace == CMYKColorspace)
1152 (void) SetImageColorspace(image,target_colorspace);
1155 image_view=AcquireCacheView(image);
1156 #if defined(_OPENMP) && (_OPENMP >= 200203)
1157 #pragma omp parallel for schedule(static,1) shared(status)
1159 for (y=0; y < (long) image->rows; y++)
1164 register IndexPacket
1165 *__restrict indexes;
1171 register PixelPacket
1174 register unsigned short
1177 if (status == MagickFalse)
1179 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1181 if (q == (PixelPacket *) NULL)
1186 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1187 id=GetOpenMPThreadId();
1188 p=source_pixels[id];
1189 for (x=0; x < (long) image->columns; x++)
1191 *p++=ScaleQuantumToShort(q->red);
1192 if (source_channels > 1)
1194 *p++=ScaleQuantumToShort(q->green);
1195 *p++=ScaleQuantumToShort(q->blue);
1197 if (source_channels > 3)
1198 *p++=ScaleQuantumToShort(indexes[x]);
1201 cmsDoTransform(transform[id],source_pixels[id],target_pixels[id],
1202 (unsigned int) image->columns);
1203 p=target_pixels[id];
1205 for (x=0; x < (long) image->columns; x++)
1207 q->red=ScaleShortToQuantum(*p);
1211 if (target_channels > 1)
1213 q->green=ScaleShortToQuantum(*p);
1215 q->blue=ScaleShortToQuantum(*p);
1218 if (target_channels > 3)
1220 indexes[x]=ScaleShortToQuantum(*p);
1225 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1226 if (sync == MagickFalse)
1228 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1233 #if defined(_OPENMP) && (_OPENMP >= 200203)
1234 #pragma omp critical (MagickCore_ProfileImage)
1236 proceed=SetImageProgress(image,ProfileImageTag,progress++,
1238 if (proceed == MagickFalse)
1242 image_view=DestroyCacheView(image_view);
1243 (void) SetImageColorspace(image,target_colorspace);
1244 switch (cmsGetColorSpace(target_profile))
1248 image->type=image->matte == MagickFalse ? TrueColorType :
1254 image->type=image->matte == MagickFalse ? ColorSeparationType :
1255 ColorSeparationMatteType;
1260 image->type=image->matte == MagickFalse ? GrayscaleType :
1267 target_pixels=DestroyPixelThreadSet(target_pixels);
1268 source_pixels=DestroyPixelThreadSet(source_pixels);
1269 transform=DestroyTransformThreadSet(transform);
1270 (void) cmsCloseProfile(target_profile);
1274 status=SetImageProfile(image,name,profile);
1275 profile=DestroyStringInfo(profile);
1280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1284 % R e m o v e I m a g e P r o f i l e %
1288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1290 % RemoveImageProfile() removes a named profile from the image and returns its
1293 % The format of the RemoveImageProfile method is:
1295 % void *RemoveImageProfile(Image *image,const char *name)
1297 % A description of each parameter follows:
1299 % o image: the image.
1301 % o name: the profile name.
1304 MagickExport StringInfo *RemoveImageProfile(Image *image,const char *name)
1309 assert(image != (Image *) NULL);
1310 assert(image->signature == MagickSignature);
1311 if (image->debug != MagickFalse)
1312 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1313 if (image->profiles == (SplayTreeInfo *) NULL)
1314 return((StringInfo *) NULL);
1315 if (LocaleCompare(name,"icc") == 0)
1318 Continue to support deprecated color profile for now.
1320 image->color_profile.length=0;
1321 image->color_profile.info=(unsigned char *) NULL;
1323 if (LocaleCompare(name,"iptc") == 0)
1326 Continue to support deprecated IPTC profile for now.
1328 image->iptc_profile.length=0;
1329 image->iptc_profile.info=(unsigned char *) NULL;
1331 profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
1332 image->profiles,name);
1337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1341 % R e s e t P r o f i l e I t e r a t o r %
1345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1347 % ResetImageProfileIterator() resets the image profile iterator. Use it in
1348 % conjunction with GetNextImageProfile() to iterate over all the profiles
1349 % associated with an image.
1351 % The format of the ResetImageProfileIterator method is:
1353 % ResetImageProfileIterator(Image *image)
1355 % A description of each parameter follows:
1357 % o image: the image.
1360 MagickExport void ResetImageProfileIterator(const Image *image)
1362 assert(image != (Image *) NULL);
1363 assert(image->signature == MagickSignature);
1364 if (image->debug != MagickFalse)
1365 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1366 if (image->profiles == (SplayTreeInfo *) NULL)
1368 ResetSplayTreeIterator((SplayTreeInfo *) image->profiles);
1372 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1376 % S e t I m a g e P r o f i l e %
1380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1382 % SetImageProfile() adds a named profile to the image. If a profile with the
1383 % same name already exists, it is replaced. This method differs from the
1384 % ProfileImage() method in that it does not apply CMS color profiles.
1386 % The format of the SetImageProfile method is:
1388 % MagickBooleanType SetImageProfile(Image *image,const char *name,
1389 % const StringInfo *profile)
1391 % A description of each parameter follows:
1393 % o image: the image.
1395 % o name: the profile name, for example icc, exif, and 8bim (8bim is the
1396 % Photoshop wrapper for iptc profiles).
1398 % o profile: A StringInfo structure that contains the named profile.
1402 static void *DestroyProfile(void *profile)
1404 return((void *) DestroyStringInfo((StringInfo *) profile));
1407 static inline const unsigned char *ReadResourceByte(const unsigned char *p,
1408 unsigned char *quantum)
1414 static inline const unsigned char *ReadResourceBytes(const unsigned char *p,
1415 const ssize_t count,unsigned char *quantum)
1420 for (i=0; i < count; i++)
1425 static inline const unsigned char *ReadResourceLong(const unsigned char *p,
1426 unsigned long *quantum)
1428 *quantum=(unsigned long) (*p++ << 24);
1429 *quantum|=(unsigned long) (*p++ << 16);
1430 *quantum|=(unsigned long) (*p++ << 8);
1431 *quantum|=(unsigned long) (*p++ << 0);
1435 static inline const unsigned char *ReadResourceShort(const unsigned char *p,
1436 unsigned short *quantum)
1438 *quantum=(unsigned short) (*p++ << 8);
1439 *quantum|=(unsigned short) (*p++ << 0);
1443 static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
1444 const StringInfo *resource_block)
1449 register const unsigned char
1467 datum=GetStringInfoDatum(resource_block);
1468 length=GetStringInfoLength(resource_block);
1469 for (p=datum; p < (datum+length-16); )
1471 if (LocaleNCompare((char *) p,"8BIM",4) != 0)
1474 p=ReadResourceShort(p,&id);
1475 p=ReadResourceByte(p,&length_byte);
1477 if (((length_byte+1) & 0x01) != 0)
1479 if (p > (datum+length-4))
1481 p=ReadResourceLong(p,&count);
1482 if ((p > (datum+length-count)) || (count > length))
1494 p=ReadResourceShort(p,&resolution)+6;
1495 image->x_resolution=(double) resolution;
1496 p=ReadResourceShort(p,&resolution)+6;
1497 image->y_resolution=(double) resolution;
1505 profile=AcquireStringInfo(count);
1506 SetStringInfoDatum(profile,p);
1507 (void) SetImageProfile(image,"iptc",profile);
1508 profile=DestroyStringInfo(profile);
1525 profile=AcquireStringInfo(count);
1526 SetStringInfoDatum(profile,p);
1527 (void) SetImageProfile(image,"icc",profile);
1528 profile=DestroyStringInfo(profile);
1537 profile=AcquireStringInfo(count);
1538 SetStringInfoDatum(profile,p);
1539 (void) SetImageProfile(image,"exif",profile);
1540 profile=DestroyStringInfo(profile);
1549 profile=AcquireStringInfo(count);
1550 SetStringInfoDatum(profile,p);
1551 (void) SetImageProfile(image,"xmp",profile);
1552 profile=DestroyStringInfo(profile);
1562 if ((count & 0x01) != 0)
1568 MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name,
1569 const StringInfo *profile)
1573 property[MaxTextExtent];
1578 assert(image != (Image *) NULL);
1579 assert(image->signature == MagickSignature);
1580 if (image->debug != MagickFalse)
1581 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1582 if (image->profiles == (SplayTreeInfo *) NULL)
1583 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
1585 (void) CopyMagickString(key,name,MaxTextExtent);
1586 status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1587 ConstantString(key),CloneStringInfo(profile));
1588 if ((status != MagickFalse) &&
1589 ((LocaleCompare(name,"icc") == 0) || (LocaleCompare(name,"icm") == 0)))
1595 Continue to support deprecated color profile member.
1597 icc_profile=GetImageProfile(image,name);
1598 if (icc_profile != (const StringInfo *) NULL)
1600 image->color_profile.length=GetStringInfoLength(icc_profile);
1601 image->color_profile.info=GetStringInfoDatum(icc_profile);
1604 if ((status != MagickFalse) &&
1605 ((LocaleCompare(name,"iptc") == 0) || (LocaleCompare(name,"8bim") == 0)))
1611 Continue to support deprecated IPTC profile member.
1613 iptc_profile=GetImageProfile(image,name);
1614 if (iptc_profile != (const StringInfo *) NULL)
1616 image->iptc_profile.length=GetStringInfoLength(iptc_profile);
1617 image->iptc_profile.info=GetStringInfoDatum(iptc_profile);
1619 (void) GetProfilesFromResourceBlock(image,profile);
1622 Inject profile into image properties.
1624 (void) FormatMagickString(property,MaxTextExtent,"%s:sans",name);
1625 (void) GetImageProperty(image,property);
1630 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1634 % S y n c I m a g e P r o f i l e s %
1638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1640 % SyncImageProfiles() synchronizes image properties with the image profiles.
1641 % Currently we only support updating the EXIF resolution and orientation.
1643 % The format of the SyncImageProfiles method is:
1645 % MagickBooleanType SyncImageProfiles(Image *image)
1647 % A description of each parameter follows:
1649 % o image: the image.
1653 static inline int ReadProfileByte(unsigned char **p,size_t *length)
1665 static inline unsigned short ReadProfileShort(const EndianType endian,
1666 unsigned char *buffer)
1671 if (endian == MSBEndian)
1673 value=(unsigned short) ((((unsigned char *) buffer)[0] << 8) |
1674 ((unsigned char *) buffer)[1]);
1675 return((unsigned short) (value & 0xffff));
1677 value=(unsigned short) ((buffer[1] << 8) | buffer[0]);
1678 return((unsigned short) (value & 0xffff));
1681 static inline unsigned long ReadProfileLong(const EndianType endian,
1682 unsigned char *buffer)
1687 if (endian == MSBEndian)
1689 value=(unsigned long) ((buffer[0] << 24) | (buffer[1] << 16) |
1690 (buffer[2] << 8) | buffer[3]);
1691 return((unsigned long) (value & 0xffffffff));
1693 value=(unsigned long) ((buffer[3] << 24) | (buffer[2] << 16) |
1694 (buffer[1] << 8 ) | (buffer[0]));
1695 return((unsigned long) (value & 0xffffffff));
1698 static inline void WriteProfileLong(const EndianType endian,
1699 const unsigned long value,unsigned char *p)
1704 if (endian == MSBEndian)
1706 buffer[0]=(unsigned char) (value >> 24);
1707 buffer[1]=(unsigned char) (value >> 16);
1708 buffer[2]=(unsigned char) (value >> 8);
1709 buffer[3]=(unsigned char) value;
1710 (void) CopyMagickMemory(p,buffer,4);
1713 buffer[0]=(unsigned char) value;
1714 buffer[1]=(unsigned char) (value >> 8);
1715 buffer[2]=(unsigned char) (value >> 16);
1716 buffer[3]=(unsigned char) (value >> 24);
1717 (void) CopyMagickMemory(p,buffer,4);
1720 static void WriteProfileShort(const EndianType endian,
1721 const unsigned short value,unsigned char *p)
1726 if (endian == MSBEndian)
1728 buffer[0]=(unsigned char) (value >> 8);
1729 buffer[1]=(unsigned char) value;
1730 (void) CopyMagickMemory(p,buffer,2);
1733 buffer[0]=(unsigned char) value;
1734 buffer[1]=(unsigned char) (value >> 8);
1735 (void) CopyMagickMemory(p,buffer,2);
1738 MagickExport MagickBooleanType SyncImageProfiles(Image *image)
1740 #define MaxDirectoryStack 16
1741 #define EXIF_DELIMITER "\n"
1742 #define EXIF_NUM_FORMATS 12
1743 #define TAG_EXIF_OFFSET 0x8769
1744 #define TAG_INTEROP_OFFSET 0xa005
1746 typedef struct _DirectoryInfo
1756 directory_stack[MaxDirectoryStack];
1772 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
1786 Set EXIF resolution tag.
1788 profile=(StringInfo *) GetImageProfile(image,"EXIF");
1789 if (profile == (StringInfo *) NULL)
1791 length=GetStringInfoLength(profile);
1792 exif=GetStringInfoDatum(profile);
1795 if (ReadProfileByte(&exif,&length) != 0x45)
1797 if (ReadProfileByte(&exif,&length) != 0x78)
1799 if (ReadProfileByte(&exif,&length) != 0x69)
1801 if (ReadProfileByte(&exif,&length) != 0x66)
1803 if (ReadProfileByte(&exif,&length) != 0x00)
1805 if (ReadProfileByte(&exif,&length) != 0x00)
1810 return(MagickFalse);
1811 id=(int) ReadProfileShort(LSBEndian,exif);
1819 return(MagickFalse);
1820 if (ReadProfileShort(endian,exif+2) != 0x002a)
1821 return(MagickFalse);
1823 This the offset to the first IFD.
1825 offset=(ssize_t) ReadProfileLong(endian,exif+4);
1826 if ((size_t) offset >= length)
1827 return(MagickFalse);
1828 directory=exif+offset;
1836 directory=directory_stack[level].directory;
1837 entry=directory_stack[level].entry;
1840 Determine how many entries there are in the current IFD.
1842 number_entries=ReadProfileShort(endian,directory);
1843 for ( ; entry < number_entries; entry++)
1850 register unsigned char
1857 q=(unsigned char *) (directory+2+(12*entry));
1858 tag_value=(long) ReadProfileShort(endian,q);
1859 format=(long) ReadProfileShort(endian,q+2);
1860 if ((format-1) >= EXIF_NUM_FORMATS)
1862 components=(long) ReadProfileLong(endian,q+4);
1863 number_bytes=(size_t) components*format_bytes[format];
1864 if (number_bytes <= 4)
1872 The directory entry contains an offset.
1874 offset=(ssize_t) ReadProfileLong(endian,q+8);
1875 if ((size_t) (offset+number_bytes) > length)
1877 p=(unsigned char *) (exif+offset);
1883 (void) WriteProfileLong(endian,(unsigned long)
1884 (image->x_resolution+0.5),p);
1885 (void) WriteProfileLong(endian,1UL,p+4);
1890 (void) WriteProfileLong(endian,(unsigned long)
1891 (image->y_resolution+0.5),p);
1892 (void) WriteProfileLong(endian,1UL,p+4);
1897 (void) WriteProfileShort(endian,(unsigned short)
1898 image->orientation,p);
1903 (void) WriteProfileShort(endian,(unsigned short)
1904 (image->units+1),p);
1910 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
1915 offset=(size_t) ReadProfileLong(endian,p);
1916 if ((offset < length) && (level < (MaxDirectoryStack-2)))
1918 directory_stack[level].directory=directory;
1920 directory_stack[level].entry=entry;
1922 directory_stack[level].directory=exif+offset;
1923 directory_stack[level].entry=0;
1925 if ((directory+2+(12*number_entries)) > (exif+length))
1927 offset=(size_t) ReadProfileLong(endian,directory+2+(12*
1929 if ((offset != 0) && (offset < length) &&
1930 (level < (MaxDirectoryStack-2)))
1932 directory_stack[level].directory=exif+offset;
1933 directory_stack[level].entry=0;
1940 } while (level > 0);