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/policy.h"
60#include "MagickCore/profile.h"
61#include "MagickCore/profile-private.h"
62#include "MagickCore/property.h"
63#include "MagickCore/quantum.h"
64#include "MagickCore/quantum-private.h"
65#include "MagickCore/resource_.h"
66#include "MagickCore/splay-tree.h"
67#include "MagickCore/string_.h"
68#include "MagickCore/string-private.h"
69#include "MagickCore/thread-private.h"
70#include "MagickCore/token.h"
71#include "MagickCore/utility.h"
72#if defined(MAGICKCORE_LCMS_DELEGATE)
74#if defined(MAGICKCORE_HAVE_LCMS_LCMS2_H)
75#include <lcms/lcms2.h>
80#if defined(MAGICKCORE_XML_DELEGATE)
81# include <libxml/parser.h>
82# include <libxml/tree.h>
88static MagickBooleanType
99 max_profile_count = 0;
133MagickPrivate
void AppendImageProfileProperty(
Image *image,
const char *profile,
134 const char *property,
const char *value,
ExceptionInfo *exception)
142 assert(image != (
Image *) NULL);
143 assert(image->signature == MagickCoreSignature);
144 assert(profile != (
const char *) NULL);
145 assert(property != (
const char *) NULL);
146 assert(value != (
const char *) NULL);
147 if (GetImageProfile(image,profile) == (
const StringInfo *) NULL)
149 current=GetImageProperty(image,property,exception);
150 if ((current == (
const char *) NULL) || (*current ==
'\0'))
152 (void) SetImageProperty(image,property,value,exception);
155 property_value=AcquireString(current);
156 (void) ConcatenateString(&property_value,
";");
157 (void) ConcatenateString(&property_value,value);
158 (void) SetImageProperty(image,property,property_value,exception);
159 property_value=DestroyString(property_value);
216 *(*CloneKeyFunc)(
const char *);
221static inline void *CloneProfileKey(
void *key)
223 return((
void *) ((CloneKeyFunc) ConstantString)((
const char *) key));
226static inline void *CloneProfileValue(
void *value)
228 return((
void *) ((CloneValueFunc) CloneStringInfo)((
const StringInfo *) value));
231MagickExport MagickBooleanType CloneImageProfiles(
Image *image,
232 const Image *clone_image)
234 assert(image != (
Image *) NULL);
235 assert(image->signature == MagickCoreSignature);
236 assert(clone_image != (
const Image *) NULL);
237 assert(clone_image->signature == MagickCoreSignature);
238 if (IsEventLogging() != MagickFalse)
239 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
240 if (clone_image->profiles != (
void *) NULL)
242 if (image->profiles != (
void *) NULL)
243 DestroyImageProfiles(image);
244 image->profiles=CloneSplayTree((
SplayTreeInfo *) clone_image->profiles,
245 CloneProfileKey,CloneProfileValue);
274MagickExport MagickBooleanType DeleteImageProfile(
Image *image,
const char *name)
276 assert(image != (
Image *) NULL);
277 assert(image->signature == MagickCoreSignature);
278 if (IsEventLogging() != MagickFalse)
279 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
282 WriteTo8BimProfile(image,name,(
StringInfo *) NULL);
283 return(DeleteNodeFromSplayTree((
SplayTreeInfo *) image->profiles,name));
308MagickExport
void DestroyImageProfiles(
Image *image)
311 image->profiles=DestroySplayTree((
SplayTreeInfo *) image->profiles);
344 assert(image != (
Image *) NULL);
345 assert(image->signature == MagickCoreSignature);
346 if (IsEventLogging() != MagickFalse)
347 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
351 image->profiles,name);
373static size_t GetMaxProfileCountFromPolicy(
void)
379 max=(size_t) MAGICK_SSIZE_MAX;
381 value=GetPolicyValue(
"system:max-profile-count");
382 if (value != (
char *) NULL)
387 max=StringToSizeType(value,100.0);
388 max=MagickMax(1,max);
389 value=DestroyString(value);
391 return(MagickMin(max,(
size_t) MAGICK_SSIZE_MAX));
394MagickExport
size_t GetMaxProfileCount(
void)
396 if (max_profile_count == 0)
397 max_profile_count=GetMaxProfileCountFromPolicy();
398 return(max_profile_count);
423MagickExport
char *GetNextImageProfile(
const Image *image)
425 assert(image != (
Image *) NULL);
426 assert(image->signature == MagickCoreSignature);
427 if (IsEventLogging() != MagickFalse)
428 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
430 return((
char *) NULL);
431 return((
char *) GetNextKeyInSplayTree((
SplayTreeInfo *) image->profiles));
475#if defined(MAGICKCORE_LCMS_DELEGATE)
477typedef struct _LCMSInfo
499 **magick_restrict pixels;
502#if LCMS_VERSION < 2060
503static void* cmsGetContextUserData(cmsContext ContextID)
508static cmsContext cmsCreateContext(
void *magick_unused(Plugin),
void *UserData)
510 magick_unreferenced(Plugin);
511 return((cmsContext) UserData);
514static void cmsSetLogErrorHandlerTHR(cmsContext magick_unused(ContextID),
515 cmsLogErrorHandlerFunction Fn)
517 magick_unreferenced(ContextID);
518 cmsSetLogErrorHandler(Fn);
521static void cmsDeleteContext(cmsContext magick_unused(ContextID))
523 magick_unreferenced(ContextID);
527static void **DestroyPixelTLS(
void **pixels)
532 if (pixels == (
void **) NULL)
533 return((
void **) NULL);
534 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
535 if (pixels[i] != (
void *) NULL)
536 pixels[i]=RelinquishMagickMemory(pixels[i]);
537 pixels=(
void **) RelinquishMagickMemory(pixels);
541static void **AcquirePixelTLS(
const size_t columns,
const size_t channels,
542 MagickBooleanType highres)
556 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
557 pixels=(
void **) AcquireQuantumMemory(number_threads,
sizeof(*pixels));
558 if (pixels == (
void **) NULL)
559 return((
void **) NULL);
560 (void) memset(pixels,0,number_threads*
sizeof(*pixels));
562 if (highres == MagickFalse)
563 size=
sizeof(Quantum);
564 for (i=0; i < (ssize_t) number_threads; i++)
566 pixels[i]=AcquireQuantumMemory(columns,channels*size);
567 if (pixels[i] == (
void *) NULL)
568 return(DestroyPixelTLS(pixels));
573static cmsHTRANSFORM *DestroyTransformTLS(cmsHTRANSFORM *transform)
578 assert(transform != (cmsHTRANSFORM *) NULL);
579 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
580 if (transform[i] != (cmsHTRANSFORM) NULL)
581 cmsDeleteTransform(transform[i]);
582 transform=(cmsHTRANSFORM *) RelinquishMagickMemory(transform);
586static cmsHTRANSFORM *AcquireTransformTLS(
const LCMSInfo *source_info,
587 const LCMSInfo *target_info,
const cmsUInt32Number flags,
588 cmsContext cms_context)
599 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
600 transform=(cmsHTRANSFORM *) AcquireQuantumMemory(number_threads,
602 if (transform == (cmsHTRANSFORM *) NULL)
603 return((cmsHTRANSFORM *) NULL);
604 (void) memset(transform,0,number_threads*
sizeof(*transform));
605 for (i=0; i < (ssize_t) number_threads; i++)
607 transform[i]=cmsCreateTransformTHR(cms_context,source_info->profile,
608 source_info->type,target_info->profile,target_info->type,
609 (cmsUInt32Number) target_info->intent,flags);
610 if (transform[i] == (cmsHTRANSFORM) NULL)
611 return(DestroyTransformTLS(transform));
616static void CMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
631 exception=cms_exception->exception;
634 image=cms_exception->image;
635 if (image == (
Image *) NULL)
637 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
638 "UnableToTransformColorspace",
"`%s'",
"unknown context");
641 if (image->debug != MagickFalse)
642 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
"lcms: #%u, %s",
643 severity,message != (
char *) NULL ? message :
"no message");
644 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
645 "UnableToTransformColorspace",
"`%s', %s (#%u)",image->filename,
646 message != (
char *) NULL ? message :
"no message",severity);
649static void TransformDoublePixels(
const int id,
const Image* image,
650 const LCMSInfo *source_info,
const LCMSInfo *target_info,
651 const cmsHTRANSFORM *transform,Quantum *q)
653#define GetLCMSPixel(source_info,pixel,index) \
654 (source_info->scale[index]*(((double) QuantumScale*(double) pixel)+ \
655 source_info->translate[index]))
656#define SetLCMSPixel(target_info,pixel,index) ClampToQuantum( \
657 target_info->scale[index]*(((double) QuantumRange*(double) pixel)+ \
658 target_info->translate[index]))
666 p=(
double *) source_info->pixels[
id];
667 for (x=0; x < (ssize_t) image->columns; x++)
669 *p++=GetLCMSPixel(source_info,GetPixelRed(image,q),0);
670 if (source_info->channels > 1)
672 *p++=GetLCMSPixel(source_info,GetPixelGreen(image,q),1);
673 *p++=GetLCMSPixel(source_info,GetPixelBlue(image,q),2);
675 if (source_info->channels > 3)
676 *p++=GetLCMSPixel(source_info,GetPixelBlack(image,q),3);
677 q+=(ptrdiff_t) GetPixelChannels(image);
679 cmsDoTransform(transform[
id],source_info->pixels[
id],target_info->pixels[
id],
680 (
unsigned int) image->columns);
681 p=(
double *) target_info->pixels[
id];
682 q-=GetPixelChannels(image)*image->columns;
683 for (x=0; x < (ssize_t) image->columns; x++)
685 if (target_info->channels == 1)
686 SetPixelGray(image,SetLCMSPixel(target_info,*p,0),q);
688 SetPixelRed(image,SetLCMSPixel(target_info,*p,0),q);
690 if (target_info->channels > 1)
692 SetPixelGreen(image,SetLCMSPixel(target_info,*p,1),q);
694 SetPixelBlue(image,SetLCMSPixel(target_info,*p,2),q);
697 if (target_info->channels > 3)
699 SetPixelBlack(image,SetLCMSPixel(target_info,*p,3),q);
702 q+=(ptrdiff_t) GetPixelChannels(image);
706static void TransformQuantumPixels(
const int id,
const Image* image,
707 const LCMSInfo *source_info,
const LCMSInfo *target_info,
708 const cmsHTRANSFORM *transform,Quantum *q)
716 p=(Quantum *) source_info->pixels[
id];
717 for (x=0; x < (ssize_t) image->columns; x++)
719 *p++=GetPixelRed(image,q);
720 if (source_info->channels > 1)
722 *p++=GetPixelGreen(image,q);
723 *p++=GetPixelBlue(image,q);
725 if (source_info->channels > 3)
726 *p++=GetPixelBlack(image,q);
727 q+=(ptrdiff_t) GetPixelChannels(image);
729 cmsDoTransform(transform[
id],source_info->pixels[
id],target_info->pixels[
id],
730 (
unsigned int) image->columns);
731 p=(Quantum *) target_info->pixels[
id];
732 q-=GetPixelChannels(image)*image->columns;
733 for (x=0; x < (ssize_t) image->columns; x++)
735 if (target_info->channels == 1)
736 SetPixelGray(image,*p++,q);
738 SetPixelRed(image,*p++,q);
739 if (target_info->channels > 1)
741 SetPixelGreen(image,*p++,q);
742 SetPixelBlue(image,*p++,q);
744 if (target_info->channels > 3)
745 SetPixelBlack(image,*p++,q);
746 q+=(ptrdiff_t) GetPixelChannels(image);
750static inline void SetLCMSInfoTranslate(LCMSInfo *info,
const double translate)
752 info->translate[0]=translate;
753 info->translate[1]=translate;
754 info->translate[2]=translate;
755 info->translate[3]=translate;
758static inline void SetLCMSInfoScale(LCMSInfo *info,
const double scale)
760 info->scale[0]=scale;
761 info->scale[1]=scale;
762 info->scale[2]=scale;
763 info->scale[3]=scale;
772 0x00, 0x00, 0x0c, 0x8c, 0x61, 0x72, 0x67, 0x6c, 0x02, 0x20, 0x00, 0x00,
773 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
774 0x07, 0xde, 0x00, 0x01, 0x00, 0x06, 0x00, 0x16, 0x00, 0x0f, 0x00, 0x3a,
775 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
776 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00,
777 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
778 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x61, 0x72, 0x67, 0x6c,
779 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
780 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
781 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
782 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
783 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x99,
784 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0xec, 0x00, 0x00, 0x00, 0x67,
785 0x64, 0x6d, 0x6e, 0x64, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70,
786 0x64, 0x6d, 0x64, 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88,
787 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x0c,
788 0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x00, 0x67,
789 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x24,
790 0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xe4, 0x00, 0x00, 0x00, 0x14,
791 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x24,
792 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x14,
793 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x14,
794 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x14,
795 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x58, 0x00, 0x00, 0x00, 0x14,
796 0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x6c, 0x00, 0x00, 0x00, 0x14,
797 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
798 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
799 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
800 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
801 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36,
802 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75, 0x69, 0x76,
803 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x77, 0x77,
804 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x31, 0x39,
805 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c,
806 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
807 0x00, 0x3f, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31,
808 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75,
809 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77,
810 0x77, 0x77, 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20,
811 0x31, 0x39, 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66,
812 0x69, 0x6c, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
813 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, 0x61,
814 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x72, 0x61, 0x65, 0x6d,
815 0x65, 0x20, 0x57, 0x2e, 0x20, 0x47, 0x69, 0x6c, 0x6c, 0x2e, 0x20, 0x52,
816 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f,
817 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
818 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x4e, 0x6f, 0x20, 0x57,
819 0x61, 0x72, 0x72, 0x61, 0x6e, 0x74, 0x79, 0x2c, 0x20, 0x55, 0x73, 0x65,
820 0x20, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e,
821 0x20, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
822 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20,
823 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
824 0x65, 0x63, 0x2e, 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
825 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74,
826 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
827 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
828 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
829 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
830 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
831 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
832 0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e,
833 0x31, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47,
834 0x42, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61,
835 0x63, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
836 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43,
837 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
838 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63,
839 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
840 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
841 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
842 0x00, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00,
843 0x43, 0x52, 0x54, 0x20, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
844 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
845 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
846 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
847 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
848 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
849 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
850 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
851 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
852 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa4, 0x7c,
853 0x00, 0x14, 0x5f, 0x30, 0x00, 0x10, 0xce, 0x02, 0x00, 0x03, 0xed, 0xb2,
854 0x00, 0x04, 0x13, 0x0a, 0x00, 0x03, 0x5c, 0x67, 0x00, 0x00, 0x00, 0x01,
855 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x0a, 0x3d,
856 0x00, 0x50, 0x00, 0x00, 0x00, 0x57, 0x1e, 0xb8, 0x6d, 0x65, 0x61, 0x73,
857 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
858 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
859 0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x58, 0x59, 0x5a, 0x20,
860 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00,
861 0x00, 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
862 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
863 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa0,
864 0x00, 0x00, 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20,
865 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x97, 0x00, 0x00, 0xb7, 0x87,
866 0x00, 0x00, 0x18, 0xd9, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
867 0x00, 0x00, 0x24, 0x9f, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0xb6, 0xc4,
868 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
869 0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19,
870 0x00, 0x1e, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37,
871 0x00, 0x3b, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54,
872 0x00, 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
873 0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00, 0x90,
874 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9, 0x00, 0xae,
875 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00, 0xc6, 0x00, 0xcb,
876 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0xeb,
877 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01, 0x01, 0x01, 0x07, 0x01, 0x0d,
878 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f, 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32,
879 0x01, 0x38, 0x01, 0x3e, 0x01, 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59,
880 0x01, 0x60, 0x01, 0x67, 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83,
881 0x01, 0x8b, 0x01, 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1,
882 0x01, 0xb9, 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1,
883 0x01, 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
884 0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02, 0x4b,
885 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a, 0x02, 0x84,
886 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02, 0xb6, 0x02, 0xc1,
887 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb, 0x02, 0xf5, 0x03, 0x00,
888 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2d, 0x03, 0x38, 0x03, 0x43,
889 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66, 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a,
890 0x03, 0x96, 0x03, 0xa2, 0x03, 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3,
891 0x03, 0xe0, 0x03, 0xec, 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20,
892 0x04, 0x2d, 0x04, 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71,
893 0x04, 0x7e, 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4,
894 0x04, 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
895 0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05, 0x77,
896 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5, 0x05, 0xd5,
897 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06, 0x27, 0x06, 0x37,
898 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b, 0x06, 0x8c, 0x06, 0x9d,
899 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06, 0xe3, 0x06, 0xf5, 0x07, 0x07,
900 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d, 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74,
901 0x07, 0x86, 0x07, 0x99, 0x07, 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5,
902 0x07, 0xf8, 0x08, 0x0b, 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a,
903 0x08, 0x6e, 0x08, 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2,
904 0x08, 0xe7, 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f,
905 0x09, 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
906 0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a, 0x54,
907 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5, 0x0a, 0xdc,
908 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b, 0x51, 0x0b, 0x69,
909 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8, 0x0b, 0xe1, 0x0b, 0xf9,
910 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c, 0x5c, 0x0c, 0x75, 0x0c, 0x8e,
911 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9, 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26,
912 0x0d, 0x40, 0x0d, 0x5a, 0x0d, 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3,
913 0x0d, 0xde, 0x0d, 0xf8, 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64,
914 0x0e, 0x7f, 0x0e, 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09,
915 0x0f, 0x25, 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3,
916 0x0f, 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
917 0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11, 0x13,
918 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa, 0x11, 0xc9,
919 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12, 0x64, 0x12, 0x84,
920 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03, 0x13, 0x23, 0x13, 0x43,
921 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13, 0xc5, 0x13, 0xe5, 0x14, 0x06,
922 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a, 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce,
923 0x14, 0xf0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b,
924 0x15, 0xbd, 0x15, 0xe0, 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c,
925 0x16, 0x8f, 0x16, 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41,
926 0x17, 0x65, 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b,
927 0x18, 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
928 0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19, 0xdd,
929 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e, 0x1a, 0xc5,
930 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b, 0x8a, 0x1b, 0xb2,
931 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52, 0x1c, 0x7b, 0x1c, 0xa3,
932 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d, 0x47, 0x1d, 0x70, 0x1d, 0x99,
933 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16, 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94,
934 0x1e, 0xbe, 0x1e, 0xe9, 0x1f, 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94,
935 0x1f, 0xbf, 0x1f, 0xea, 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98,
936 0x20, 0xc4, 0x20, 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1,
937 0x21, 0xce, 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf,
938 0x22, 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
939 0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24, 0xda,
940 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7, 0x25, 0xf7,
941 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26, 0xe8, 0x27, 0x18,
942 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc, 0x28, 0x0d, 0x28, 0x3f,
943 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29, 0x06, 0x29, 0x38, 0x29, 0x6b,
944 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02, 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b,
945 0x2a, 0xcf, 0x2b, 0x02, 0x2b, 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1,
946 0x2c, 0x05, 0x2c, 0x39, 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c,
947 0x2d, 0x41, 0x2d, 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c,
948 0x2e, 0x82, 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91,
949 0x2f, 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
950 0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32, 0x2a,
951 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46, 0x33, 0x7f,
952 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34, 0x9e, 0x34, 0xd8,
953 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2, 0x35, 0xfd, 0x36, 0x37,
954 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37, 0x24, 0x37, 0x60, 0x37, 0x9c,
955 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05,
956 0x39, 0x42, 0x39, 0x7f, 0x39, 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74,
957 0x3a, 0xb2, 0x3a, 0xef, 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8,
958 0x3c, 0x27, 0x3c, 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61,
959 0x3d, 0xa1, 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0,
960 0x3f, 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
961 0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41, 0xee,
962 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a, 0x43, 0x7d,
963 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44, 0xce, 0x45, 0x12,
964 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22, 0x46, 0x67, 0x46, 0xab,
965 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47, 0xc0, 0x48, 0x05, 0x48, 0x4b,
966 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d, 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0,
967 0x4a, 0x37, 0x4a, 0x7d, 0x4a, 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a,
968 0x4b, 0xe2, 0x4c, 0x2a, 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a,
969 0x4d, 0x93, 0x4d, 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00,
970 0x4f, 0x49, 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb,
971 0x51, 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
972 0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54, 0x42,
973 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2, 0x56, 0x0f,
974 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57, 0x92, 0x57, 0xe0,
975 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a, 0x59, 0x69, 0x59, 0xb8,
976 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a, 0xf5, 0x5b, 0x45, 0x5b, 0x95,
977 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86, 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78,
978 0x5d, 0xc9, 0x5e, 0x1a, 0x5e, 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61,
979 0x5f, 0xb3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f,
980 0x61, 0xa2, 0x61, 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43,
981 0x63, 0x97, 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d,
982 0x65, 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
983 0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69, 0x43,
984 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7, 0x6b, 0x4f,
985 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d, 0x08, 0x6d, 0x60,
986 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4, 0x6f, 0x1e, 0x6f, 0x78,
987 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70, 0xe0, 0x71, 0x3a, 0x71, 0x95,
988 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6, 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8,
989 0x74, 0x14, 0x74, 0x70, 0x74, 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1,
990 0x76, 0x3e, 0x76, 0x9b, 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11,
991 0x78, 0x6e, 0x78, 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46,
992 0x7a, 0xa5, 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81,
993 0x7c, 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
994 0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81, 0x0a,
995 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4, 0x83, 0x57,
996 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85, 0x47, 0x85, 0xab,
997 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b, 0x87, 0x9f, 0x88, 0x04,
998 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89, 0x99, 0x89, 0xfe, 0x8a, 0x64,
999 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96, 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca,
1000 0x8d, 0x31, 0x8d, 0x98, 0x8d, 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36,
1001 0x8f, 0x9e, 0x90, 0x06, 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8,
1002 0x92, 0x11, 0x92, 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20,
1003 0x94, 0x8a, 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f,
1004 0x97, 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
1005 0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b, 0xaf,
1006 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2, 0x9e, 0x40,
1007 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0, 0x69, 0xa0, 0xd8,
1008 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96, 0xa3, 0x06, 0xa3, 0x76,
1009 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5, 0x38, 0xa5, 0xa9, 0xa6, 0x1a,
1010 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e, 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4,
1011 0xa9, 0x37, 0xa9, 0xa9, 0xaa, 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75,
1012 0xab, 0xe9, 0xac, 0x5c, 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d,
1013 0xae, 0xa1, 0xaf, 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea,
1014 0xb1, 0x60, 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae,
1015 0xb4, 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
1016 0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9, 0x4a,
1017 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7, 0xbc, 0x21,
1018 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe, 0x84, 0xbe, 0xff,
1019 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec, 0xc1, 0x67, 0xc1, 0xe3,
1020 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3, 0xd4, 0xc4, 0x51, 0xc4, 0xce,
1021 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46, 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf,
1022 0xc8, 0x3d, 0xc8, 0xbc, 0xc9, 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7,
1023 0xcb, 0x36, 0xcb, 0xb6, 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5,
1024 0xce, 0x36, 0xce, 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba,
1025 0xd1, 0x3c, 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6,
1026 0xd4, 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
1027 0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9, 0xf1,
1028 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a, 0xdd, 0x10,
1029 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf, 0xaf, 0xe0, 0x36,
1030 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53, 0xe2, 0xdb, 0xe3, 0x63,
1031 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5, 0x84, 0xe6, 0x0d, 0xe6, 0x96,
1032 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32, 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0,
1033 0xea, 0x5b, 0xea, 0xe5, 0xeb, 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11,
1034 0xed, 0x9c, 0xee, 0x28, 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58,
1035 0xf0, 0xe5, 0xf1, 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7,
1036 0xf4, 0x34, 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb,
1037 0xf7, 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
1038 0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd, 0xba,
1039 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
1045 assert(image != (
Image *) NULL);
1046 assert(image->signature == MagickCoreSignature);
1047 if (GetImageProfile(image,
"icc") != (
const StringInfo *) NULL)
1049 profile=BlobToProfileStringInfo(
"icc",sRGBProfile,
sizeof(sRGBProfile),
1051 (void) SetImageProfilePrivate(image,profile,exception);
1054MagickExport MagickBooleanType ProfileImage(
Image *image,
const char *name,
1055 const void *datum,
const size_t length,
ExceptionInfo *exception)
1057#define ProfileImageTag "Profile/Image"
1059 #define TYPE_XYZ_8 (COLORSPACE_SH(PT_XYZ)|CHANNELS_SH(3)|BYTES_SH(1))
1061#define ThrowProfileException(severity,tag,context) \
1063 if (profile != (StringInfo *) NULL) \
1064 profile=DestroyStringInfo(profile); \
1065 if (cms_context != (cmsContext) NULL) \
1066 cmsDeleteContext(cms_context); \
1067 if (source_info.profile != (cmsHPROFILE) NULL) \
1068 (void) cmsCloseProfile(source_info.profile); \
1069 if (target_info.profile != (cmsHPROFILE) NULL) \
1070 (void) cmsCloseProfile(target_info.profile); \
1071 ThrowBinaryException(severity,tag,context); \
1080 assert(image != (
Image *) NULL);
1081 assert(image->signature == MagickCoreSignature);
1082 assert(name != (
const char *) NULL);
1083 if (IsEventLogging() != MagickFalse)
1084 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1085 if ((datum == (
const void *) NULL) || (length == 0))
1093 ResetImageProfileIterator(image);
1094 for (next=GetNextImageProfile(image); next != (
const char *) NULL; )
1096 if (IsOptionMember(next,name) != MagickFalse)
1098 (void) DeleteImageProfile(image,next);
1099 ResetImageProfileIterator(image);
1101 next=GetNextImageProfile(image);
1109 profile=AcquireProfileStringInfo(name,(
size_t) length,exception);
1111 return(MagickFalse);
1112 SetStringInfoDatum(profile,(
unsigned char *) datum);
1113 if ((LocaleCompare(name,
"icc") != 0) && (LocaleCompare(name,
"icm") != 0))
1114 status=SetImageProfilePrivate(image,profile,exception);
1120 icc_profile=GetImageProfile(image,
"icc");
1121 if ((icc_profile != (
const StringInfo *) NULL) &&
1122 (CompareStringInfo(icc_profile,profile) == 0))
1127 value=GetImageProperty(image,
"exif:ColorSpace",exception);
1129 if (LocaleCompare(value,
"1") != 0)
1130 SetsRGBImageProfile(image,exception);
1131 value=GetImageProperty(image,
"exif:InteroperabilityIndex",exception);
1132 if (LocaleCompare(value,
"R98.") != 0)
1133 SetsRGBImageProfile(image,exception);
1134 icc_profile=GetImageProfile(image,
"icc");
1136 if ((icc_profile != (
const StringInfo *) NULL) &&
1137 (CompareStringInfo(icc_profile,profile) == 0))
1139 profile=DestroyStringInfo(profile);
1142#if !defined(MAGICKCORE_LCMS_DELEGATE)
1143 (void) ThrowMagickException(exception,GetMagickModule(),
1144 MissingDelegateWarning,
"DelegateLibrarySupportNotBuiltIn",
1145 "'%s' (LCMS)",image->filename);
1161 cms_exception.image=image;
1162 cms_exception.exception=exception;
1163 cms_context=cmsCreateContext(NULL,&cms_exception);
1164 if (cms_context == (cmsContext) NULL)
1166 profile=DestroyStringInfo(profile);
1167 ThrowBinaryException(ResourceLimitError,
1168 "ColorspaceColorProfileMismatch",name);
1170 cmsSetLogErrorHandlerTHR(cms_context,CMSExceptionHandler);
1171 source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
1172 GetStringInfoDatum(profile),(cmsUInt32Number)
1173 GetStringInfoLength(profile));
1174 if (source_info.profile == (cmsHPROFILE) NULL)
1176 profile=DestroyStringInfo(profile);
1177 cmsDeleteContext(cms_context);
1178 ThrowBinaryException(ResourceLimitError,
1179 "ColorspaceColorProfileMismatch",name);
1181 if ((cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass) &&
1183 status=SetImageProfilePrivate(image,profile,exception);
1189 cmsColorSpaceSignature
1193 *magick_restrict transform;
1207 target_info.profile=(cmsHPROFILE) NULL;
1210 target_info.profile=source_info.profile;
1211 source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
1212 GetStringInfoDatum(icc_profile),(cmsUInt32Number)
1213 GetStringInfoLength(icc_profile));
1214 if (source_info.profile == (cmsHPROFILE) NULL)
1215 ThrowProfileException(ResourceLimitError,
1216 "ColorspaceColorProfileMismatch",name);
1219#if !defined(MAGICKCORE_HDRI_SUPPORT) || (MAGICKCORE_QUANTUM_DEPTH > 16)
1224 artifact=GetImageArtifact(image,
"profile:highres-transform");
1225 if (IsStringFalse(artifact) != MagickFalse)
1226 highres=MagickFalse;
1229 SetLCMSInfoScale(&source_info,1.0);
1230 SetLCMSInfoTranslate(&source_info,0.0);
1231 source_info.colorspace=sRGBColorspace;
1232 source_info.channels=3;
1233 switch (cmsGetColorSpace(source_info.profile))
1235 case cmsSigCmykData:
1237 source_info.colorspace=CMYKColorspace;
1238 source_info.channels=4;
1239 if (highres != MagickFalse)
1241 source_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1242 SetLCMSInfoScale(&source_info,100.0);
1244#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1246 source_info.type=(cmsUInt32Number) TYPE_CMYK_8;
1247#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1249 source_info.type=(cmsUInt32Number) TYPE_CMYK_16;
1253 case cmsSigGrayData:
1255 source_info.colorspace=GRAYColorspace;
1256 source_info.channels=1;
1257 if (highres != MagickFalse)
1258 source_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1259#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1261 source_info.type=(cmsUInt32Number) TYPE_GRAY_8;
1262#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1264 source_info.type=(cmsUInt32Number) TYPE_GRAY_16;
1270 source_info.colorspace=LabColorspace;
1271 if (highres != MagickFalse)
1273 source_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1274 source_info.scale[0]=100.0;
1275 source_info.scale[1]=255.0;
1276 source_info.scale[2]=255.0;
1277#if !defined(MAGICKCORE_HDRI_SUPPORT)
1278 source_info.translate[1]=(-0.5);
1279 source_info.translate[2]=(-0.5);
1282#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1284 source_info.type=(cmsUInt32Number) TYPE_Lab_8;
1285#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1287 source_info.type=(cmsUInt32Number) TYPE_Lab_16;
1293 source_info.colorspace=sRGBColorspace;
1294 if (highres != MagickFalse)
1295 source_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1296#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1298 source_info.type=(cmsUInt32Number) TYPE_RGB_8;
1299#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1301 source_info.type=(cmsUInt32Number) TYPE_RGB_16;
1307 source_info.colorspace=XYZColorspace;
1308 if (highres != MagickFalse)
1309 source_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1310#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1312 source_info.type=(cmsUInt32Number) TYPE_XYZ_8;
1313#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1315 source_info.type=(cmsUInt32Number) TYPE_XYZ_16;
1320 ThrowProfileException(ImageError,
1321 "ColorspaceColorProfileMismatch",name);
1323 signature=cmsGetPCS(source_info.profile);
1324 if (target_info.profile != (cmsHPROFILE) NULL)
1325 signature=cmsGetColorSpace(target_info.profile);
1326 SetLCMSInfoScale(&target_info,1.0);
1327 SetLCMSInfoTranslate(&target_info,0.0);
1328 target_info.channels=3;
1331 case cmsSigCmykData:
1333 target_info.colorspace=CMYKColorspace;
1334 target_info.channels=4;
1335 if (highres != MagickFalse)
1337 target_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1338 SetLCMSInfoScale(&target_info,0.01);
1340#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1342 target_info.type=(cmsUInt32Number) TYPE_CMYK_8;
1343#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1345 target_info.type=(cmsUInt32Number) TYPE_CMYK_16;
1349 case cmsSigGrayData:
1351 target_info.colorspace=GRAYColorspace;
1352 target_info.channels=1;
1353 if (highres != MagickFalse)
1354 target_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1355#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1357 target_info.type=(cmsUInt32Number) TYPE_GRAY_8;
1358#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1360 target_info.type=(cmsUInt32Number) TYPE_GRAY_16;
1366 target_info.colorspace=LabColorspace;
1367 if (highres != MagickFalse)
1369 target_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1370 target_info.scale[0]=0.01;
1371 target_info.scale[1]=1/255.0;
1372 target_info.scale[2]=1/255.0;
1373#if !defined(MAGICKCORE_HDRI_SUPPORT)
1374 target_info.translate[1]=0.5;
1375 target_info.translate[2]=0.5;
1378#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1380 target_info.type=(cmsUInt32Number) TYPE_Lab_8;
1381#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1383 target_info.type=(cmsUInt32Number) TYPE_Lab_16;
1389 target_info.colorspace=sRGBColorspace;
1390 if (highres != MagickFalse)
1391 target_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1392#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1394 target_info.type=(cmsUInt32Number) TYPE_RGB_8;
1395#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1397 target_info.type=(cmsUInt32Number) TYPE_RGB_16;
1403 target_info.colorspace=XYZColorspace;
1404 if (highres != MagickFalse)
1405 target_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1406#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1408 target_info.type=(cmsUInt32Number) TYPE_XYZ_8;
1409#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1411 target_info.type=(cmsUInt32Number) TYPE_XYZ_16;
1416 ThrowProfileException(ImageError,
1417 "ColorspaceColorProfileMismatch",name);
1419 switch (image->rendering_intent)
1421 case AbsoluteIntent:
1423 target_info.intent=INTENT_ABSOLUTE_COLORIMETRIC;
1426 case PerceptualIntent:
1428 target_info.intent=INTENT_PERCEPTUAL;
1431 case RelativeIntent:
1433 target_info.intent=INTENT_RELATIVE_COLORIMETRIC;
1436 case SaturationIntent:
1438 target_info.intent=INTENT_SATURATION;
1443 target_info.intent=INTENT_PERCEPTUAL;
1447 flags=cmsFLAGS_HIGHRESPRECALC;
1448#if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1449 if (image->black_point_compensation != MagickFalse)
1450 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1452 transform=AcquireTransformTLS(&source_info,&target_info,flags,
1454 if (transform == (cmsHTRANSFORM *) NULL)
1455 ThrowProfileException(ImageError,
"UnableToCreateColorTransform",
1460 source_info.pixels=AcquirePixelTLS(image->columns,
1461 source_info.channels,highres);
1462 target_info.pixels=AcquirePixelTLS(image->columns,
1463 target_info.channels,highres);
1464 if ((source_info.pixels == (
void **) NULL) ||
1465 (target_info.pixels == (
void **) NULL))
1467 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1468 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1469 transform=DestroyTransformTLS(transform);
1470 ThrowProfileException(ResourceLimitError,
1471 "MemoryAllocationFailed",image->filename);
1473 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1475 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1476 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1477 transform=DestroyTransformTLS(transform);
1478 if (source_info.profile != (cmsHPROFILE) NULL)
1479 (void) cmsCloseProfile(source_info.profile);
1480 if (target_info.profile != (cmsHPROFILE) NULL)
1481 (void) cmsCloseProfile(target_info.profile);
1482 return(MagickFalse);
1484 if (target_info.colorspace == CMYKColorspace)
1485 (void) SetImageColorspace(image,target_info.colorspace,exception);
1487 image_view=AcquireAuthenticCacheView(image,exception);
1488#if defined(MAGICKCORE_OPENMP_SUPPORT)
1489 #pragma omp parallel for schedule(static) shared(status) \
1490 magick_number_threads(image,image,image->rows,1)
1492 for (y=0; y < (ssize_t) image->rows; y++)
1495 id = GetOpenMPThreadId();
1503 if (status == MagickFalse)
1505 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1507 if (q == (Quantum *) NULL)
1512 if (highres != MagickFalse)
1513 TransformDoublePixels(
id,image,&source_info,&target_info,
1516 TransformQuantumPixels(
id,image,&source_info,&target_info,
1518 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1519 if (sync == MagickFalse)
1521 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1526#if defined(MAGICKCORE_OPENMP_SUPPORT)
1530 proceed=SetImageProgress(image,ProfileImageTag,progress,
1532 if (proceed == MagickFalse)
1536 image_view=DestroyCacheView(image_view);
1537 (void) SetImageColorspace(image,target_info.colorspace,exception);
1542 image->type=image->alpha_trait == UndefinedPixelTrait ?
1543 TrueColorType : TrueColorAlphaType;
1546 case cmsSigCmykData:
1548 image->type=image->alpha_trait == UndefinedPixelTrait ?
1549 ColorSeparationType : ColorSeparationAlphaType;
1552 case cmsSigGrayData:
1554 image->type=image->alpha_trait == UndefinedPixelTrait ?
1555 GrayscaleType : GrayscaleAlphaType;
1561 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1562 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1563 transform=DestroyTransformTLS(transform);
1564 if ((status != MagickFalse) &&
1565 (cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass))
1566 status=SetImageProfilePrivate(image,profile,exception);
1568 profile=DestroyStringInfo(profile);
1569 if (target_info.profile != (cmsHPROFILE) NULL)
1570 (void) cmsCloseProfile(target_info.profile);
1572 (void) cmsCloseProfile(source_info.profile);
1573 cmsDeleteContext(cms_context);
1605MagickExport
StringInfo *RemoveImageProfile(
Image *image,
const char *name)
1610 assert(image != (
Image *) NULL);
1611 assert(image->signature == MagickCoreSignature);
1612 if (IsEventLogging() != MagickFalse)
1613 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1616 WriteTo8BimProfile(image,name,(
StringInfo *) NULL);
1618 image->profiles,name);
1646MagickExport
void ResetImageProfileIterator(
const Image *image)
1648 assert(image != (
Image *) NULL);
1649 assert(image->signature == MagickCoreSignature);
1650 if (IsEventLogging() != MagickFalse)
1651 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1688static void *DestroyProfile(
void *profile)
1690 return((
void *) DestroyStringInfo((
StringInfo *) profile));
1693static inline const unsigned char *ReadResourceByte(
const unsigned char *p,
1694 unsigned char *quantum)
1700static inline const unsigned char *ReadResourceLong(
const unsigned char *p,
1701 unsigned int *quantum)
1703 *quantum=(
unsigned int) (*p++) << 24;
1704 *quantum|=(
unsigned int) (*p++) << 16;
1705 *quantum|=(
unsigned int) (*p++) << 8;
1706 *quantum|=(
unsigned int) (*p++);
1710static inline const unsigned char *ReadResourceShort(
const unsigned char *p,
1711 unsigned short *quantum)
1713 *quantum=(
unsigned short) (*p++) << 8;
1714 *quantum|=(
unsigned short) (*p++);
1718static inline void WriteResourceLong(
unsigned char *p,
1719 const unsigned int quantum)
1724 buffer[0]=(
unsigned char) (quantum >> 24);
1725 buffer[1]=(
unsigned char) (quantum >> 16);
1726 buffer[2]=(
unsigned char) (quantum >> 8);
1727 buffer[3]=(
unsigned char) quantum;
1728 (void) memcpy(p,buffer,4);
1731static void WriteTo8BimProfile(
Image *image,
const char *name,
1760 if (LocaleCompare(name,
"icc") == 0)
1763 if (LocaleCompare(name,
"iptc") == 0)
1766 if (LocaleCompare(name,
"xmp") == 0)
1771 image->profiles,
"8bim");
1774 datum=GetStringInfoDatum(profile_8bim);
1775 length=GetStringInfoLength(profile_8bim);
1776 for (p=datum; p < (datum+length-16); )
1779 if (LocaleNCompare((
char *) p,
"8BIM",4) != 0)
1782 p=ReadResourceShort(p,&
id);
1783 p=ReadResourceByte(p,&length_byte);
1784 p+=(ptrdiff_t) length_byte;
1785 if (((length_byte+1) & 0x01) != 0)
1787 if (p > (datum+length-4))
1789 p=ReadResourceLong(p,&value);
1790 count=(ssize_t) value;
1791 if ((count & 0x01) != 0)
1793 if ((count < 0) || (p > (datum+length-count)) || (count > (ssize_t) length))
1795 if (
id != profile_id)
1796 p+=(ptrdiff_t) count;
1810 extent=(size_t) ((datum+length)-(p+count));
1813 offset=(size_t) (q-datum);
1814 extract_profile=AcquireStringInfo(offset+extent);
1815 (void) memcpy(extract_profile->datum,datum,offset);
1819 offset=(size_t) (p-datum);
1820 extract_extent=(ssize_t) profile->length;
1821 if ((extract_extent & 0x01) != 0)
1823 extract_profile=AcquireStringInfo(offset+(
size_t) extract_extent+
1825 (void) memcpy(extract_profile->datum,datum,offset-4);
1826 WriteResourceLong(extract_profile->datum+offset-4,(
unsigned int)
1828 (void) memcpy(extract_profile->datum+offset,
1829 profile->datum,profile->length);
1831 (void) memcpy(extract_profile->datum+offset+extract_extent,
1833 (void) AddValueToSplayTree((
SplayTreeInfo *) image->profiles,
1834 ConstantString(
"8bim"),CloneStringInfo(extract_profile));
1835 extract_profile=DestroyStringInfo(extract_profile);
1841static void GetProfilesFromResourceBlock(
Image *image,
1868 datum=GetStringInfoDatum(resource_block);
1869 length=GetStringInfoLength(resource_block);
1870 for (p=datum; p < (datum+length-16); )
1872 if (LocaleNCompare((
char *) p,
"8BIM",4) != 0)
1875 p=ReadResourceShort(p,&
id);
1876 p=ReadResourceByte(p,&length_byte);
1877 p+=(ptrdiff_t) length_byte;
1878 if (((length_byte+1) & 0x01) != 0)
1880 if (p > (datum+length-4))
1882 p=ReadResourceLong(p,&value);
1883 count=(ssize_t) value;
1884 if ((p > (datum+length-count)) || (count > (ssize_t) length) ||
1902 p=ReadResourceLong(p,&resolution);
1903 image->resolution.x=((double) resolution)/65536.0;
1904 p=ReadResourceShort(p,&units)+2;
1905 p=ReadResourceLong(p,&resolution)+4;
1906 image->resolution.y=((double) resolution)/65536.0;
1910 if ((ResolutionType) units != PixelsPerCentimeterResolution)
1911 image->units=PixelsPerInchResolution;
1914 image->units=PixelsPerCentimeterResolution;
1915 image->resolution.x/=2.54;
1916 image->resolution.y/=2.54;
1925 profile=BlobToProfileStringInfo(
"iptc",p,(
size_t) count,exception);
1927 (void) SetImageProfileInternal(image,GetStringInfoName(profile),
1928 profile,MagickTrue,exception);
1929 p+=(ptrdiff_t) count;
1937 p+=(ptrdiff_t) count;
1945 profile=BlobToProfileStringInfo(
"icc",p,(
size_t) count,exception);
1947 (void) SetImageProfileInternal(image,GetStringInfoName(profile),
1948 profile,MagickTrue,exception);
1949 p+=(ptrdiff_t) count;
1957 profile=BlobToProfileStringInfo(
"exif",p,(
size_t) count,exception);
1959 (void) SetImageProfileInternal(image,GetStringInfoName(profile),
1960 profile,MagickTrue,exception);
1961 p+=(ptrdiff_t) count;
1969 profile=BlobToProfileStringInfo(
"xmp",p,(
size_t) count,exception);
1971 (void) SetImageProfileInternal(image,GetStringInfoName(profile),
1972 profile,MagickTrue,exception);
1973 p+=(ptrdiff_t) count;
1978 p+=(ptrdiff_t) count;
1982 if ((count & 0x01) != 0)
1987static void PatchCorruptProfile(
const char *name,
StringInfo *profile)
1998 if (LocaleCompare(name,
"xmp") == 0)
2003 p=GetStringInfoDatum(profile);
2004 p=(
unsigned char *) strstr((
const char *) p,
"<?xpacket end=\"w\"?>");
2005 if (p != (
unsigned char *) NULL)
2008 length=(size_t) (p-GetStringInfoDatum(profile));
2009 if (length != GetStringInfoLength(profile))
2012 SetStringInfoLength(profile,length);
2017 if (((LocaleCompare(name,
"exif") == 0) || (LocaleCompare(name,
"app1") == 0)) &&
2018 (GetStringInfoLength(profile) > 2))
2023 p=GetStringInfoDatum(profile);
2024 if ((LocaleNCompare((
const char *) p,
"MM",2) == 0) ||
2025 (LocaleNCompare((
const char *) p,
"II",2) == 0))
2028 profile_start[] =
"Exif\0\0";
2033 exif_profile=AcquireStringInfo(6);
2036 SetStringInfoDatum(exif_profile,profile_start);
2037 ConcatenateStringInfo(exif_profile,profile);
2038 SetStringInfoLength(profile,GetStringInfoLength(exif_profile));
2039 SetStringInfo(profile,exif_profile);
2040 exif_profile=DestroyStringInfo(exif_profile);
2046static MagickBooleanType ValidateXMPProfile(
Image *image,
2049#if defined(MAGICKCORE_XML_DELEGATE)
2056 const char *artifact=GetImageArtifact(image,
"xmp:validate");
2057 if (IsStringTrue(artifact) == MagickFalse)
2059 document=xmlReadMemory((
const char *) GetStringInfoDatum(profile),(
int)
2060 GetStringInfoLength(profile),
"xmp.xml",NULL,XML_PARSE_NOERROR |
2061 XML_PARSE_NOWARNING);
2062 if (document == (xmlDocPtr) NULL)
2064 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
2065 "CorruptImageProfile",
"`%s' (XMP)",image->filename);
2066 return(MagickFalse);
2068 xmlFreeDoc(document);
2072 (void) ThrowMagickException(exception,GetMagickModule(),
2073 MissingDelegateWarning,
"DelegateLibrarySupportNotBuiltIn",
"`%s' (XML)",
2075 return(MagickFalse);
2079static MagickBooleanType SetImageProfileInternal(
Image *image,
const char *name,
2080 StringInfo *profile,
const MagickBooleanType recursive,
2084 key[MagickPathExtent];
2092 assert(image != (
Image *) NULL);
2093 assert(image->signature == MagickCoreSignature);
2095 assert(name != (
const char *) NULL);
2096 if (IsEventLogging() != MagickFalse)
2097 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2099 (GetNumberOfNodesInSplayTree((
SplayTreeInfo*) image->profiles) >= GetMaxProfileCount()))
2101 (void) ThrowMagickException(exception,GetMagickModule(),
2102 ResourceLimitWarning,
"MaximumProfilesExceeded",
"`%s'",name);
2103 profile=DestroyStringInfo(profile);
2106 length=GetStringInfoLength(profile);
2107 if ((length == 0) || (length > GetMaxProfileSize()))
2110 (void) ThrowMagickException(exception,GetMagickModule(),
2111 ResourceLimitWarning,
"ProfileSizeExceedsLimit",
"`%llu'",
2112 (
unsigned long long) length);
2113 profile=DestroyStringInfo(profile);
2116 PatchCorruptProfile(name,profile);
2117 if ((LocaleCompare(name,
"xmp") == 0) &&
2118 (ValidateXMPProfile(image,profile,exception) == MagickFalse))
2120 profile=DestroyStringInfo(profile);
2124 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
2126 (void) CopyMagickString(key,name,MagickPathExtent);
2132 if ((length > 4) && (LocaleCompare(key,
"app1") == 0) &&
2133 (LocaleNCompare((
const char *) GetStringInfoDatum(profile),
"exif",4) == 0))
2134 (void) CopyMagickString(key,
"exif",MagickPathExtent);
2137 status=AddValueToSplayTree((
SplayTreeInfo *) image->profiles,
2138 ConstantString(key),profile);
2139 if (status == MagickFalse)
2140 profile=DestroyStringInfo(profile);
2143 if (LocaleCompare(key,
"8bim") == 0)
2144 GetProfilesFromResourceBlock(image,profile,exception);
2146 if (recursive == MagickFalse)
2147 WriteTo8BimProfile(image,key,profile);
2152MagickExport
StringInfo *AcquireProfileStringInfo(
const char *name,
2158 if (length > GetMaxProfileSize())
2159 (void) ThrowMagickException(exception,GetMagickModule(),
2160 ResourceLimitWarning,
"ProfileSizeExceedsLimit",
"`%llu'",
2161 (
unsigned long long) length);
2164 profile=AcquireStringInfo(length);
2165 SetStringInfoName(profile,name);
2170MagickExport
StringInfo *BlobToProfileStringInfo(
const char *name,
2171 const void *blob,
const size_t length,
ExceptionInfo *exception)
2176 profile=AcquireProfileStringInfo(name,length,exception);
2178 (void) memcpy(profile->datum,blob,length);
2182MagickExport MagickBooleanType SetImageProfile(
Image *image,
const char *name,
2189 return(MagickFalse);
2190 clone_profile=CloneStringInfo(profile);
2191 return(SetImageProfileInternal(image,name,clone_profile,MagickFalse,
2195MagickExport MagickBooleanType SetImageProfilePrivate(
Image *image,
2199 return(MagickFalse);
2200 return(SetImageProfileInternal(image,GetStringInfoName(profile),profile,
2201 MagickFalse,exception));
2227static inline int ReadProfileByte(
unsigned char **p,
size_t *length)
2239static inline signed short ReadProfileShort(
const EndianType endian,
2240 unsigned char *buffer)
2254 if (endian == LSBEndian)
2256 value=(
unsigned short) buffer[1] << 8;
2257 value|=(
unsigned short) buffer[0];
2258 quantum.unsigned_value=value & 0xffff;
2259 return((
signed short) quantum.signed_value);
2261 value=(
unsigned short) buffer[0] << 8;
2262 value|=(
unsigned short) buffer[1];
2263 quantum.unsigned_value=value & 0xffff;
2264 return((
signed short) quantum.signed_value);
2267static inline signed int ReadProfileLong(
const EndianType endian,
2268 unsigned char *buffer)
2282 if (endian == LSBEndian)
2284 value=(
unsigned int) buffer[3] << 24;
2285 value|=(
unsigned int) buffer[2] << 16;
2286 value|=(
unsigned int) buffer[1] << 8;
2287 value|=(
unsigned int) buffer[0];
2288 quantum.unsigned_value=value & 0xffffffff;
2289 return(quantum.signed_value);
2291 value=(
unsigned int) buffer[0] << 24;
2292 value|=(
unsigned int) buffer[1] << 16;
2293 value|=(
unsigned int) buffer[2] << 8;
2294 value|=(
unsigned int) buffer[3];
2295 quantum.unsigned_value=value & 0xffffffff;
2296 return(quantum.signed_value);
2299static inline signed int ReadProfileMSBLong(
unsigned char **p,
size_t *length)
2306 value=ReadProfileLong(MSBEndian,*p);
2312static inline signed short ReadProfileMSBShort(
unsigned char **p,
2320 value=ReadProfileShort(MSBEndian,*p);
2326static inline void WriteProfileLong(
const EndianType endian,
2327 const size_t value,
unsigned char *p)
2332 if (endian == LSBEndian)
2334 buffer[0]=(
unsigned char) value;
2335 buffer[1]=(
unsigned char) (value >> 8);
2336 buffer[2]=(
unsigned char) (value >> 16);
2337 buffer[3]=(
unsigned char) (value >> 24);
2338 (void) memcpy(p,buffer,4);
2341 buffer[0]=(
unsigned char) (value >> 24);
2342 buffer[1]=(
unsigned char) (value >> 16);
2343 buffer[2]=(
unsigned char) (value >> 8);
2344 buffer[3]=(
unsigned char) value;
2345 (void) memcpy(p,buffer,4);
2348static void WriteProfileShort(
const EndianType endian,
2349 const unsigned short value,
unsigned char *p)
2354 if (endian == LSBEndian)
2356 buffer[0]=(
unsigned char) value;
2357 buffer[1]=(
unsigned char) (value >> 8);
2358 (void) memcpy(p,buffer,2);
2361 buffer[0]=(
unsigned char) (value >> 8);
2362 buffer[1]=(
unsigned char) value;
2363 (void) memcpy(p,buffer,2);
2366static inline void WriteProfileDimension(
const EndianType endian,
2367 const size_t dimension,
const ssize_t format,
const int components,
2368 unsigned char *entry,
unsigned char *value)
2370 if ((components != 1) || ((format != 3) && (format != 4)))
2372 if ((format == 3) && (dimension <= MAGICK_USHORT_MAX))
2374 WriteProfileShort(endian,(
unsigned short) dimension,value);
2377 if (dimension > UINT32_MAX)
2380 WriteProfileShort(endian,4,entry+2);
2381 WriteProfileLong(endian,dimension,value);
2384static void SyncExifProfile(
const Image *image,
unsigned char *exif,
2387#define MaxDirectoryStack 16
2388#define EXIF_DELIMITER "\n"
2389#define EXIF_NUM_FORMATS 12
2390#define TAG_IMAGE_WIDTH 0x0100
2391#define TAG_IMAGE_LENGTH 0x0101
2392#define TAG_EXIF_OFFSET 0x8769
2393#define TAG_INTEROP_OFFSET 0xa005
2394#define TAG_PIXEL_X_DIMENSION 0xa002
2395#define TAG_PIXEL_Y_DIMENSION 0xa003
2397 typedef struct _DirectoryInfo
2407 directory_stack[MaxDirectoryStack] = { { 0, 0 } };
2426 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
2435 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2436 if ((
id != 0x4949) && (
id != 0x4D4D))
2440 if (ReadProfileByte(&exif,&length) != 0x45)
2442 if (ReadProfileByte(&exif,&length) != 0x78)
2444 if (ReadProfileByte(&exif,&length) != 0x69)
2446 if (ReadProfileByte(&exif,&length) != 0x66)
2448 if (ReadProfileByte(&exif,&length) != 0x00)
2450 if (ReadProfileByte(&exif,&length) != 0x00)
2456 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2466 if (ReadProfileShort(endian,exif+2) != 0x002a)
2471 offset=(ssize_t) ReadProfileLong(endian,exif+4);
2472 if ((offset < 0) || ((
size_t) offset >= length))
2474 directory=exif+offset;
2475 exif_directory=(
unsigned char *) NULL;
2479 exif_resources=NewSplayTree((
int (*)(
const void *,
const void *)) NULL,
2480 (
void *(*)(
void *)) NULL,(
void *(*)(
void *)) NULL);
2486 directory=directory_stack[level].directory;
2487 entry=directory_stack[level].entry;
2489 if ((directory < exif) || (directory > (exif+length-2)))
2494 directory_length=length-(size_t) (directory-exif);
2495 if (directory_length < 6)
2497 number_entries=(size_t) (
unsigned short) ReadProfileShort(endian,
2499 if (number_entries > ((directory_length-6)/12))
2501 for ( ; entry < number_entries; entry++)
2519 q=(
unsigned char *) (directory+2+(12*entry));
2520 if (q > (exif+length-12))
2522 if (GetValueFromSplayTree(exif_resources,q) == q)
2524 (void) AddValueToSplayTree(exif_resources,q,q);
2525 tag_value=(
unsigned short) ReadProfileShort(endian,q);
2526 format=(ssize_t) ReadProfileShort(endian,q+2);
2527 if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2529 components=(int) ReadProfileLong(endian,q+4);
2532 number_bytes=(size_t) components*(
size_t) format_bytes[format];
2533 if ((ssize_t) number_bytes < components)
2535 if (number_bytes <= 4)
2542 offset=(ssize_t) ReadProfileLong(endian,q+8);
2544 ((
size_t) (offset+(ssize_t) number_bytes) > length))
2546 if (~length < number_bytes)
2548 p=(
unsigned char *) (exif+offset);
2552 case TAG_IMAGE_WIDTH:
2553 case TAG_IMAGE_LENGTH:
2555 if (directory == ifd0)
2556 WriteProfileDimension(endian,tag_value == TAG_IMAGE_WIDTH ?
2557 image->columns : image->rows,format,components,q,p);
2560 case TAG_PIXEL_X_DIMENSION:
2561 case TAG_PIXEL_Y_DIMENSION:
2563 if (directory == exif_directory)
2564 WriteProfileDimension(endian,tag_value == TAG_PIXEL_X_DIMENSION ?
2565 image->columns : image->rows,format,components,q,p);
2570 if (directory != ifd0)
2572 (void) WriteProfileLong(endian,(
size_t) (image->resolution.x+0.5),p);
2573 if (number_bytes == 8)
2574 (void) WriteProfileLong(endian,1UL,p+4);
2579 if (directory != ifd0)
2581 (void) WriteProfileLong(endian,(
size_t) (image->resolution.y+0.5),p);
2582 if (number_bytes == 8)
2583 (void) WriteProfileLong(endian,1UL,p+4);
2588 if (directory != ifd0)
2590 if (number_bytes == 4)
2592 (void) WriteProfileLong(endian,(
size_t) image->orientation,p);
2595 (void) WriteProfileShort(endian,(
unsigned short) image->orientation,
2601 if (directory != ifd0)
2603 if (number_bytes == 4)
2605 (void) WriteProfileLong(endian,((
size_t) image->units)+1,p);
2608 (void) WriteProfileShort(endian,(
unsigned short) (image->units+1),p);
2614 if (((tag_value == TAG_EXIF_OFFSET) ||
2615 (tag_value == TAG_INTEROP_OFFSET)) && (format == 4) &&
2616 (components == 1) && (number_bytes == 4))
2618 offset=(ssize_t) ReadProfileLong(endian,p);
2619 if (((
size_t) offset < (length-1)) &&
2620 (level < (MaxDirectoryStack-2)))
2622 if ((directory == ifd0) && (tag_value == TAG_EXIF_OFFSET))
2623 exif_directory=exif+offset;
2624 directory_stack[level].directory=directory;
2626 directory_stack[level].entry=entry;
2628 directory_stack[level].directory=exif+offset;
2629 directory_stack[level].entry=0;
2631 if ((directory+2+(12*number_entries)) > (exif+length))
2633 offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2635 if ((offset != 0) && ((
size_t) offset < (length-1)) &&
2636 (level < (MaxDirectoryStack-2)))
2638 directory_stack[level].directory=exif+offset;
2639 directory_stack[level].entry=0;
2646 }
while (level > 0);
2647 exif_resources=DestroySplayTree(exif_resources);
2651static void Sync8BimProfile(
const Image *image,
const StringInfo *profile)
2665 length=GetStringInfoLength(profile);
2666 p=GetStringInfoDatum(profile);
2669 if (ReadProfileByte(&p,&length) != 0x38)
2671 if (ReadProfileByte(&p,&length) != 0x42)
2673 if (ReadProfileByte(&p,&length) != 0x49)
2675 if (ReadProfileByte(&p,&length) != 0x4D)
2679 id=(
unsigned short) ReadProfileMSBShort(&p,&length);
2680 count=(ssize_t) ReadProfileByte(&p,&length);
2681 if ((count >= (ssize_t) length) || (count < 0))
2683 p+=(ptrdiff_t) count;
2684 length-=(size_t) count;
2685 if ((*p & 0x01) == 0)
2686 (void) ReadProfileByte(&p,&length);
2687 count=(ssize_t) ReadProfileMSBLong(&p,&length);
2688 if ((count > (ssize_t) length) || (count < 0))
2690 if ((
id == 0x3ED) && (count == 16))
2692 if (image->units == PixelsPerCentimeterResolution)
2693 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToSsizeT(
2694 image->resolution.x*2.54*65536.0),p);
2696 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToSsizeT(
2697 image->resolution.x*65536.0),p);
2698 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+4);
2699 if (image->units == PixelsPerCentimeterResolution)
2700 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToSsizeT(
2701 image->resolution.y*2.54*65536.0),p+8);
2703 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToSsizeT(
2704 image->resolution.y*65536.0),p+8);
2705 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+12);
2708 SyncExifProfile(image,p,(
size_t) count);
2709 p+=(ptrdiff_t) count;
2710 length-=(size_t) count;
2715static void ReplaceXMPValue(
StringInfo *profile,
size_t start,
size_t end,
2726 length=GetStringInfoLength(profile);
2727 value_length=strlen(value);
2728 new_length=length-(end-start)+value_length;
2729 if (new_length > length)
2730 SetStringInfoLength(profile,new_length);
2731 datum=(
char *) GetStringInfoDatum(profile);
2732 (void) memmove(datum+start+value_length,datum+end,length-end);
2733 (void) memcpy(datum+start,value,value_length);
2734 *(datum+new_length)=
'\0';
2735 if (new_length < length)
2737 SetStringInfoLength(profile,new_length);
2738 datum=(
char *) GetStringInfoDatum(profile);
2742static MagickBooleanType GetXMPOffsets(
const StringInfo *profile,
2743 const char *tag,
size_t *start,
size_t *end)
2753 datum=(
char *) GetStringInfoDatum(profile);
2754 length=GetStringInfoLength(profile);
2755 pos=strstr(datum,tag);
2756 tag_length=strlen(tag);
2757 if ((pos == (
char *) NULL) || ((pos-datum) < 1) || (*(pos-1) !=
'<') ||
2758 (((
size_t) (pos-datum)+tag_length) > length) ||
2759 (*(pos+tag_length) !=
'>'))
2760 return(MagickFalse);
2761 *start=(size_t) (pos-datum)+tag_length+1;
2762 pos=strstr(datum+*start,
"<");
2763 if (pos == (
char *) NULL)
2764 return(MagickFalse);
2765 *end=(size_t) (pos-datum);
2769static MagickBooleanType TryAccumulate(
const double term,
2770 const unsigned long previous,
const unsigned long before_previous,
2771 unsigned long *result)
2777 if (term > (
double) MAGICK_ULONG_MAX)
2778 return(MagickFalse);
2779 accumulated=(term*previous)+before_previous;
2780 if ((accumulated < 0.0) || (accumulated > (
double) MAGICK_ULONG_MAX))
2781 return(MagickFalse);
2782 *result=(
unsigned long) accumulated;
2786static void GetXMPNumeratorAndDenominator(
double value,
2787 unsigned long *numerator,
unsigned long *denominator)
2805 if (value <= MagickEpsilon)
2807 if (value > (
double) MAGICK_ULONG_MAX)
2809 *numerator=MAGICK_ULONG_MAX;
2813 if (floor(value) == value)
2815 *numerator=(
unsigned long) value;
2824 for (i=0; i < 128; i++)
2831 term=floor(remainder);
2832 if ((TryAccumulate(term,num,prev_num,&new_num) == MagickFalse) ||
2833 (TryAccumulate(term,den,prev_den,&new_den) == MagickFalse) ||
2840 approximation=num/(double) den;
2841 if (fabs(approximation-value) <= MagickEpsilon)
2843 fraction=remainder-term;
2844 if (fraction <= 0.0)
2846 remainder=1.0/fraction;
2849 *denominator=(den == 0 ? 1 : den);
2855 value[MagickPathExtent];
2866 if (GetXMPOffsets(profile,
"tiff:XResolution",&start,&end) != MagickFalse)
2868 GetXMPNumeratorAndDenominator(image->resolution.x,&numerator,
2870 (void) FormatLocaleString(value,MagickPathExtent,
"%lu/%lu",numerator,
2872 ReplaceXMPValue(profile,start,end,value);
2874 if (GetXMPOffsets(profile,
"tiff:YResolution",&start,&end) != MagickFalse)
2876 if ((fabs(image->resolution.x-image->resolution.y) > MagickEpsilon) ||
2879 GetXMPNumeratorAndDenominator(image->resolution.y,&numerator,
2881 (void) FormatLocaleString(value,MagickPathExtent,
"%lu/%lu",
2882 numerator,denominator);
2884 ReplaceXMPValue(profile,start,end,value);
2886 if (GetXMPOffsets(profile,
"tiff:ResolutionUnit",&start,&end) != MagickFalse)
2888 (void) FormatLocaleString(value,MagickPathExtent,
"%d",
2889 ((
int) image->units)+1);
2890 ReplaceXMPValue(profile,start,end,value);
2892 if (GetXMPOffsets(profile,
"tiff:Orientation",&start,&end) != MagickFalse)
2894 (void) FormatLocaleString(value,MagickPathExtent,
"%d",
2895 (
int) image->orientation);
2896 ReplaceXMPValue(profile,start,end,value);
2900MagickPrivate
void SyncImageProfiles(
Image *image)
2905 profile=(
StringInfo *) GetImageProfile(image,
"8BIM");
2907 Sync8BimProfile(image,profile);
2908 profile=(
StringInfo *) GetImageProfile(image,
"EXIF");
2910 SyncExifProfile(image,GetStringInfoDatum(profile),GetStringInfoLength(
2912 profile=(
StringInfo *) GetImageProfile(image,
"XMP");
2914 SyncXMPProfile(image,profile);
2917static void UpdateClipPath(
unsigned char *blob,
size_t length,
2918 const size_t old_columns,
const size_t old_rows,
2929 selector=(ssize_t) ReadProfileMSBShort(&blob,&length);
2935 if (knot_count != 0)
2938 length-=(size_t) MagickMin(length,24U);
2944 knot_count=(ssize_t) ReadProfileMSBShort(&blob,&length);
2946 length-=(size_t) MagickMin(length,22);
2954 if (knot_count == 0)
2960 length-=(size_t) MagickMin(length,24);
2966 for (i=0; i < 3; i++)
2976 y=(double) ReadProfileMSBLong(&blob,&length);
2977 y=y*old_rows/4096.0/4096.0;
2979 yy=(
signed int) ((y*4096*4096)/new_geometry->height);
2980 WriteProfileLong(MSBEndian,(
size_t) yy,blob-4);
2981 x=(double) ReadProfileMSBLong(&blob,&length);
2982 x=x*old_columns/4096.0/4096.0;
2984 xx=(
signed int) ((x*4096*4096)/new_geometry->width);
2985 WriteProfileLong(MSBEndian,(
size_t) xx,blob-4);
2996 length-=(size_t) MagickMin(length,24);
3003MagickPrivate
void Update8BIMClipPath(
const Image *image,
3004 const size_t old_columns,
const size_t old_rows,
3020 assert(image != (
Image *) NULL);
3022 profile=GetImageProfile(image,
"8bim");
3025 length=GetStringInfoLength(profile);
3026 info=GetStringInfoDatum(profile);
3029 if (ReadProfileByte(&info,&length) != (
unsigned char)
'8')
3031 if (ReadProfileByte(&info,&length) != (
unsigned char)
'B')
3033 if (ReadProfileByte(&info,&length) != (
unsigned char)
'I')
3035 if (ReadProfileByte(&info,&length) != (
unsigned char)
'M')
3037 id=(ssize_t) ReadProfileMSBShort(&info,&length);
3038 count=(ssize_t) ReadProfileByte(&info,&length);
3039 if ((count != 0) && ((
size_t) count <= length))
3042 length-=(size_t) count;
3044 if ((count & 0x01) == 0)
3045 (void) ReadProfileByte(&info,&length);
3046 count=(ssize_t) ReadProfileMSBLong(&info,&length);
3047 if ((count < 0) || ((
size_t) count > length))
3052 if ((
id > 1999) && (
id < 2999))
3053 UpdateClipPath(info,(
size_t) count,old_columns,old_rows,new_geometry);
3055 length-=(size_t) MagickMin(length,(
size_t) count);