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) ||
1603 p=ReadResourceLong(p,&resolution);
1604 image->x_resolution=((double) resolution)/65536.0;
1605 p=ReadResourceShort(p,&units)+2;
1606 p=ReadResourceLong(p,&resolution)+4;
1607 image->y_resolution=((double) resolution)/65536.0;
1611 if ((ResolutionType) units != PixelsPerCentimeterResolution)
1612 image->units=PixelsPerInchResolution;
1615 image->units=PixelsPerCentimeterResolution;
1616 image->x_resolution/=2.54;
1617 image->y_resolution/=2.54;
1626 profile=AcquireStringInfo(count);
1627 SetStringInfoDatum(profile,p);
1628 (void) SetImageProfileInternal(image,
"iptc",profile,MagickTrue);
1629 profile=DestroyStringInfo(profile);
1646 profile=AcquireStringInfo(count);
1647 SetStringInfoDatum(profile,p);
1648 (void) SetImageProfileInternal(image,
"icc",profile,MagickTrue);
1649 profile=DestroyStringInfo(profile);
1658 profile=AcquireStringInfo(count);
1659 SetStringInfoDatum(profile,p);
1660 (void) SetImageProfileInternal(image,
"exif",profile,MagickTrue);
1661 profile=DestroyStringInfo(profile);
1670 profile=AcquireStringInfo(count);
1671 SetStringInfoDatum(profile,p);
1672 (void) SetImageProfileInternal(image,
"xmp",profile,MagickTrue);
1673 profile=DestroyStringInfo(profile);
1683 if ((count & 0x01) != 0)
1688 #if defined(MAGICKCORE_XML_DELEGATE)
1689 static MagickBooleanType ValidateXMPProfile(
Image *image,
1698 document=xmlReadMemory((
const char *) GetStringInfoDatum(profile),(
int)
1699 GetStringInfoLength(profile),
"xmp.xml",NULL,XML_PARSE_NOERROR |
1700 XML_PARSE_NOWARNING);
1701 if (document == (xmlDocPtr) NULL)
1703 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1704 ImageWarning,
"CorruptImageProfile",
"`%s' (XMP)",image->filename);
1705 return(MagickFalse);
1707 xmlFreeDoc(document);
1711 static MagickBooleanType ValidateXMPProfile(
Image *image,
1714 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1715 MissingDelegateWarning,
"DelegateLibrarySupportNotBuiltIn",
"'%s' (XML)",
1717 return(MagickFalse);
1721 static MagickBooleanType SetImageProfileInternal(
Image *image,
const char *name,
1722 const StringInfo *profile,
const MagickBooleanType recursive)
1730 assert(image != (
Image *) NULL);
1731 assert(image->signature == MagickCoreSignature);
1732 if (IsEventLogging() != MagickFalse)
1733 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1734 if ((LocaleCompare(name,
"xmp") == 0) &&
1735 (ValidateXMPProfile(image,profile) == MagickFalse))
1738 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
1740 (void) CopyMagickString(key,name,MaxTextExtent);
1742 status=AddValueToSplayTree((
SplayTreeInfo *) image->profiles,
1743 ConstantString(key),CloneStringInfo(profile));
1744 if ((status != MagickFalse) &&
1745 ((LocaleCompare(name,
"icc") == 0) || (LocaleCompare(name,
"icm") == 0)))
1753 icc_profile=GetImageProfile(image,name);
1754 if (icc_profile != (
const StringInfo *) NULL)
1756 image->color_profile.length=GetStringInfoLength(icc_profile);
1757 image->color_profile.info=GetStringInfoDatum(icc_profile);
1760 if ((status != MagickFalse) &&
1761 ((LocaleCompare(name,
"iptc") == 0) || (LocaleCompare(name,
"8bim") == 0)))
1769 iptc_profile=GetImageProfile(image,name);
1770 if (iptc_profile != (
const StringInfo *) NULL)
1772 image->iptc_profile.length=GetStringInfoLength(iptc_profile);
1773 image->iptc_profile.info=GetStringInfoDatum(iptc_profile);
1776 if (status != MagickFalse)
1778 if (LocaleCompare(name,
"8bim") == 0)
1779 GetProfilesFromResourceBlock(image,profile);
1781 if (recursive == MagickFalse)
1782 WriteTo8BimProfile(image,name,profile);
1787 MagickExport MagickBooleanType SetImageProfile(
Image *image,
const char *name,
1790 return(SetImageProfileInternal(image,name,profile,MagickFalse));
1817 static inline int ReadProfileByte(
unsigned char **p,
size_t *length)
1829 static inline signed short ReadProfileShort(
const EndianType endian,
1830 unsigned char *buffer)
1844 if (endian == LSBEndian)
1846 value=(
unsigned short) buffer[1] << 8;
1847 value|=(
unsigned short) buffer[0];
1848 quantum.unsigned_value=value & 0xffff;
1849 return(quantum.signed_value);
1851 value=(
unsigned short) buffer[0] << 8;
1852 value|=(
unsigned short) buffer[1];
1853 quantum.unsigned_value=value & 0xffff;
1854 return(quantum.signed_value);
1857 static inline signed int ReadProfileLong(
const EndianType endian,
1858 unsigned char *buffer)
1872 if (endian == LSBEndian)
1874 value=(
unsigned int) buffer[3] << 24;
1875 value|=(
unsigned int) buffer[2] << 16;
1876 value|=(
unsigned int) buffer[1] << 8;
1877 value|=(
unsigned int) buffer[0];
1878 quantum.unsigned_value=value & 0xffffffff;
1879 return(quantum.signed_value);
1881 value=(
unsigned int) buffer[0] << 24;
1882 value|=(
unsigned int) buffer[1] << 16;
1883 value|=(
unsigned int) buffer[2] << 8;
1884 value|=(
unsigned int) buffer[3];
1885 quantum.unsigned_value=value & 0xffffffff;
1886 return(quantum.signed_value);
1889 static inline signed int ReadProfileMSBLong(
unsigned char **p,
size_t *length)
1896 value=ReadProfileLong(MSBEndian,*p);
1902 static inline signed short ReadProfileMSBShort(
unsigned char **p,
1910 value=ReadProfileShort(MSBEndian,*p);
1916 static inline void WriteProfileLong(
const EndianType endian,
1917 const size_t value,
unsigned char *p)
1922 if (endian == LSBEndian)
1924 buffer[0]=(
unsigned char) value;
1925 buffer[1]=(
unsigned char) (value >> 8);
1926 buffer[2]=(
unsigned char) (value >> 16);
1927 buffer[3]=(
unsigned char) (value >> 24);
1928 (void) memcpy(p,buffer,4);
1931 buffer[0]=(
unsigned char) (value >> 24);
1932 buffer[1]=(
unsigned char) (value >> 16);
1933 buffer[2]=(
unsigned char) (value >> 8);
1934 buffer[3]=(
unsigned char) value;
1935 (void) memcpy(p,buffer,4);
1938 static void WriteProfileShort(
const EndianType endian,
1939 const unsigned short value,
unsigned char *p)
1944 if (endian == LSBEndian)
1946 buffer[0]=(
unsigned char) value;
1947 buffer[1]=(
unsigned char) (value >> 8);
1948 (void) memcpy(p,buffer,2);
1951 buffer[0]=(
unsigned char) (value >> 8);
1952 buffer[1]=(
unsigned char) value;
1953 (void) memcpy(p,buffer,2);
1956 static MagickBooleanType SyncExifProfile(
const Image *image,
unsigned char *exif,
1959 #define MaxDirectoryStack 16
1960 #define EXIF_DELIMITER "\n"
1961 #define EXIF_NUM_FORMATS 12
1962 #define TAG_EXIF_OFFSET 0x8769
1963 #define TAG_INTEROP_OFFSET 0xa005
1965 typedef struct _DirectoryInfo
1975 directory_stack[MaxDirectoryStack] = {{ 0 }};
1993 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
1999 return(MagickFalse);
2000 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2001 if ((
id != 0x4949) && (
id != 0x4D4D))
2005 if (ReadProfileByte(&exif,&length) != 0x45)
2007 if (ReadProfileByte(&exif,&length) != 0x78)
2009 if (ReadProfileByte(&exif,&length) != 0x69)
2011 if (ReadProfileByte(&exif,&length) != 0x66)
2013 if (ReadProfileByte(&exif,&length) != 0x00)
2015 if (ReadProfileByte(&exif,&length) != 0x00)
2020 return(MagickFalse);
2021 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2030 return(MagickFalse);
2031 if (ReadProfileShort(endian,exif+2) != 0x002a)
2032 return(MagickFalse);
2036 offset=(ssize_t) ReadProfileLong(endian,exif+4);
2037 if ((offset < 0) || ((size_t) offset >= length))
2038 return(MagickFalse);
2039 directory=exif+offset;
2042 exif_resources=NewSplayTree((
int (*)(
const void *,
const void *)) NULL,
2043 (
void *(*)(
void *)) NULL,(
void *(*)(
void *)) NULL);
2049 directory=directory_stack[level].directory;
2050 entry=directory_stack[level].entry;
2052 if ((directory < exif) || (directory > (exif+length-2)))
2057 number_entries=ReadProfileShort(endian,directory);
2058 for ( ; entry < number_entries; entry++)
2074 q=(
unsigned char *) (directory+2+(12*entry));
2075 if (q > (exif+length-12))
2077 if (GetValueFromSplayTree(exif_resources,q) == q)
2079 (void) AddValueToSplayTree(exif_resources,q,q);
2080 tag_value=(ssize_t) ReadProfileShort(endian,q);
2081 format=(ssize_t) ReadProfileShort(endian,q+2);
2082 if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2084 components=(int) ReadProfileLong(endian,q+4);
2087 number_bytes=(size_t) components*format_bytes[format];
2088 if ((ssize_t) number_bytes < components)
2090 if (number_bytes <= 4)
2097 offset=(ssize_t) ReadProfileLong(endian,q+8);
2098 if ((offset < 0) || ((size_t) (offset+number_bytes) > length))
2100 if (~length < number_bytes)
2102 p=(
unsigned char *) (exif+offset);
2108 (void) WriteProfileLong(endian,(
size_t) (image->x_resolution+0.5),p);
2109 if (number_bytes == 8)
2110 (void) WriteProfileLong(endian,1UL,p+4);
2115 (void) WriteProfileLong(endian,(
size_t) (image->y_resolution+0.5),p);
2116 if (number_bytes == 8)
2117 (void) WriteProfileLong(endian,1UL,p+4);
2122 if (number_bytes == 4)
2124 (void) WriteProfileLong(endian,(
size_t) image->orientation,p);
2127 (void) WriteProfileShort(endian,(
unsigned short) image->orientation,
2133 if (number_bytes == 4)
2135 (void) WriteProfileLong(endian,((
size_t) image->units)+1,p);
2138 (void) WriteProfileShort(endian,(
unsigned short) (image->units+1),p);
2144 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2146 offset=(ssize_t) ReadProfileLong(endian,p);
2147 if (((
size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2149 directory_stack[level].directory=directory;
2151 directory_stack[level].entry=entry;
2153 directory_stack[level].directory=exif+offset;
2154 directory_stack[level].entry=0;
2156 if ((directory+2+(12*number_entries)) > (exif+length))
2158 offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2160 if ((offset != 0) && ((size_t) offset < length) &&
2161 (level < (MaxDirectoryStack-2)))
2163 directory_stack[level].directory=exif+offset;
2164 directory_stack[level].entry=0;
2171 }
while (level > 0);
2172 exif_resources=DestroySplayTree(exif_resources);
2176 static MagickBooleanType Sync8BimProfile(
const Image *image,
2191 length=GetStringInfoLength(profile);
2192 p=GetStringInfoDatum(profile);
2195 if (ReadProfileByte(&p,&length) != 0x38)
2197 if (ReadProfileByte(&p,&length) != 0x42)
2199 if (ReadProfileByte(&p,&length) != 0x49)
2201 if (ReadProfileByte(&p,&length) != 0x4D)
2204 return(MagickFalse);
2205 id=ReadProfileMSBShort(&p,&length);
2206 count=(ssize_t) ReadProfileByte(&p,&length);
2207 if ((count >= (ssize_t) length) || (count < 0))
2208 return(MagickFalse);
2211 if ((*p & 0x01) == 0)
2212 (
void) ReadProfileByte(&p,&length);
2213 count=(ssize_t) ReadProfileMSBLong(&p,&length);
2214 if ((count > (ssize_t) length) || (count < 0))
2215 return(MagickFalse);
2216 if ((
id == 0x3ED) && (count == 16))
2218 if (image->units == PixelsPerCentimeterResolution)
2219 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2220 image->x_resolution*2.54*65536.0),p);
2222 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2223 image->x_resolution*65536.0),p);
2224 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+4);
2225 if (image->units == PixelsPerCentimeterResolution)
2226 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2227 image->y_resolution*2.54*65536.0),p+8);
2229 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2230 image->y_resolution*65536.0),p+8);
2231 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+12);
2234 (void) SyncExifProfile(image,p,count);
2241 MagickExport MagickBooleanType SyncImageProfiles(
Image *image)
2250 profile=(
StringInfo *) GetImageProfile(image,
"8BIM");
2252 if (Sync8BimProfile(image,profile) == MagickFalse)
2254 profile=(
StringInfo *) GetImageProfile(image,
"EXIF");
2256 if (SyncExifProfile(image,GetStringInfoDatum(profile),
2257 GetStringInfoLength(profile)) == MagickFalse)