42#include "MagickCore/studio.h"
43#include "MagickCore/artifact.h"
44#include "MagickCore/attribute.h"
45#include "MagickCore/cache.h"
46#include "MagickCore/color.h"
47#include "MagickCore/colorspace-private.h"
48#include "MagickCore/configure.h"
49#include "MagickCore/exception.h"
50#include "MagickCore/exception-private.h"
51#include "MagickCore/image.h"
52#include "MagickCore/linked-list.h"
53#include "MagickCore/memory_.h"
54#include "MagickCore/monitor.h"
55#include "MagickCore/monitor-private.h"
56#include "MagickCore/option.h"
57#include "MagickCore/option-private.h"
58#include "MagickCore/pixel-accessor.h"
59#include "MagickCore/profile.h"
60#include "MagickCore/profile-private.h"
61#include "MagickCore/property.h"
62#include "MagickCore/quantum.h"
63#include "MagickCore/quantum-private.h"
64#include "MagickCore/resource_.h"
65#include "MagickCore/splay-tree.h"
66#include "MagickCore/string_.h"
67#include "MagickCore/string-private.h"
68#include "MagickCore/thread-private.h"
69#include "MagickCore/token.h"
70#include "MagickCore/utility.h"
71#if defined(MAGICKCORE_LCMS_DELEGATE)
73#if defined(MAGICKCORE_HAVE_LCMS_LCMS2_H)
74#include <lcms/lcms2.h>
79#if defined(MAGICKCORE_XML_DELEGATE)
80# include <libxml/parser.h>
81# include <libxml/tree.h>
87static MagickBooleanType
146MagickExport MagickBooleanType CloneImageProfiles(
Image *image,
147 const Image *clone_image)
149 assert(image != (
Image *) NULL);
150 assert(image->signature == MagickCoreSignature);
151 assert(clone_image != (
const Image *) NULL);
152 assert(clone_image->signature == MagickCoreSignature);
153 if (IsEventLogging() != MagickFalse)
154 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
155 if (clone_image->profiles != (
void *) NULL)
157 if (image->profiles != (
void *) NULL)
158 DestroyImageProfiles(image);
159 image->profiles=CloneSplayTree((
SplayTreeInfo *) clone_image->profiles,
160 (
void *(*)(
void *)) ConstantString,(
void *(*)(
void *)) CloneStringInfo);
189MagickExport MagickBooleanType DeleteImageProfile(
Image *image,
const char *name)
191 assert(image != (
Image *) NULL);
192 assert(image->signature == MagickCoreSignature);
193 if (IsEventLogging() != MagickFalse)
194 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
197 WriteTo8BimProfile(image,name,(
StringInfo *) NULL);
198 return(DeleteNodeFromSplayTree((
SplayTreeInfo *) image->profiles,name));
223MagickExport
void DestroyImageProfiles(
Image *image)
226 image->profiles=DestroySplayTree((
SplayTreeInfo *) image->profiles);
259 assert(image != (
Image *) NULL);
260 assert(image->signature == MagickCoreSignature);
261 if (IsEventLogging() != MagickFalse)
262 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
266 image->profiles,name);
292MagickExport
char *GetNextImageProfile(
const Image *image)
294 assert(image != (
Image *) NULL);
295 assert(image->signature == MagickCoreSignature);
296 if (IsEventLogging() != MagickFalse)
297 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
299 return((
char *) NULL);
300 return((
char *) GetNextKeyInSplayTree((
SplayTreeInfo *) image->profiles));
344#if defined(MAGICKCORE_LCMS_DELEGATE)
346typedef struct _LCMSInfo
368 **magick_restrict pixels;
371#if LCMS_VERSION < 2060
372static void* cmsGetContextUserData(cmsContext ContextID)
377static cmsContext cmsCreateContext(
void *magick_unused(Plugin),
void *UserData)
379 magick_unreferenced(Plugin);
380 return((cmsContext) UserData);
383static void cmsSetLogErrorHandlerTHR(cmsContext magick_unused(ContextID),
384 cmsLogErrorHandlerFunction Fn)
386 magick_unreferenced(ContextID);
387 cmsSetLogErrorHandler(Fn);
390static void cmsDeleteContext(cmsContext magick_unused(ContextID))
392 magick_unreferenced(ContextID);
396static void **DestroyPixelTLS(
void **pixels)
401 if (pixels == (
void **) NULL)
402 return((
void **) NULL);
403 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
404 if (pixels[i] != (
void *) NULL)
405 pixels[i]=RelinquishMagickMemory(pixels[i]);
406 pixels=(
void **) RelinquishMagickMemory(pixels);
410static void **AcquirePixelTLS(
const size_t columns,
const size_t channels,
411 MagickBooleanType highres)
425 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
426 pixels=(
void **) AcquireQuantumMemory(number_threads,
sizeof(*pixels));
427 if (pixels == (
void **) NULL)
428 return((
void **) NULL);
429 (void) memset(pixels,0,number_threads*
sizeof(*pixels));
431 if (highres == MagickFalse)
432 size=
sizeof(Quantum);
433 for (i=0; i < (ssize_t) number_threads; i++)
435 pixels[i]=AcquireQuantumMemory(columns,channels*size);
436 if (pixels[i] == (
void *) NULL)
437 return(DestroyPixelTLS(pixels));
442static cmsHTRANSFORM *DestroyTransformTLS(cmsHTRANSFORM *transform)
447 assert(transform != (cmsHTRANSFORM *) NULL);
448 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
449 if (transform[i] != (cmsHTRANSFORM) NULL)
450 cmsDeleteTransform(transform[i]);
451 transform=(cmsHTRANSFORM *) RelinquishMagickMemory(transform);
455static cmsHTRANSFORM *AcquireTransformTLS(
const LCMSInfo *source_info,
456 const LCMSInfo *target_info,
const cmsUInt32Number flags,
457 cmsContext cms_context)
468 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
469 transform=(cmsHTRANSFORM *) AcquireQuantumMemory(number_threads,
471 if (transform == (cmsHTRANSFORM *) NULL)
472 return((cmsHTRANSFORM *) NULL);
473 (void) memset(transform,0,number_threads*
sizeof(*transform));
474 for (i=0; i < (ssize_t) number_threads; i++)
476 transform[i]=cmsCreateTransformTHR(cms_context,source_info->profile,
477 source_info->type,target_info->profile,target_info->type,
478 (cmsUInt32Number) target_info->intent,flags);
479 if (transform[i] == (cmsHTRANSFORM) NULL)
480 return(DestroyTransformTLS(transform));
485static void CMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
500 exception=cms_exception->exception;
503 image=cms_exception->image;
504 if (image == (
Image *) NULL)
506 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
507 "UnableToTransformColorspace",
"`%s'",
"unknown context");
510 if (image->debug != MagickFalse)
511 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
"lcms: #%u, %s",
512 severity,message != (
char *) NULL ? message :
"no message");
513 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
514 "UnableToTransformColorspace",
"`%s', %s (#%u)",image->filename,
515 message != (
char *) NULL ? message :
"no message",severity);
518static void TransformDoublePixels(
const int id,
const Image* image,
519 const LCMSInfo *source_info,
const LCMSInfo *target_info,
520 const cmsHTRANSFORM *transform,Quantum *q)
522#define GetLCMSPixel(source_info,pixel,index) \
523 (source_info->scale[index]*(((double) QuantumScale*(double) pixel)+ \
524 source_info->translate[index]))
525#define SetLCMSPixel(target_info,pixel,index) ClampToQuantum( \
526 target_info->scale[index]*(((double) QuantumRange*(double) pixel)+ \
527 target_info->translate[index]))
535 p=(
double *) source_info->pixels[
id];
536 for (x=0; x < (ssize_t) image->columns; x++)
538 *p++=GetLCMSPixel(source_info,GetPixelRed(image,q),0);
539 if (source_info->channels > 1)
541 *p++=GetLCMSPixel(source_info,GetPixelGreen(image,q),1);
542 *p++=GetLCMSPixel(source_info,GetPixelBlue(image,q),2);
544 if (source_info->channels > 3)
545 *p++=GetLCMSPixel(source_info,GetPixelBlack(image,q),3);
546 q+=GetPixelChannels(image);
548 cmsDoTransform(transform[
id],source_info->pixels[
id],target_info->pixels[
id],
549 (
unsigned int) image->columns);
550 p=(
double *) target_info->pixels[
id];
551 q-=GetPixelChannels(image)*image->columns;
552 for (x=0; x < (ssize_t) image->columns; x++)
554 if (target_info->channels == 1)
555 SetPixelGray(image,SetLCMSPixel(target_info,*p,0),q);
557 SetPixelRed(image,SetLCMSPixel(target_info,*p,0),q);
559 if (target_info->channels > 1)
561 SetPixelGreen(image,SetLCMSPixel(target_info,*p,1),q);
563 SetPixelBlue(image,SetLCMSPixel(target_info,*p,2),q);
566 if (target_info->channels > 3)
568 SetPixelBlack(image,SetLCMSPixel(target_info,*p,3),q);
571 q+=GetPixelChannels(image);
575static void TransformQuantumPixels(
const int id,
const Image* image,
576 const LCMSInfo *source_info,
const LCMSInfo *target_info,
577 const cmsHTRANSFORM *transform,Quantum *q)
585 p=(Quantum *) source_info->pixels[
id];
586 for (x=0; x < (ssize_t) image->columns; x++)
588 *p++=GetPixelRed(image,q);
589 if (source_info->channels > 1)
591 *p++=GetPixelGreen(image,q);
592 *p++=GetPixelBlue(image,q);
594 if (source_info->channels > 3)
595 *p++=GetPixelBlack(image,q);
596 q+=GetPixelChannels(image);
598 cmsDoTransform(transform[
id],source_info->pixels[
id],target_info->pixels[
id],
599 (
unsigned int) image->columns);
600 p=(Quantum *) target_info->pixels[
id];
601 q-=GetPixelChannels(image)*image->columns;
602 for (x=0; x < (ssize_t) image->columns; x++)
604 if (target_info->channels == 1)
605 SetPixelGray(image,*p++,q);
607 SetPixelRed(image,*p++,q);
608 if (target_info->channels > 1)
610 SetPixelGreen(image,*p++,q);
611 SetPixelBlue(image,*p++,q);
613 if (target_info->channels > 3)
614 SetPixelBlack(image,*p++,q);
615 q+=GetPixelChannels(image);
619static inline void SetLCMSInfoTranslate(LCMSInfo *info,
const double translate)
621 info->translate[0]=translate;
622 info->translate[1]=translate;
623 info->translate[2]=translate;
624 info->translate[3]=translate;
627static inline void SetLCMSInfoScale(LCMSInfo *info,
const double scale)
629 info->scale[0]=scale;
630 info->scale[1]=scale;
631 info->scale[2]=scale;
632 info->scale[3]=scale;
636static MagickBooleanType SetsRGBImageProfile(
Image *image,
642 0x00, 0x00, 0x0c, 0x8c, 0x61, 0x72, 0x67, 0x6c, 0x02, 0x20, 0x00, 0x00,
643 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
644 0x07, 0xde, 0x00, 0x01, 0x00, 0x06, 0x00, 0x16, 0x00, 0x0f, 0x00, 0x3a,
645 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
646 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
648 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x61, 0x72, 0x67, 0x6c,
649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
653 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x99,
654 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0xec, 0x00, 0x00, 0x00, 0x67,
655 0x64, 0x6d, 0x6e, 0x64, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70,
656 0x64, 0x6d, 0x64, 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88,
657 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x0c,
658 0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x00, 0x67,
659 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x24,
660 0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xe4, 0x00, 0x00, 0x00, 0x14,
661 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x24,
662 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x14,
663 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x14,
664 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x14,
665 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x58, 0x00, 0x00, 0x00, 0x14,
666 0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x6c, 0x00, 0x00, 0x00, 0x14,
667 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
668 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
669 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
670 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
671 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36,
672 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75, 0x69, 0x76,
673 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x77, 0x77,
674 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x31, 0x39,
675 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c,
676 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
677 0x00, 0x3f, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31,
678 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75,
679 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77,
680 0x77, 0x77, 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20,
681 0x31, 0x39, 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66,
682 0x69, 0x6c, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
683 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, 0x61,
684 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x72, 0x61, 0x65, 0x6d,
685 0x65, 0x20, 0x57, 0x2e, 0x20, 0x47, 0x69, 0x6c, 0x6c, 0x2e, 0x20, 0x52,
686 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f,
687 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
688 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x4e, 0x6f, 0x20, 0x57,
689 0x61, 0x72, 0x72, 0x61, 0x6e, 0x74, 0x79, 0x2c, 0x20, 0x55, 0x73, 0x65,
690 0x20, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e,
691 0x20, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20,
693 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
694 0x65, 0x63, 0x2e, 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
695 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74,
696 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
697 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
700 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
701 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
702 0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e,
703 0x31, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47,
704 0x42, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61,
705 0x63, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
706 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43,
707 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
708 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63,
709 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
710 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
711 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
712 0x00, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00,
713 0x43, 0x52, 0x54, 0x20, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
714 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
715 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
716 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
717 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
718 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
719 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
720 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
721 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
722 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa4, 0x7c,
723 0x00, 0x14, 0x5f, 0x30, 0x00, 0x10, 0xce, 0x02, 0x00, 0x03, 0xed, 0xb2,
724 0x00, 0x04, 0x13, 0x0a, 0x00, 0x03, 0x5c, 0x67, 0x00, 0x00, 0x00, 0x01,
725 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x0a, 0x3d,
726 0x00, 0x50, 0x00, 0x00, 0x00, 0x57, 0x1e, 0xb8, 0x6d, 0x65, 0x61, 0x73,
727 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
728 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
729 0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x58, 0x59, 0x5a, 0x20,
730 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00,
731 0x00, 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
732 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
733 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa0,
734 0x00, 0x00, 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20,
735 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x97, 0x00, 0x00, 0xb7, 0x87,
736 0x00, 0x00, 0x18, 0xd9, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
737 0x00, 0x00, 0x24, 0x9f, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0xb6, 0xc4,
738 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
739 0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19,
740 0x00, 0x1e, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37,
741 0x00, 0x3b, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54,
742 0x00, 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
743 0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00, 0x90,
744 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9, 0x00, 0xae,
745 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00, 0xc6, 0x00, 0xcb,
746 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0xeb,
747 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01, 0x01, 0x01, 0x07, 0x01, 0x0d,
748 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f, 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32,
749 0x01, 0x38, 0x01, 0x3e, 0x01, 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59,
750 0x01, 0x60, 0x01, 0x67, 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83,
751 0x01, 0x8b, 0x01, 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1,
752 0x01, 0xb9, 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1,
753 0x01, 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
754 0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02, 0x4b,
755 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a, 0x02, 0x84,
756 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02, 0xb6, 0x02, 0xc1,
757 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb, 0x02, 0xf5, 0x03, 0x00,
758 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2d, 0x03, 0x38, 0x03, 0x43,
759 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66, 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a,
760 0x03, 0x96, 0x03, 0xa2, 0x03, 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3,
761 0x03, 0xe0, 0x03, 0xec, 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20,
762 0x04, 0x2d, 0x04, 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71,
763 0x04, 0x7e, 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4,
764 0x04, 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
765 0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05, 0x77,
766 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5, 0x05, 0xd5,
767 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06, 0x27, 0x06, 0x37,
768 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b, 0x06, 0x8c, 0x06, 0x9d,
769 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06, 0xe3, 0x06, 0xf5, 0x07, 0x07,
770 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d, 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74,
771 0x07, 0x86, 0x07, 0x99, 0x07, 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5,
772 0x07, 0xf8, 0x08, 0x0b, 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a,
773 0x08, 0x6e, 0x08, 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2,
774 0x08, 0xe7, 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f,
775 0x09, 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
776 0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a, 0x54,
777 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5, 0x0a, 0xdc,
778 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b, 0x51, 0x0b, 0x69,
779 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8, 0x0b, 0xe1, 0x0b, 0xf9,
780 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c, 0x5c, 0x0c, 0x75, 0x0c, 0x8e,
781 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9, 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26,
782 0x0d, 0x40, 0x0d, 0x5a, 0x0d, 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3,
783 0x0d, 0xde, 0x0d, 0xf8, 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64,
784 0x0e, 0x7f, 0x0e, 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09,
785 0x0f, 0x25, 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3,
786 0x0f, 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
787 0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11, 0x13,
788 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa, 0x11, 0xc9,
789 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12, 0x64, 0x12, 0x84,
790 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03, 0x13, 0x23, 0x13, 0x43,
791 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13, 0xc5, 0x13, 0xe5, 0x14, 0x06,
792 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a, 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce,
793 0x14, 0xf0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b,
794 0x15, 0xbd, 0x15, 0xe0, 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c,
795 0x16, 0x8f, 0x16, 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41,
796 0x17, 0x65, 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b,
797 0x18, 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
798 0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19, 0xdd,
799 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e, 0x1a, 0xc5,
800 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b, 0x8a, 0x1b, 0xb2,
801 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52, 0x1c, 0x7b, 0x1c, 0xa3,
802 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d, 0x47, 0x1d, 0x70, 0x1d, 0x99,
803 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16, 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94,
804 0x1e, 0xbe, 0x1e, 0xe9, 0x1f, 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94,
805 0x1f, 0xbf, 0x1f, 0xea, 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98,
806 0x20, 0xc4, 0x20, 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1,
807 0x21, 0xce, 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf,
808 0x22, 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
809 0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24, 0xda,
810 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7, 0x25, 0xf7,
811 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26, 0xe8, 0x27, 0x18,
812 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc, 0x28, 0x0d, 0x28, 0x3f,
813 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29, 0x06, 0x29, 0x38, 0x29, 0x6b,
814 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02, 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b,
815 0x2a, 0xcf, 0x2b, 0x02, 0x2b, 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1,
816 0x2c, 0x05, 0x2c, 0x39, 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c,
817 0x2d, 0x41, 0x2d, 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c,
818 0x2e, 0x82, 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91,
819 0x2f, 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
820 0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32, 0x2a,
821 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46, 0x33, 0x7f,
822 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34, 0x9e, 0x34, 0xd8,
823 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2, 0x35, 0xfd, 0x36, 0x37,
824 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37, 0x24, 0x37, 0x60, 0x37, 0x9c,
825 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05,
826 0x39, 0x42, 0x39, 0x7f, 0x39, 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74,
827 0x3a, 0xb2, 0x3a, 0xef, 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8,
828 0x3c, 0x27, 0x3c, 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61,
829 0x3d, 0xa1, 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0,
830 0x3f, 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
831 0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41, 0xee,
832 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a, 0x43, 0x7d,
833 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44, 0xce, 0x45, 0x12,
834 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22, 0x46, 0x67, 0x46, 0xab,
835 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47, 0xc0, 0x48, 0x05, 0x48, 0x4b,
836 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d, 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0,
837 0x4a, 0x37, 0x4a, 0x7d, 0x4a, 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a,
838 0x4b, 0xe2, 0x4c, 0x2a, 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a,
839 0x4d, 0x93, 0x4d, 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00,
840 0x4f, 0x49, 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb,
841 0x51, 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
842 0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54, 0x42,
843 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2, 0x56, 0x0f,
844 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57, 0x92, 0x57, 0xe0,
845 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a, 0x59, 0x69, 0x59, 0xb8,
846 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a, 0xf5, 0x5b, 0x45, 0x5b, 0x95,
847 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86, 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78,
848 0x5d, 0xc9, 0x5e, 0x1a, 0x5e, 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61,
849 0x5f, 0xb3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f,
850 0x61, 0xa2, 0x61, 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43,
851 0x63, 0x97, 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d,
852 0x65, 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
853 0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69, 0x43,
854 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7, 0x6b, 0x4f,
855 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d, 0x08, 0x6d, 0x60,
856 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4, 0x6f, 0x1e, 0x6f, 0x78,
857 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70, 0xe0, 0x71, 0x3a, 0x71, 0x95,
858 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6, 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8,
859 0x74, 0x14, 0x74, 0x70, 0x74, 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1,
860 0x76, 0x3e, 0x76, 0x9b, 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11,
861 0x78, 0x6e, 0x78, 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46,
862 0x7a, 0xa5, 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81,
863 0x7c, 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
864 0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81, 0x0a,
865 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4, 0x83, 0x57,
866 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85, 0x47, 0x85, 0xab,
867 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b, 0x87, 0x9f, 0x88, 0x04,
868 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89, 0x99, 0x89, 0xfe, 0x8a, 0x64,
869 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96, 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca,
870 0x8d, 0x31, 0x8d, 0x98, 0x8d, 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36,
871 0x8f, 0x9e, 0x90, 0x06, 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8,
872 0x92, 0x11, 0x92, 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20,
873 0x94, 0x8a, 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f,
874 0x97, 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
875 0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b, 0xaf,
876 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2, 0x9e, 0x40,
877 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0, 0x69, 0xa0, 0xd8,
878 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96, 0xa3, 0x06, 0xa3, 0x76,
879 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5, 0x38, 0xa5, 0xa9, 0xa6, 0x1a,
880 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e, 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4,
881 0xa9, 0x37, 0xa9, 0xa9, 0xaa, 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75,
882 0xab, 0xe9, 0xac, 0x5c, 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d,
883 0xae, 0xa1, 0xaf, 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea,
884 0xb1, 0x60, 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae,
885 0xb4, 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
886 0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9, 0x4a,
887 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7, 0xbc, 0x21,
888 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe, 0x84, 0xbe, 0xff,
889 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec, 0xc1, 0x67, 0xc1, 0xe3,
890 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3, 0xd4, 0xc4, 0x51, 0xc4, 0xce,
891 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46, 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf,
892 0xc8, 0x3d, 0xc8, 0xbc, 0xc9, 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7,
893 0xcb, 0x36, 0xcb, 0xb6, 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5,
894 0xce, 0x36, 0xce, 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba,
895 0xd1, 0x3c, 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6,
896 0xd4, 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
897 0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9, 0xf1,
898 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a, 0xdd, 0x10,
899 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf, 0xaf, 0xe0, 0x36,
900 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53, 0xe2, 0xdb, 0xe3, 0x63,
901 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5, 0x84, 0xe6, 0x0d, 0xe6, 0x96,
902 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32, 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0,
903 0xea, 0x5b, 0xea, 0xe5, 0xeb, 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11,
904 0xed, 0x9c, 0xee, 0x28, 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58,
905 0xf0, 0xe5, 0xf1, 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7,
906 0xf4, 0x34, 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb,
907 0xf7, 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
908 0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd, 0xba,
909 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
918 assert(image != (
Image *) NULL);
919 assert(image->signature == MagickCoreSignature);
920 if (GetImageProfile(image,
"icc") != (
const StringInfo *) NULL)
922 profile=AcquireStringInfo(
sizeof(sRGBProfile));
923 SetStringInfoDatum(profile,sRGBProfile);
924 status=SetImageProfile(image,
"icc",profile,exception);
925 profile=DestroyStringInfo(profile);
929MagickExport MagickBooleanType ProfileImage(
Image *image,
const char *name,
930 const void *datum,
const size_t length,
ExceptionInfo *exception)
932#define ProfileImageTag "Profile/Image"
934 #define TYPE_XYZ_8 (COLORSPACE_SH(PT_XYZ)|CHANNELS_SH(3)|BYTES_SH(1))
936#define ThrowProfileException(severity,tag,context) \
938 if (profile != (StringInfo *) NULL) \
939 profile=DestroyStringInfo(profile); \
940 if (cms_context != (cmsContext) NULL) \
941 cmsDeleteContext(cms_context); \
942 if (source_info.profile != (cmsHPROFILE) NULL) \
943 (void) cmsCloseProfile(source_info.profile); \
944 if (target_info.profile != (cmsHPROFILE) NULL) \
945 (void) cmsCloseProfile(target_info.profile); \
946 ThrowBinaryException(severity,tag,context); \
955 assert(image != (
Image *) NULL);
956 assert(image->signature == MagickCoreSignature);
957 assert(name != (
const char *) NULL);
958 if (IsEventLogging() != MagickFalse)
959 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
960 if ((datum == (
const void *) NULL) || (length == 0))
968 ResetImageProfileIterator(image);
969 for (next=GetNextImageProfile(image); next != (
const char *) NULL; )
971 if (IsOptionMember(next,name) != MagickFalse)
973 (void) DeleteImageProfile(image,next);
974 ResetImageProfileIterator(image);
976 next=GetNextImageProfile(image);
984 profile=AcquireStringInfo((
size_t) length);
985 SetStringInfoDatum(profile,(
unsigned char *) datum);
986 if ((LocaleCompare(name,
"icc") != 0) && (LocaleCompare(name,
"icm") != 0))
987 status=SetImageProfile(image,name,profile,exception);
993 icc_profile=GetImageProfile(image,
"icc");
994 if ((icc_profile != (
const StringInfo *) NULL) &&
995 (CompareStringInfo(icc_profile,profile) == 0))
1000 value=GetImageProperty(image,
"exif:ColorSpace",exception);
1002 if (LocaleCompare(value,
"1") != 0)
1003 (
void) SetsRGBImageProfile(image,exception);
1004 value=GetImageProperty(image,
"exif:InteroperabilityIndex",exception);
1005 if (LocaleCompare(value,
"R98.") != 0)
1006 (void) SetsRGBImageProfile(image,exception);
1007 icc_profile=GetImageProfile(image,
"icc");
1009 if ((icc_profile != (
const StringInfo *) NULL) &&
1010 (CompareStringInfo(icc_profile,profile) == 0))
1012 profile=DestroyStringInfo(profile);
1015#if !defined(MAGICKCORE_LCMS_DELEGATE)
1016 (void) ThrowMagickException(exception,GetMagickModule(),
1017 MissingDelegateWarning,
"DelegateLibrarySupportNotBuiltIn",
1018 "'%s' (LCMS)",image->filename);
1034 cms_exception.image=image;
1035 cms_exception.exception=exception;
1036 cms_context=cmsCreateContext(NULL,&cms_exception);
1037 if (cms_context == (cmsContext) NULL)
1039 profile=DestroyStringInfo(profile);
1040 ThrowBinaryException(ResourceLimitError,
1041 "ColorspaceColorProfileMismatch",name);
1043 cmsSetLogErrorHandlerTHR(cms_context,CMSExceptionHandler);
1044 source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
1045 GetStringInfoDatum(profile),(cmsUInt32Number)
1046 GetStringInfoLength(profile));
1047 if (source_info.profile == (cmsHPROFILE) NULL)
1049 profile=DestroyStringInfo(profile);
1050 cmsDeleteContext(cms_context);
1051 ThrowBinaryException(ResourceLimitError,
1052 "ColorspaceColorProfileMismatch",name);
1054 if ((cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass) &&
1056 status=SetImageProfile(image,name,profile,exception);
1062 cmsColorSpaceSignature
1066 *magick_restrict transform;
1080 target_info.profile=(cmsHPROFILE) NULL;
1083 target_info.profile=source_info.profile;
1084 source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
1085 GetStringInfoDatum(icc_profile),(cmsUInt32Number)
1086 GetStringInfoLength(icc_profile));
1087 if (source_info.profile == (cmsHPROFILE) NULL)
1088 ThrowProfileException(ResourceLimitError,
1089 "ColorspaceColorProfileMismatch",name);
1092#if !defined(MAGICKCORE_HDRI_SUPPORT) || (MAGICKCORE_QUANTUM_DEPTH > 16)
1097 artifact=GetImageArtifact(image,
"profile:highres-transform");
1098 if (IsStringFalse(artifact) != MagickFalse)
1099 highres=MagickFalse;
1102 SetLCMSInfoScale(&source_info,1.0);
1103 SetLCMSInfoTranslate(&source_info,0.0);
1104 source_info.colorspace=sRGBColorspace;
1105 source_info.channels=3;
1106 switch (cmsGetColorSpace(source_info.profile))
1108 case cmsSigCmykData:
1110 source_info.colorspace=CMYKColorspace;
1111 source_info.channels=4;
1112 if (highres != MagickFalse)
1114 source_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1115 SetLCMSInfoScale(&source_info,100.0);
1117#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1119 source_info.type=(cmsUInt32Number) TYPE_CMYK_8;
1120#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1122 source_info.type=(cmsUInt32Number) TYPE_CMYK_16;
1126 case cmsSigGrayData:
1128 source_info.colorspace=GRAYColorspace;
1129 source_info.channels=1;
1130 if (highres != MagickFalse)
1131 source_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1132#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1134 source_info.type=(cmsUInt32Number) TYPE_GRAY_8;
1135#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1137 source_info.type=(cmsUInt32Number) TYPE_GRAY_16;
1143 source_info.colorspace=LabColorspace;
1144 if (highres != MagickFalse)
1146 source_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1147 source_info.scale[0]=100.0;
1148 source_info.scale[1]=255.0;
1149 source_info.scale[2]=255.0;
1150 source_info.translate[1]=(-0.5);
1151 source_info.translate[2]=(-0.5);
1153#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1155 source_info.type=(cmsUInt32Number) TYPE_Lab_8;
1156#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1158 source_info.type=(cmsUInt32Number) TYPE_Lab_16;
1164 source_info.colorspace=sRGBColorspace;
1165 if (highres != MagickFalse)
1166 source_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1167#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1169 source_info.type=(cmsUInt32Number) TYPE_RGB_8;
1170#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1172 source_info.type=(cmsUInt32Number) TYPE_RGB_16;
1178 source_info.colorspace=XYZColorspace;
1179 if (highres != MagickFalse)
1180 source_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1181#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1183 source_info.type=(cmsUInt32Number) TYPE_XYZ_8;
1184#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1186 source_info.type=(cmsUInt32Number) TYPE_XYZ_16;
1191 ThrowProfileException(ImageError,
1192 "ColorspaceColorProfileMismatch",name);
1194 signature=cmsGetPCS(source_info.profile);
1195 if (target_info.profile != (cmsHPROFILE) NULL)
1196 signature=cmsGetColorSpace(target_info.profile);
1197 SetLCMSInfoScale(&target_info,1.0);
1198 SetLCMSInfoTranslate(&target_info,0.0);
1199 target_info.channels=3;
1202 case cmsSigCmykData:
1204 target_info.colorspace=CMYKColorspace;
1205 target_info.channels=4;
1206 if (highres != MagickFalse)
1208 target_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1209 SetLCMSInfoScale(&target_info,0.01);
1211#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1213 target_info.type=(cmsUInt32Number) TYPE_CMYK_8;
1214#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1216 target_info.type=(cmsUInt32Number) TYPE_CMYK_16;
1220 case cmsSigGrayData:
1222 target_info.colorspace=GRAYColorspace;
1223 target_info.channels=1;
1224 if (highres != MagickFalse)
1225 target_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1226#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1228 target_info.type=(cmsUInt32Number) TYPE_GRAY_8;
1229#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1231 target_info.type=(cmsUInt32Number) TYPE_GRAY_16;
1237 target_info.colorspace=LabColorspace;
1238 if (highres != MagickFalse)
1240 target_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1241 target_info.scale[0]=0.01;
1242 target_info.scale[1]=1/255.0;
1243 target_info.scale[2]=1/255.0;
1244 target_info.translate[1]=0.5;
1245 target_info.translate[2]=0.5;
1247#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1249 target_info.type=(cmsUInt32Number) TYPE_Lab_8;
1250#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1252 target_info.type=(cmsUInt32Number) TYPE_Lab_16;
1258 target_info.colorspace=sRGBColorspace;
1259 if (highres != MagickFalse)
1260 target_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1261#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1263 target_info.type=(cmsUInt32Number) TYPE_RGB_8;
1264#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1266 target_info.type=(cmsUInt32Number) TYPE_RGB_16;
1272 target_info.colorspace=XYZColorspace;
1273 if (highres != MagickFalse)
1274 target_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1275#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1277 target_info.type=(cmsUInt32Number) TYPE_XYZ_8;
1278#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1280 source_info.type=(cmsUInt32Number) TYPE_XYZ_16;
1285 ThrowProfileException(ImageError,
1286 "ColorspaceColorProfileMismatch",name);
1288 switch (image->rendering_intent)
1290 case AbsoluteIntent:
1292 target_info.intent=INTENT_ABSOLUTE_COLORIMETRIC;
1295 case PerceptualIntent:
1297 target_info.intent=INTENT_PERCEPTUAL;
1300 case RelativeIntent:
1302 target_info.intent=INTENT_RELATIVE_COLORIMETRIC;
1305 case SaturationIntent:
1307 target_info.intent=INTENT_SATURATION;
1312 target_info.intent=INTENT_PERCEPTUAL;
1316 flags=cmsFLAGS_HIGHRESPRECALC;
1317#if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1318 if (image->black_point_compensation != MagickFalse)
1319 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1321 transform=AcquireTransformTLS(&source_info,&target_info,flags,
1323 if (transform == (cmsHTRANSFORM *) NULL)
1324 ThrowProfileException(ImageError,
"UnableToCreateColorTransform",
1329 source_info.pixels=AcquirePixelTLS(image->columns,
1330 source_info.channels,highres);
1331 target_info.pixels=AcquirePixelTLS(image->columns,
1332 target_info.channels,highres);
1333 if ((source_info.pixels == (
void **) NULL) ||
1334 (target_info.pixels == (
void **) NULL))
1336 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1337 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1338 transform=DestroyTransformTLS(transform);
1339 ThrowProfileException(ResourceLimitError,
1340 "MemoryAllocationFailed",image->filename);
1342 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1344 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1345 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1346 transform=DestroyTransformTLS(transform);
1347 if (source_info.profile != (cmsHPROFILE) NULL)
1348 (void) cmsCloseProfile(source_info.profile);
1349 if (target_info.profile != (cmsHPROFILE) NULL)
1350 (
void) cmsCloseProfile(target_info.profile);
1351 return(MagickFalse);
1353 if (target_info.colorspace == CMYKColorspace)
1354 (void) SetImageColorspace(image,target_info.colorspace,exception);
1356 image_view=AcquireAuthenticCacheView(image,exception);
1357#if defined(MAGICKCORE_OPENMP_SUPPORT)
1358 #pragma omp parallel for schedule(static) shared(status) \
1359 magick_number_threads(image,image,image->rows,1)
1361 for (y=0; y < (ssize_t) image->rows; y++)
1364 id = GetOpenMPThreadId();
1372 if (status == MagickFalse)
1374 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1376 if (q == (Quantum *) NULL)
1381 if (highres != MagickFalse)
1382 TransformDoublePixels(
id,image,&source_info,&target_info,
1385 TransformQuantumPixels(
id,image,&source_info,&target_info,
1387 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1388 if (sync == MagickFalse)
1390 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1395#if defined(MAGICKCORE_OPENMP_SUPPORT)
1399 proceed=SetImageProgress(image,ProfileImageTag,progress,
1401 if (proceed == MagickFalse)
1405 image_view=DestroyCacheView(image_view);
1406 (void) SetImageColorspace(image,target_info.colorspace,exception);
1411 image->type=image->alpha_trait == UndefinedPixelTrait ?
1412 TrueColorType : TrueColorAlphaType;
1415 case cmsSigCmykData:
1417 image->type=image->alpha_trait == UndefinedPixelTrait ?
1418 ColorSeparationType : ColorSeparationAlphaType;
1421 case cmsSigGrayData:
1423 image->type=image->alpha_trait == UndefinedPixelTrait ?
1424 GrayscaleType : GrayscaleAlphaType;
1430 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1431 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1432 transform=DestroyTransformTLS(transform);
1433 if ((status != MagickFalse) &&
1434 (cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass))
1435 status=SetImageProfile(image,name,profile,exception);
1436 if (target_info.profile != (cmsHPROFILE) NULL)
1437 (void) cmsCloseProfile(target_info.profile);
1439 (void) cmsCloseProfile(source_info.profile);
1440 cmsDeleteContext(cms_context);
1444 profile=DestroyStringInfo(profile);
1473MagickExport
StringInfo *RemoveImageProfile(
Image *image,
const char *name)
1478 assert(image != (
Image *) NULL);
1479 assert(image->signature == MagickCoreSignature);
1480 if (IsEventLogging() != MagickFalse)
1481 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1484 WriteTo8BimProfile(image,name,(
StringInfo *) NULL);
1486 image->profiles,name);
1514MagickExport
void ResetImageProfileIterator(
const Image *image)
1516 assert(image != (
Image *) NULL);
1517 assert(image->signature == MagickCoreSignature);
1518 if (IsEventLogging() != MagickFalse)
1519 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1556static void *DestroyProfile(
void *profile)
1558 return((
void *) DestroyStringInfo((
StringInfo *) profile));
1561static inline const unsigned char *ReadResourceByte(
const unsigned char *p,
1562 unsigned char *quantum)
1568static inline const unsigned char *ReadResourceLong(
const unsigned char *p,
1569 unsigned int *quantum)
1571 *quantum=(
unsigned int) (*p++) << 24;
1572 *quantum|=(
unsigned int) (*p++) << 16;
1573 *quantum|=(
unsigned int) (*p++) << 8;
1574 *quantum|=(
unsigned int) (*p++);
1578static inline const unsigned char *ReadResourceShort(
const unsigned char *p,
1579 unsigned short *quantum)
1581 *quantum=(
unsigned short) (*p++) << 8;
1582 *quantum|=(
unsigned short) (*p++);
1586static inline void WriteResourceLong(
unsigned char *p,
1587 const unsigned int quantum)
1592 buffer[0]=(
unsigned char) (quantum >> 24);
1593 buffer[1]=(
unsigned char) (quantum >> 16);
1594 buffer[2]=(
unsigned char) (quantum >> 8);
1595 buffer[3]=(
unsigned char) quantum;
1596 (void) memcpy(p,buffer,4);
1599static void WriteTo8BimProfile(
Image *image,
const char *name,
1628 if (LocaleCompare(name,
"icc") == 0)
1631 if (LocaleCompare(name,
"iptc") == 0)
1634 if (LocaleCompare(name,
"xmp") == 0)
1639 image->profiles,
"8bim");
1642 datum=GetStringInfoDatum(profile_8bim);
1643 length=GetStringInfoLength(profile_8bim);
1644 for (p=datum; p < (datum+length-16); )
1647 if (LocaleNCompare((
char *) p,
"8BIM",4) != 0)
1650 p=ReadResourceShort(p,&
id);
1651 p=ReadResourceByte(p,&length_byte);
1653 if (((length_byte+1) & 0x01) != 0)
1655 if (p > (datum+length-4))
1657 p=ReadResourceLong(p,&value);
1658 count=(ssize_t) value;
1659 if ((count & 0x01) != 0)
1661 if ((count < 0) || (p > (datum+length-count)) || (count > (ssize_t) length))
1663 if (
id != profile_id)
1678 extent=(size_t) ((datum+length)-(p+count));
1681 offset=(size_t) (q-datum);
1682 extract_profile=AcquireStringInfo(offset+extent);
1683 (void) memcpy(extract_profile->datum,datum,offset);
1687 offset=(size_t) (p-datum);
1688 extract_extent=(ssize_t) profile->length;
1689 if ((extract_extent & 0x01) != 0)
1691 extract_profile=AcquireStringInfo(offset+(
size_t) extract_extent+
1693 (void) memcpy(extract_profile->datum,datum,offset-4);
1694 WriteResourceLong(extract_profile->datum+offset-4,(
unsigned int)
1696 (void) memcpy(extract_profile->datum+offset,
1697 profile->datum,profile->length);
1699 (void) memcpy(extract_profile->datum+offset+extract_extent,
1701 (void) AddValueToSplayTree((
SplayTreeInfo *) image->profiles,
1702 ConstantString(
"8bim"),CloneStringInfo(extract_profile));
1703 extract_profile=DestroyStringInfo(extract_profile);
1709static void GetProfilesFromResourceBlock(
Image *image,
1736 datum=GetStringInfoDatum(resource_block);
1737 length=GetStringInfoLength(resource_block);
1738 for (p=datum; p < (datum+length-16); )
1740 if (LocaleNCompare((
char *) p,
"8BIM",4) != 0)
1743 p=ReadResourceShort(p,&
id);
1744 p=ReadResourceByte(p,&length_byte);
1746 if (((length_byte+1) & 0x01) != 0)
1748 if (p > (datum+length-4))
1750 p=ReadResourceLong(p,&value);
1751 count=(ssize_t) value;
1752 if ((p > (datum+length-count)) || (count > (ssize_t) length) ||
1770 p=ReadResourceLong(p,&resolution);
1771 image->resolution.x=((double) resolution)/65536.0;
1772 p=ReadResourceShort(p,&units)+2;
1773 p=ReadResourceLong(p,&resolution)+4;
1774 image->resolution.y=((double) resolution)/65536.0;
1778 if ((ResolutionType) units != PixelsPerCentimeterResolution)
1779 image->units=PixelsPerInchResolution;
1782 image->units=PixelsPerCentimeterResolution;
1783 image->resolution.x/=2.54;
1784 image->resolution.y/=2.54;
1793 profile=AcquireStringInfo((
size_t) count);
1794 SetStringInfoDatum(profile,p);
1795 (void) SetImageProfileInternal(image,
"iptc",profile,MagickTrue,
1797 profile=DestroyStringInfo(profile);
1814 profile=AcquireStringInfo((
size_t) count);
1815 SetStringInfoDatum(profile,p);
1816 (void) SetImageProfileInternal(image,
"icc",profile,MagickTrue,
1818 profile=DestroyStringInfo(profile);
1827 profile=AcquireStringInfo((
size_t) count);
1828 SetStringInfoDatum(profile,p);
1829 (void) SetImageProfileInternal(image,
"exif",profile,MagickTrue,
1831 profile=DestroyStringInfo(profile);
1840 profile=AcquireStringInfo((
size_t) count);
1841 SetStringInfoDatum(profile,p);
1842 (void) SetImageProfileInternal(image,
"xmp",profile,MagickTrue,
1844 profile=DestroyStringInfo(profile);
1854 if ((count & 0x01) != 0)
1859static void PatchCorruptProfile(
const char *name,
StringInfo *profile)
1870 if (LocaleCompare(name,
"xmp") == 0)
1875 p=GetStringInfoDatum(profile);
1876 p=(
unsigned char *) strstr((
const char *) p,
"<?xpacket end=\"w\"?>");
1877 if (p != (
unsigned char *) NULL)
1880 length=(size_t) (p-GetStringInfoDatum(profile));
1881 if (length != GetStringInfoLength(profile))
1884 SetStringInfoLength(profile,length);
1889 if (LocaleCompare(name,
"exif") == 0)
1894 p=GetStringInfoDatum(profile);
1895 if ((LocaleNCompare((
const char *) p,
"MM",2) == 0) ||
1896 (LocaleNCompare((
const char *) p,
"II",2) == 0))
1899 profile_start[] =
"Exif\0\0";
1904 exif_profile=AcquireStringInfo(6);
1907 SetStringInfoDatum(exif_profile,profile_start);
1908 ConcatenateStringInfo(exif_profile,profile);
1909 SetStringInfoLength(profile,GetStringInfoLength(exif_profile));
1910 SetStringInfo(profile,exif_profile);
1911 exif_profile=DestroyStringInfo(exif_profile);
1917static MagickBooleanType ValidateXMPProfile(
Image *image,
1920#if defined(MAGICKCORE_XML_DELEGATE)
1927 const char *artifact=GetImageArtifact(image,
"xmp:validate");
1928 if (IsStringTrue(artifact) == MagickFalse)
1930 document=xmlReadMemory((
const char *) GetStringInfoDatum(profile),(
int)
1931 GetStringInfoLength(profile),
"xmp.xml",NULL,XML_PARSE_NOERROR |
1932 XML_PARSE_NOWARNING);
1933 if (document == (xmlDocPtr) NULL)
1935 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
1936 "CorruptImageProfile",
"`%s' (XMP)",image->filename);
1937 return(MagickFalse);
1939 xmlFreeDoc(document);
1943 (void) ThrowMagickException(exception,GetMagickModule(),
1944 MissingDelegateWarning,
"DelegateLibrarySupportNotBuiltIn",
"`%s' (XML)",
1946 return(MagickFalse);
1950static MagickBooleanType SetImageProfileInternal(
Image *image,
const char *name,
1951 const StringInfo *profile,
const MagickBooleanType recursive,
1955 key[MagickPathExtent];
1963 assert(image != (
Image *) NULL);
1964 assert(image->signature == MagickCoreSignature);
1965 if (IsEventLogging() != MagickFalse)
1966 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1967 clone_profile=CloneStringInfo(profile);
1968 PatchCorruptProfile(name,clone_profile);
1969 if ((LocaleCompare(name,
"xmp") == 0) &&
1970 (ValidateXMPProfile(image,clone_profile,exception) == MagickFalse))
1972 clone_profile=DestroyStringInfo(clone_profile);
1976 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
1978 (void) CopyMagickString(key,name,MagickPathExtent);
1980 status=AddValueToSplayTree((
SplayTreeInfo *) image->profiles,
1981 ConstantString(key),clone_profile);
1982 if (status != MagickFalse)
1984 if (LocaleCompare(name,
"8bim") == 0)
1985 GetProfilesFromResourceBlock(image,clone_profile,exception);
1987 if (recursive == MagickFalse)
1988 WriteTo8BimProfile(image,name,clone_profile);
1993MagickExport MagickBooleanType SetImageProfile(
Image *image,
const char *name,
1996 return(SetImageProfileInternal(image,name,profile,MagickFalse,exception));
2022static inline int ReadProfileByte(
unsigned char **p,
size_t *length)
2034static inline signed short ReadProfileShort(
const EndianType endian,
2035 unsigned char *buffer)
2049 if (endian == LSBEndian)
2051 value=(
unsigned short) buffer[1] << 8;
2052 value|=(
unsigned short) buffer[0];
2053 quantum.unsigned_value=value & 0xffff;
2054 return(quantum.signed_value);
2056 value=(
unsigned short) buffer[0] << 8;
2057 value|=(
unsigned short) buffer[1];
2058 quantum.unsigned_value=value & 0xffff;
2059 return(quantum.signed_value);
2062static inline signed int ReadProfileLong(
const EndianType endian,
2063 unsigned char *buffer)
2077 if (endian == LSBEndian)
2079 value=(
unsigned int) buffer[3] << 24;
2080 value|=(
unsigned int) buffer[2] << 16;
2081 value|=(
unsigned int) buffer[1] << 8;
2082 value|=(
unsigned int) buffer[0];
2083 quantum.unsigned_value=value & 0xffffffff;
2084 return(quantum.signed_value);
2086 value=(
unsigned int) buffer[0] << 24;
2087 value|=(
unsigned int) buffer[1] << 16;
2088 value|=(
unsigned int) buffer[2] << 8;
2089 value|=(
unsigned int) buffer[3];
2090 quantum.unsigned_value=value & 0xffffffff;
2091 return(quantum.signed_value);
2094static inline signed int ReadProfileMSBLong(
unsigned char **p,
size_t *length)
2101 value=ReadProfileLong(MSBEndian,*p);
2107static inline signed short ReadProfileMSBShort(
unsigned char **p,
2115 value=ReadProfileShort(MSBEndian,*p);
2121static inline void WriteProfileLong(
const EndianType endian,
2122 const size_t value,
unsigned char *p)
2127 if (endian == LSBEndian)
2129 buffer[0]=(
unsigned char) value;
2130 buffer[1]=(
unsigned char) (value >> 8);
2131 buffer[2]=(
unsigned char) (value >> 16);
2132 buffer[3]=(
unsigned char) (value >> 24);
2133 (void) memcpy(p,buffer,4);
2136 buffer[0]=(
unsigned char) (value >> 24);
2137 buffer[1]=(
unsigned char) (value >> 16);
2138 buffer[2]=(
unsigned char) (value >> 8);
2139 buffer[3]=(
unsigned char) value;
2140 (void) memcpy(p,buffer,4);
2143static void WriteProfileShort(
const EndianType endian,
2144 const unsigned short value,
unsigned char *p)
2149 if (endian == LSBEndian)
2151 buffer[0]=(
unsigned char) value;
2152 buffer[1]=(
unsigned char) (value >> 8);
2153 (void) memcpy(p,buffer,2);
2156 buffer[0]=(
unsigned char) (value >> 8);
2157 buffer[1]=(
unsigned char) value;
2158 (void) memcpy(p,buffer,2);
2161static void SyncExifProfile(
const Image *image,
unsigned char *exif,
2164#define MaxDirectoryStack 16
2165#define EXIF_DELIMITER "\n"
2166#define EXIF_NUM_FORMATS 12
2167#define TAG_EXIF_OFFSET 0x8769
2168#define TAG_INTEROP_OFFSET 0xa005
2170 typedef struct _DirectoryInfo
2180 directory_stack[MaxDirectoryStack] = { { 0, 0 } };
2198 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
2205 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2206 if ((
id != 0x4949) && (
id != 0x4D4D))
2210 if (ReadProfileByte(&exif,&length) != 0x45)
2212 if (ReadProfileByte(&exif,&length) != 0x78)
2214 if (ReadProfileByte(&exif,&length) != 0x69)
2216 if (ReadProfileByte(&exif,&length) != 0x66)
2218 if (ReadProfileByte(&exif,&length) != 0x00)
2220 if (ReadProfileByte(&exif,&length) != 0x00)
2226 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2236 if (ReadProfileShort(endian,exif+2) != 0x002a)
2241 offset=(ssize_t) ReadProfileLong(endian,exif+4);
2242 if ((offset < 0) || ((size_t) offset >= length))
2244 directory=exif+offset;
2247 exif_resources=NewSplayTree((
int (*)(
const void *,
const void *)) NULL,
2248 (
void *(*)(
void *)) NULL,(
void *(*)(
void *)) NULL);
2254 directory=directory_stack[level].directory;
2255 entry=directory_stack[level].entry;
2257 if ((directory < exif) || (directory > (exif+length-2)))
2262 number_entries=(size_t) ReadProfileShort(endian,directory);
2263 for ( ; entry < number_entries; entry++)
2279 q=(
unsigned char *) (directory+2+(12*entry));
2280 if (q > (exif+length-12))
2282 if (GetValueFromSplayTree(exif_resources,q) == q)
2284 (void) AddValueToSplayTree(exif_resources,q,q);
2285 tag_value=(ssize_t) ReadProfileShort(endian,q);
2286 format=(ssize_t) ReadProfileShort(endian,q+2);
2287 if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2289 components=(int) ReadProfileLong(endian,q+4);
2292 number_bytes=(size_t) components*(
size_t) format_bytes[format];
2293 if ((ssize_t) number_bytes < components)
2295 if (number_bytes <= 4)
2302 offset=(ssize_t) ReadProfileLong(endian,q+8);
2304 ((size_t) (offset+(ssize_t) number_bytes) > length))
2306 if (~length < number_bytes)
2308 p=(
unsigned char *) (exif+offset);
2314 (void) WriteProfileLong(endian,(
size_t) (image->resolution.x+0.5),p);
2315 if (number_bytes == 8)
2316 (void) WriteProfileLong(endian,1UL,p+4);
2321 (void) WriteProfileLong(endian,(
size_t) (image->resolution.y+0.5),p);
2322 if (number_bytes == 8)
2323 (void) WriteProfileLong(endian,1UL,p+4);
2328 if (number_bytes == 4)
2330 (void) WriteProfileLong(endian,(
size_t) image->orientation,p);
2333 (void) WriteProfileShort(endian,(
unsigned short) image->orientation,
2339 if (number_bytes == 4)
2341 (void) WriteProfileLong(endian,((
size_t) image->units)+1,p);
2344 (void) WriteProfileShort(endian,(
unsigned short) (image->units+1),p);
2350 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2352 offset=(ssize_t) ReadProfileLong(endian,p);
2353 if (((
size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2355 directory_stack[level].directory=directory;
2357 directory_stack[level].entry=entry;
2359 directory_stack[level].directory=exif+offset;
2360 directory_stack[level].entry=0;
2362 if ((directory+2+(12*number_entries)) > (exif+length))
2364 offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2366 if ((offset != 0) && ((size_t) offset < length) &&
2367 (level < (MaxDirectoryStack-2)))
2369 directory_stack[level].directory=exif+offset;
2370 directory_stack[level].entry=0;
2377 }
while (level > 0);
2378 exif_resources=DestroySplayTree(exif_resources);
2382static void Sync8BimProfile(
const Image *image,
const StringInfo *profile)
2396 length=GetStringInfoLength(profile);
2397 p=GetStringInfoDatum(profile);
2400 if (ReadProfileByte(&p,&length) != 0x38)
2402 if (ReadProfileByte(&p,&length) != 0x42)
2404 if (ReadProfileByte(&p,&length) != 0x49)
2406 if (ReadProfileByte(&p,&length) != 0x4D)
2410 id=(
unsigned short) ReadProfileMSBShort(&p,&length);
2411 count=(ssize_t) ReadProfileByte(&p,&length);
2412 if ((count >= (ssize_t) length) || (count < 0))
2415 length-=(size_t) count;
2416 if ((*p & 0x01) == 0)
2417 (
void) ReadProfileByte(&p,&length);
2418 count=(ssize_t) ReadProfileMSBLong(&p,&length);
2419 if ((count > (ssize_t) length) || (count < 0))
2421 if ((
id == 0x3ED) && (count == 16))
2423 if (image->units == PixelsPerCentimeterResolution)
2424 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2425 image->resolution.x*2.54*65536.0),p);
2427 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2428 image->resolution.x*65536.0),p);
2429 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+4);
2430 if (image->units == PixelsPerCentimeterResolution)
2431 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2432 image->resolution.y*2.54*65536.0),p+8);
2434 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToLong(
2435 image->resolution.y*65536.0),p+8);
2436 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+12);
2439 SyncExifProfile(image,p,(
size_t) count);
2441 length-=(size_t) count;
2446static void ReplaceXmpValue(
StringInfo *profile,
size_t start,
size_t end,
2457 length=GetStringInfoLength(profile);
2458 value_length=strlen(value);
2459 new_length=length-(end-start)+value_length;
2460 if (new_length > length)
2461 SetStringInfoLength(profile,new_length);
2462 datum=(
char *) GetStringInfoDatum(profile);
2463 (void) memmove(datum+start+value_length,datum+end,length-end);
2464 (void) memcpy(datum+start,value,value_length);
2465 if (new_length < length)
2467 SetStringInfoLength(profile,new_length);
2468 datum=(
char *) GetStringInfoDatum(profile);
2469 *(datum+new_length)=
'\0';
2473static MagickBooleanType GetXmpOffsets(
const StringInfo *profile,
2474 const char *tag,
size_t *start,
size_t *end)
2484 datum=(
char *) GetStringInfoDatum(profile);
2485 length=GetStringInfoLength(profile);
2486 pos=strstr(datum,tag);
2487 tag_length=strlen(tag);
2488 if ((pos == (
char *) NULL) || ((pos-datum) < 1) || (*(pos-1) !=
'<') ||
2489 (((
size_t) (pos-datum)+tag_length) > length) ||
2490 (*(pos+tag_length) !=
'>'))
2491 return(MagickFalse);
2492 *start=(size_t) (pos-datum)+tag_length+1;
2493 pos=strstr(datum+*start,
"<");
2494 if (pos == (
char *) NULL)
2495 return(MagickFalse);
2496 *end=(size_t) (pos-datum);
2500static void GetXmpNumeratorAndDenominator(
double value,
2501 unsigned long *numerator,
unsigned long *denominator)
2508 if (value <= MagickEpsilon)
2512 while(fabs(df - value) > MagickEpsilon)
2519 *numerator=(
unsigned long) (value*(*denominator));
2521 df=*numerator/(double)*denominator;
2528 value[MagickPathExtent];
2539 if (GetXmpOffsets(profile,
"tiff:XResolution",&start,&end) != MagickFalse)
2541 GetXmpNumeratorAndDenominator(image->resolution.x,&numerator,
2543 (void) FormatLocaleString(value,MagickPathExtent,
"%lu/%lu",numerator,
2545 ReplaceXmpValue(profile,start,end,value);
2547 if (GetXmpOffsets(profile,
"tiff:YResolution",&start,&end) != MagickFalse)
2549 if ((fabs(image->resolution.x-image->resolution.y) > MagickEpsilon) ||
2552 GetXmpNumeratorAndDenominator(image->resolution.y,&numerator,
2554 (void) FormatLocaleString(value,MagickPathExtent,
"%lu/%lu",
2555 numerator,denominator);
2557 ReplaceXmpValue(profile,start,end,value);
2559 if (GetXmpOffsets(profile,
"tiff:ResolutionUnit",&start,&end) != MagickFalse)
2561 (void) FormatLocaleString(value,MagickPathExtent,
"%d",
2562 ((
int) image->units)+1);
2563 ReplaceXmpValue(profile,start,end,value);
2565 if (GetXmpOffsets(profile,
"tiff:Orientation",&start,&end) != MagickFalse)
2567 (void) FormatLocaleString(value,MagickPathExtent,
"%d",
2568 (
int) image->orientation);
2569 ReplaceXmpValue(profile,start,end,value);
2573MagickPrivate
void SyncImageProfiles(
Image *image)
2578 profile=(
StringInfo *) GetImageProfile(image,
"8BIM");
2580 Sync8BimProfile(image,profile);
2581 profile=(
StringInfo *) GetImageProfile(image,
"EXIF");
2583 SyncExifProfile(image,GetStringInfoDatum(profile),GetStringInfoLength(
2585 profile=(
StringInfo *) GetImageProfile(image,
"XMP");
2587 SyncXmpProfile(image,profile);
2590static void UpdateClipPath(
unsigned char *blob,
size_t length,
2591 const size_t old_columns,
const size_t old_rows,
2602 selector=(ssize_t) ReadProfileMSBShort(&blob,&length);
2608 if (knot_count != 0)
2611 length-=(size_t) MagickMin(length,24U);
2617 knot_count=(ssize_t) ReadProfileMSBShort(&blob,&length);
2619 length-=(size_t) MagickMin(length,22);
2627 if (knot_count == 0)
2633 length-=(size_t) MagickMin(length,24);
2639 for (i=0; i < 3; i++)
2649 y=(double) ReadProfileMSBLong(&blob,&length);
2650 y=y*old_rows/4096.0/4096.0;
2652 yy=(
signed int) ((y*4096*4096)/new_geometry->height);
2653 WriteProfileLong(MSBEndian,(
size_t) yy,blob-4);
2654 x=(double) ReadProfileMSBLong(&blob,&length);
2655 x=x*old_columns/4096.0/4096.0;
2657 xx=(
signed int) ((x*4096*4096)/new_geometry->width);
2658 WriteProfileLong(MSBEndian,(
size_t) xx,blob-4);
2669 length-=(size_t) MagickMin(length,24);
2676MagickPrivate
void Update8BIMClipPath(
const Image *image,
2677 const size_t old_columns,
const size_t old_rows,
2693 assert(image != (
Image *) NULL);
2695 profile=GetImageProfile(image,
"8bim");
2698 length=GetStringInfoLength(profile);
2699 info=GetStringInfoDatum(profile);
2702 if (ReadProfileByte(&info,&length) != (
unsigned char)
'8')
2704 if (ReadProfileByte(&info,&length) != (
unsigned char)
'B')
2706 if (ReadProfileByte(&info,&length) != (
unsigned char)
'I')
2708 if (ReadProfileByte(&info,&length) != (
unsigned char)
'M')
2710 id=(ssize_t) ReadProfileMSBShort(&info,&length);
2711 count=(ssize_t) ReadProfileByte(&info,&length);
2712 if ((count != 0) && ((size_t) count <= length))
2715 length-=(size_t) count;
2717 if ((count & 0x01) == 0)
2718 (
void) ReadProfileByte(&info,&length);
2719 count=(ssize_t) ReadProfileMSBLong(&info,&length);
2720 if ((count < 0) || ((size_t) count > length))
2725 if ((
id > 1999) && (
id < 2999))
2726 UpdateClipPath(info,(
size_t) count,old_columns,old_rows,new_geometry);
2728 length-=(size_t) MagickMin(length,(
size_t) count);