42 #include "magick/studio.h"
43 #include "magick/attribute.h"
44 #include "magick/cache.h"
45 #include "magick/color.h"
46 #include "magick/colorspace-private.h"
47 #include "magick/configure.h"
48 #include "magick/exception.h"
49 #include "magick/exception-private.h"
50 #include "magick/hashmap.h"
51 #include "magick/image.h"
52 #include "magick/memory_.h"
53 #include "magick/monitor.h"
54 #include "magick/monitor-private.h"
55 #include "magick/option.h"
56 #include "magick/option-private.h"
57 #include "magick/profile.h"
58 #include "magick/property.h"
59 #include "magick/quantum.h"
60 #include "magick/quantum-private.h"
61 #include "magick/resource_.h"
62 #include "magick/splay-tree.h"
63 #include "magick/string_.h"
64 #include "magick/string-private.h"
65 #include "magick/thread-private.h"
66 #include "magick/token.h"
67 #include "magick/utility.h"
68 #if defined(MAGICKCORE_LCMS_DELEGATE)
69 #if defined(MAGICKCORE_HAVE_LCMS_LCMS2_H)
71 #include <lcms/lcms2.h>
77 #if defined(MAGICKCORE_XML_DELEGATE)
78 # if defined(MAGICKCORE_WINDOWS_SUPPORT)
79 # if !defined(__MINGW32__)
80 # include <win32config.h>
83 # include <libxml/parser.h>
84 # include <libxml/tree.h>
90 static MagickBooleanType
92 const MagickBooleanType);
122 MagickExport MagickBooleanType CloneImageProfiles(
Image *image,
123 const Image *clone_image)
125 assert(image != (
Image *) NULL);
126 assert(image->signature == MagickCoreSignature);
127 assert(clone_image != (
const Image *) NULL);
128 assert(clone_image->signature == MagickCoreSignature);
129 if (IsEventLogging() != MagickFalse)
130 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
131 image->color_profile.length=clone_image->color_profile.length;
132 image->color_profile.info=clone_image->color_profile.info;
133 image->iptc_profile.length=clone_image->iptc_profile.length;
134 image->iptc_profile.info=clone_image->iptc_profile.info;
135 if (clone_image->profiles != (
void *) NULL)
137 if (image->profiles != (
void *) NULL)
138 DestroyImageProfiles(image);
139 image->profiles=CloneSplayTree((
SplayTreeInfo *) clone_image->profiles,
140 (
void *(*)(
void *)) ConstantString,(
void *(*)(
void *)) CloneStringInfo);
169 MagickExport MagickBooleanType DeleteImageProfile(
Image *image,
const char *name)
171 assert(image != (
Image *) NULL);
172 assert(image->signature == MagickCoreSignature);
173 if (image->debug != MagickFalse)
174 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
177 if (LocaleCompare(name,
"icc") == 0)
182 image->color_profile.length=0;
183 image->color_profile.info=(
unsigned char *) NULL;
185 if (LocaleCompare(name,
"iptc") == 0)
190 image->iptc_profile.length=0;
191 image->iptc_profile.info=(
unsigned char *) NULL;
193 WriteTo8BimProfile(image,name,(
StringInfo *) NULL);
194 return(DeleteNodeFromSplayTree((
SplayTreeInfo *) image->profiles,name));
219 MagickExport
void DestroyImageProfiles(
Image *image)
222 image->profiles=DestroySplayTree((
SplayTreeInfo *) image->profiles);
255 assert(image != (
Image *) NULL);
256 assert(image->signature == MagickCoreSignature);
257 if (image->debug != MagickFalse)
258 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
262 image->profiles,name);
288 MagickExport
char *GetNextImageProfile(
const Image *image)
290 assert(image != (
Image *) NULL);
291 assert(image->signature == MagickCoreSignature);
292 if (IsEventLogging() != MagickFalse)
293 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
295 return((
char *) NULL);
296 return((
char *) GetNextKeyInSplayTree((
SplayTreeInfo *) image->profiles));
340 #if defined(MAGICKCORE_LCMS_DELEGATE)
342 typedef struct _LCMSInfo
360 **magick_restrict pixels,
365 #if LCMS_VERSION < 2060
366 static void* cmsGetContextUserData(cmsContext ContextID)
371 static cmsContext cmsCreateContext(
void *magick_unused(Plugin),
void *UserData)
373 magick_unreferenced(Plugin);
374 return((cmsContext) UserData);
377 static void cmsSetLogErrorHandlerTHR(cmsContext magick_unused(ContextID),
378 cmsLogErrorHandlerFunction Fn)
380 magick_unreferenced(ContextID);
381 cmsSetLogErrorHandler(Fn);
384 static void cmsDeleteContext(cmsContext magick_unused(ContextID))
386 magick_unreferenced(ContextID);
390 static double **DestroyPixelTLS(
double **pixels)
395 if (pixels == (
double **) NULL)
396 return((
double **) NULL);
397 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
398 if (pixels[i] != (
double *) NULL)
399 pixels[i]=(
double *) RelinquishMagickMemory(pixels[i]);
400 pixels=(
double **) RelinquishMagickMemory(pixels);
404 static double **AcquirePixelTLS(
const size_t columns,
405 const size_t channels)
416 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
417 pixels=(
double **) AcquireQuantumMemory(number_threads,
sizeof(*pixels));
418 if (pixels == (
double **) NULL)
419 return((
double **) NULL);
420 (void) memset(pixels,0,number_threads*
sizeof(*pixels));
421 for (i=0; i < (ssize_t) number_threads; i++)
423 pixels[i]=(
double *) AcquireQuantumMemory(columns,channels*
sizeof(**pixels));
424 if (pixels[i] == (
double *) NULL)
425 return(DestroyPixelTLS(pixels));
430 static cmsHTRANSFORM *DestroyTransformTLS(cmsHTRANSFORM *transform)
435 assert(transform != (cmsHTRANSFORM *) NULL);
436 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
437 if (transform[i] != (cmsHTRANSFORM) NULL)
438 cmsDeleteTransform(transform[i]);
439 transform=(cmsHTRANSFORM *) RelinquishMagickMemory(transform);
443 static cmsHTRANSFORM *AcquireTransformTLS(
const LCMSInfo *source_info,
444 const LCMSInfo *target_info,
const cmsUInt32Number flags,
445 cmsContext cms_context)
456 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
457 transform=(cmsHTRANSFORM *) AcquireQuantumMemory(number_threads,
459 if (transform == (cmsHTRANSFORM *) NULL)
460 return((cmsHTRANSFORM *) NULL);
461 (void) memset(transform,0,number_threads*
sizeof(*transform));
462 for (i=0; i < (ssize_t) number_threads; i++)
464 transform[i]=cmsCreateTransformTHR(cms_context,source_info->profile,
465 source_info->type,target_info->profile,target_info->type,
466 target_info->intent,flags);
467 if (transform[i] == (cmsHTRANSFORM) NULL)
468 return(DestroyTransformTLS(transform));
473 static void LCMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
479 if (IsEventLogging() != MagickFalse)
480 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
"lcms: #%u, %s",
481 severity,message != (
char *) NULL ? message :
"no message");
482 image=(
Image *) cmsGetContextUserData(context);
483 if (image != (
Image *) NULL)
484 (
void) ThrowMagickException(&image->exception,GetMagickModule(),
485 ImageWarning,
"UnableToTransformColorspace",
"`%s'",image->filename);
488 static inline void SetLCMSInfoTranslate(LCMSInfo *info,
const double translate)
490 info->translate[0]=translate;
491 info->translate[1]=translate;
492 info->translate[2]=translate;
493 info->translate[3]=translate;
496 static inline void SetLCMSInfoScale(LCMSInfo *info,
const double scale)
498 info->scale[0]=scale;
499 info->scale[1]=scale;
500 info->scale[2]=scale;
501 info->scale[3]=scale;
505 static MagickBooleanType SetsRGBImageProfile(
Image *image)
510 0x00, 0x00, 0x0c, 0x8c, 0x61, 0x72, 0x67, 0x6c, 0x02, 0x20, 0x00, 0x00,
511 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
512 0x07, 0xde, 0x00, 0x01, 0x00, 0x06, 0x00, 0x16, 0x00, 0x0f, 0x00, 0x3a,
513 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
514 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00,
515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
516 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x61, 0x72, 0x67, 0x6c,
517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
521 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x99,
522 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0xec, 0x00, 0x00, 0x00, 0x67,
523 0x64, 0x6d, 0x6e, 0x64, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70,
524 0x64, 0x6d, 0x64, 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88,
525 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x0c,
526 0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x00, 0x67,
527 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x24,
528 0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xe4, 0x00, 0x00, 0x00, 0x14,
529 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x24,
530 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x14,
531 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x14,
532 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x14,
533 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x58, 0x00, 0x00, 0x00, 0x14,
534 0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x6c, 0x00, 0x00, 0x00, 0x14,
535 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
536 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
537 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
538 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
539 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36,
540 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75, 0x69, 0x76,
541 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x77, 0x77,
542 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x31, 0x39,
543 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c,
544 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x3f, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31,
546 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75,
547 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77,
548 0x77, 0x77, 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20,
549 0x31, 0x39, 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66,
550 0x69, 0x6c, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
551 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, 0x61,
552 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x72, 0x61, 0x65, 0x6d,
553 0x65, 0x20, 0x57, 0x2e, 0x20, 0x47, 0x69, 0x6c, 0x6c, 0x2e, 0x20, 0x52,
554 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f,
555 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
556 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x4e, 0x6f, 0x20, 0x57,
557 0x61, 0x72, 0x72, 0x61, 0x6e, 0x74, 0x79, 0x2c, 0x20, 0x55, 0x73, 0x65,
558 0x20, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e,
559 0x20, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20,
561 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
562 0x65, 0x63, 0x2e, 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74,
564 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
565 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
570 0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e,
571 0x31, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47,
572 0x42, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61,
573 0x63, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43,
575 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
576 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63,
577 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
578 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00,
581 0x43, 0x52, 0x54, 0x20, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
582 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
583 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
585 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa4, 0x7c,
591 0x00, 0x14, 0x5f, 0x30, 0x00, 0x10, 0xce, 0x02, 0x00, 0x03, 0xed, 0xb2,
592 0x00, 0x04, 0x13, 0x0a, 0x00, 0x03, 0x5c, 0x67, 0x00, 0x00, 0x00, 0x01,
593 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x0a, 0x3d,
594 0x00, 0x50, 0x00, 0x00, 0x00, 0x57, 0x1e, 0xb8, 0x6d, 0x65, 0x61, 0x73,
595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x58, 0x59, 0x5a, 0x20,
598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00,
599 0x00, 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa0,
602 0x00, 0x00, 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20,
603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x97, 0x00, 0x00, 0xb7, 0x87,
604 0x00, 0x00, 0x18, 0xd9, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
605 0x00, 0x00, 0x24, 0x9f, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0xb6, 0xc4,
606 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
607 0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19,
608 0x00, 0x1e, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37,
609 0x00, 0x3b, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54,
610 0x00, 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
611 0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00, 0x90,
612 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9, 0x00, 0xae,
613 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00, 0xc6, 0x00, 0xcb,
614 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0xeb,
615 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01, 0x01, 0x01, 0x07, 0x01, 0x0d,
616 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f, 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32,
617 0x01, 0x38, 0x01, 0x3e, 0x01, 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59,
618 0x01, 0x60, 0x01, 0x67, 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83,
619 0x01, 0x8b, 0x01, 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1,
620 0x01, 0xb9, 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1,
621 0x01, 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
622 0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02, 0x4b,
623 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a, 0x02, 0x84,
624 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02, 0xb6, 0x02, 0xc1,
625 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb, 0x02, 0xf5, 0x03, 0x00,
626 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2d, 0x03, 0x38, 0x03, 0x43,
627 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66, 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a,
628 0x03, 0x96, 0x03, 0xa2, 0x03, 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3,
629 0x03, 0xe0, 0x03, 0xec, 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20,
630 0x04, 0x2d, 0x04, 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71,
631 0x04, 0x7e, 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4,
632 0x04, 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
633 0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05, 0x77,
634 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5, 0x05, 0xd5,
635 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06, 0x27, 0x06, 0x37,
636 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b, 0x06, 0x8c, 0x06, 0x9d,
637 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06, 0xe3, 0x06, 0xf5, 0x07, 0x07,
638 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d, 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74,
639 0x07, 0x86, 0x07, 0x99, 0x07, 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5,
640 0x07, 0xf8, 0x08, 0x0b, 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a,
641 0x08, 0x6e, 0x08, 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2,
642 0x08, 0xe7, 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f,
643 0x09, 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
644 0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a, 0x54,
645 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5, 0x0a, 0xdc,
646 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b, 0x51, 0x0b, 0x69,
647 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8, 0x0b, 0xe1, 0x0b, 0xf9,
648 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c, 0x5c, 0x0c, 0x75, 0x0c, 0x8e,
649 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9, 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26,
650 0x0d, 0x40, 0x0d, 0x5a, 0x0d, 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3,
651 0x0d, 0xde, 0x0d, 0xf8, 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64,
652 0x0e, 0x7f, 0x0e, 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09,
653 0x0f, 0x25, 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3,
654 0x0f, 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
655 0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11, 0x13,
656 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa, 0x11, 0xc9,
657 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12, 0x64, 0x12, 0x84,
658 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03, 0x13, 0x23, 0x13, 0x43,
659 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13, 0xc5, 0x13, 0xe5, 0x14, 0x06,
660 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a, 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce,
661 0x14, 0xf0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b,
662 0x15, 0xbd, 0x15, 0xe0, 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c,
663 0x16, 0x8f, 0x16, 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41,
664 0x17, 0x65, 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b,
665 0x18, 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
666 0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19, 0xdd,
667 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e, 0x1a, 0xc5,
668 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b, 0x8a, 0x1b, 0xb2,
669 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52, 0x1c, 0x7b, 0x1c, 0xa3,
670 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d, 0x47, 0x1d, 0x70, 0x1d, 0x99,
671 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16, 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94,
672 0x1e, 0xbe, 0x1e, 0xe9, 0x1f, 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94,
673 0x1f, 0xbf, 0x1f, 0xea, 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98,
674 0x20, 0xc4, 0x20, 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1,
675 0x21, 0xce, 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf,
676 0x22, 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
677 0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24, 0xda,
678 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7, 0x25, 0xf7,
679 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26, 0xe8, 0x27, 0x18,
680 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc, 0x28, 0x0d, 0x28, 0x3f,
681 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29, 0x06, 0x29, 0x38, 0x29, 0x6b,
682 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02, 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b,
683 0x2a, 0xcf, 0x2b, 0x02, 0x2b, 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1,
684 0x2c, 0x05, 0x2c, 0x39, 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c,
685 0x2d, 0x41, 0x2d, 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c,
686 0x2e, 0x82, 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91,
687 0x2f, 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
688 0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32, 0x2a,
689 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46, 0x33, 0x7f,
690 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34, 0x9e, 0x34, 0xd8,
691 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2, 0x35, 0xfd, 0x36, 0x37,
692 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37, 0x24, 0x37, 0x60, 0x37, 0x9c,
693 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05,
694 0x39, 0x42, 0x39, 0x7f, 0x39, 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74,
695 0x3a, 0xb2, 0x3a, 0xef, 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8,
696 0x3c, 0x27, 0x3c, 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61,
697 0x3d, 0xa1, 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0,
698 0x3f, 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
699 0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41, 0xee,
700 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a, 0x43, 0x7d,
701 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44, 0xce, 0x45, 0x12,
702 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22, 0x46, 0x67, 0x46, 0xab,
703 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47, 0xc0, 0x48, 0x05, 0x48, 0x4b,
704 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d, 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0,
705 0x4a, 0x37, 0x4a, 0x7d, 0x4a, 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a,
706 0x4b, 0xe2, 0x4c, 0x2a, 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a,
707 0x4d, 0x93, 0x4d, 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00,
708 0x4f, 0x49, 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb,
709 0x51, 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
710 0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54, 0x42,
711 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2, 0x56, 0x0f,
712 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57, 0x92, 0x57, 0xe0,
713 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a, 0x59, 0x69, 0x59, 0xb8,
714 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a, 0xf5, 0x5b, 0x45, 0x5b, 0x95,
715 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86, 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78,
716 0x5d, 0xc9, 0x5e, 0x1a, 0x5e, 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61,
717 0x5f, 0xb3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f,
718 0x61, 0xa2, 0x61, 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43,
719 0x63, 0x97, 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d,
720 0x65, 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
721 0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69, 0x43,
722 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7, 0x6b, 0x4f,
723 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d, 0x08, 0x6d, 0x60,
724 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4, 0x6f, 0x1e, 0x6f, 0x78,
725 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70, 0xe0, 0x71, 0x3a, 0x71, 0x95,
726 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6, 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8,
727 0x74, 0x14, 0x74, 0x70, 0x74, 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1,
728 0x76, 0x3e, 0x76, 0x9b, 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11,
729 0x78, 0x6e, 0x78, 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46,
730 0x7a, 0xa5, 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81,
731 0x7c, 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
732 0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81, 0x0a,
733 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4, 0x83, 0x57,
734 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85, 0x47, 0x85, 0xab,
735 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b, 0x87, 0x9f, 0x88, 0x04,
736 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89, 0x99, 0x89, 0xfe, 0x8a, 0x64,
737 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96, 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca,
738 0x8d, 0x31, 0x8d, 0x98, 0x8d, 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36,
739 0x8f, 0x9e, 0x90, 0x06, 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8,
740 0x92, 0x11, 0x92, 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20,
741 0x94, 0x8a, 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f,
742 0x97, 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
743 0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b, 0xaf,
744 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2, 0x9e, 0x40,
745 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0, 0x69, 0xa0, 0xd8,
746 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96, 0xa3, 0x06, 0xa3, 0x76,
747 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5, 0x38, 0xa5, 0xa9, 0xa6, 0x1a,
748 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e, 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4,
749 0xa9, 0x37, 0xa9, 0xa9, 0xaa, 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75,
750 0xab, 0xe9, 0xac, 0x5c, 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d,
751 0xae, 0xa1, 0xaf, 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea,
752 0xb1, 0x60, 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae,
753 0xb4, 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
754 0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9, 0x4a,
755 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7, 0xbc, 0x21,
756 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe, 0x84, 0xbe, 0xff,
757 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec, 0xc1, 0x67, 0xc1, 0xe3,
758 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3, 0xd4, 0xc4, 0x51, 0xc4, 0xce,
759 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46, 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf,
760 0xc8, 0x3d, 0xc8, 0xbc, 0xc9, 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7,
761 0xcb, 0x36, 0xcb, 0xb6, 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5,
762 0xce, 0x36, 0xce, 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba,
763 0xd1, 0x3c, 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6,
764 0xd4, 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
765 0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9, 0xf1,
766 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a, 0xdd, 0x10,
767 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf, 0xaf, 0xe0, 0x36,
768 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53, 0xe2, 0xdb, 0xe3, 0x63,
769 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5, 0x84, 0xe6, 0x0d, 0xe6, 0x96,
770 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32, 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0,
771 0xea, 0x5b, 0xea, 0xe5, 0xeb, 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11,
772 0xed, 0x9c, 0xee, 0x28, 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58,
773 0xf0, 0xe5, 0xf1, 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7,
774 0xf4, 0x34, 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb,
775 0xf7, 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
776 0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd, 0xba,
777 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
786 assert(image != (
Image *) NULL);
787 assert(image->signature == MagickCoreSignature);
788 if (GetImageProfile(image,
"icc") != (
const StringInfo *) NULL)
790 profile=AcquireStringInfo(
sizeof(sRGBProfile));
791 SetStringInfoDatum(profile,sRGBProfile);
792 status=SetImageProfile(image,
"icc",profile);
793 profile=DestroyStringInfo(profile);
797 MagickExport MagickBooleanType ProfileImage(
Image *image,
const char *name,
798 const void *datum,
const size_t length,
799 const MagickBooleanType magick_unused(clone))
801 #define GetLCMSPixel(source_info,pixel,index) \
802 (source_info.scale[index]*((QuantumScale*pixel)+source_info.translate[index]))
803 #define ProfileImageTag "Profile/Image"
804 #define SetLCMSPixel(target_info,pixel,index) \
805 ClampToQuantum(target_info.scale[index]*((QuantumRange*pixel)+target_info.translate[index]))
806 #define ThrowProfileException(severity,tag,context) \
808 if (profile != (StringInfo *) NULL) \
809 profile=DestroyStringInfo(profile); \
810 if (cms_context != (cmsContext) NULL) \
811 cmsDeleteContext(cms_context); \
812 if (source_info.profile != (cmsHPROFILE) NULL) \
813 (void) cmsCloseProfile(source_info.profile); \
814 if (target_info.profile != (cmsHPROFILE) NULL) \
815 (void) cmsCloseProfile(target_info.profile); \
816 ThrowBinaryException(severity,tag,context); \
825 magick_unreferenced(clone);
827 assert(image != (
Image *) NULL);
828 assert(image->signature == MagickCoreSignature);
829 assert(name != (
const char *) NULL);
830 if (IsEventLogging() != MagickFalse)
831 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
832 if ((datum == (
const void *) NULL) || (length == 0))
840 ResetImageProfileIterator(image);
841 for (next=GetNextImageProfile(image); next != (
const char *) NULL; )
843 if (IsOptionMember(next,name) != MagickFalse)
845 (void) DeleteImageProfile(image,next);
846 ResetImageProfileIterator(image);
848 next=GetNextImageProfile(image);
856 profile=AcquireStringInfo((
size_t) length);
857 SetStringInfoDatum(profile,(
unsigned char *) datum);
858 if ((LocaleCompare(name,
"icc") != 0) && (LocaleCompare(name,
"icm") != 0))
859 status=SetImageProfile(image,name,profile);
865 icc_profile=GetImageProfile(image,
"icc");
866 if ((icc_profile != (
const StringInfo *) NULL) &&
867 (CompareStringInfo(icc_profile,profile) == 0))
872 value=GetImageProperty(image,
"exif:ColorSpace");
874 if (LocaleCompare(value,
"1") != 0)
875 (
void) SetsRGBImageProfile(image);
876 value=GetImageProperty(image,
"exif:InteroperabilityIndex");
877 if (LocaleCompare(value,
"R98.") != 0)
878 (void) SetsRGBImageProfile(image);
879 icc_profile=GetImageProfile(image,
"icc");
881 if ((icc_profile != (
const StringInfo *) NULL) &&
882 (CompareStringInfo(icc_profile,profile) == 0))
884 profile=DestroyStringInfo(profile);
887 #if !defined(MAGICKCORE_LCMS_DELEGATE)
888 (void) ThrowMagickException(&image->exception,GetMagickModule(),
889 MissingDelegateWarning,
"DelegateLibrarySupportNotBuiltIn",
"`%s' (LCMS)",
903 cms_context=cmsCreateContext(NULL,image);
904 if (cms_context == (cmsContext) NULL)
906 profile=DestroyStringInfo(profile);
907 ThrowBinaryImageException(ResourceLimitError,
908 "ColorspaceColorProfileMismatch",name);
910 cmsSetLogErrorHandlerTHR(cms_context,LCMSExceptionHandler);
911 source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
912 GetStringInfoDatum(profile),(cmsUInt32Number)
913 GetStringInfoLength(profile));
914 if (source_info.profile == (cmsHPROFILE) NULL)
916 profile=DestroyStringInfo(profile);
917 cmsDeleteContext(cms_context);
918 ThrowBinaryImageException(ResourceLimitError,
919 "ColorspaceColorProfileMismatch",name);
921 if ((cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass) &&
923 status=SetImageProfile(image,name,profile);
929 cmsColorSpaceSignature
933 *magick_restrict transform;
947 exception=(&image->exception);
948 target_info.profile=(cmsHPROFILE) NULL;
951 target_info.profile=source_info.profile;
952 source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
953 GetStringInfoDatum(icc_profile),(cmsUInt32Number)
954 GetStringInfoLength(icc_profile));
955 if (source_info.profile == (cmsHPROFILE) NULL)
956 ThrowProfileException(ResourceLimitError,
957 "ColorspaceColorProfileMismatch",name);
959 SetLCMSInfoScale(&source_info,1.0);
960 SetLCMSInfoTranslate(&source_info,0.0);
961 source_info.colorspace=sRGBColorspace;
962 source_info.channels=3;
963 switch (cmsGetColorSpace(source_info.profile))
967 source_info.colorspace=CMYKColorspace;
968 source_info.channels=4;
969 source_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
970 SetLCMSInfoScale(&source_info,100.0);
975 source_info.colorspace=GRAYColorspace;
976 source_info.channels=1;
977 source_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
982 source_info.colorspace=LabColorspace;
983 source_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
984 source_info.scale[0]=100.0;
985 source_info.scale[1]=255.0;
986 source_info.scale[2]=255.0;
987 source_info.translate[1]=(-0.5);
988 source_info.translate[2]=(-0.5);
993 source_info.colorspace=sRGBColorspace;
994 source_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
999 source_info.colorspace=XYZColorspace;
1000 source_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1004 ThrowProfileException(ImageError,
1005 "ColorspaceColorProfileMismatch",name);
1007 signature=cmsGetPCS(source_info.profile);
1008 if (target_info.profile != (cmsHPROFILE) NULL)
1009 signature=cmsGetColorSpace(target_info.profile);
1010 SetLCMSInfoScale(&target_info,1.0);
1011 SetLCMSInfoTranslate(&target_info,0.0);
1012 target_info.channels=3;
1015 case cmsSigCmykData:
1017 target_info.colorspace=CMYKColorspace;
1018 target_info.channels=4;
1019 target_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1020 SetLCMSInfoScale(&target_info,0.01);
1023 case cmsSigGrayData:
1025 target_info.colorspace=GRAYColorspace;
1026 target_info.channels=1;
1027 target_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1032 target_info.colorspace=LabColorspace;
1033 target_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1034 target_info.scale[0]=0.01;
1035 target_info.scale[1]=1/255.0;
1036 target_info.scale[2]=1/255.0;
1037 target_info.translate[1]=0.5;
1038 target_info.translate[2]=0.5;
1043 target_info.colorspace=sRGBColorspace;
1044 target_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1049 target_info.colorspace=XYZColorspace;
1050 target_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1054 ThrowProfileException(ImageError,
1055 "ColorspaceColorProfileMismatch",name);
1057 switch (image->rendering_intent)
1059 case AbsoluteIntent:
1061 target_info.intent=INTENT_ABSOLUTE_COLORIMETRIC;
1064 case PerceptualIntent:
1066 target_info.intent=INTENT_PERCEPTUAL;
1069 case RelativeIntent:
1071 target_info.intent=INTENT_RELATIVE_COLORIMETRIC;
1074 case SaturationIntent:
1076 target_info.intent=INTENT_SATURATION;
1081 target_info.intent=INTENT_PERCEPTUAL;
1085 flags=cmsFLAGS_HIGHRESPRECALC;
1086 #if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1087 if (image->black_point_compensation != MagickFalse)
1088 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1090 transform=AcquireTransformTLS(&source_info,&target_info,
1092 if (transform == (cmsHTRANSFORM *) NULL)
1093 ThrowProfileException(ImageError,
"UnableToCreateColorTransform",
1098 source_info.pixels=AcquirePixelTLS(image->columns,
1099 source_info.channels);
1100 target_info.pixels=AcquirePixelTLS(image->columns,
1101 target_info.channels);
1102 if ((source_info.pixels == (
double **) NULL) ||
1103 (target_info.pixels == (
double **) NULL))
1105 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1106 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1107 transform=DestroyTransformTLS(transform);
1108 ThrowProfileException(ResourceLimitError,
1109 "MemoryAllocationFailed",image->filename);
1111 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1113 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1114 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1115 transform=DestroyTransformTLS(transform);
1116 profile=DestroyStringInfo(profile);
1117 if (source_info.profile != (cmsHPROFILE) NULL)
1118 (void) cmsCloseProfile(source_info.profile);
1119 if (target_info.profile != (cmsHPROFILE) NULL)
1120 (
void) cmsCloseProfile(target_info.profile);
1121 return(MagickFalse);
1123 if (target_info.colorspace == CMYKColorspace)
1124 (void) SetImageColorspace(image,target_info.colorspace);
1126 image_view=AcquireAuthenticCacheView(image,exception);
1127 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1128 #pragma omp parallel for schedule(static) shared(status) \
1129 magick_number_threads(image,image,image->rows,1)
1131 for (y=0; y < (ssize_t) image->rows; y++)
1134 id = GetOpenMPThreadId();
1140 *magick_restrict indexes;
1151 if (status == MagickFalse)
1153 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1160 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1161 p=source_info.pixels[id];
1162 for (x=0; x < (ssize_t) image->columns; x++)
1164 *p++=GetLCMSPixel(source_info,GetPixelRed(q),0);
1165 if (source_info.channels > 1)
1167 *p++=GetLCMSPixel(source_info,GetPixelGreen(q),1);
1168 *p++=GetLCMSPixel(source_info,GetPixelBlue(q),2);
1170 if (source_info.channels > 3)
1172 *p=GetLCMSPixel(source_info,0,3);
1173 if (indexes != (IndexPacket *) NULL)
1174 *p=GetLCMSPixel(source_info,GetPixelIndex(indexes+x),3);
1179 cmsDoTransform(transform[
id],source_info.pixels[
id],
1180 target_info.pixels[
id],(
unsigned int) image->columns);
1181 p=target_info.pixels[id];
1183 for (x=0; x < (ssize_t) image->columns; x++)
1185 SetPixelRed(q,SetLCMSPixel(target_info,*p,0));
1186 SetPixelGreen(q,GetPixelRed(q));
1187 SetPixelBlue(q,GetPixelRed(q));
1189 if (target_info.channels > 1)
1191 SetPixelGreen(q,SetLCMSPixel(target_info,*p,1));
1193 SetPixelBlue(q,SetLCMSPixel(target_info,*p,2));
1196 if (target_info.channels > 3)
1198 if (indexes != (IndexPacket *) NULL)
1199 SetPixelIndex(indexes+x,SetLCMSPixel(target_info,*p,3));
1204 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1205 if (sync == MagickFalse)
1207 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1212 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1216 proceed=SetImageProgress(image,ProfileImageTag,progress,
1218 if (proceed == MagickFalse)
1222 image_view=DestroyCacheView(image_view);
1223 (void) SetImageColorspace(image,target_info.colorspace);
1228 image->type=image->matte == MagickFalse ? TrueColorType :
1232 case cmsSigCmykData:
1234 image->type=image->matte == MagickFalse ? ColorSeparationType :
1235 ColorSeparationMatteType;
1238 case cmsSigGrayData:
1240 image->type=image->matte == MagickFalse ? GrayscaleType :
1247 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1248 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1249 transform=DestroyTransformTLS(transform);
1250 if ((status != MagickFalse) &&
1251 (cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass))
1252 status=SetImageProfile(image,name,profile);
1253 if (target_info.profile != (cmsHPROFILE) NULL)
1254 (void) cmsCloseProfile(target_info.profile);
1256 (void) cmsCloseProfile(source_info.profile);
1257 cmsDeleteContext(cms_context);
1261 profile=DestroyStringInfo(profile);
1290 MagickExport
StringInfo *RemoveImageProfile(
Image *image,
const char *name)
1295 assert(image != (
Image *) NULL);
1296 assert(image->signature == MagickCoreSignature);
1297 if (IsEventLogging() != MagickFalse)
1298 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1301 if (LocaleCompare(name,
"icc") == 0)
1306 image->color_profile.length=0;
1307 image->color_profile.info=(
unsigned char *) NULL;
1309 if (LocaleCompare(name,
"iptc") == 0)
1314 image->iptc_profile.length=0;
1315 image->iptc_profile.info=(
unsigned char *) NULL;
1317 WriteTo8BimProfile(image,name,(
StringInfo *) NULL);
1319 image->profiles,name);
1347 MagickExport
void ResetImageProfileIterator(
const Image *image)
1349 assert(image != (
Image *) NULL);
1350 assert(image->signature == MagickCoreSignature);
1351 if (IsEventLogging() != MagickFalse)
1352 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1389 static void *DestroyProfile(
void *profile)
1391 return((
void *) DestroyStringInfo((
StringInfo *) profile));
1394 static inline const unsigned char *ReadResourceByte(
const unsigned char *p,
1395 unsigned char *quantum)
1401 static inline const unsigned char *ReadResourceLong(
const unsigned char *p,
1402 unsigned int *quantum)
1404 *quantum=(
unsigned int) (*p++) << 24;
1405 *quantum|=(
unsigned int) (*p++) << 16;
1406 *quantum|=(
unsigned int) (*p++) << 8;
1407 *quantum|=(
unsigned int) (*p++);
1411 static inline const unsigned char *ReadResourceShort(
const unsigned char *p,
1412 unsigned short *quantum)
1414 *quantum=(
unsigned short) (*p++) << 8;
1415 *quantum|=(
unsigned short) (*p++);
1419 static inline void WriteResourceLong(
unsigned char *p,
1420 const unsigned int quantum)
1425 buffer[0]=(
unsigned char) (quantum >> 24);
1426 buffer[1]=(
unsigned char) (quantum >> 16);
1427 buffer[2]=(
unsigned char) (quantum >> 8);
1428 buffer[3]=(
unsigned char) quantum;
1429 (void) memcpy(p,buffer,4);
1432 static void WriteTo8BimProfile(
Image *image,
const char *name,
1462 if (LocaleCompare(name,
"icc") == 0)
1465 if (LocaleCompare(name,
"iptc") == 0)
1468 if (LocaleCompare(name,
"xmp") == 0)
1473 image->profiles,
"8bim");
1476 datum=GetStringInfoDatum(profile_8bim);
1477 length=GetStringInfoLength(profile_8bim);
1478 for (p=datum; p < (datum+length-16); )
1481 if (LocaleNCompare((
char *) p,
"8BIM",4) != 0)
1484 p=ReadResourceShort(p,&
id);
1485 p=ReadResourceByte(p,&length_byte);
1487 if (((length_byte+1) & 0x01) != 0)
1489 if (p > (datum+length-4))
1491 p=ReadResourceLong(p,&value);
1492 count=(ssize_t) value;
1493 if ((count & 0x01) != 0)
1495 if ((count < 0) || (p > (datum+length-count)) || (count > (ssize_t) length))
1497 if (
id != profile_id)
1512 extent=(datum+length)-(p+count);
1516 extract_profile=AcquireStringInfo(offset+extent);
1517 (void) memcpy(extract_profile->datum,datum,offset);
1522 extract_extent=profile->length;
1523 if ((extract_extent & 0x01) != 0)
1525 extract_profile=AcquireStringInfo(offset+extract_extent+extent);
1526 (void) memcpy(extract_profile->datum,datum,offset-4);
1527 WriteResourceLong(extract_profile->datum+offset-4,(
unsigned int)
1529 (void) memcpy(extract_profile->datum+offset,
1530 profile->datum,profile->length);
1532 (void) memcpy(extract_profile->datum+offset+extract_extent,
1534 (void) AddValueToSplayTree((
SplayTreeInfo *) image->profiles,
1535 ConstantString(
"8bim"),CloneStringInfo(extract_profile));
1536 extract_profile=DestroyStringInfo(extract_profile);
1542 static void GetProfilesFromResourceBlock(
Image *image,
1569 datum=GetStringInfoDatum(resource_block);
1570 length=GetStringInfoLength(resource_block);
1571 for (p=datum; p < (datum+length-16); )
1573 if (LocaleNCompare((
char *) p,
"8BIM",4) != 0)
1576 p=ReadResourceShort(p,&
id);
1577 p=ReadResourceByte(p,&length_byte);
1579 if (((length_byte+1) & 0x01) != 0)
1581 if (p > (datum+length-4))
1583 p=ReadResourceLong(p,&value);
1584 count=(ssize_t) value;
1585 if ((p > (datum+length-count)) || (count > (ssize_t) length) || (count < 0))
1602 p=ReadResourceLong(p,&resolution);
1603 image->x_resolution=((double) resolution)/65536.0;
1604 p=ReadResourceShort(p,&units)+2;
1605 p=ReadResourceLong(p,&resolution)+4;
1606 image->y_resolution=((double) resolution)/65536.0;
1610 if ((ResolutionType) units != PixelsPerCentimeterResolution)
1611 image->units=PixelsPerInchResolution;
1614 image->units=PixelsPerCentimeterResolution;
1615 image->x_resolution/=2.54;
1616 image->y_resolution/=2.54;
1625 profile=AcquireStringInfo(count);
1626 SetStringInfoDatum(profile,p);
1627 (void) SetImageProfileInternal(image,
"iptc",profile,MagickTrue);
1628 profile=DestroyStringInfo(profile);
1645 profile=AcquireStringInfo(count);
1646 SetStringInfoDatum(profile,p);
1647 (void) SetImageProfileInternal(image,
"icc",profile,MagickTrue);
1648 profile=DestroyStringInfo(profile);
1657 profile=AcquireStringInfo(count);
1658 SetStringInfoDatum(profile,p);
1659 (void) SetImageProfileInternal(image,
"exif",profile,MagickTrue);
1660 profile=DestroyStringInfo(profile);
1669 profile=AcquireStringInfo(count);
1670 SetStringInfoDatum(profile,p);
1671 (void) SetImageProfileInternal(image,
"xmp",profile,MagickTrue);
1672 profile=DestroyStringInfo(profile);
1682 if ((count & 0x01) != 0)
1687 #if defined(MAGICKCORE_XML_DELEGATE)
1688 static MagickBooleanType ValidateXMPProfile(
Image *image,
1697 document=xmlReadMemory((
const char *) GetStringInfoDatum(profile),(
int)
1698 GetStringInfoLength(profile),
"xmp.xml",NULL,XML_PARSE_NOERROR |
1699 XML_PARSE_NOWARNING);
1700 if (document == (xmlDocPtr) NULL)
1702 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1703 ImageWarning,
"CorruptImageProfile",
"`%s' (XMP)",image->filename);
1704 return(MagickFalse);
1706 xmlFreeDoc(document);
1710 static MagickBooleanType ValidateXMPProfile(
Image *image,
1713 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1714 MissingDelegateWarning,
"DelegateLibrarySupportNotBuiltIn",
"'%s' (XML)",
1716 return(MagickFalse);
1720 static MagickBooleanType SetImageProfileInternal(
Image *image,
const char *name,
1721 const StringInfo *profile,
const MagickBooleanType recursive)
1729 assert(image != (
Image *) NULL);
1730 assert(image->signature == MagickCoreSignature);
1731 if (IsEventLogging() != MagickFalse)
1732 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1733 if ((LocaleCompare(name,
"xmp") == 0) &&
1734 (ValidateXMPProfile(image,profile) == MagickFalse))
1737 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
1739 (void) CopyMagickString(key,name,MaxTextExtent);
1741 status=AddValueToSplayTree((
SplayTreeInfo *) image->profiles,
1742 ConstantString(key),CloneStringInfo(profile));
1743 if ((status != MagickFalse) &&
1744 ((LocaleCompare(name,
"icc") == 0) || (LocaleCompare(name,
"icm") == 0)))
1752 icc_profile=GetImageProfile(image,name);
1753 if (icc_profile != (
const StringInfo *) NULL)
1755 image->color_profile.length=GetStringInfoLength(icc_profile);
1756 image->color_profile.info=GetStringInfoDatum(icc_profile);
1759 if ((status != MagickFalse) &&
1760 ((LocaleCompare(name,
"iptc") == 0) || (LocaleCompare(name,
"8bim") == 0)))
1768 iptc_profile=GetImageProfile(image,name);
1769 if (iptc_profile != (
const StringInfo *) NULL)
1771 image->iptc_profile.length=GetStringInfoLength(iptc_profile);
1772 image->iptc_profile.info=GetStringInfoDatum(iptc_profile);
1775 if (status != MagickFalse)
1777 if (LocaleCompare(name,
"8bim") == 0)
1778 GetProfilesFromResourceBlock(image,profile);
1780 if (recursive == MagickFalse)
1781 WriteTo8BimProfile(image,name,profile);
1786 MagickExport MagickBooleanType SetImageProfile(
Image *image,
const char *name,
1789 return(SetImageProfileInternal(image,name,profile,MagickFalse));
1816 static inline int ReadProfileByte(
unsigned char **p,
size_t *length)
1828 static inline signed short ReadProfileShort(
const EndianType endian,
1829 unsigned char *buffer)
1843 if (endian == LSBEndian)
1845 value=(
unsigned short) buffer[1] << 8;
1846 value|=(
unsigned short) buffer[0];
1847 quantum.unsigned_value=value & 0xffff;
1848 return(quantum.signed_value);
1850 value=(
unsigned short) buffer[0] << 8;
1851 value|=(
unsigned short) buffer[1];
1852 quantum.unsigned_value=value & 0xffff;
1853 return(quantum.signed_value);
1856 static inline signed int ReadProfileLong(
const EndianType endian,
1857 unsigned char *buffer)
1871 if (endian == LSBEndian)
1873 value=(
unsigned int) buffer[3] << 24;
1874 value|=(
unsigned int) buffer[2] << 16;
1875 value|=(
unsigned int) buffer[1] << 8;
1876 value|=(
unsigned int) buffer[0];
1877 quantum.unsigned_value=value & 0xffffffff;
1878 return(quantum.signed_value);
1880 value=(
unsigned int) buffer[0] << 24;
1881 value|=(
unsigned int) buffer[1] << 16;
1882 value|=(
unsigned int) buffer[2] << 8;
1883 value|=(
unsigned int) buffer[3];
1884 quantum.unsigned_value=value & 0xffffffff;
1885 return(quantum.signed_value);
1888 static inline signed int ReadProfileMSBLong(
unsigned char **p,
size_t *length)
1895 value=ReadProfileLong(MSBEndian,*p);
1901 static inline signed short ReadProfileMSBShort(
unsigned char **p,
1909 value=ReadProfileShort(MSBEndian,*p);
1915 static inline void WriteProfileLong(
const EndianType endian,
1916 const size_t value,
unsigned char *p)
1921 if (endian == LSBEndian)
1923 buffer[0]=(
unsigned char) value;
1924 buffer[1]=(
unsigned char) (value >> 8);
1925 buffer[2]=(
unsigned char) (value >> 16);
1926 buffer[3]=(
unsigned char) (value >> 24);
1927 (void) memcpy(p,buffer,4);
1930 buffer[0]=(
unsigned char) (value >> 24);
1931 buffer[1]=(
unsigned char) (value >> 16);
1932 buffer[2]=(
unsigned char) (value >> 8);
1933 buffer[3]=(
unsigned char) value;
1934 (void) memcpy(p,buffer,4);
1937 static void WriteProfileShort(
const EndianType endian,
1938 const unsigned short value,
unsigned char *p)
1943 if (endian == LSBEndian)
1945 buffer[0]=(
unsigned char) value;
1946 buffer[1]=(
unsigned char) (value >> 8);
1947 (void) memcpy(p,buffer,2);
1950 buffer[0]=(
unsigned char) (value >> 8);
1951 buffer[1]=(
unsigned char) value;
1952 (void) memcpy(p,buffer,2);
1955 static MagickBooleanType SyncExifProfile(
const Image *image,
unsigned char *exif,
1958 #define MaxDirectoryStack 16
1959 #define EXIF_DELIMITER "\n"
1960 #define EXIF_NUM_FORMATS 12
1961 #define TAG_EXIF_OFFSET 0x8769
1962 #define TAG_INTEROP_OFFSET 0xa005
1964 typedef struct _DirectoryInfo
1974 directory_stack[MaxDirectoryStack] = {{ 0 }};
1992 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
1998 return(MagickFalse);
1999 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2000 if ((
id != 0x4949) && (
id != 0x4D4D))
2004 if (ReadProfileByte(&exif,&length) != 0x45)
2006 if (ReadProfileByte(&exif,&length) != 0x78)
2008 if (ReadProfileByte(&exif,&length) != 0x69)
2010 if (ReadProfileByte(&exif,&length) != 0x66)
2012 if (ReadProfileByte(&exif,&length) != 0x00)
2014 if (ReadProfileByte(&exif,&length) != 0x00)
2019 return(MagickFalse);
2020 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2029 return(MagickFalse);
2030 if (ReadProfileShort(endian,exif+2) != 0x002a)
2031 return(MagickFalse);
2035 offset=(ssize_t) ReadProfileLong(endian,exif+4);
2036 if ((offset < 0) || ((size_t) offset >= length))
2037 return(MagickFalse);
2038 directory=exif+offset;
2041 exif_resources=NewSplayTree((
int (*)(
const void *,
const void *)) NULL,
2042 (
void *(*)(
void *)) NULL,(
void *(*)(
void *)) NULL);
2048 directory=directory_stack[level].directory;
2049 entry=directory_stack[level].entry;
2051 if ((directory < exif) || (directory > (exif+length-2)))
2056 number_entries=ReadProfileShort(endian,directory);
2057 for ( ; entry < number_entries; entry++)
2073 q=(
unsigned char *) (directory+2+(12*entry));
2074 if (q > (exif+length-12))
2076 if (GetValueFromSplayTree(exif_resources,q) == q)
2078 (void) AddValueToSplayTree(exif_resources,q,q);
2079 tag_value=(ssize_t) ReadProfileShort(endian,q);
2080 format=(ssize_t) ReadProfileShort(endian,q+2);
2081 if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2083 components=(int) ReadProfileLong(endian,q+4);
2086 number_bytes=(size_t) components*format_bytes[format];
2087 if ((ssize_t) number_bytes < components)
2089 if (number_bytes <= 4)
2096 offset=(ssize_t) ReadProfileLong(endian,q+8);
2097 if ((offset < 0) || ((size_t) (offset+number_bytes) > length))
2099 if (~length < number_bytes)
2101 p=(
unsigned char *) (exif+offset);
2107 (void) WriteProfileLong(endian,(
size_t) (image->x_resolution+0.5),p);
2108 if (number_bytes == 8)
2109 (void) WriteProfileLong(endian,1UL,p+4);
2114 (void) WriteProfileLong(endian,(
size_t) (image->y_resolution+0.5),p);
2115 if (number_bytes == 8)
2116 (void) WriteProfileLong(endian,1UL,p+4);
2121 if (number_bytes == 4)
2123 (void) WriteProfileLong(endian,(
size_t) image->orientation,p);
2126 (void) WriteProfileShort(endian,(
unsigned short) image->orientation,
2132 if (number_bytes == 4)
2134 (void) WriteProfileLong(endian,((
size_t) image->units)+1,p);
2137 (void) WriteProfileShort(endian,(
unsigned short) (image->units+1),p);
2143 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2145 offset=(ssize_t) ReadProfileLong(endian,p);
2146 if (((
size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2148 directory_stack[level].directory=directory;
2150 directory_stack[level].entry=entry;
2152 directory_stack[level].directory=exif+offset;
2153 directory_stack[level].entry=0;
2155 if ((directory+2+(12*number_entries)) > (exif+length))
2157 offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2159 if ((offset != 0) && ((size_t) offset < length) &&
2160 (level < (MaxDirectoryStack-2)))
2162 directory_stack[level].directory=exif+offset;
2163 directory_stack[level].entry=0;
2170 }
while (level > 0);
2171 exif_resources=DestroySplayTree(exif_resources);
2175 static MagickBooleanType Sync8BimProfile(
const Image *image,
2190 length=GetStringInfoLength(profile);
2191 p=GetStringInfoDatum(profile);
2194 if (ReadProfileByte(&p,&length) != 0x38)
2196 if (ReadProfileByte(&p,&length) != 0x42)
2198 if (ReadProfileByte(&p,&length) != 0x49)
2200 if (ReadProfileByte(&p,&length) != 0x4D)
2203 return(MagickFalse);
2204 id=ReadProfileMSBShort(&p,&length);
2205 count=(ssize_t) ReadProfileByte(&p,&length);
2206 if ((count >= (ssize_t) length) || (count < 0))
2207 return(MagickFalse);
2210 if ((*p & 0x01) == 0)
2211 (
void) ReadProfileByte(&p,&length);
2212 count=(ssize_t) ReadProfileMSBLong(&p,&length);
2213 if ((count > (ssize_t) length) || (count < 0))
2214 return(MagickFalse);
2215 if ((
id == 0x3ED) && (count == 16))
2217 if (image->units == PixelsPerCentimeterResolution)
2218 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2219 image->x_resolution*2.54*65536.0),p);
2221 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2222 image->x_resolution*65536.0),p);
2223 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+4);
2224 if (image->units == PixelsPerCentimeterResolution)
2225 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2226 image->y_resolution*2.54*65536.0),p+8);
2228 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2229 image->y_resolution*65536.0),p+8);
2230 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+12);
2233 (void) SyncExifProfile(image,p,count);
2240 MagickExport MagickBooleanType SyncImageProfiles(
Image *image)
2249 profile=(
StringInfo *) GetImageProfile(image,
"8BIM");
2251 if (Sync8BimProfile(image,profile) == MagickFalse)
2253 profile=(
StringInfo *) GetImageProfile(image,
"EXIF");
2255 if (SyncExifProfile(image,GetStringInfoDatum(profile),
2256 GetStringInfoLength(profile)) == MagickFalse)