42#include "magick/studio.h"
43#include "magick/artifact.h"
44#include "magick/attribute.h"
45#include "magick/cache.h"
46#include "magick/color.h"
47#include "magick/colorspace-private.h"
48#include "magick/configure.h"
49#include "magick/exception.h"
50#include "magick/exception-private.h"
51#include "magick/hashmap.h"
52#include "magick/image.h"
53#include "magick/memory_.h"
54#include "magick/monitor.h"
55#include "magick/monitor-private.h"
56#include "magick/option.h"
57#include "magick/option-private.h"
58#include "magick/profile.h"
59#include "magick/property.h"
60#include "magick/quantum.h"
61#include "magick/quantum-private.h"
62#include "magick/resource_.h"
63#include "magick/splay-tree.h"
64#include "magick/string_.h"
65#include "magick/string-private.h"
66#include "magick/thread-private.h"
67#include "magick/token.h"
68#include "magick/utility.h"
69#if defined(MAGICKCORE_LCMS_DELEGATE)
70#if defined(MAGICKCORE_HAVE_LCMS_LCMS2_H)
72#include <lcms/lcms2.h>
78#if defined(MAGICKCORE_XML_DELEGATE)
79# include <libxml/parser.h>
80# include <libxml/tree.h>
86static MagickBooleanType
87 SetImageProfileInternal(Image *,
const char *,
const StringInfo *,
88 const MagickBooleanType);
91 WriteTo8BimProfile(Image *,
const char*,
const StringInfo *);
120 *(*CloneKeyFunc)(
const char *);
123 *(*CloneValueFunc)(
const StringInfo *);
125static inline void *CloneProfileKey(
void *key)
127 return((
void *) ((CloneKeyFunc) ConstantString)((
const char *) key));
130static inline void *CloneProfileValue(
void *value)
132 return((
void *) ((CloneValueFunc) CloneStringInfo)((
const StringInfo *) value));
135MagickExport MagickBooleanType CloneImageProfiles(Image *image,
136 const Image *clone_image)
138 assert(image != (Image *) NULL);
139 assert(image->signature == MagickCoreSignature);
140 assert(clone_image != (
const Image *) NULL);
141 assert(clone_image->signature == MagickCoreSignature);
142 if (IsEventLogging() != MagickFalse)
143 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
144 image->color_profile.length=clone_image->color_profile.length;
145 image->color_profile.info=clone_image->color_profile.info;
146 image->iptc_profile.length=clone_image->iptc_profile.length;
147 image->iptc_profile.info=clone_image->iptc_profile.info;
148 if (clone_image->profiles != (
void *) NULL)
150 if (image->profiles != (
void *) NULL)
151 DestroyImageProfiles(image);
152 image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
153 CloneProfileKey,CloneProfileValue);
182MagickExport MagickBooleanType DeleteImageProfile(Image *image,
const char *name)
184 assert(image != (Image *) NULL);
185 assert(image->signature == MagickCoreSignature);
186 if (image->debug != MagickFalse)
187 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
188 if (image->profiles == (SplayTreeInfo *) NULL)
190 if (LocaleCompare(name,
"icc") == 0)
195 image->color_profile.length=0;
196 image->color_profile.info=(
unsigned char *) NULL;
198 if (LocaleCompare(name,
"iptc") == 0)
203 image->iptc_profile.length=0;
204 image->iptc_profile.info=(
unsigned char *) NULL;
206 WriteTo8BimProfile(image,name,(StringInfo *) NULL);
207 return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->profiles,name));
232MagickExport
void DestroyImageProfiles(Image *image)
234 if (image->profiles != (SplayTreeInfo *) NULL)
235 image->profiles=DestroySplayTree((SplayTreeInfo *) image->profiles);
262MagickExport
const StringInfo *GetImageProfile(
const Image *image,
268 assert(image != (Image *) NULL);
269 assert(image->signature == MagickCoreSignature);
270 if (image->debug != MagickFalse)
271 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
272 if (image->profiles == (SplayTreeInfo *) NULL)
273 return((StringInfo *) NULL);
274 profile=(
const StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
275 image->profiles,name);
301MagickExport
char *GetNextImageProfile(
const Image *image)
303 assert(image != (Image *) NULL);
304 assert(image->signature == MagickCoreSignature);
305 if (IsEventLogging() != MagickFalse)
306 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
307 if (image->profiles == (SplayTreeInfo *) NULL)
308 return((
char *) NULL);
309 return((
char *) GetNextKeyInSplayTree((SplayTreeInfo *) image->profiles));
353#if defined(MAGICKCORE_LCMS_DELEGATE)
355typedef struct _LCMSInfo
373 **magick_restrict pixels,
378#if LCMS_VERSION < 2060
379static void* cmsGetContextUserData(cmsContext ContextID)
384static cmsContext cmsCreateContext(
void *magick_unused(Plugin),
void *UserData)
386 magick_unreferenced(Plugin);
387 return((cmsContext) UserData);
390static void cmsSetLogErrorHandlerTHR(cmsContext magick_unused(ContextID),
391 cmsLogErrorHandlerFunction Fn)
393 magick_unreferenced(ContextID);
394 cmsSetLogErrorHandler(Fn);
397static void cmsDeleteContext(cmsContext magick_unused(ContextID))
399 magick_unreferenced(ContextID);
403static double **DestroyPixelTLS(
double **pixels)
408 if (pixels == (
double **) NULL)
409 return((
double **) NULL);
410 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
411 if (pixels[i] != (
double *) NULL)
412 pixels[i]=(
double *) RelinquishMagickMemory(pixels[i]);
413 pixels=(
double **) RelinquishMagickMemory(pixels);
417static double **AcquirePixelTLS(
const size_t columns,
418 const size_t channels)
429 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
430 pixels=(
double **) AcquireQuantumMemory(number_threads,
sizeof(*pixels));
431 if (pixels == (
double **) NULL)
432 return((
double **) NULL);
433 (void) memset(pixels,0,number_threads*
sizeof(*pixels));
434 for (i=0; i < (ssize_t) number_threads; i++)
436 pixels[i]=(
double *) AcquireQuantumMemory(columns,channels*
sizeof(**pixels));
437 if (pixels[i] == (
double *) NULL)
438 return(DestroyPixelTLS(pixels));
443static cmsHTRANSFORM *DestroyTransformTLS(cmsHTRANSFORM *transform)
448 assert(transform != (cmsHTRANSFORM *) NULL);
449 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
450 if (transform[i] != (cmsHTRANSFORM) NULL)
451 cmsDeleteTransform(transform[i]);
452 transform=(cmsHTRANSFORM *) RelinquishMagickMemory(transform);
456static cmsHTRANSFORM *AcquireTransformTLS(
const LCMSInfo *source_info,
457 const LCMSInfo *target_info,
const cmsUInt32Number flags,
458 cmsContext cms_context)
469 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
470 transform=(cmsHTRANSFORM *) AcquireQuantumMemory(number_threads,
472 if (transform == (cmsHTRANSFORM *) NULL)
473 return((cmsHTRANSFORM *) NULL);
474 (void) memset(transform,0,number_threads*
sizeof(*transform));
475 for (i=0; i < (ssize_t) number_threads; i++)
477 transform[i]=cmsCreateTransformTHR(cms_context,source_info->profile,
478 source_info->type,target_info->profile,target_info->type,
479 target_info->intent,flags);
480 if (transform[i] == (cmsHTRANSFORM) NULL)
481 return(DestroyTransformTLS(transform));
486static void LCMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
492 if (IsEventLogging() != MagickFalse)
493 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
"lcms: #%u, %s",
494 severity,message != (
char *) NULL ? message :
"no message");
495 image=(Image *) cmsGetContextUserData(context);
496 if (image != (Image *) NULL)
497 (void) ThrowMagickException(&image->exception,GetMagickModule(),
498 ImageWarning,
"UnableToTransformColorspace",
"`%s'",image->filename);
501static inline void SetLCMSInfoTranslate(LCMSInfo *info,
const double translate)
503 info->translate[0]=translate;
504 info->translate[1]=translate;
505 info->translate[2]=translate;
506 info->translate[3]=translate;
509static inline void SetLCMSInfoScale(LCMSInfo *info,
const double scale)
511 info->scale[0]=scale;
512 info->scale[1]=scale;
513 info->scale[2]=scale;
514 info->scale[3]=scale;
518static MagickBooleanType SetsRGBImageProfile(Image *image)
523 0x00, 0x00, 0x0c, 0x8c, 0x61, 0x72, 0x67, 0x6c, 0x02, 0x20, 0x00, 0x00,
524 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
525 0x07, 0xde, 0x00, 0x01, 0x00, 0x06, 0x00, 0x16, 0x00, 0x0f, 0x00, 0x3a,
526 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
527 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00,
528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
529 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x61, 0x72, 0x67, 0x6c,
530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
532 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
534 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x99,
535 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0xec, 0x00, 0x00, 0x00, 0x67,
536 0x64, 0x6d, 0x6e, 0x64, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70,
537 0x64, 0x6d, 0x64, 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88,
538 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x0c,
539 0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x00, 0x67,
540 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x24,
541 0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xe4, 0x00, 0x00, 0x00, 0x14,
542 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x24,
543 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x14,
544 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x14,
545 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x14,
546 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x58, 0x00, 0x00, 0x00, 0x14,
547 0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x6c, 0x00, 0x00, 0x00, 0x14,
548 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
549 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
550 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
551 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
552 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36,
553 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75, 0x69, 0x76,
554 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x77, 0x77,
555 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x31, 0x39,
556 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c,
557 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x00, 0x3f, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31,
559 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75,
560 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77,
561 0x77, 0x77, 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20,
562 0x31, 0x39, 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66,
563 0x69, 0x6c, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, 0x61,
565 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x72, 0x61, 0x65, 0x6d,
566 0x65, 0x20, 0x57, 0x2e, 0x20, 0x47, 0x69, 0x6c, 0x6c, 0x2e, 0x20, 0x52,
567 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f,
568 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
569 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x4e, 0x6f, 0x20, 0x57,
570 0x61, 0x72, 0x72, 0x61, 0x6e, 0x74, 0x79, 0x2c, 0x20, 0x55, 0x73, 0x65,
571 0x20, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e,
572 0x20, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20,
574 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
575 0x65, 0x63, 0x2e, 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74,
577 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
578 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
583 0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e,
584 0x31, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47,
585 0x42, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61,
586 0x63, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43,
588 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
589 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63,
590 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
591 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 0x00, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00,
594 0x43, 0x52, 0x54, 0x20, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
595 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
596 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
598 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa4, 0x7c,
604 0x00, 0x14, 0x5f, 0x30, 0x00, 0x10, 0xce, 0x02, 0x00, 0x03, 0xed, 0xb2,
605 0x00, 0x04, 0x13, 0x0a, 0x00, 0x03, 0x5c, 0x67, 0x00, 0x00, 0x00, 0x01,
606 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x0a, 0x3d,
607 0x00, 0x50, 0x00, 0x00, 0x00, 0x57, 0x1e, 0xb8, 0x6d, 0x65, 0x61, 0x73,
608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
610 0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x58, 0x59, 0x5a, 0x20,
611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00,
612 0x00, 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa0,
615 0x00, 0x00, 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20,
616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x97, 0x00, 0x00, 0xb7, 0x87,
617 0x00, 0x00, 0x18, 0xd9, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
618 0x00, 0x00, 0x24, 0x9f, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0xb6, 0xc4,
619 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
620 0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19,
621 0x00, 0x1e, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37,
622 0x00, 0x3b, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54,
623 0x00, 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
624 0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00, 0x90,
625 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9, 0x00, 0xae,
626 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00, 0xc6, 0x00, 0xcb,
627 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0xeb,
628 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01, 0x01, 0x01, 0x07, 0x01, 0x0d,
629 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f, 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32,
630 0x01, 0x38, 0x01, 0x3e, 0x01, 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59,
631 0x01, 0x60, 0x01, 0x67, 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83,
632 0x01, 0x8b, 0x01, 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1,
633 0x01, 0xb9, 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1,
634 0x01, 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
635 0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02, 0x4b,
636 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a, 0x02, 0x84,
637 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02, 0xb6, 0x02, 0xc1,
638 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb, 0x02, 0xf5, 0x03, 0x00,
639 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2d, 0x03, 0x38, 0x03, 0x43,
640 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66, 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a,
641 0x03, 0x96, 0x03, 0xa2, 0x03, 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3,
642 0x03, 0xe0, 0x03, 0xec, 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20,
643 0x04, 0x2d, 0x04, 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71,
644 0x04, 0x7e, 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4,
645 0x04, 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
646 0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05, 0x77,
647 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5, 0x05, 0xd5,
648 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06, 0x27, 0x06, 0x37,
649 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b, 0x06, 0x8c, 0x06, 0x9d,
650 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06, 0xe3, 0x06, 0xf5, 0x07, 0x07,
651 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d, 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74,
652 0x07, 0x86, 0x07, 0x99, 0x07, 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5,
653 0x07, 0xf8, 0x08, 0x0b, 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a,
654 0x08, 0x6e, 0x08, 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2,
655 0x08, 0xe7, 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f,
656 0x09, 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
657 0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a, 0x54,
658 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5, 0x0a, 0xdc,
659 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b, 0x51, 0x0b, 0x69,
660 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8, 0x0b, 0xe1, 0x0b, 0xf9,
661 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c, 0x5c, 0x0c, 0x75, 0x0c, 0x8e,
662 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9, 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26,
663 0x0d, 0x40, 0x0d, 0x5a, 0x0d, 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3,
664 0x0d, 0xde, 0x0d, 0xf8, 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64,
665 0x0e, 0x7f, 0x0e, 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09,
666 0x0f, 0x25, 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3,
667 0x0f, 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
668 0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11, 0x13,
669 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa, 0x11, 0xc9,
670 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12, 0x64, 0x12, 0x84,
671 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03, 0x13, 0x23, 0x13, 0x43,
672 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13, 0xc5, 0x13, 0xe5, 0x14, 0x06,
673 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a, 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce,
674 0x14, 0xf0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b,
675 0x15, 0xbd, 0x15, 0xe0, 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c,
676 0x16, 0x8f, 0x16, 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41,
677 0x17, 0x65, 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b,
678 0x18, 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
679 0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19, 0xdd,
680 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e, 0x1a, 0xc5,
681 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b, 0x8a, 0x1b, 0xb2,
682 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52, 0x1c, 0x7b, 0x1c, 0xa3,
683 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d, 0x47, 0x1d, 0x70, 0x1d, 0x99,
684 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16, 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94,
685 0x1e, 0xbe, 0x1e, 0xe9, 0x1f, 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94,
686 0x1f, 0xbf, 0x1f, 0xea, 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98,
687 0x20, 0xc4, 0x20, 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1,
688 0x21, 0xce, 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf,
689 0x22, 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
690 0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24, 0xda,
691 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7, 0x25, 0xf7,
692 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26, 0xe8, 0x27, 0x18,
693 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc, 0x28, 0x0d, 0x28, 0x3f,
694 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29, 0x06, 0x29, 0x38, 0x29, 0x6b,
695 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02, 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b,
696 0x2a, 0xcf, 0x2b, 0x02, 0x2b, 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1,
697 0x2c, 0x05, 0x2c, 0x39, 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c,
698 0x2d, 0x41, 0x2d, 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c,
699 0x2e, 0x82, 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91,
700 0x2f, 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
701 0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32, 0x2a,
702 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46, 0x33, 0x7f,
703 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34, 0x9e, 0x34, 0xd8,
704 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2, 0x35, 0xfd, 0x36, 0x37,
705 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37, 0x24, 0x37, 0x60, 0x37, 0x9c,
706 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05,
707 0x39, 0x42, 0x39, 0x7f, 0x39, 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74,
708 0x3a, 0xb2, 0x3a, 0xef, 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8,
709 0x3c, 0x27, 0x3c, 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61,
710 0x3d, 0xa1, 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0,
711 0x3f, 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
712 0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41, 0xee,
713 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a, 0x43, 0x7d,
714 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44, 0xce, 0x45, 0x12,
715 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22, 0x46, 0x67, 0x46, 0xab,
716 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47, 0xc0, 0x48, 0x05, 0x48, 0x4b,
717 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d, 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0,
718 0x4a, 0x37, 0x4a, 0x7d, 0x4a, 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a,
719 0x4b, 0xe2, 0x4c, 0x2a, 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a,
720 0x4d, 0x93, 0x4d, 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00,
721 0x4f, 0x49, 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb,
722 0x51, 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
723 0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54, 0x42,
724 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2, 0x56, 0x0f,
725 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57, 0x92, 0x57, 0xe0,
726 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a, 0x59, 0x69, 0x59, 0xb8,
727 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a, 0xf5, 0x5b, 0x45, 0x5b, 0x95,
728 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86, 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78,
729 0x5d, 0xc9, 0x5e, 0x1a, 0x5e, 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61,
730 0x5f, 0xb3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f,
731 0x61, 0xa2, 0x61, 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43,
732 0x63, 0x97, 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d,
733 0x65, 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
734 0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69, 0x43,
735 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7, 0x6b, 0x4f,
736 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d, 0x08, 0x6d, 0x60,
737 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4, 0x6f, 0x1e, 0x6f, 0x78,
738 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70, 0xe0, 0x71, 0x3a, 0x71, 0x95,
739 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6, 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8,
740 0x74, 0x14, 0x74, 0x70, 0x74, 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1,
741 0x76, 0x3e, 0x76, 0x9b, 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11,
742 0x78, 0x6e, 0x78, 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46,
743 0x7a, 0xa5, 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81,
744 0x7c, 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
745 0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81, 0x0a,
746 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4, 0x83, 0x57,
747 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85, 0x47, 0x85, 0xab,
748 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b, 0x87, 0x9f, 0x88, 0x04,
749 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89, 0x99, 0x89, 0xfe, 0x8a, 0x64,
750 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96, 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca,
751 0x8d, 0x31, 0x8d, 0x98, 0x8d, 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36,
752 0x8f, 0x9e, 0x90, 0x06, 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8,
753 0x92, 0x11, 0x92, 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20,
754 0x94, 0x8a, 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f,
755 0x97, 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
756 0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b, 0xaf,
757 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2, 0x9e, 0x40,
758 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0, 0x69, 0xa0, 0xd8,
759 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96, 0xa3, 0x06, 0xa3, 0x76,
760 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5, 0x38, 0xa5, 0xa9, 0xa6, 0x1a,
761 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e, 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4,
762 0xa9, 0x37, 0xa9, 0xa9, 0xaa, 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75,
763 0xab, 0xe9, 0xac, 0x5c, 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d,
764 0xae, 0xa1, 0xaf, 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea,
765 0xb1, 0x60, 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae,
766 0xb4, 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
767 0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9, 0x4a,
768 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7, 0xbc, 0x21,
769 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe, 0x84, 0xbe, 0xff,
770 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec, 0xc1, 0x67, 0xc1, 0xe3,
771 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3, 0xd4, 0xc4, 0x51, 0xc4, 0xce,
772 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46, 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf,
773 0xc8, 0x3d, 0xc8, 0xbc, 0xc9, 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7,
774 0xcb, 0x36, 0xcb, 0xb6, 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5,
775 0xce, 0x36, 0xce, 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba,
776 0xd1, 0x3c, 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6,
777 0xd4, 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
778 0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9, 0xf1,
779 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a, 0xdd, 0x10,
780 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf, 0xaf, 0xe0, 0x36,
781 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53, 0xe2, 0xdb, 0xe3, 0x63,
782 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5, 0x84, 0xe6, 0x0d, 0xe6, 0x96,
783 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32, 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0,
784 0xea, 0x5b, 0xea, 0xe5, 0xeb, 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11,
785 0xed, 0x9c, 0xee, 0x28, 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58,
786 0xf0, 0xe5, 0xf1, 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7,
787 0xf4, 0x34, 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb,
788 0xf7, 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
789 0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd, 0xba,
790 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
799 assert(image != (Image *) NULL);
800 assert(image->signature == MagickCoreSignature);
801 if (GetImageProfile(image,
"icc") != (
const StringInfo *) NULL)
803 profile=AcquireStringInfo(
sizeof(sRGBProfile));
804 SetStringInfoDatum(profile,sRGBProfile);
805 status=SetImageProfile(image,
"icc",profile);
806 profile=DestroyStringInfo(profile);
810MagickExport MagickBooleanType ProfileImage(Image *image,
const char *name,
811 const void *datum,
const size_t length,
812 const MagickBooleanType magick_unused(clone))
814#define GetLCMSPixel(source_info,pixel,index) (source_info.scale[index]* \
815 ((QuantumScale*(MagickRealType) (pixel))+source_info.translate[index]))
816#define ProfileImageTag "Profile/Image"
817#define SetLCMSPixel(target_info,pixel,index) ClampToQuantum( \
818 target_info.scale[index]*(((MagickRealType) QuantumRange*pixel)+ \
819 target_info.translate[index]))
820#define ThrowProfileException(severity,tag,context) \
822 if (profile != (StringInfo *) NULL) \
823 profile=DestroyStringInfo(profile); \
824 if (cms_context != (cmsContext) NULL) \
825 cmsDeleteContext(cms_context); \
826 if (source_info.profile != (cmsHPROFILE) NULL) \
827 (void) cmsCloseProfile(source_info.profile); \
828 if (target_info.profile != (cmsHPROFILE) NULL) \
829 (void) cmsCloseProfile(target_info.profile); \
830 ThrowBinaryException(severity,tag,context); \
839 magick_unreferenced(clone);
841 assert(image != (Image *) NULL);
842 assert(image->signature == MagickCoreSignature);
843 assert(name != (
const char *) NULL);
844 if (IsEventLogging() != MagickFalse)
845 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
846 if ((datum == (
const void *) NULL) || (length == 0))
854 ResetImageProfileIterator(image);
855 for (next=GetNextImageProfile(image); next != (
const char *) NULL; )
857 if (IsOptionMember(next,name) != MagickFalse)
859 (void) DeleteImageProfile(image,next);
860 ResetImageProfileIterator(image);
862 next=GetNextImageProfile(image);
870 profile=AcquireStringInfo((
size_t) length);
871 SetStringInfoDatum(profile,(
unsigned char *) datum);
872 if ((LocaleCompare(name,
"icc") != 0) && (LocaleCompare(name,
"icm") != 0))
873 status=SetImageProfile(image,name,profile);
879 icc_profile=GetImageProfile(image,
"icc");
880 if ((icc_profile != (
const StringInfo *) NULL) &&
881 (CompareStringInfo(icc_profile,profile) == 0))
886 value=GetImageProperty(image,
"exif:ColorSpace");
888 if (LocaleCompare(value,
"1") != 0)
889 (void) SetsRGBImageProfile(image);
890 value=GetImageProperty(image,
"exif:InteroperabilityIndex");
891 if (LocaleCompare(value,
"R98.") != 0)
892 (void) SetsRGBImageProfile(image);
893 icc_profile=GetImageProfile(image,
"icc");
895 if ((icc_profile != (
const StringInfo *) NULL) &&
896 (CompareStringInfo(icc_profile,profile) == 0))
898 profile=DestroyStringInfo(profile);
901#if !defined(MAGICKCORE_LCMS_DELEGATE)
902 (void) ThrowMagickException(&image->exception,GetMagickModule(),
903 MissingDelegateWarning,
"DelegateLibrarySupportNotBuiltIn",
"`%s' (LCMS)",
917 cms_context=cmsCreateContext(NULL,image);
918 if (cms_context == (cmsContext) NULL)
920 profile=DestroyStringInfo(profile);
921 ThrowBinaryImageException(ResourceLimitError,
922 "ColorspaceColorProfileMismatch",name);
924 cmsSetLogErrorHandlerTHR(cms_context,LCMSExceptionHandler);
925 source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
926 GetStringInfoDatum(profile),(cmsUInt32Number)
927 GetStringInfoLength(profile));
928 if (source_info.profile == (cmsHPROFILE) NULL)
930 profile=DestroyStringInfo(profile);
931 cmsDeleteContext(cms_context);
932 ThrowBinaryImageException(ResourceLimitError,
933 "ColorspaceColorProfileMismatch",name);
935 if ((cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass) &&
936 (icc_profile == (StringInfo *) NULL))
937 status=SetImageProfile(image,name,profile);
943 cmsColorSpaceSignature
947 *magick_restrict transform;
961 exception=(&image->exception);
962 target_info.profile=(cmsHPROFILE) NULL;
963 if (icc_profile != (StringInfo *) NULL)
965 target_info.profile=source_info.profile;
966 source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
967 GetStringInfoDatum(icc_profile),(cmsUInt32Number)
968 GetStringInfoLength(icc_profile));
969 if (source_info.profile == (cmsHPROFILE) NULL)
970 ThrowProfileException(ResourceLimitError,
971 "ColorspaceColorProfileMismatch",name);
973 SetLCMSInfoScale(&source_info,1.0);
974 SetLCMSInfoTranslate(&source_info,0.0);
975 source_info.colorspace=sRGBColorspace;
976 source_info.channels=3;
977 switch (cmsGetColorSpace(source_info.profile))
981 source_info.colorspace=CMYKColorspace;
982 source_info.channels=4;
983 source_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
984 SetLCMSInfoScale(&source_info,100.0);
989 source_info.colorspace=GRAYColorspace;
990 source_info.channels=1;
991 source_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
996 source_info.colorspace=LabColorspace;
997 source_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
998 source_info.scale[0]=100.0;
999 source_info.scale[1]=255.0;
1000 source_info.scale[2]=255.0;
1001#if !defined(MAGICKCORE_HDRI_SUPPORT)
1002 source_info.translate[1]=(-0.5);
1003 source_info.translate[2]=(-0.5);
1009 source_info.colorspace=sRGBColorspace;
1010 source_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1015 source_info.colorspace=XYZColorspace;
1016 source_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1020 ThrowProfileException(ImageError,
1021 "ColorspaceColorProfileMismatch",name);
1023 signature=cmsGetPCS(source_info.profile);
1024 if (target_info.profile != (cmsHPROFILE) NULL)
1025 signature=cmsGetColorSpace(target_info.profile);
1026 SetLCMSInfoScale(&target_info,1.0);
1027 SetLCMSInfoTranslate(&target_info,0.0);
1028 target_info.channels=3;
1031 case cmsSigCmykData:
1033 target_info.colorspace=CMYKColorspace;
1034 target_info.channels=4;
1035 target_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1036 SetLCMSInfoScale(&target_info,0.01);
1039 case cmsSigGrayData:
1041 target_info.colorspace=GRAYColorspace;
1042 target_info.channels=1;
1043 target_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1048 target_info.colorspace=LabColorspace;
1049 target_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1050 target_info.scale[0]=0.01;
1051 target_info.scale[1]=1/255.0;
1052 target_info.scale[2]=1/255.0;
1053#if !defined(MAGICKCORE_HDRI_SUPPORT)
1054 target_info.translate[1]=0.5;
1055 target_info.translate[2]=0.5;
1061 target_info.colorspace=sRGBColorspace;
1062 target_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1067 target_info.colorspace=XYZColorspace;
1068 target_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1072 ThrowProfileException(ImageError,
1073 "ColorspaceColorProfileMismatch",name);
1075 switch (image->rendering_intent)
1077 case AbsoluteIntent:
1079 target_info.intent=INTENT_ABSOLUTE_COLORIMETRIC;
1082 case PerceptualIntent:
1084 target_info.intent=INTENT_PERCEPTUAL;
1087 case RelativeIntent:
1089 target_info.intent=INTENT_RELATIVE_COLORIMETRIC;
1092 case SaturationIntent:
1094 target_info.intent=INTENT_SATURATION;
1099 target_info.intent=INTENT_PERCEPTUAL;
1103 flags=cmsFLAGS_HIGHRESPRECALC;
1104#if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1105 if (image->black_point_compensation != MagickFalse)
1106 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1108 transform=AcquireTransformTLS(&source_info,&target_info,
1110 if (transform == (cmsHTRANSFORM *) NULL)
1111 ThrowProfileException(ImageError,
"UnableToCreateColorTransform",
1116 source_info.pixels=AcquirePixelTLS(image->columns,
1117 source_info.channels);
1118 target_info.pixels=AcquirePixelTLS(image->columns,
1119 target_info.channels);
1120 if ((source_info.pixels == (
double **) NULL) ||
1121 (target_info.pixels == (
double **) NULL))
1123 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1124 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1125 transform=DestroyTransformTLS(transform);
1126 ThrowProfileException(ResourceLimitError,
1127 "MemoryAllocationFailed",image->filename);
1129 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1131 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1132 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1133 transform=DestroyTransformTLS(transform);
1134 profile=DestroyStringInfo(profile);
1135 if (source_info.profile != (cmsHPROFILE) NULL)
1136 (void) cmsCloseProfile(source_info.profile);
1137 if (target_info.profile != (cmsHPROFILE) NULL)
1138 (void) cmsCloseProfile(target_info.profile);
1139 return(MagickFalse);
1141 if (target_info.colorspace == CMYKColorspace)
1142 (void) SetImageColorspace(image,target_info.colorspace);
1144 image_view=AcquireAuthenticCacheView(image,exception);
1145#if defined(MAGICKCORE_OPENMP_SUPPORT)
1146 #pragma omp parallel for schedule(static) shared(status) \
1147 magick_number_threads(image,image,image->rows,1)
1149 for (y=0; y < (ssize_t) image->rows; y++)
1152 id = GetOpenMPThreadId();
1158 *magick_restrict indexes;
1169 if (status == MagickFalse)
1171 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1173 if (q == (PixelPacket *) NULL)
1178 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1179 p=source_info.pixels[id];
1180 for (x=0; x < (ssize_t) image->columns; x++)
1182 *p++=GetLCMSPixel(source_info,GetPixelRed(q),0);
1183 if (source_info.channels > 1)
1185 *p++=GetLCMSPixel(source_info,GetPixelGreen(q),1);
1186 *p++=GetLCMSPixel(source_info,GetPixelBlue(q),2);
1188 if (source_info.channels > 3)
1190 *p=GetLCMSPixel(source_info,0,3);
1191 if (indexes != (IndexPacket *) NULL)
1192 *p=GetLCMSPixel(source_info,GetPixelIndex(indexes+x),3);
1197 cmsDoTransform(transform[
id],source_info.pixels[
id],
1198 target_info.pixels[
id],(
unsigned int) image->columns);
1199 p=target_info.pixels[id];
1201 for (x=0; x < (ssize_t) image->columns; x++)
1203 SetPixelRed(q,SetLCMSPixel(target_info,*p,0));
1204 SetPixelGreen(q,GetPixelRed(q));
1205 SetPixelBlue(q,GetPixelRed(q));
1207 if (target_info.channels > 1)
1209 SetPixelGreen(q,SetLCMSPixel(target_info,*p,1));
1211 SetPixelBlue(q,SetLCMSPixel(target_info,*p,2));
1214 if (target_info.channels > 3)
1216 if (indexes != (IndexPacket *) NULL)
1217 SetPixelIndex(indexes+x,SetLCMSPixel(target_info,*p,3));
1222 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1223 if (sync == MagickFalse)
1225 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1230#if defined(MAGICKCORE_OPENMP_SUPPORT)
1234 proceed=SetImageProgress(image,ProfileImageTag,progress,
1236 if (proceed == MagickFalse)
1240 image_view=DestroyCacheView(image_view);
1241 (void) SetImageColorspace(image,target_info.colorspace);
1246 image->type=image->matte == MagickFalse ? TrueColorType :
1250 case cmsSigCmykData:
1252 image->type=image->matte == MagickFalse ? ColorSeparationType :
1253 ColorSeparationMatteType;
1256 case cmsSigGrayData:
1258 image->type=image->matte == MagickFalse ? GrayscaleType :
1265 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1266 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1267 transform=DestroyTransformTLS(transform);
1268 if ((status != MagickFalse) &&
1269 (cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass))
1270 status=SetImageProfile(image,name,profile);
1271 if (target_info.profile != (cmsHPROFILE) NULL)
1272 (void) cmsCloseProfile(target_info.profile);
1274 (void) cmsCloseProfile(source_info.profile);
1275 cmsDeleteContext(cms_context);
1279 profile=DestroyStringInfo(profile);
1308MagickExport StringInfo *RemoveImageProfile(Image *image,
const char *name)
1313 assert(image != (Image *) NULL);
1314 assert(image->signature == MagickCoreSignature);
1315 if (IsEventLogging() != MagickFalse)
1316 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1317 if (image->profiles == (SplayTreeInfo *) NULL)
1318 return((StringInfo *) NULL);
1319 if (LocaleCompare(name,
"icc") == 0)
1324 image->color_profile.length=0;
1325 image->color_profile.info=(
unsigned char *) NULL;
1327 if (LocaleCompare(name,
"iptc") == 0)
1332 image->iptc_profile.length=0;
1333 image->iptc_profile.info=(
unsigned char *) NULL;
1335 WriteTo8BimProfile(image,name,(StringInfo *) NULL);
1336 profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
1337 image->profiles,name);
1365MagickExport
void ResetImageProfileIterator(
const Image *image)
1367 assert(image != (Image *) NULL);
1368 assert(image->signature == MagickCoreSignature);
1369 if (IsEventLogging() != MagickFalse)
1370 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1371 if (image->profiles == (SplayTreeInfo *) NULL)
1373 ResetSplayTreeIterator((SplayTreeInfo *) image->profiles);
1407static void *DestroyProfile(
void *profile)
1409 return((
void *) DestroyStringInfo((StringInfo *) profile));
1412static inline const unsigned char *ReadResourceByte(
const unsigned char *p,
1413 unsigned char *quantum)
1419static inline const unsigned char *ReadResourceLong(
const unsigned char *p,
1420 unsigned int *quantum)
1422 *quantum=(
unsigned int) (*p++) << 24;
1423 *quantum|=(
unsigned int) (*p++) << 16;
1424 *quantum|=(
unsigned int) (*p++) << 8;
1425 *quantum|=(
unsigned int) (*p++);
1429static inline const unsigned char *ReadResourceShort(
const unsigned char *p,
1430 unsigned short *quantum)
1432 *quantum=(
unsigned short) (*p++) << 8;
1433 *quantum|=(
unsigned short) (*p++);
1437static inline void WriteResourceLong(
unsigned char *p,
1438 const unsigned int quantum)
1443 buffer[0]=(
unsigned char) (quantum >> 24);
1444 buffer[1]=(
unsigned char) (quantum >> 16);
1445 buffer[2]=(
unsigned char) (quantum >> 8);
1446 buffer[3]=(
unsigned char) quantum;
1447 (void) memcpy(p,buffer,4);
1450static void WriteTo8BimProfile(Image *image,
const char *name,
1451 const StringInfo *profile)
1480 if (LocaleCompare(name,
"icc") == 0)
1483 if (LocaleCompare(name,
"iptc") == 0)
1486 if (LocaleCompare(name,
"xmp") == 0)
1490 profile_8bim=(StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
1491 image->profiles,
"8bim");
1492 if (profile_8bim == (StringInfo *) NULL)
1494 datum=GetStringInfoDatum(profile_8bim);
1495 length=GetStringInfoLength(profile_8bim);
1496 for (p=datum; p < (datum+length-16); )
1499 if (LocaleNCompare((
char *) p,
"8BIM",4) != 0)
1502 p=ReadResourceShort(p,&
id);
1503 p=ReadResourceByte(p,&length_byte);
1504 p+=(ptrdiff_t) length_byte;
1505 if (((length_byte+1) & 0x01) != 0)
1507 if (p > (datum+length-4))
1509 p=ReadResourceLong(p,&value);
1510 count=(ssize_t) value;
1511 if ((count & 0x01) != 0)
1513 if ((count < 0) || (p > (datum+length-count)) || (count > (ssize_t) length))
1515 if (
id != profile_id)
1516 p+=(ptrdiff_t) count;
1530 extent=(datum+length)-(p+count);
1531 if (profile == (StringInfo *) NULL)
1534 extract_profile=AcquireStringInfo(offset+extent);
1535 (void) memcpy(extract_profile->datum,datum,offset);
1540 extract_extent=profile->length;
1541 if ((extract_extent & 0x01) != 0)
1543 extract_profile=AcquireStringInfo(offset+extract_extent+extent);
1544 (void) memcpy(extract_profile->datum,datum,offset-4);
1545 WriteResourceLong(extract_profile->datum+offset-4,(
unsigned int)
1547 (void) memcpy(extract_profile->datum+offset,
1548 profile->datum,profile->length);
1550 (void) memcpy(extract_profile->datum+offset+extract_extent,
1552 (void) AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1553 ConstantString(
"8bim"),CloneStringInfo(extract_profile));
1554 extract_profile=DestroyStringInfo(extract_profile);
1560static void GetProfilesFromResourceBlock(Image *image,
1561 const StringInfo *resource_block)
1587 datum=GetStringInfoDatum(resource_block);
1588 length=GetStringInfoLength(resource_block);
1589 for (p=datum; p < (datum+length-16); )
1591 if (LocaleNCompare((
char *) p,
"8BIM",4) != 0)
1594 p=ReadResourceShort(p,&
id);
1595 p=ReadResourceByte(p,&length_byte);
1596 p+=(ptrdiff_t) length_byte;
1597 if (((length_byte+1) & 0x01) != 0)
1599 if (p > (datum+length-4))
1601 p=ReadResourceLong(p,&value);
1602 count=(ssize_t) value;
1603 if ((p > (datum+length-count)) || (count > (ssize_t) length) ||
1621 p=ReadResourceLong(p,&resolution);
1622 image->x_resolution=((double) resolution)/65536.0;
1623 p=ReadResourceShort(p,&units)+2;
1624 p=ReadResourceLong(p,&resolution)+4;
1625 image->y_resolution=((double) resolution)/65536.0;
1629 if ((ResolutionType) units != PixelsPerCentimeterResolution)
1630 image->units=PixelsPerInchResolution;
1633 image->units=PixelsPerCentimeterResolution;
1634 image->x_resolution/=2.54;
1635 image->y_resolution/=2.54;
1644 profile=AcquireStringInfo(count);
1645 SetStringInfoDatum(profile,p);
1646 (void) SetImageProfileInternal(image,
"iptc",profile,MagickTrue);
1647 profile=DestroyStringInfo(profile);
1648 p+=(ptrdiff_t) count;
1656 p+=(ptrdiff_t) count;
1664 profile=AcquireStringInfo(count);
1665 SetStringInfoDatum(profile,p);
1666 (void) SetImageProfileInternal(image,
"icc",profile,MagickTrue);
1667 profile=DestroyStringInfo(profile);
1668 p+=(ptrdiff_t) count;
1676 profile=AcquireStringInfo(count);
1677 SetStringInfoDatum(profile,p);
1678 (void) SetImageProfileInternal(image,
"exif",profile,MagickTrue);
1679 profile=DestroyStringInfo(profile);
1680 p+=(ptrdiff_t) count;
1688 profile=AcquireStringInfo(count);
1689 SetStringInfoDatum(profile,p);
1690 (void) SetImageProfileInternal(image,
"xmp",profile,MagickTrue);
1691 profile=DestroyStringInfo(profile);
1692 p+=(ptrdiff_t) count;
1697 p+=(ptrdiff_t) count;
1701 if ((count & 0x01) != 0)
1706#if defined(MAGICKCORE_XML_DELEGATE)
1707static MagickBooleanType ValidateXMPProfile(Image *image,
1708 const StringInfo *profile)
1716 const char *artifact=GetImageArtifact(image,
"xmp:validate");
1717 if (IsStringTrue(artifact) == MagickFalse)
1719 document=xmlReadMemory((
const char *) GetStringInfoDatum(profile),(
int)
1720 GetStringInfoLength(profile),
"xmp.xml",NULL,XML_PARSE_NOERROR |
1721 XML_PARSE_NOWARNING);
1722 if (document == (xmlDocPtr) NULL)
1724 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1725 ImageWarning,
"CorruptImageProfile",
"`%s' (XMP)",image->filename);
1726 return(MagickFalse);
1728 xmlFreeDoc(document);
1732static MagickBooleanType ValidateXMPProfile(Image *image,
1733 const StringInfo *profile)
1735 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1736 MissingDelegateWarning,
"DelegateLibrarySupportNotBuiltIn",
"'%s' (XML)",
1738 return(MagickFalse);
1742static MagickBooleanType SetImageProfileInternal(Image *image,
const char *name,
1743 const StringInfo *profile,
const MagickBooleanType recursive)
1751 assert(image != (Image *) NULL);
1752 assert(image->signature == MagickCoreSignature);
1753 if (IsEventLogging() != MagickFalse)
1754 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1755 if ((LocaleCompare(name,
"xmp") == 0) &&
1756 (ValidateXMPProfile(image,profile) == MagickFalse))
1758 if (image->profiles == (SplayTreeInfo *) NULL)
1759 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
1761 (void) CopyMagickString(key,name,MaxTextExtent);
1763 status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1764 ConstantString(key),CloneStringInfo(profile));
1765 if ((status != MagickFalse) &&
1766 ((LocaleCompare(name,
"icc") == 0) || (LocaleCompare(name,
"icm") == 0)))
1774 icc_profile=GetImageProfile(image,name);
1775 if (icc_profile != (
const StringInfo *) NULL)
1777 image->color_profile.length=GetStringInfoLength(icc_profile);
1778 image->color_profile.info=GetStringInfoDatum(icc_profile);
1781 if ((status != MagickFalse) &&
1782 ((LocaleCompare(name,
"iptc") == 0) || (LocaleCompare(name,
"8bim") == 0)))
1790 iptc_profile=GetImageProfile(image,name);
1791 if (iptc_profile != (
const StringInfo *) NULL)
1793 image->iptc_profile.length=GetStringInfoLength(iptc_profile);
1794 image->iptc_profile.info=GetStringInfoDatum(iptc_profile);
1797 if (status != MagickFalse)
1799 if (LocaleCompare(name,
"8bim") == 0)
1800 GetProfilesFromResourceBlock(image,profile);
1802 if (recursive == MagickFalse)
1803 WriteTo8BimProfile(image,name,profile);
1808MagickExport MagickBooleanType SetImageProfile(Image *image,
const char *name,
1809 const StringInfo *profile)
1811 return(SetImageProfileInternal(image,name,profile,MagickFalse));
1838static inline int ReadProfileByte(
unsigned char **p,
size_t *length)
1850static inline signed short ReadProfileShort(
const EndianType endian,
1851 unsigned char *buffer)
1865 if (endian == LSBEndian)
1867 value=(
unsigned short) buffer[1] << 8;
1868 value|=(
unsigned short) buffer[0];
1869 quantum.unsigned_value=value & 0xffff;
1870 return(quantum.signed_value);
1872 value=(
unsigned short) buffer[0] << 8;
1873 value|=(
unsigned short) buffer[1];
1874 quantum.unsigned_value=value & 0xffff;
1875 return(quantum.signed_value);
1878static inline signed int ReadProfileLong(
const EndianType endian,
1879 unsigned char *buffer)
1893 if (endian == LSBEndian)
1895 value=(
unsigned int) buffer[3] << 24;
1896 value|=(
unsigned int) buffer[2] << 16;
1897 value|=(
unsigned int) buffer[1] << 8;
1898 value|=(
unsigned int) buffer[0];
1899 quantum.unsigned_value=value & 0xffffffff;
1900 return(quantum.signed_value);
1902 value=(
unsigned int) buffer[0] << 24;
1903 value|=(
unsigned int) buffer[1] << 16;
1904 value|=(
unsigned int) buffer[2] << 8;
1905 value|=(
unsigned int) buffer[3];
1906 quantum.unsigned_value=value & 0xffffffff;
1907 return(quantum.signed_value);
1910static inline signed int ReadProfileMSBLong(
unsigned char **p,
size_t *length)
1917 value=ReadProfileLong(MSBEndian,*p);
1923static inline signed short ReadProfileMSBShort(
unsigned char **p,
1931 value=ReadProfileShort(MSBEndian,*p);
1937static inline void WriteProfileLong(
const EndianType endian,
1938 const size_t value,
unsigned char *p)
1943 if (endian == LSBEndian)
1945 buffer[0]=(
unsigned char) value;
1946 buffer[1]=(
unsigned char) (value >> 8);
1947 buffer[2]=(
unsigned char) (value >> 16);
1948 buffer[3]=(
unsigned char) (value >> 24);
1949 (void) memcpy(p,buffer,4);
1952 buffer[0]=(
unsigned char) (value >> 24);
1953 buffer[1]=(
unsigned char) (value >> 16);
1954 buffer[2]=(
unsigned char) (value >> 8);
1955 buffer[3]=(
unsigned char) value;
1956 (void) memcpy(p,buffer,4);
1959static void WriteProfileShort(
const EndianType endian,
1960 const unsigned short value,
unsigned char *p)
1965 if (endian == LSBEndian)
1967 buffer[0]=(
unsigned char) value;
1968 buffer[1]=(
unsigned char) (value >> 8);
1969 (void) memcpy(p,buffer,2);
1972 buffer[0]=(
unsigned char) (value >> 8);
1973 buffer[1]=(
unsigned char) value;
1974 (void) memcpy(p,buffer,2);
1977static MagickBooleanType SyncExifProfile(
const Image *image,
unsigned char *exif,
1980#define MaxDirectoryStack 16
1981#define EXIF_DELIMITER "\n"
1982#define EXIF_NUM_FORMATS 12
1983#define TAG_EXIF_OFFSET 0x8769
1984#define TAG_INTEROP_OFFSET 0xa005
1986 typedef struct _DirectoryInfo
1996 directory_stack[MaxDirectoryStack] = { { 0, 0 } };
2014 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
2020 return(MagickFalse);
2021 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2022 if ((
id != 0x4949) && (
id != 0x4D4D))
2026 if (ReadProfileByte(&exif,&length) != 0x45)
2028 if (ReadProfileByte(&exif,&length) != 0x78)
2030 if (ReadProfileByte(&exif,&length) != 0x69)
2032 if (ReadProfileByte(&exif,&length) != 0x66)
2034 if (ReadProfileByte(&exif,&length) != 0x00)
2036 if (ReadProfileByte(&exif,&length) != 0x00)
2041 return(MagickFalse);
2042 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2051 return(MagickFalse);
2052 if (ReadProfileShort(endian,exif+2) != 0x002a)
2053 return(MagickFalse);
2057 offset=(ssize_t) ReadProfileLong(endian,exif+4);
2058 if ((offset < 0) || ((
size_t) offset >= length))
2059 return(MagickFalse);
2060 directory=exif+offset;
2063 exif_resources=NewSplayTree((
int (*)(
const void *,
const void *)) NULL,
2064 (
void *(*)(
void *)) NULL,(
void *(*)(
void *)) NULL);
2070 directory=directory_stack[level].directory;
2071 entry=directory_stack[level].entry;
2073 if ((directory < exif) || (directory > (exif+length-2)))
2078 number_entries=ReadProfileShort(endian,directory);
2079 for ( ; entry < number_entries; entry++)
2095 q=(
unsigned char *) (directory+2+(12*entry));
2096 if (q > (exif+length-12))
2098 if (GetValueFromSplayTree(exif_resources,q) == q)
2100 (void) AddValueToSplayTree(exif_resources,q,q);
2101 tag_value=(ssize_t) ReadProfileShort(endian,q);
2102 format=(ssize_t) ReadProfileShort(endian,q+2);
2103 if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2105 components=(int) ReadProfileLong(endian,q+4);
2108 number_bytes=(size_t) components*format_bytes[format];
2109 if ((ssize_t) number_bytes < components)
2111 if (number_bytes <= 4)
2118 offset=(ssize_t) ReadProfileLong(endian,q+8);
2119 if ((offset < 0) || ((
size_t) (offset+number_bytes) > length))
2121 if (~length < number_bytes)
2123 p=(
unsigned char *) (exif+offset);
2129 (void) WriteProfileLong(endian,(
size_t) (image->x_resolution+0.5),p);
2130 if (number_bytes == 8)
2131 (void) WriteProfileLong(endian,1UL,p+4);
2136 (void) WriteProfileLong(endian,(
size_t) (image->y_resolution+0.5),p);
2137 if (number_bytes == 8)
2138 (void) WriteProfileLong(endian,1UL,p+4);
2143 if (number_bytes == 4)
2145 (void) WriteProfileLong(endian,(
size_t) image->orientation,p);
2148 (void) WriteProfileShort(endian,(
unsigned short) image->orientation,
2154 if (number_bytes == 4)
2156 (void) WriteProfileLong(endian,((
size_t) image->units)+1,p);
2159 (void) WriteProfileShort(endian,(
unsigned short) (image->units+1),p);
2165 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2167 offset=(ssize_t) ReadProfileLong(endian,p);
2168 if (((
size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2170 directory_stack[level].directory=directory;
2172 directory_stack[level].entry=entry;
2174 directory_stack[level].directory=exif+offset;
2175 directory_stack[level].entry=0;
2177 if ((directory+2+(12*number_entries)) > (exif+length))
2179 offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2181 if ((offset != 0) && ((
size_t) offset < length) &&
2182 (level < (MaxDirectoryStack-2)))
2184 directory_stack[level].directory=exif+offset;
2185 directory_stack[level].entry=0;
2192 }
while (level > 0);
2193 exif_resources=DestroySplayTree(exif_resources);
2197static MagickBooleanType Sync8BimProfile(
const Image *image,
2198 const StringInfo *profile)
2212 length=GetStringInfoLength(profile);
2213 p=GetStringInfoDatum(profile);
2216 if (ReadProfileByte(&p,&length) != 0x38)
2218 if (ReadProfileByte(&p,&length) != 0x42)
2220 if (ReadProfileByte(&p,&length) != 0x49)
2222 if (ReadProfileByte(&p,&length) != 0x4D)
2225 return(MagickFalse);
2226 id=ReadProfileMSBShort(&p,&length);
2227 count=(ssize_t) ReadProfileByte(&p,&length);
2228 if ((count >= (ssize_t) length) || (count < 0))
2229 return(MagickFalse);
2230 p+=(ptrdiff_t) count;
2232 if ((*p & 0x01) == 0)
2233 (void) ReadProfileByte(&p,&length);
2234 count=(ssize_t) ReadProfileMSBLong(&p,&length);
2235 if ((count > (ssize_t) length) || (count < 0))
2236 return(MagickFalse);
2237 if ((
id == 0x3ED) && (count == 16))
2239 if (image->units == PixelsPerCentimeterResolution)
2240 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2241 image->x_resolution*2.54*65536.0),p);
2243 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2244 image->x_resolution*65536.0),p);
2245 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+4);
2246 if (image->units == PixelsPerCentimeterResolution)
2247 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2248 image->y_resolution*2.54*65536.0),p+8);
2250 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2251 image->y_resolution*65536.0),p+8);
2252 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+12);
2255 (void) SyncExifProfile(image,p,count);
2256 p+=(ptrdiff_t) count;
2262MagickExport MagickBooleanType SyncImageProfiles(Image *image)
2271 profile=(StringInfo *) GetImageProfile(image,
"8BIM");
2272 if (profile != (StringInfo *) NULL)
2273 if (Sync8BimProfile(image,profile) == MagickFalse)
2275 profile=(StringInfo *) GetImageProfile(image,
"EXIF");
2276 if (profile != (StringInfo *) NULL)
2277 if (SyncExifProfile(image,GetStringInfoDatum(profile),
2278 GetStringInfoLength(profile)) == MagickFalse)