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 *);
118MagickExport MagickBooleanType CloneImageProfiles(Image *image,
119 const Image *clone_image)
121 assert(image != (Image *) NULL);
122 assert(image->signature == MagickCoreSignature);
123 assert(clone_image != (
const Image *) NULL);
124 assert(clone_image->signature == MagickCoreSignature);
125 if (IsEventLogging() != MagickFalse)
126 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
127 image->color_profile.length=clone_image->color_profile.length;
128 image->color_profile.info=clone_image->color_profile.info;
129 image->iptc_profile.length=clone_image->iptc_profile.length;
130 image->iptc_profile.info=clone_image->iptc_profile.info;
131 if (clone_image->profiles != (
void *) NULL)
133 if (image->profiles != (
void *) NULL)
134 DestroyImageProfiles(image);
135 image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
136 (
void *(*)(
void *)) ConstantString,(
void *(*)(
void *)) CloneStringInfo);
165MagickExport MagickBooleanType DeleteImageProfile(Image *image,
const char *name)
167 assert(image != (Image *) NULL);
168 assert(image->signature == MagickCoreSignature);
169 if (image->debug != MagickFalse)
170 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
171 if (image->profiles == (SplayTreeInfo *) NULL)
173 if (LocaleCompare(name,
"icc") == 0)
178 image->color_profile.length=0;
179 image->color_profile.info=(
unsigned char *) NULL;
181 if (LocaleCompare(name,
"iptc") == 0)
186 image->iptc_profile.length=0;
187 image->iptc_profile.info=(
unsigned char *) NULL;
189 WriteTo8BimProfile(image,name,(StringInfo *) NULL);
190 return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->profiles,name));
215MagickExport
void DestroyImageProfiles(Image *image)
217 if (image->profiles != (SplayTreeInfo *) NULL)
218 image->profiles=DestroySplayTree((SplayTreeInfo *) image->profiles);
245MagickExport
const StringInfo *GetImageProfile(
const Image *image,
251 assert(image != (Image *) NULL);
252 assert(image->signature == MagickCoreSignature);
253 if (image->debug != MagickFalse)
254 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
255 if (image->profiles == (SplayTreeInfo *) NULL)
256 return((StringInfo *) NULL);
257 profile=(
const StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
258 image->profiles,name);
284MagickExport
char *GetNextImageProfile(
const Image *image)
286 assert(image != (Image *) NULL);
287 assert(image->signature == MagickCoreSignature);
288 if (IsEventLogging() != MagickFalse)
289 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
290 if (image->profiles == (SplayTreeInfo *) NULL)
291 return((
char *) NULL);
292 return((
char *) GetNextKeyInSplayTree((SplayTreeInfo *) image->profiles));
336#if defined(MAGICKCORE_LCMS_DELEGATE)
338typedef struct _LCMSInfo
356 **magick_restrict pixels,
361#if LCMS_VERSION < 2060
362static void* cmsGetContextUserData(cmsContext ContextID)
367static cmsContext cmsCreateContext(
void *magick_unused(Plugin),
void *UserData)
369 magick_unreferenced(Plugin);
370 return((cmsContext) UserData);
373static void cmsSetLogErrorHandlerTHR(cmsContext magick_unused(ContextID),
374 cmsLogErrorHandlerFunction Fn)
376 magick_unreferenced(ContextID);
377 cmsSetLogErrorHandler(Fn);
380static void cmsDeleteContext(cmsContext magick_unused(ContextID))
382 magick_unreferenced(ContextID);
386static double **DestroyPixelTLS(
double **pixels)
391 if (pixels == (
double **) NULL)
392 return((
double **) NULL);
393 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
394 if (pixels[i] != (
double *) NULL)
395 pixels[i]=(
double *) RelinquishMagickMemory(pixels[i]);
396 pixels=(
double **) RelinquishMagickMemory(pixels);
400static double **AcquirePixelTLS(
const size_t columns,
401 const size_t channels)
412 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
413 pixels=(
double **) AcquireQuantumMemory(number_threads,
sizeof(*pixels));
414 if (pixels == (
double **) NULL)
415 return((
double **) NULL);
416 (void) memset(pixels,0,number_threads*
sizeof(*pixels));
417 for (i=0; i < (ssize_t) number_threads; i++)
419 pixels[i]=(
double *) AcquireQuantumMemory(columns,channels*
sizeof(**pixels));
420 if (pixels[i] == (
double *) NULL)
421 return(DestroyPixelTLS(pixels));
426static cmsHTRANSFORM *DestroyTransformTLS(cmsHTRANSFORM *transform)
431 assert(transform != (cmsHTRANSFORM *) NULL);
432 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
433 if (transform[i] != (cmsHTRANSFORM) NULL)
434 cmsDeleteTransform(transform[i]);
435 transform=(cmsHTRANSFORM *) RelinquishMagickMemory(transform);
439static cmsHTRANSFORM *AcquireTransformTLS(
const LCMSInfo *source_info,
440 const LCMSInfo *target_info,
const cmsUInt32Number flags,
441 cmsContext cms_context)
452 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
453 transform=(cmsHTRANSFORM *) AcquireQuantumMemory(number_threads,
455 if (transform == (cmsHTRANSFORM *) NULL)
456 return((cmsHTRANSFORM *) NULL);
457 (void) memset(transform,0,number_threads*
sizeof(*transform));
458 for (i=0; i < (ssize_t) number_threads; i++)
460 transform[i]=cmsCreateTransformTHR(cms_context,source_info->profile,
461 source_info->type,target_info->profile,target_info->type,
462 target_info->intent,flags);
463 if (transform[i] == (cmsHTRANSFORM) NULL)
464 return(DestroyTransformTLS(transform));
469static void LCMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
475 if (IsEventLogging() != MagickFalse)
476 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
"lcms: #%u, %s",
477 severity,message != (
char *) NULL ? message :
"no message");
478 image=(Image *) cmsGetContextUserData(context);
479 if (image != (Image *) NULL)
480 (void) ThrowMagickException(&image->exception,GetMagickModule(),
481 ImageWarning,
"UnableToTransformColorspace",
"`%s'",image->filename);
484static inline void SetLCMSInfoTranslate(LCMSInfo *info,
const double translate)
486 info->translate[0]=translate;
487 info->translate[1]=translate;
488 info->translate[2]=translate;
489 info->translate[3]=translate;
492static inline void SetLCMSInfoScale(LCMSInfo *info,
const double scale)
494 info->scale[0]=scale;
495 info->scale[1]=scale;
496 info->scale[2]=scale;
497 info->scale[3]=scale;
501static MagickBooleanType SetsRGBImageProfile(Image *image)
506 0x00, 0x00, 0x0c, 0x8c, 0x61, 0x72, 0x67, 0x6c, 0x02, 0x20, 0x00, 0x00,
507 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
508 0x07, 0xde, 0x00, 0x01, 0x00, 0x06, 0x00, 0x16, 0x00, 0x0f, 0x00, 0x3a,
509 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
510 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00,
511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
512 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x61, 0x72, 0x67, 0x6c,
513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
517 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x99,
518 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0xec, 0x00, 0x00, 0x00, 0x67,
519 0x64, 0x6d, 0x6e, 0x64, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70,
520 0x64, 0x6d, 0x64, 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88,
521 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x0c,
522 0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x00, 0x67,
523 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x24,
524 0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xe4, 0x00, 0x00, 0x00, 0x14,
525 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x24,
526 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x14,
527 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x14,
528 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x14,
529 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x58, 0x00, 0x00, 0x00, 0x14,
530 0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x6c, 0x00, 0x00, 0x00, 0x14,
531 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
532 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
533 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
534 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
535 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36,
536 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75, 0x69, 0x76,
537 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x77, 0x77,
538 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x31, 0x39,
539 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c,
540 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 0x00, 0x3f, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31,
542 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75,
543 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77,
544 0x77, 0x77, 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20,
545 0x31, 0x39, 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66,
546 0x69, 0x6c, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, 0x61,
548 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x72, 0x61, 0x65, 0x6d,
549 0x65, 0x20, 0x57, 0x2e, 0x20, 0x47, 0x69, 0x6c, 0x6c, 0x2e, 0x20, 0x52,
550 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f,
551 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
552 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x4e, 0x6f, 0x20, 0x57,
553 0x61, 0x72, 0x72, 0x61, 0x6e, 0x74, 0x79, 0x2c, 0x20, 0x55, 0x73, 0x65,
554 0x20, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e,
555 0x20, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20,
557 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
558 0x65, 0x63, 0x2e, 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74,
560 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
561 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
566 0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e,
567 0x31, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47,
568 0x42, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61,
569 0x63, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
570 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43,
571 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
572 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63,
573 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
574 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00,
577 0x43, 0x52, 0x54, 0x20, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
579 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
581 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa4, 0x7c,
587 0x00, 0x14, 0x5f, 0x30, 0x00, 0x10, 0xce, 0x02, 0x00, 0x03, 0xed, 0xb2,
588 0x00, 0x04, 0x13, 0x0a, 0x00, 0x03, 0x5c, 0x67, 0x00, 0x00, 0x00, 0x01,
589 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x0a, 0x3d,
590 0x00, 0x50, 0x00, 0x00, 0x00, 0x57, 0x1e, 0xb8, 0x6d, 0x65, 0x61, 0x73,
591 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x58, 0x59, 0x5a, 0x20,
594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00,
595 0x00, 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa0,
598 0x00, 0x00, 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20,
599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x97, 0x00, 0x00, 0xb7, 0x87,
600 0x00, 0x00, 0x18, 0xd9, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
601 0x00, 0x00, 0x24, 0x9f, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0xb6, 0xc4,
602 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
603 0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19,
604 0x00, 0x1e, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37,
605 0x00, 0x3b, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54,
606 0x00, 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
607 0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00, 0x90,
608 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9, 0x00, 0xae,
609 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00, 0xc6, 0x00, 0xcb,
610 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0xeb,
611 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01, 0x01, 0x01, 0x07, 0x01, 0x0d,
612 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f, 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32,
613 0x01, 0x38, 0x01, 0x3e, 0x01, 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59,
614 0x01, 0x60, 0x01, 0x67, 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83,
615 0x01, 0x8b, 0x01, 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1,
616 0x01, 0xb9, 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1,
617 0x01, 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
618 0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02, 0x4b,
619 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a, 0x02, 0x84,
620 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02, 0xb6, 0x02, 0xc1,
621 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb, 0x02, 0xf5, 0x03, 0x00,
622 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2d, 0x03, 0x38, 0x03, 0x43,
623 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66, 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a,
624 0x03, 0x96, 0x03, 0xa2, 0x03, 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3,
625 0x03, 0xe0, 0x03, 0xec, 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20,
626 0x04, 0x2d, 0x04, 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71,
627 0x04, 0x7e, 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4,
628 0x04, 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
629 0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05, 0x77,
630 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5, 0x05, 0xd5,
631 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06, 0x27, 0x06, 0x37,
632 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b, 0x06, 0x8c, 0x06, 0x9d,
633 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06, 0xe3, 0x06, 0xf5, 0x07, 0x07,
634 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d, 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74,
635 0x07, 0x86, 0x07, 0x99, 0x07, 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5,
636 0x07, 0xf8, 0x08, 0x0b, 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a,
637 0x08, 0x6e, 0x08, 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2,
638 0x08, 0xe7, 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f,
639 0x09, 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
640 0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a, 0x54,
641 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5, 0x0a, 0xdc,
642 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b, 0x51, 0x0b, 0x69,
643 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8, 0x0b, 0xe1, 0x0b, 0xf9,
644 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c, 0x5c, 0x0c, 0x75, 0x0c, 0x8e,
645 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9, 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26,
646 0x0d, 0x40, 0x0d, 0x5a, 0x0d, 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3,
647 0x0d, 0xde, 0x0d, 0xf8, 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64,
648 0x0e, 0x7f, 0x0e, 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09,
649 0x0f, 0x25, 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3,
650 0x0f, 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
651 0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11, 0x13,
652 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa, 0x11, 0xc9,
653 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12, 0x64, 0x12, 0x84,
654 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03, 0x13, 0x23, 0x13, 0x43,
655 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13, 0xc5, 0x13, 0xe5, 0x14, 0x06,
656 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a, 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce,
657 0x14, 0xf0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b,
658 0x15, 0xbd, 0x15, 0xe0, 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c,
659 0x16, 0x8f, 0x16, 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41,
660 0x17, 0x65, 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b,
661 0x18, 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
662 0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19, 0xdd,
663 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e, 0x1a, 0xc5,
664 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b, 0x8a, 0x1b, 0xb2,
665 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52, 0x1c, 0x7b, 0x1c, 0xa3,
666 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d, 0x47, 0x1d, 0x70, 0x1d, 0x99,
667 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16, 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94,
668 0x1e, 0xbe, 0x1e, 0xe9, 0x1f, 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94,
669 0x1f, 0xbf, 0x1f, 0xea, 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98,
670 0x20, 0xc4, 0x20, 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1,
671 0x21, 0xce, 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf,
672 0x22, 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
673 0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24, 0xda,
674 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7, 0x25, 0xf7,
675 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26, 0xe8, 0x27, 0x18,
676 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc, 0x28, 0x0d, 0x28, 0x3f,
677 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29, 0x06, 0x29, 0x38, 0x29, 0x6b,
678 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02, 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b,
679 0x2a, 0xcf, 0x2b, 0x02, 0x2b, 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1,
680 0x2c, 0x05, 0x2c, 0x39, 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c,
681 0x2d, 0x41, 0x2d, 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c,
682 0x2e, 0x82, 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91,
683 0x2f, 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
684 0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32, 0x2a,
685 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46, 0x33, 0x7f,
686 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34, 0x9e, 0x34, 0xd8,
687 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2, 0x35, 0xfd, 0x36, 0x37,
688 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37, 0x24, 0x37, 0x60, 0x37, 0x9c,
689 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05,
690 0x39, 0x42, 0x39, 0x7f, 0x39, 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74,
691 0x3a, 0xb2, 0x3a, 0xef, 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8,
692 0x3c, 0x27, 0x3c, 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61,
693 0x3d, 0xa1, 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0,
694 0x3f, 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
695 0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41, 0xee,
696 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a, 0x43, 0x7d,
697 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44, 0xce, 0x45, 0x12,
698 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22, 0x46, 0x67, 0x46, 0xab,
699 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47, 0xc0, 0x48, 0x05, 0x48, 0x4b,
700 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d, 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0,
701 0x4a, 0x37, 0x4a, 0x7d, 0x4a, 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a,
702 0x4b, 0xe2, 0x4c, 0x2a, 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a,
703 0x4d, 0x93, 0x4d, 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00,
704 0x4f, 0x49, 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb,
705 0x51, 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
706 0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54, 0x42,
707 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2, 0x56, 0x0f,
708 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57, 0x92, 0x57, 0xe0,
709 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a, 0x59, 0x69, 0x59, 0xb8,
710 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a, 0xf5, 0x5b, 0x45, 0x5b, 0x95,
711 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86, 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78,
712 0x5d, 0xc9, 0x5e, 0x1a, 0x5e, 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61,
713 0x5f, 0xb3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f,
714 0x61, 0xa2, 0x61, 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43,
715 0x63, 0x97, 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d,
716 0x65, 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
717 0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69, 0x43,
718 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7, 0x6b, 0x4f,
719 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d, 0x08, 0x6d, 0x60,
720 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4, 0x6f, 0x1e, 0x6f, 0x78,
721 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70, 0xe0, 0x71, 0x3a, 0x71, 0x95,
722 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6, 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8,
723 0x74, 0x14, 0x74, 0x70, 0x74, 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1,
724 0x76, 0x3e, 0x76, 0x9b, 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11,
725 0x78, 0x6e, 0x78, 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46,
726 0x7a, 0xa5, 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81,
727 0x7c, 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
728 0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81, 0x0a,
729 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4, 0x83, 0x57,
730 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85, 0x47, 0x85, 0xab,
731 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b, 0x87, 0x9f, 0x88, 0x04,
732 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89, 0x99, 0x89, 0xfe, 0x8a, 0x64,
733 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96, 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca,
734 0x8d, 0x31, 0x8d, 0x98, 0x8d, 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36,
735 0x8f, 0x9e, 0x90, 0x06, 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8,
736 0x92, 0x11, 0x92, 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20,
737 0x94, 0x8a, 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f,
738 0x97, 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
739 0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b, 0xaf,
740 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2, 0x9e, 0x40,
741 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0, 0x69, 0xa0, 0xd8,
742 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96, 0xa3, 0x06, 0xa3, 0x76,
743 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5, 0x38, 0xa5, 0xa9, 0xa6, 0x1a,
744 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e, 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4,
745 0xa9, 0x37, 0xa9, 0xa9, 0xaa, 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75,
746 0xab, 0xe9, 0xac, 0x5c, 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d,
747 0xae, 0xa1, 0xaf, 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea,
748 0xb1, 0x60, 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae,
749 0xb4, 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
750 0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9, 0x4a,
751 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7, 0xbc, 0x21,
752 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe, 0x84, 0xbe, 0xff,
753 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec, 0xc1, 0x67, 0xc1, 0xe3,
754 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3, 0xd4, 0xc4, 0x51, 0xc4, 0xce,
755 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46, 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf,
756 0xc8, 0x3d, 0xc8, 0xbc, 0xc9, 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7,
757 0xcb, 0x36, 0xcb, 0xb6, 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5,
758 0xce, 0x36, 0xce, 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba,
759 0xd1, 0x3c, 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6,
760 0xd4, 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
761 0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9, 0xf1,
762 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a, 0xdd, 0x10,
763 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf, 0xaf, 0xe0, 0x36,
764 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53, 0xe2, 0xdb, 0xe3, 0x63,
765 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5, 0x84, 0xe6, 0x0d, 0xe6, 0x96,
766 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32, 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0,
767 0xea, 0x5b, 0xea, 0xe5, 0xeb, 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11,
768 0xed, 0x9c, 0xee, 0x28, 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58,
769 0xf0, 0xe5, 0xf1, 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7,
770 0xf4, 0x34, 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb,
771 0xf7, 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
772 0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd, 0xba,
773 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
782 assert(image != (Image *) NULL);
783 assert(image->signature == MagickCoreSignature);
784 if (GetImageProfile(image,
"icc") != (
const StringInfo *) NULL)
786 profile=AcquireStringInfo(
sizeof(sRGBProfile));
787 SetStringInfoDatum(profile,sRGBProfile);
788 status=SetImageProfile(image,
"icc",profile);
789 profile=DestroyStringInfo(profile);
793MagickExport MagickBooleanType ProfileImage(Image *image,
const char *name,
794 const void *datum,
const size_t length,
795 const MagickBooleanType magick_unused(clone))
797#define GetLCMSPixel(source_info,pixel,index) (source_info.scale[index]* \
798 ((QuantumScale*(MagickRealType) (pixel))+source_info.translate[index]))
799#define ProfileImageTag "Profile/Image"
800#define SetLCMSPixel(target_info,pixel,index) ClampToQuantum( \
801 target_info.scale[index]*(((MagickRealType) QuantumRange*pixel)+ \
802 target_info.translate[index]))
803#define ThrowProfileException(severity,tag,context) \
805 if (profile != (StringInfo *) NULL) \
806 profile=DestroyStringInfo(profile); \
807 if (cms_context != (cmsContext) NULL) \
808 cmsDeleteContext(cms_context); \
809 if (source_info.profile != (cmsHPROFILE) NULL) \
810 (void) cmsCloseProfile(source_info.profile); \
811 if (target_info.profile != (cmsHPROFILE) NULL) \
812 (void) cmsCloseProfile(target_info.profile); \
813 ThrowBinaryException(severity,tag,context); \
822 magick_unreferenced(clone);
824 assert(image != (Image *) NULL);
825 assert(image->signature == MagickCoreSignature);
826 assert(name != (
const char *) NULL);
827 if (IsEventLogging() != MagickFalse)
828 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
829 if ((datum == (
const void *) NULL) || (length == 0))
837 ResetImageProfileIterator(image);
838 for (next=GetNextImageProfile(image); next != (
const char *) NULL; )
840 if (IsOptionMember(next,name) != MagickFalse)
842 (void) DeleteImageProfile(image,next);
843 ResetImageProfileIterator(image);
845 next=GetNextImageProfile(image);
853 profile=AcquireStringInfo((
size_t) length);
854 SetStringInfoDatum(profile,(
unsigned char *) datum);
855 if ((LocaleCompare(name,
"icc") != 0) && (LocaleCompare(name,
"icm") != 0))
856 status=SetImageProfile(image,name,profile);
862 icc_profile=GetImageProfile(image,
"icc");
863 if ((icc_profile != (
const StringInfo *) NULL) &&
864 (CompareStringInfo(icc_profile,profile) == 0))
869 value=GetImageProperty(image,
"exif:ColorSpace");
871 if (LocaleCompare(value,
"1") != 0)
872 (void) SetsRGBImageProfile(image);
873 value=GetImageProperty(image,
"exif:InteroperabilityIndex");
874 if (LocaleCompare(value,
"R98.") != 0)
875 (void) SetsRGBImageProfile(image);
876 icc_profile=GetImageProfile(image,
"icc");
878 if ((icc_profile != (
const StringInfo *) NULL) &&
879 (CompareStringInfo(icc_profile,profile) == 0))
881 profile=DestroyStringInfo(profile);
884#if !defined(MAGICKCORE_LCMS_DELEGATE)
885 (void) ThrowMagickException(&image->exception,GetMagickModule(),
886 MissingDelegateWarning,
"DelegateLibrarySupportNotBuiltIn",
"`%s' (LCMS)",
900 cms_context=cmsCreateContext(NULL,image);
901 if (cms_context == (cmsContext) NULL)
903 profile=DestroyStringInfo(profile);
904 ThrowBinaryImageException(ResourceLimitError,
905 "ColorspaceColorProfileMismatch",name);
907 cmsSetLogErrorHandlerTHR(cms_context,LCMSExceptionHandler);
908 source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
909 GetStringInfoDatum(profile),(cmsUInt32Number)
910 GetStringInfoLength(profile));
911 if (source_info.profile == (cmsHPROFILE) NULL)
913 profile=DestroyStringInfo(profile);
914 cmsDeleteContext(cms_context);
915 ThrowBinaryImageException(ResourceLimitError,
916 "ColorspaceColorProfileMismatch",name);
918 if ((cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass) &&
919 (icc_profile == (StringInfo *) NULL))
920 status=SetImageProfile(image,name,profile);
926 cmsColorSpaceSignature
930 *magick_restrict transform;
944 exception=(&image->exception);
945 target_info.profile=(cmsHPROFILE) NULL;
946 if (icc_profile != (StringInfo *) NULL)
948 target_info.profile=source_info.profile;
949 source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
950 GetStringInfoDatum(icc_profile),(cmsUInt32Number)
951 GetStringInfoLength(icc_profile));
952 if (source_info.profile == (cmsHPROFILE) NULL)
953 ThrowProfileException(ResourceLimitError,
954 "ColorspaceColorProfileMismatch",name);
956 SetLCMSInfoScale(&source_info,1.0);
957 SetLCMSInfoTranslate(&source_info,0.0);
958 source_info.colorspace=sRGBColorspace;
959 source_info.channels=3;
960 switch (cmsGetColorSpace(source_info.profile))
964 source_info.colorspace=CMYKColorspace;
965 source_info.channels=4;
966 source_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
967 SetLCMSInfoScale(&source_info,100.0);
972 source_info.colorspace=GRAYColorspace;
973 source_info.channels=1;
974 source_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
979 source_info.colorspace=LabColorspace;
980 source_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
981 source_info.scale[0]=100.0;
982 source_info.scale[1]=255.0;
983 source_info.scale[2]=255.0;
984#if !defined(MAGICKCORE_HDRI_SUPPORT)
985 source_info.translate[1]=(-0.5);
986 source_info.translate[2]=(-0.5);
992 source_info.colorspace=sRGBColorspace;
993 source_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
998 source_info.colorspace=XYZColorspace;
999 source_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1003 ThrowProfileException(ImageError,
1004 "ColorspaceColorProfileMismatch",name);
1006 signature=cmsGetPCS(source_info.profile);
1007 if (target_info.profile != (cmsHPROFILE) NULL)
1008 signature=cmsGetColorSpace(target_info.profile);
1009 SetLCMSInfoScale(&target_info,1.0);
1010 SetLCMSInfoTranslate(&target_info,0.0);
1011 target_info.channels=3;
1014 case cmsSigCmykData:
1016 target_info.colorspace=CMYKColorspace;
1017 target_info.channels=4;
1018 target_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1019 SetLCMSInfoScale(&target_info,0.01);
1022 case cmsSigGrayData:
1024 target_info.colorspace=GRAYColorspace;
1025 target_info.channels=1;
1026 target_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1031 target_info.colorspace=LabColorspace;
1032 target_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1033 target_info.scale[0]=0.01;
1034 target_info.scale[1]=1/255.0;
1035 target_info.scale[2]=1/255.0;
1036#if !defined(MAGICKCORE_HDRI_SUPPORT)
1037 target_info.translate[1]=0.5;
1038 target_info.translate[2]=0.5;
1044 target_info.colorspace=sRGBColorspace;
1045 target_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1050 target_info.colorspace=XYZColorspace;
1051 target_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1055 ThrowProfileException(ImageError,
1056 "ColorspaceColorProfileMismatch",name);
1058 switch (image->rendering_intent)
1060 case AbsoluteIntent:
1062 target_info.intent=INTENT_ABSOLUTE_COLORIMETRIC;
1065 case PerceptualIntent:
1067 target_info.intent=INTENT_PERCEPTUAL;
1070 case RelativeIntent:
1072 target_info.intent=INTENT_RELATIVE_COLORIMETRIC;
1075 case SaturationIntent:
1077 target_info.intent=INTENT_SATURATION;
1082 target_info.intent=INTENT_PERCEPTUAL;
1086 flags=cmsFLAGS_HIGHRESPRECALC;
1087#if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1088 if (image->black_point_compensation != MagickFalse)
1089 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1091 transform=AcquireTransformTLS(&source_info,&target_info,
1093 if (transform == (cmsHTRANSFORM *) NULL)
1094 ThrowProfileException(ImageError,
"UnableToCreateColorTransform",
1099 source_info.pixels=AcquirePixelTLS(image->columns,
1100 source_info.channels);
1101 target_info.pixels=AcquirePixelTLS(image->columns,
1102 target_info.channels);
1103 if ((source_info.pixels == (
double **) NULL) ||
1104 (target_info.pixels == (
double **) NULL))
1106 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1107 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1108 transform=DestroyTransformTLS(transform);
1109 ThrowProfileException(ResourceLimitError,
1110 "MemoryAllocationFailed",image->filename);
1112 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1114 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1115 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1116 transform=DestroyTransformTLS(transform);
1117 profile=DestroyStringInfo(profile);
1118 if (source_info.profile != (cmsHPROFILE) NULL)
1119 (void) cmsCloseProfile(source_info.profile);
1120 if (target_info.profile != (cmsHPROFILE) NULL)
1121 (void) cmsCloseProfile(target_info.profile);
1122 return(MagickFalse);
1124 if (target_info.colorspace == CMYKColorspace)
1125 (void) SetImageColorspace(image,target_info.colorspace);
1127 image_view=AcquireAuthenticCacheView(image,exception);
1128#if defined(MAGICKCORE_OPENMP_SUPPORT)
1129 #pragma omp parallel for schedule(static) shared(status) \
1130 magick_number_threads(image,image,image->rows,1)
1132 for (y=0; y < (ssize_t) image->rows; y++)
1135 id = GetOpenMPThreadId();
1141 *magick_restrict indexes;
1152 if (status == MagickFalse)
1154 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1156 if (q == (PixelPacket *) NULL)
1161 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1162 p=source_info.pixels[id];
1163 for (x=0; x < (ssize_t) image->columns; x++)
1165 *p++=GetLCMSPixel(source_info,GetPixelRed(q),0);
1166 if (source_info.channels > 1)
1168 *p++=GetLCMSPixel(source_info,GetPixelGreen(q),1);
1169 *p++=GetLCMSPixel(source_info,GetPixelBlue(q),2);
1171 if (source_info.channels > 3)
1173 *p=GetLCMSPixel(source_info,0,3);
1174 if (indexes != (IndexPacket *) NULL)
1175 *p=GetLCMSPixel(source_info,GetPixelIndex(indexes+x),3);
1180 cmsDoTransform(transform[
id],source_info.pixels[
id],
1181 target_info.pixels[
id],(
unsigned int) image->columns);
1182 p=target_info.pixels[id];
1184 for (x=0; x < (ssize_t) image->columns; x++)
1186 SetPixelRed(q,SetLCMSPixel(target_info,*p,0));
1187 SetPixelGreen(q,GetPixelRed(q));
1188 SetPixelBlue(q,GetPixelRed(q));
1190 if (target_info.channels > 1)
1192 SetPixelGreen(q,SetLCMSPixel(target_info,*p,1));
1194 SetPixelBlue(q,SetLCMSPixel(target_info,*p,2));
1197 if (target_info.channels > 3)
1199 if (indexes != (IndexPacket *) NULL)
1200 SetPixelIndex(indexes+x,SetLCMSPixel(target_info,*p,3));
1205 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1206 if (sync == MagickFalse)
1208 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1213#if defined(MAGICKCORE_OPENMP_SUPPORT)
1217 proceed=SetImageProgress(image,ProfileImageTag,progress,
1219 if (proceed == MagickFalse)
1223 image_view=DestroyCacheView(image_view);
1224 (void) SetImageColorspace(image,target_info.colorspace);
1229 image->type=image->matte == MagickFalse ? TrueColorType :
1233 case cmsSigCmykData:
1235 image->type=image->matte == MagickFalse ? ColorSeparationType :
1236 ColorSeparationMatteType;
1239 case cmsSigGrayData:
1241 image->type=image->matte == MagickFalse ? GrayscaleType :
1248 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1249 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1250 transform=DestroyTransformTLS(transform);
1251 if ((status != MagickFalse) &&
1252 (cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass))
1253 status=SetImageProfile(image,name,profile);
1254 if (target_info.profile != (cmsHPROFILE) NULL)
1255 (void) cmsCloseProfile(target_info.profile);
1257 (void) cmsCloseProfile(source_info.profile);
1258 cmsDeleteContext(cms_context);
1262 profile=DestroyStringInfo(profile);
1291MagickExport StringInfo *RemoveImageProfile(Image *image,
const char *name)
1296 assert(image != (Image *) NULL);
1297 assert(image->signature == MagickCoreSignature);
1298 if (IsEventLogging() != MagickFalse)
1299 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1300 if (image->profiles == (SplayTreeInfo *) NULL)
1301 return((StringInfo *) NULL);
1302 if (LocaleCompare(name,
"icc") == 0)
1307 image->color_profile.length=0;
1308 image->color_profile.info=(
unsigned char *) NULL;
1310 if (LocaleCompare(name,
"iptc") == 0)
1315 image->iptc_profile.length=0;
1316 image->iptc_profile.info=(
unsigned char *) NULL;
1318 WriteTo8BimProfile(image,name,(StringInfo *) NULL);
1319 profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
1320 image->profiles,name);
1348MagickExport
void ResetImageProfileIterator(
const Image *image)
1350 assert(image != (Image *) NULL);
1351 assert(image->signature == MagickCoreSignature);
1352 if (IsEventLogging() != MagickFalse)
1353 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1354 if (image->profiles == (SplayTreeInfo *) NULL)
1356 ResetSplayTreeIterator((SplayTreeInfo *) image->profiles);
1390static void *DestroyProfile(
void *profile)
1392 return((
void *) DestroyStringInfo((StringInfo *) profile));
1395static inline const unsigned char *ReadResourceByte(
const unsigned char *p,
1396 unsigned char *quantum)
1402static inline const unsigned char *ReadResourceLong(
const unsigned char *p,
1403 unsigned int *quantum)
1405 *quantum=(
unsigned int) (*p++) << 24;
1406 *quantum|=(
unsigned int) (*p++) << 16;
1407 *quantum|=(
unsigned int) (*p++) << 8;
1408 *quantum|=(
unsigned int) (*p++);
1412static inline const unsigned char *ReadResourceShort(
const unsigned char *p,
1413 unsigned short *quantum)
1415 *quantum=(
unsigned short) (*p++) << 8;
1416 *quantum|=(
unsigned short) (*p++);
1420static inline void WriteResourceLong(
unsigned char *p,
1421 const unsigned int quantum)
1426 buffer[0]=(
unsigned char) (quantum >> 24);
1427 buffer[1]=(
unsigned char) (quantum >> 16);
1428 buffer[2]=(
unsigned char) (quantum >> 8);
1429 buffer[3]=(
unsigned char) quantum;
1430 (void) memcpy(p,buffer,4);
1433static void WriteTo8BimProfile(Image *image,
const char *name,
1434 const StringInfo *profile)
1463 if (LocaleCompare(name,
"icc") == 0)
1466 if (LocaleCompare(name,
"iptc") == 0)
1469 if (LocaleCompare(name,
"xmp") == 0)
1473 profile_8bim=(StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
1474 image->profiles,
"8bim");
1475 if (profile_8bim == (StringInfo *) NULL)
1477 datum=GetStringInfoDatum(profile_8bim);
1478 length=GetStringInfoLength(profile_8bim);
1479 for (p=datum; p < (datum+length-16); )
1482 if (LocaleNCompare((
char *) p,
"8BIM",4) != 0)
1485 p=ReadResourceShort(p,&
id);
1486 p=ReadResourceByte(p,&length_byte);
1487 p+=(ptrdiff_t) length_byte;
1488 if (((length_byte+1) & 0x01) != 0)
1490 if (p > (datum+length-4))
1492 p=ReadResourceLong(p,&value);
1493 count=(ssize_t) value;
1494 if ((count & 0x01) != 0)
1496 if ((count < 0) || (p > (datum+length-count)) || (count > (ssize_t) length))
1498 if (
id != profile_id)
1499 p+=(ptrdiff_t) count;
1513 extent=(datum+length)-(p+count);
1514 if (profile == (StringInfo *) NULL)
1517 extract_profile=AcquireStringInfo(offset+extent);
1518 (void) memcpy(extract_profile->datum,datum,offset);
1523 extract_extent=profile->length;
1524 if ((extract_extent & 0x01) != 0)
1526 extract_profile=AcquireStringInfo(offset+extract_extent+extent);
1527 (void) memcpy(extract_profile->datum,datum,offset-4);
1528 WriteResourceLong(extract_profile->datum+offset-4,(
unsigned int)
1530 (void) memcpy(extract_profile->datum+offset,
1531 profile->datum,profile->length);
1533 (void) memcpy(extract_profile->datum+offset+extract_extent,
1535 (void) AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1536 ConstantString(
"8bim"),CloneStringInfo(extract_profile));
1537 extract_profile=DestroyStringInfo(extract_profile);
1543static void GetProfilesFromResourceBlock(Image *image,
1544 const StringInfo *resource_block)
1570 datum=GetStringInfoDatum(resource_block);
1571 length=GetStringInfoLength(resource_block);
1572 for (p=datum; p < (datum+length-16); )
1574 if (LocaleNCompare((
char *) p,
"8BIM",4) != 0)
1577 p=ReadResourceShort(p,&
id);
1578 p=ReadResourceByte(p,&length_byte);
1579 p+=(ptrdiff_t) length_byte;
1580 if (((length_byte+1) & 0x01) != 0)
1582 if (p > (datum+length-4))
1584 p=ReadResourceLong(p,&value);
1585 count=(ssize_t) value;
1586 if ((p > (datum+length-count)) || (count > (ssize_t) length) ||
1604 p=ReadResourceLong(p,&resolution);
1605 image->x_resolution=((double) resolution)/65536.0;
1606 p=ReadResourceShort(p,&units)+2;
1607 p=ReadResourceLong(p,&resolution)+4;
1608 image->y_resolution=((double) resolution)/65536.0;
1612 if ((ResolutionType) units != PixelsPerCentimeterResolution)
1613 image->units=PixelsPerInchResolution;
1616 image->units=PixelsPerCentimeterResolution;
1617 image->x_resolution/=2.54;
1618 image->y_resolution/=2.54;
1627 profile=AcquireStringInfo(count);
1628 SetStringInfoDatum(profile,p);
1629 (void) SetImageProfileInternal(image,
"iptc",profile,MagickTrue);
1630 profile=DestroyStringInfo(profile);
1631 p+=(ptrdiff_t) count;
1639 p+=(ptrdiff_t) count;
1647 profile=AcquireStringInfo(count);
1648 SetStringInfoDatum(profile,p);
1649 (void) SetImageProfileInternal(image,
"icc",profile,MagickTrue);
1650 profile=DestroyStringInfo(profile);
1651 p+=(ptrdiff_t) count;
1659 profile=AcquireStringInfo(count);
1660 SetStringInfoDatum(profile,p);
1661 (void) SetImageProfileInternal(image,
"exif",profile,MagickTrue);
1662 profile=DestroyStringInfo(profile);
1663 p+=(ptrdiff_t) count;
1671 profile=AcquireStringInfo(count);
1672 SetStringInfoDatum(profile,p);
1673 (void) SetImageProfileInternal(image,
"xmp",profile,MagickTrue);
1674 profile=DestroyStringInfo(profile);
1675 p+=(ptrdiff_t) count;
1680 p+=(ptrdiff_t) count;
1684 if ((count & 0x01) != 0)
1689#if defined(MAGICKCORE_XML_DELEGATE)
1690static MagickBooleanType ValidateXMPProfile(Image *image,
1691 const StringInfo *profile)
1699 const char *artifact=GetImageArtifact(image,
"xmp:validate");
1700 if (IsStringTrue(artifact) == MagickFalse)
1702 document=xmlReadMemory((
const char *) GetStringInfoDatum(profile),(
int)
1703 GetStringInfoLength(profile),
"xmp.xml",NULL,XML_PARSE_NOERROR |
1704 XML_PARSE_NOWARNING);
1705 if (document == (xmlDocPtr) NULL)
1707 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1708 ImageWarning,
"CorruptImageProfile",
"`%s' (XMP)",image->filename);
1709 return(MagickFalse);
1711 xmlFreeDoc(document);
1715static MagickBooleanType ValidateXMPProfile(Image *image,
1716 const StringInfo *profile)
1718 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1719 MissingDelegateWarning,
"DelegateLibrarySupportNotBuiltIn",
"'%s' (XML)",
1721 return(MagickFalse);
1725static MagickBooleanType SetImageProfileInternal(Image *image,
const char *name,
1726 const StringInfo *profile,
const MagickBooleanType recursive)
1734 assert(image != (Image *) NULL);
1735 assert(image->signature == MagickCoreSignature);
1736 if (IsEventLogging() != MagickFalse)
1737 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1738 if ((LocaleCompare(name,
"xmp") == 0) &&
1739 (ValidateXMPProfile(image,profile) == MagickFalse))
1741 if (image->profiles == (SplayTreeInfo *) NULL)
1742 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
1744 (void) CopyMagickString(key,name,MaxTextExtent);
1746 status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1747 ConstantString(key),CloneStringInfo(profile));
1748 if ((status != MagickFalse) &&
1749 ((LocaleCompare(name,
"icc") == 0) || (LocaleCompare(name,
"icm") == 0)))
1757 icc_profile=GetImageProfile(image,name);
1758 if (icc_profile != (
const StringInfo *) NULL)
1760 image->color_profile.length=GetStringInfoLength(icc_profile);
1761 image->color_profile.info=GetStringInfoDatum(icc_profile);
1764 if ((status != MagickFalse) &&
1765 ((LocaleCompare(name,
"iptc") == 0) || (LocaleCompare(name,
"8bim") == 0)))
1773 iptc_profile=GetImageProfile(image,name);
1774 if (iptc_profile != (
const StringInfo *) NULL)
1776 image->iptc_profile.length=GetStringInfoLength(iptc_profile);
1777 image->iptc_profile.info=GetStringInfoDatum(iptc_profile);
1780 if (status != MagickFalse)
1782 if (LocaleCompare(name,
"8bim") == 0)
1783 GetProfilesFromResourceBlock(image,profile);
1785 if (recursive == MagickFalse)
1786 WriteTo8BimProfile(image,name,profile);
1791MagickExport MagickBooleanType SetImageProfile(Image *image,
const char *name,
1792 const StringInfo *profile)
1794 return(SetImageProfileInternal(image,name,profile,MagickFalse));
1821static inline int ReadProfileByte(
unsigned char **p,
size_t *length)
1833static inline signed short ReadProfileShort(
const EndianType endian,
1834 unsigned char *buffer)
1848 if (endian == LSBEndian)
1850 value=(
unsigned short) buffer[1] << 8;
1851 value|=(
unsigned short) buffer[0];
1852 quantum.unsigned_value=value & 0xffff;
1853 return(quantum.signed_value);
1855 value=(
unsigned short) buffer[0] << 8;
1856 value|=(
unsigned short) buffer[1];
1857 quantum.unsigned_value=value & 0xffff;
1858 return(quantum.signed_value);
1861static inline signed int ReadProfileLong(
const EndianType endian,
1862 unsigned char *buffer)
1876 if (endian == LSBEndian)
1878 value=(
unsigned int) buffer[3] << 24;
1879 value|=(
unsigned int) buffer[2] << 16;
1880 value|=(
unsigned int) buffer[1] << 8;
1881 value|=(
unsigned int) buffer[0];
1882 quantum.unsigned_value=value & 0xffffffff;
1883 return(quantum.signed_value);
1885 value=(
unsigned int) buffer[0] << 24;
1886 value|=(
unsigned int) buffer[1] << 16;
1887 value|=(
unsigned int) buffer[2] << 8;
1888 value|=(
unsigned int) buffer[3];
1889 quantum.unsigned_value=value & 0xffffffff;
1890 return(quantum.signed_value);
1893static inline signed int ReadProfileMSBLong(
unsigned char **p,
size_t *length)
1900 value=ReadProfileLong(MSBEndian,*p);
1906static inline signed short ReadProfileMSBShort(
unsigned char **p,
1914 value=ReadProfileShort(MSBEndian,*p);
1920static inline void WriteProfileLong(
const EndianType endian,
1921 const size_t value,
unsigned char *p)
1926 if (endian == LSBEndian)
1928 buffer[0]=(
unsigned char) value;
1929 buffer[1]=(
unsigned char) (value >> 8);
1930 buffer[2]=(
unsigned char) (value >> 16);
1931 buffer[3]=(
unsigned char) (value >> 24);
1932 (void) memcpy(p,buffer,4);
1935 buffer[0]=(
unsigned char) (value >> 24);
1936 buffer[1]=(
unsigned char) (value >> 16);
1937 buffer[2]=(
unsigned char) (value >> 8);
1938 buffer[3]=(
unsigned char) value;
1939 (void) memcpy(p,buffer,4);
1942static void WriteProfileShort(
const EndianType endian,
1943 const unsigned short value,
unsigned char *p)
1948 if (endian == LSBEndian)
1950 buffer[0]=(
unsigned char) value;
1951 buffer[1]=(
unsigned char) (value >> 8);
1952 (void) memcpy(p,buffer,2);
1955 buffer[0]=(
unsigned char) (value >> 8);
1956 buffer[1]=(
unsigned char) value;
1957 (void) memcpy(p,buffer,2);
1960static MagickBooleanType SyncExifProfile(
const Image *image,
unsigned char *exif,
1963#define MaxDirectoryStack 16
1964#define EXIF_DELIMITER "\n"
1965#define EXIF_NUM_FORMATS 12
1966#define TAG_EXIF_OFFSET 0x8769
1967#define TAG_INTEROP_OFFSET 0xa005
1969 typedef struct _DirectoryInfo
1979 directory_stack[MaxDirectoryStack] = { { 0, 0 } };
1997 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
2003 return(MagickFalse);
2004 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2005 if ((
id != 0x4949) && (
id != 0x4D4D))
2009 if (ReadProfileByte(&exif,&length) != 0x45)
2011 if (ReadProfileByte(&exif,&length) != 0x78)
2013 if (ReadProfileByte(&exif,&length) != 0x69)
2015 if (ReadProfileByte(&exif,&length) != 0x66)
2017 if (ReadProfileByte(&exif,&length) != 0x00)
2019 if (ReadProfileByte(&exif,&length) != 0x00)
2024 return(MagickFalse);
2025 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2034 return(MagickFalse);
2035 if (ReadProfileShort(endian,exif+2) != 0x002a)
2036 return(MagickFalse);
2040 offset=(ssize_t) ReadProfileLong(endian,exif+4);
2041 if ((offset < 0) || ((
size_t) offset >= length))
2042 return(MagickFalse);
2043 directory=exif+offset;
2046 exif_resources=NewSplayTree((
int (*)(
const void *,
const void *)) NULL,
2047 (
void *(*)(
void *)) NULL,(
void *(*)(
void *)) NULL);
2053 directory=directory_stack[level].directory;
2054 entry=directory_stack[level].entry;
2056 if ((directory < exif) || (directory > (exif+length-2)))
2061 number_entries=ReadProfileShort(endian,directory);
2062 for ( ; entry < number_entries; entry++)
2078 q=(
unsigned char *) (directory+2+(12*entry));
2079 if (q > (exif+length-12))
2081 if (GetValueFromSplayTree(exif_resources,q) == q)
2083 (void) AddValueToSplayTree(exif_resources,q,q);
2084 tag_value=(ssize_t) ReadProfileShort(endian,q);
2085 format=(ssize_t) ReadProfileShort(endian,q+2);
2086 if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2088 components=(int) ReadProfileLong(endian,q+4);
2091 number_bytes=(size_t) components*format_bytes[format];
2092 if ((ssize_t) number_bytes < components)
2094 if (number_bytes <= 4)
2101 offset=(ssize_t) ReadProfileLong(endian,q+8);
2102 if ((offset < 0) || ((
size_t) (offset+number_bytes) > length))
2104 if (~length < number_bytes)
2106 p=(
unsigned char *) (exif+offset);
2112 (void) WriteProfileLong(endian,(
size_t) (image->x_resolution+0.5),p);
2113 if (number_bytes == 8)
2114 (void) WriteProfileLong(endian,1UL,p+4);
2119 (void) WriteProfileLong(endian,(
size_t) (image->y_resolution+0.5),p);
2120 if (number_bytes == 8)
2121 (void) WriteProfileLong(endian,1UL,p+4);
2126 if (number_bytes == 4)
2128 (void) WriteProfileLong(endian,(
size_t) image->orientation,p);
2131 (void) WriteProfileShort(endian,(
unsigned short) image->orientation,
2137 if (number_bytes == 4)
2139 (void) WriteProfileLong(endian,((
size_t) image->units)+1,p);
2142 (void) WriteProfileShort(endian,(
unsigned short) (image->units+1),p);
2148 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2150 offset=(ssize_t) ReadProfileLong(endian,p);
2151 if (((
size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2153 directory_stack[level].directory=directory;
2155 directory_stack[level].entry=entry;
2157 directory_stack[level].directory=exif+offset;
2158 directory_stack[level].entry=0;
2160 if ((directory+2+(12*number_entries)) > (exif+length))
2162 offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2164 if ((offset != 0) && ((
size_t) offset < length) &&
2165 (level < (MaxDirectoryStack-2)))
2167 directory_stack[level].directory=exif+offset;
2168 directory_stack[level].entry=0;
2175 }
while (level > 0);
2176 exif_resources=DestroySplayTree(exif_resources);
2180static MagickBooleanType Sync8BimProfile(
const Image *image,
2181 const StringInfo *profile)
2195 length=GetStringInfoLength(profile);
2196 p=GetStringInfoDatum(profile);
2199 if (ReadProfileByte(&p,&length) != 0x38)
2201 if (ReadProfileByte(&p,&length) != 0x42)
2203 if (ReadProfileByte(&p,&length) != 0x49)
2205 if (ReadProfileByte(&p,&length) != 0x4D)
2208 return(MagickFalse);
2209 id=ReadProfileMSBShort(&p,&length);
2210 count=(ssize_t) ReadProfileByte(&p,&length);
2211 if ((count >= (ssize_t) length) || (count < 0))
2212 return(MagickFalse);
2213 p+=(ptrdiff_t) count;
2215 if ((*p & 0x01) == 0)
2216 (void) ReadProfileByte(&p,&length);
2217 count=(ssize_t) ReadProfileMSBLong(&p,&length);
2218 if ((count > (ssize_t) length) || (count < 0))
2219 return(MagickFalse);
2220 if ((
id == 0x3ED) && (count == 16))
2222 if (image->units == PixelsPerCentimeterResolution)
2223 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2224 image->x_resolution*2.54*65536.0),p);
2226 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2227 image->x_resolution*65536.0),p);
2228 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+4);
2229 if (image->units == PixelsPerCentimeterResolution)
2230 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2231 image->y_resolution*2.54*65536.0),p+8);
2233 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2234 image->y_resolution*65536.0),p+8);
2235 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+12);
2238 (void) SyncExifProfile(image,p,count);
2239 p+=(ptrdiff_t) count;
2245MagickExport MagickBooleanType SyncImageProfiles(Image *image)
2254 profile=(StringInfo *) GetImageProfile(image,
"8BIM");
2255 if (profile != (StringInfo *) NULL)
2256 if (Sync8BimProfile(image,profile) == MagickFalse)
2258 profile=(StringInfo *) GetImageProfile(image,
"EXIF");
2259 if (profile != (StringInfo *) NULL)
2260 if (SyncExifProfile(image,GetStringInfoDatum(profile),
2261 GetStringInfoLength(profile)) == MagickFalse)