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
88 SetImageProfileInternal(Image *,
const char *,StringInfo *,
89 const MagickBooleanType,ExceptionInfo *);
92 WriteTo8BimProfile(Image *,
const char*,
const StringInfo *);
126MagickPrivate
void AppendImageProfileProperty(Image *image,
const char *profile,
127 const char *property,
const char *value,ExceptionInfo *exception)
135 assert(image != (Image *) NULL);
136 assert(image->signature == MagickCoreSignature);
137 assert(profile != (
const char *) NULL);
138 assert(property != (
const char *) NULL);
139 assert(value != (
const char *) NULL);
140 if (GetImageProfile(image,profile) == (
const StringInfo *) NULL)
142 current=GetImageProperty(image,property,exception);
143 if ((current == (
const char *) NULL) || (*current ==
'\0'))
145 (void) SetImageProperty(image,property,value,exception);
148 property_value=AcquireString(current);
149 (void) ConcatenateString(&property_value,
";");
150 (void) ConcatenateString(&property_value,value);
151 (void) SetImageProperty(image,property,property_value,exception);
152 property_value=DestroyString(property_value);
209 *(*CloneKeyFunc)(
const char *);
212 *(*CloneValueFunc)(
const StringInfo *);
214static inline void *CloneProfileKey(
void *key)
216 return((
void *) ((CloneKeyFunc) ConstantString)((
const char *) key));
219static inline void *CloneProfileValue(
void *value)
221 return((
void *) ((CloneValueFunc) CloneStringInfo)((
const StringInfo *) value));
224MagickExport MagickBooleanType CloneImageProfiles(Image *image,
225 const Image *clone_image)
227 assert(image != (Image *) NULL);
228 assert(image->signature == MagickCoreSignature);
229 assert(clone_image != (
const Image *) NULL);
230 assert(clone_image->signature == MagickCoreSignature);
231 if (IsEventLogging() != MagickFalse)
232 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
233 if (clone_image->profiles != (
void *) NULL)
235 if (image->profiles != (
void *) NULL)
236 DestroyImageProfiles(image);
237 image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
238 CloneProfileKey,CloneProfileValue);
267MagickExport MagickBooleanType DeleteImageProfile(Image *image,
const char *name)
269 assert(image != (Image *) NULL);
270 assert(image->signature == MagickCoreSignature);
271 if (IsEventLogging() != MagickFalse)
272 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
273 if (image->profiles == (SplayTreeInfo *) NULL)
275 WriteTo8BimProfile(image,name,(StringInfo *) NULL);
276 return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->profiles,name));
301MagickExport
void DestroyImageProfiles(Image *image)
303 if (image->profiles != (SplayTreeInfo *) NULL)
304 image->profiles=DestroySplayTree((SplayTreeInfo *) image->profiles);
331MagickExport
const StringInfo *GetImageProfile(
const Image *image,
337 assert(image != (Image *) NULL);
338 assert(image->signature == MagickCoreSignature);
339 if (IsEventLogging() != MagickFalse)
340 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
341 if (image->profiles == (SplayTreeInfo *) NULL)
342 return((StringInfo *) NULL);
343 profile=(
const StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
344 image->profiles,name);
370MagickExport
char *GetNextImageProfile(
const Image *image)
372 assert(image != (Image *) NULL);
373 assert(image->signature == MagickCoreSignature);
374 if (IsEventLogging() != MagickFalse)
375 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
376 if (image->profiles == (SplayTreeInfo *) NULL)
377 return((
char *) NULL);
378 return((
char *) GetNextKeyInSplayTree((SplayTreeInfo *) image->profiles));
422#if defined(MAGICKCORE_LCMS_DELEGATE)
424typedef struct _LCMSInfo
446 **magick_restrict pixels;
449#if LCMS_VERSION < 2060
450static void* cmsGetContextUserData(cmsContext ContextID)
455static cmsContext cmsCreateContext(
void *magick_unused(Plugin),
void *UserData)
457 magick_unreferenced(Plugin);
458 return((cmsContext) UserData);
461static void cmsSetLogErrorHandlerTHR(cmsContext magick_unused(ContextID),
462 cmsLogErrorHandlerFunction Fn)
464 magick_unreferenced(ContextID);
465 cmsSetLogErrorHandler(Fn);
468static void cmsDeleteContext(cmsContext magick_unused(ContextID))
470 magick_unreferenced(ContextID);
474static void **DestroyPixelTLS(
void **pixels)
479 if (pixels == (
void **) NULL)
480 return((
void **) NULL);
481 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
482 if (pixels[i] != (
void *) NULL)
483 pixels[i]=RelinquishMagickMemory(pixels[i]);
484 pixels=(
void **) RelinquishMagickMemory(pixels);
488static void **AcquirePixelTLS(
const size_t columns,
const size_t channels,
489 MagickBooleanType highres)
503 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
504 pixels=(
void **) AcquireQuantumMemory(number_threads,
sizeof(*pixels));
505 if (pixels == (
void **) NULL)
506 return((
void **) NULL);
507 (void) memset(pixels,0,number_threads*
sizeof(*pixels));
509 if (highres == MagickFalse)
510 size=
sizeof(Quantum);
511 for (i=0; i < (ssize_t) number_threads; i++)
513 pixels[i]=AcquireQuantumMemory(columns,channels*size);
514 if (pixels[i] == (
void *) NULL)
515 return(DestroyPixelTLS(pixels));
520static cmsHTRANSFORM *DestroyTransformTLS(cmsHTRANSFORM *transform)
525 assert(transform != (cmsHTRANSFORM *) NULL);
526 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
527 if (transform[i] != (cmsHTRANSFORM) NULL)
528 cmsDeleteTransform(transform[i]);
529 transform=(cmsHTRANSFORM *) RelinquishMagickMemory(transform);
533static cmsHTRANSFORM *AcquireTransformTLS(
const LCMSInfo *source_info,
534 const LCMSInfo *target_info,
const cmsUInt32Number flags,
535 cmsContext cms_context)
546 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
547 transform=(cmsHTRANSFORM *) AcquireQuantumMemory(number_threads,
549 if (transform == (cmsHTRANSFORM *) NULL)
550 return((cmsHTRANSFORM *) NULL);
551 (void) memset(transform,0,number_threads*
sizeof(*transform));
552 for (i=0; i < (ssize_t) number_threads; i++)
554 transform[i]=cmsCreateTransformTHR(cms_context,source_info->profile,
555 source_info->type,target_info->profile,target_info->type,
556 (cmsUInt32Number) target_info->intent,flags);
557 if (transform[i] == (cmsHTRANSFORM) NULL)
558 return(DestroyTransformTLS(transform));
563static void CMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
575 cms_exception=(CMSExceptionInfo *) cmsGetContextUserData(context);
576 if (cms_exception == (CMSExceptionInfo *) NULL)
578 exception=cms_exception->exception;
579 if (exception == (ExceptionInfo *) NULL)
581 image=cms_exception->image;
582 if (image == (Image *) NULL)
584 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
585 "UnableToTransformColorspace",
"`%s'",
"unknown context");
588 if (image->debug != MagickFalse)
589 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
"lcms: #%u, %s",
590 severity,message != (
char *) NULL ? message :
"no message");
591 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
592 "UnableToTransformColorspace",
"`%s', %s (#%u)",image->filename,
593 message != (
char *) NULL ? message :
"no message",severity);
596static void TransformDoublePixels(
const int id,
const Image* image,
597 const LCMSInfo *source_info,
const LCMSInfo *target_info,
598 const cmsHTRANSFORM *transform,Quantum *q)
600#define GetLCMSPixel(source_info,pixel,index) \
601 (source_info->scale[index]*(((double) QuantumScale*(double) pixel)+ \
602 source_info->translate[index]))
603#define SetLCMSPixel(target_info,pixel,index) ClampToQuantum( \
604 target_info->scale[index]*(((double) QuantumRange*(double) pixel)+ \
605 target_info->translate[index]))
613 p=(
double *) source_info->pixels[
id];
614 for (x=0; x < (ssize_t) image->columns; x++)
616 *p++=GetLCMSPixel(source_info,GetPixelRed(image,q),0);
617 if (source_info->channels > 1)
619 *p++=GetLCMSPixel(source_info,GetPixelGreen(image,q),1);
620 *p++=GetLCMSPixel(source_info,GetPixelBlue(image,q),2);
622 if (source_info->channels > 3)
623 *p++=GetLCMSPixel(source_info,GetPixelBlack(image,q),3);
624 q+=(ptrdiff_t) GetPixelChannels(image);
626 cmsDoTransform(transform[
id],source_info->pixels[
id],target_info->pixels[
id],
627 (
unsigned int) image->columns);
628 p=(
double *) target_info->pixels[
id];
629 q-=GetPixelChannels(image)*image->columns;
630 for (x=0; x < (ssize_t) image->columns; x++)
632 if (target_info->channels == 1)
633 SetPixelGray(image,SetLCMSPixel(target_info,*p,0),q);
635 SetPixelRed(image,SetLCMSPixel(target_info,*p,0),q);
637 if (target_info->channels > 1)
639 SetPixelGreen(image,SetLCMSPixel(target_info,*p,1),q);
641 SetPixelBlue(image,SetLCMSPixel(target_info,*p,2),q);
644 if (target_info->channels > 3)
646 SetPixelBlack(image,SetLCMSPixel(target_info,*p,3),q);
649 q+=(ptrdiff_t) GetPixelChannels(image);
653static void TransformQuantumPixels(
const int id,
const Image* image,
654 const LCMSInfo *source_info,
const LCMSInfo *target_info,
655 const cmsHTRANSFORM *transform,Quantum *q)
663 p=(Quantum *) source_info->pixels[
id];
664 for (x=0; x < (ssize_t) image->columns; x++)
666 *p++=GetPixelRed(image,q);
667 if (source_info->channels > 1)
669 *p++=GetPixelGreen(image,q);
670 *p++=GetPixelBlue(image,q);
672 if (source_info->channels > 3)
673 *p++=GetPixelBlack(image,q);
674 q+=(ptrdiff_t) GetPixelChannels(image);
676 cmsDoTransform(transform[
id],source_info->pixels[
id],target_info->pixels[
id],
677 (
unsigned int) image->columns);
678 p=(Quantum *) target_info->pixels[
id];
679 q-=GetPixelChannels(image)*image->columns;
680 for (x=0; x < (ssize_t) image->columns; x++)
682 if (target_info->channels == 1)
683 SetPixelGray(image,*p++,q);
685 SetPixelRed(image,*p++,q);
686 if (target_info->channels > 1)
688 SetPixelGreen(image,*p++,q);
689 SetPixelBlue(image,*p++,q);
691 if (target_info->channels > 3)
692 SetPixelBlack(image,*p++,q);
693 q+=(ptrdiff_t) GetPixelChannels(image);
697static inline void SetLCMSInfoTranslate(LCMSInfo *info,
const double translate)
699 info->translate[0]=translate;
700 info->translate[1]=translate;
701 info->translate[2]=translate;
702 info->translate[3]=translate;
705static inline void SetLCMSInfoScale(LCMSInfo *info,
const double scale)
707 info->scale[0]=scale;
708 info->scale[1]=scale;
709 info->scale[2]=scale;
710 info->scale[3]=scale;
714static void SetsRGBImageProfile(Image *image,ExceptionInfo *exception)
719 0x00, 0x00, 0x0c, 0x8c, 0x61, 0x72, 0x67, 0x6c, 0x02, 0x20, 0x00, 0x00,
720 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
721 0x07, 0xde, 0x00, 0x01, 0x00, 0x06, 0x00, 0x16, 0x00, 0x0f, 0x00, 0x3a,
722 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
723 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00,
724 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
725 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x61, 0x72, 0x67, 0x6c,
726 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
727 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
728 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
729 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
730 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x99,
731 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0xec, 0x00, 0x00, 0x00, 0x67,
732 0x64, 0x6d, 0x6e, 0x64, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70,
733 0x64, 0x6d, 0x64, 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88,
734 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x0c,
735 0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x00, 0x67,
736 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x24,
737 0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xe4, 0x00, 0x00, 0x00, 0x14,
738 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x24,
739 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x14,
740 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x14,
741 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x14,
742 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x58, 0x00, 0x00, 0x00, 0x14,
743 0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x6c, 0x00, 0x00, 0x00, 0x14,
744 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
745 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
746 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
747 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
748 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36,
749 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75, 0x69, 0x76,
750 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x77, 0x77,
751 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x31, 0x39,
752 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c,
753 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
754 0x00, 0x3f, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31,
755 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75,
756 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77,
757 0x77, 0x77, 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20,
758 0x31, 0x39, 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66,
759 0x69, 0x6c, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
760 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, 0x61,
761 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x72, 0x61, 0x65, 0x6d,
762 0x65, 0x20, 0x57, 0x2e, 0x20, 0x47, 0x69, 0x6c, 0x6c, 0x2e, 0x20, 0x52,
763 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f,
764 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
765 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x4e, 0x6f, 0x20, 0x57,
766 0x61, 0x72, 0x72, 0x61, 0x6e, 0x74, 0x79, 0x2c, 0x20, 0x55, 0x73, 0x65,
767 0x20, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e,
768 0x20, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
769 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20,
770 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
771 0x65, 0x63, 0x2e, 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
772 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74,
773 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
774 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
775 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
776 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
778 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
779 0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e,
780 0x31, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47,
781 0x42, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61,
782 0x63, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
783 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43,
784 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
785 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63,
786 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
787 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
788 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
789 0x00, 0x00, 0x00, 0x00, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00,
790 0x43, 0x52, 0x54, 0x20, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
791 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
792 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
793 0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
794 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
795 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
796 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
797 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
798 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
799 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa4, 0x7c,
800 0x00, 0x14, 0x5f, 0x30, 0x00, 0x10, 0xce, 0x02, 0x00, 0x03, 0xed, 0xb2,
801 0x00, 0x04, 0x13, 0x0a, 0x00, 0x03, 0x5c, 0x67, 0x00, 0x00, 0x00, 0x01,
802 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x0a, 0x3d,
803 0x00, 0x50, 0x00, 0x00, 0x00, 0x57, 0x1e, 0xb8, 0x6d, 0x65, 0x61, 0x73,
804 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
805 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
806 0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x58, 0x59, 0x5a, 0x20,
807 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00,
808 0x00, 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
809 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
810 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa0,
811 0x00, 0x00, 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20,
812 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x97, 0x00, 0x00, 0xb7, 0x87,
813 0x00, 0x00, 0x18, 0xd9, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
814 0x00, 0x00, 0x24, 0x9f, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0xb6, 0xc4,
815 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
816 0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19,
817 0x00, 0x1e, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37,
818 0x00, 0x3b, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54,
819 0x00, 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
820 0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00, 0x90,
821 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9, 0x00, 0xae,
822 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00, 0xc6, 0x00, 0xcb,
823 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0xeb,
824 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01, 0x01, 0x01, 0x07, 0x01, 0x0d,
825 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f, 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32,
826 0x01, 0x38, 0x01, 0x3e, 0x01, 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59,
827 0x01, 0x60, 0x01, 0x67, 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83,
828 0x01, 0x8b, 0x01, 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1,
829 0x01, 0xb9, 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1,
830 0x01, 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
831 0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02, 0x4b,
832 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a, 0x02, 0x84,
833 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02, 0xb6, 0x02, 0xc1,
834 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb, 0x02, 0xf5, 0x03, 0x00,
835 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2d, 0x03, 0x38, 0x03, 0x43,
836 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66, 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a,
837 0x03, 0x96, 0x03, 0xa2, 0x03, 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3,
838 0x03, 0xe0, 0x03, 0xec, 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20,
839 0x04, 0x2d, 0x04, 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71,
840 0x04, 0x7e, 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4,
841 0x04, 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
842 0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05, 0x77,
843 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5, 0x05, 0xd5,
844 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06, 0x27, 0x06, 0x37,
845 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b, 0x06, 0x8c, 0x06, 0x9d,
846 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06, 0xe3, 0x06, 0xf5, 0x07, 0x07,
847 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d, 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74,
848 0x07, 0x86, 0x07, 0x99, 0x07, 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5,
849 0x07, 0xf8, 0x08, 0x0b, 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a,
850 0x08, 0x6e, 0x08, 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2,
851 0x08, 0xe7, 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f,
852 0x09, 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
853 0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a, 0x54,
854 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5, 0x0a, 0xdc,
855 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b, 0x51, 0x0b, 0x69,
856 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8, 0x0b, 0xe1, 0x0b, 0xf9,
857 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c, 0x5c, 0x0c, 0x75, 0x0c, 0x8e,
858 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9, 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26,
859 0x0d, 0x40, 0x0d, 0x5a, 0x0d, 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3,
860 0x0d, 0xde, 0x0d, 0xf8, 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64,
861 0x0e, 0x7f, 0x0e, 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09,
862 0x0f, 0x25, 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3,
863 0x0f, 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
864 0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11, 0x13,
865 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa, 0x11, 0xc9,
866 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12, 0x64, 0x12, 0x84,
867 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03, 0x13, 0x23, 0x13, 0x43,
868 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13, 0xc5, 0x13, 0xe5, 0x14, 0x06,
869 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a, 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce,
870 0x14, 0xf0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b,
871 0x15, 0xbd, 0x15, 0xe0, 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c,
872 0x16, 0x8f, 0x16, 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41,
873 0x17, 0x65, 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b,
874 0x18, 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
875 0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19, 0xdd,
876 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e, 0x1a, 0xc5,
877 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b, 0x8a, 0x1b, 0xb2,
878 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52, 0x1c, 0x7b, 0x1c, 0xa3,
879 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d, 0x47, 0x1d, 0x70, 0x1d, 0x99,
880 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16, 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94,
881 0x1e, 0xbe, 0x1e, 0xe9, 0x1f, 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94,
882 0x1f, 0xbf, 0x1f, 0xea, 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98,
883 0x20, 0xc4, 0x20, 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1,
884 0x21, 0xce, 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf,
885 0x22, 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
886 0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24, 0xda,
887 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7, 0x25, 0xf7,
888 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26, 0xe8, 0x27, 0x18,
889 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc, 0x28, 0x0d, 0x28, 0x3f,
890 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29, 0x06, 0x29, 0x38, 0x29, 0x6b,
891 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02, 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b,
892 0x2a, 0xcf, 0x2b, 0x02, 0x2b, 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1,
893 0x2c, 0x05, 0x2c, 0x39, 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c,
894 0x2d, 0x41, 0x2d, 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c,
895 0x2e, 0x82, 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91,
896 0x2f, 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
897 0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32, 0x2a,
898 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46, 0x33, 0x7f,
899 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34, 0x9e, 0x34, 0xd8,
900 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2, 0x35, 0xfd, 0x36, 0x37,
901 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37, 0x24, 0x37, 0x60, 0x37, 0x9c,
902 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05,
903 0x39, 0x42, 0x39, 0x7f, 0x39, 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74,
904 0x3a, 0xb2, 0x3a, 0xef, 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8,
905 0x3c, 0x27, 0x3c, 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61,
906 0x3d, 0xa1, 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0,
907 0x3f, 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
908 0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41, 0xee,
909 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a, 0x43, 0x7d,
910 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44, 0xce, 0x45, 0x12,
911 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22, 0x46, 0x67, 0x46, 0xab,
912 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47, 0xc0, 0x48, 0x05, 0x48, 0x4b,
913 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d, 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0,
914 0x4a, 0x37, 0x4a, 0x7d, 0x4a, 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a,
915 0x4b, 0xe2, 0x4c, 0x2a, 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a,
916 0x4d, 0x93, 0x4d, 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00,
917 0x4f, 0x49, 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb,
918 0x51, 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
919 0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54, 0x42,
920 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2, 0x56, 0x0f,
921 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57, 0x92, 0x57, 0xe0,
922 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a, 0x59, 0x69, 0x59, 0xb8,
923 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a, 0xf5, 0x5b, 0x45, 0x5b, 0x95,
924 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86, 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78,
925 0x5d, 0xc9, 0x5e, 0x1a, 0x5e, 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61,
926 0x5f, 0xb3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f,
927 0x61, 0xa2, 0x61, 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43,
928 0x63, 0x97, 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d,
929 0x65, 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
930 0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69, 0x43,
931 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7, 0x6b, 0x4f,
932 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d, 0x08, 0x6d, 0x60,
933 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4, 0x6f, 0x1e, 0x6f, 0x78,
934 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70, 0xe0, 0x71, 0x3a, 0x71, 0x95,
935 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6, 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8,
936 0x74, 0x14, 0x74, 0x70, 0x74, 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1,
937 0x76, 0x3e, 0x76, 0x9b, 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11,
938 0x78, 0x6e, 0x78, 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46,
939 0x7a, 0xa5, 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81,
940 0x7c, 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
941 0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81, 0x0a,
942 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4, 0x83, 0x57,
943 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85, 0x47, 0x85, 0xab,
944 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b, 0x87, 0x9f, 0x88, 0x04,
945 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89, 0x99, 0x89, 0xfe, 0x8a, 0x64,
946 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96, 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca,
947 0x8d, 0x31, 0x8d, 0x98, 0x8d, 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36,
948 0x8f, 0x9e, 0x90, 0x06, 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8,
949 0x92, 0x11, 0x92, 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20,
950 0x94, 0x8a, 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f,
951 0x97, 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
952 0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b, 0xaf,
953 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2, 0x9e, 0x40,
954 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0, 0x69, 0xa0, 0xd8,
955 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96, 0xa3, 0x06, 0xa3, 0x76,
956 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5, 0x38, 0xa5, 0xa9, 0xa6, 0x1a,
957 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e, 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4,
958 0xa9, 0x37, 0xa9, 0xa9, 0xaa, 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75,
959 0xab, 0xe9, 0xac, 0x5c, 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d,
960 0xae, 0xa1, 0xaf, 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea,
961 0xb1, 0x60, 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae,
962 0xb4, 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
963 0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9, 0x4a,
964 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7, 0xbc, 0x21,
965 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe, 0x84, 0xbe, 0xff,
966 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec, 0xc1, 0x67, 0xc1, 0xe3,
967 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3, 0xd4, 0xc4, 0x51, 0xc4, 0xce,
968 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46, 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf,
969 0xc8, 0x3d, 0xc8, 0xbc, 0xc9, 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7,
970 0xcb, 0x36, 0xcb, 0xb6, 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5,
971 0xce, 0x36, 0xce, 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba,
972 0xd1, 0x3c, 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6,
973 0xd4, 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
974 0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9, 0xf1,
975 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a, 0xdd, 0x10,
976 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf, 0xaf, 0xe0, 0x36,
977 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53, 0xe2, 0xdb, 0xe3, 0x63,
978 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5, 0x84, 0xe6, 0x0d, 0xe6, 0x96,
979 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32, 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0,
980 0xea, 0x5b, 0xea, 0xe5, 0xeb, 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11,
981 0xed, 0x9c, 0xee, 0x28, 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58,
982 0xf0, 0xe5, 0xf1, 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7,
983 0xf4, 0x34, 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb,
984 0xf7, 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
985 0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd, 0xba,
986 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
992 assert(image != (Image *) NULL);
993 assert(image->signature == MagickCoreSignature);
994 if (GetImageProfile(image,
"icc") != (
const StringInfo *) NULL)
996 profile=BlobToProfileStringInfo(
"icc",sRGBProfile,
sizeof(sRGBProfile),
998 (void) SetImageProfilePrivate(image,profile,exception);
1001MagickExport MagickBooleanType ProfileImage(Image *image,
const char *name,
1002 const void *datum,
const size_t length,ExceptionInfo *exception)
1004#define ProfileImageTag "Profile/Image"
1006 #define TYPE_XYZ_8 (COLORSPACE_SH(PT_XYZ)|CHANNELS_SH(3)|BYTES_SH(1))
1008#define ThrowProfileException(severity,tag,context) \
1010 if (profile != (StringInfo *) NULL) \
1011 profile=DestroyStringInfo(profile); \
1012 if (cms_context != (cmsContext) NULL) \
1013 cmsDeleteContext(cms_context); \
1014 if (source_info.profile != (cmsHPROFILE) NULL) \
1015 (void) cmsCloseProfile(source_info.profile); \
1016 if (target_info.profile != (cmsHPROFILE) NULL) \
1017 (void) cmsCloseProfile(target_info.profile); \
1018 ThrowBinaryException(severity,tag,context); \
1027 assert(image != (Image *) NULL);
1028 assert(image->signature == MagickCoreSignature);
1029 assert(name != (
const char *) NULL);
1030 if (IsEventLogging() != MagickFalse)
1031 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1032 if ((datum == (
const void *) NULL) || (length == 0))
1040 ResetImageProfileIterator(image);
1041 for (next=GetNextImageProfile(image); next != (
const char *) NULL; )
1043 if (IsOptionMember(next,name) != MagickFalse)
1045 (void) DeleteImageProfile(image,next);
1046 ResetImageProfileIterator(image);
1048 next=GetNextImageProfile(image);
1056 profile=AcquireProfileStringInfo(name,(
size_t) length,exception);
1057 if (profile == (StringInfo *) NULL)
1058 return(MagickFalse);
1059 SetStringInfoDatum(profile,(
unsigned char *) datum);
1060 if ((LocaleCompare(name,
"icc") != 0) && (LocaleCompare(name,
"icm") != 0))
1061 status=SetImageProfilePrivate(image,profile,exception);
1067 icc_profile=GetImageProfile(image,
"icc");
1068 if ((icc_profile != (
const StringInfo *) NULL) &&
1069 (CompareStringInfo(icc_profile,profile) == 0))
1074 value=GetImageProperty(image,
"exif:ColorSpace",exception);
1076 if (LocaleCompare(value,
"1") != 0)
1077 SetsRGBImageProfile(image,exception);
1078 value=GetImageProperty(image,
"exif:InteroperabilityIndex",exception);
1079 if (LocaleCompare(value,
"R98.") != 0)
1080 SetsRGBImageProfile(image,exception);
1081 icc_profile=GetImageProfile(image,
"icc");
1083 if ((icc_profile != (
const StringInfo *) NULL) &&
1084 (CompareStringInfo(icc_profile,profile) == 0))
1086 profile=DestroyStringInfo(profile);
1089#if !defined(MAGICKCORE_LCMS_DELEGATE)
1090 (void) ThrowMagickException(exception,GetMagickModule(),
1091 MissingDelegateWarning,
"DelegateLibrarySupportNotBuiltIn",
1092 "'%s' (LCMS)",image->filename);
1108 cms_exception.image=image;
1109 cms_exception.exception=exception;
1110 cms_context=cmsCreateContext(NULL,&cms_exception);
1111 if (cms_context == (cmsContext) NULL)
1113 profile=DestroyStringInfo(profile);
1114 ThrowBinaryException(ResourceLimitError,
1115 "ColorspaceColorProfileMismatch",name);
1117 cmsSetLogErrorHandlerTHR(cms_context,CMSExceptionHandler);
1118 source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
1119 GetStringInfoDatum(profile),(cmsUInt32Number)
1120 GetStringInfoLength(profile));
1121 if (source_info.profile == (cmsHPROFILE) NULL)
1123 profile=DestroyStringInfo(profile);
1124 cmsDeleteContext(cms_context);
1125 ThrowBinaryException(ResourceLimitError,
1126 "ColorspaceColorProfileMismatch",name);
1128 if ((cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass) &&
1129 (icc_profile == (StringInfo *) NULL))
1130 status=SetImageProfilePrivate(image,profile,exception);
1136 cmsColorSpaceSignature
1140 *magick_restrict transform;
1154 target_info.profile=(cmsHPROFILE) NULL;
1155 if (icc_profile != (StringInfo *) NULL)
1157 target_info.profile=source_info.profile;
1158 source_info.profile=cmsOpenProfileFromMemTHR(cms_context,
1159 GetStringInfoDatum(icc_profile),(cmsUInt32Number)
1160 GetStringInfoLength(icc_profile));
1161 if (source_info.profile == (cmsHPROFILE) NULL)
1162 ThrowProfileException(ResourceLimitError,
1163 "ColorspaceColorProfileMismatch",name);
1166#if !defined(MAGICKCORE_HDRI_SUPPORT) || (MAGICKCORE_QUANTUM_DEPTH > 16)
1171 artifact=GetImageArtifact(image,
"profile:highres-transform");
1172 if (IsStringFalse(artifact) != MagickFalse)
1173 highres=MagickFalse;
1176 SetLCMSInfoScale(&source_info,1.0);
1177 SetLCMSInfoTranslate(&source_info,0.0);
1178 source_info.colorspace=sRGBColorspace;
1179 source_info.channels=3;
1180 switch (cmsGetColorSpace(source_info.profile))
1182 case cmsSigCmykData:
1184 source_info.colorspace=CMYKColorspace;
1185 source_info.channels=4;
1186 if (highres != MagickFalse)
1188 source_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1189 SetLCMSInfoScale(&source_info,100.0);
1191#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1193 source_info.type=(cmsUInt32Number) TYPE_CMYK_8;
1194#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1196 source_info.type=(cmsUInt32Number) TYPE_CMYK_16;
1200 case cmsSigGrayData:
1202 source_info.colorspace=GRAYColorspace;
1203 source_info.channels=1;
1204 if (highres != MagickFalse)
1205 source_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1206#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1208 source_info.type=(cmsUInt32Number) TYPE_GRAY_8;
1209#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1211 source_info.type=(cmsUInt32Number) TYPE_GRAY_16;
1217 source_info.colorspace=LabColorspace;
1218 if (highres != MagickFalse)
1220 source_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1221 source_info.scale[0]=100.0;
1222 source_info.scale[1]=255.0;
1223 source_info.scale[2]=255.0;
1224#if !defined(MAGICKCORE_HDRI_SUPPORT)
1225 source_info.translate[1]=(-0.5);
1226 source_info.translate[2]=(-0.5);
1229#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1231 source_info.type=(cmsUInt32Number) TYPE_Lab_8;
1232#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1234 source_info.type=(cmsUInt32Number) TYPE_Lab_16;
1240 source_info.colorspace=sRGBColorspace;
1241 if (highres != MagickFalse)
1242 source_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1243#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1245 source_info.type=(cmsUInt32Number) TYPE_RGB_8;
1246#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1248 source_info.type=(cmsUInt32Number) TYPE_RGB_16;
1254 source_info.colorspace=XYZColorspace;
1255 if (highres != MagickFalse)
1256 source_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1257#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1259 source_info.type=(cmsUInt32Number) TYPE_XYZ_8;
1260#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1262 source_info.type=(cmsUInt32Number) TYPE_XYZ_16;
1267 ThrowProfileException(ImageError,
1268 "ColorspaceColorProfileMismatch",name);
1270 signature=cmsGetPCS(source_info.profile);
1271 if (target_info.profile != (cmsHPROFILE) NULL)
1272 signature=cmsGetColorSpace(target_info.profile);
1273 SetLCMSInfoScale(&target_info,1.0);
1274 SetLCMSInfoTranslate(&target_info,0.0);
1275 target_info.channels=3;
1278 case cmsSigCmykData:
1280 target_info.colorspace=CMYKColorspace;
1281 target_info.channels=4;
1282 if (highres != MagickFalse)
1284 target_info.type=(cmsUInt32Number) TYPE_CMYK_DBL;
1285 SetLCMSInfoScale(&target_info,0.01);
1287#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1289 target_info.type=(cmsUInt32Number) TYPE_CMYK_8;
1290#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1292 target_info.type=(cmsUInt32Number) TYPE_CMYK_16;
1296 case cmsSigGrayData:
1298 target_info.colorspace=GRAYColorspace;
1299 target_info.channels=1;
1300 if (highres != MagickFalse)
1301 target_info.type=(cmsUInt32Number) TYPE_GRAY_DBL;
1302#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1304 target_info.type=(cmsUInt32Number) TYPE_GRAY_8;
1305#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1307 target_info.type=(cmsUInt32Number) TYPE_GRAY_16;
1313 target_info.colorspace=LabColorspace;
1314 if (highres != MagickFalse)
1316 target_info.type=(cmsUInt32Number) TYPE_Lab_DBL;
1317 target_info.scale[0]=0.01;
1318 target_info.scale[1]=1/255.0;
1319 target_info.scale[2]=1/255.0;
1320#if !defined(MAGICKCORE_HDRI_SUPPORT)
1321 target_info.translate[1]=0.5;
1322 target_info.translate[2]=0.5;
1325#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1327 target_info.type=(cmsUInt32Number) TYPE_Lab_8;
1328#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1330 target_info.type=(cmsUInt32Number) TYPE_Lab_16;
1336 target_info.colorspace=sRGBColorspace;
1337 if (highres != MagickFalse)
1338 target_info.type=(cmsUInt32Number) TYPE_RGB_DBL;
1339#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1341 target_info.type=(cmsUInt32Number) TYPE_RGB_8;
1342#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1344 target_info.type=(cmsUInt32Number) TYPE_RGB_16;
1350 target_info.colorspace=XYZColorspace;
1351 if (highres != MagickFalse)
1352 target_info.type=(cmsUInt32Number) TYPE_XYZ_DBL;
1353#if (MAGICKCORE_QUANTUM_DEPTH == 8)
1355 target_info.type=(cmsUInt32Number) TYPE_XYZ_8;
1356#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
1358 target_info.type=(cmsUInt32Number) TYPE_XYZ_16;
1363 ThrowProfileException(ImageError,
1364 "ColorspaceColorProfileMismatch",name);
1366 switch (image->rendering_intent)
1368 case AbsoluteIntent:
1370 target_info.intent=INTENT_ABSOLUTE_COLORIMETRIC;
1373 case PerceptualIntent:
1375 target_info.intent=INTENT_PERCEPTUAL;
1378 case RelativeIntent:
1380 target_info.intent=INTENT_RELATIVE_COLORIMETRIC;
1383 case SaturationIntent:
1385 target_info.intent=INTENT_SATURATION;
1390 target_info.intent=INTENT_PERCEPTUAL;
1394 flags=cmsFLAGS_HIGHRESPRECALC;
1395#if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
1396 if (image->black_point_compensation != MagickFalse)
1397 flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
1399 transform=AcquireTransformTLS(&source_info,&target_info,flags,
1401 if (transform == (cmsHTRANSFORM *) NULL)
1402 ThrowProfileException(ImageError,
"UnableToCreateColorTransform",
1407 source_info.pixels=AcquirePixelTLS(image->columns,
1408 source_info.channels,highres);
1409 target_info.pixels=AcquirePixelTLS(image->columns,
1410 target_info.channels,highres);
1411 if ((source_info.pixels == (
void **) NULL) ||
1412 (target_info.pixels == (
void **) NULL))
1414 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1415 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1416 transform=DestroyTransformTLS(transform);
1417 ThrowProfileException(ResourceLimitError,
1418 "MemoryAllocationFailed",image->filename);
1420 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1422 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1423 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1424 transform=DestroyTransformTLS(transform);
1425 if (source_info.profile != (cmsHPROFILE) NULL)
1426 (void) cmsCloseProfile(source_info.profile);
1427 if (target_info.profile != (cmsHPROFILE) NULL)
1428 (void) cmsCloseProfile(target_info.profile);
1429 return(MagickFalse);
1431 if (target_info.colorspace == CMYKColorspace)
1432 (void) SetImageColorspace(image,target_info.colorspace,exception);
1434 image_view=AcquireAuthenticCacheView(image,exception);
1435#if defined(MAGICKCORE_OPENMP_SUPPORT)
1436 #pragma omp parallel for schedule(static) shared(status) \
1437 magick_number_threads(image,image,image->rows,1)
1439 for (y=0; y < (ssize_t) image->rows; y++)
1442 id = GetOpenMPThreadId();
1450 if (status == MagickFalse)
1452 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1454 if (q == (Quantum *) NULL)
1459 if (highres != MagickFalse)
1460 TransformDoublePixels(
id,image,&source_info,&target_info,
1463 TransformQuantumPixels(
id,image,&source_info,&target_info,
1465 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1466 if (sync == MagickFalse)
1468 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1473#if defined(MAGICKCORE_OPENMP_SUPPORT)
1477 proceed=SetImageProgress(image,ProfileImageTag,progress,
1479 if (proceed == MagickFalse)
1483 image_view=DestroyCacheView(image_view);
1484 (void) SetImageColorspace(image,target_info.colorspace,exception);
1489 image->type=image->alpha_trait == UndefinedPixelTrait ?
1490 TrueColorType : TrueColorAlphaType;
1493 case cmsSigCmykData:
1495 image->type=image->alpha_trait == UndefinedPixelTrait ?
1496 ColorSeparationType : ColorSeparationAlphaType;
1499 case cmsSigGrayData:
1501 image->type=image->alpha_trait == UndefinedPixelTrait ?
1502 GrayscaleType : GrayscaleAlphaType;
1508 target_info.pixels=DestroyPixelTLS(target_info.pixels);
1509 source_info.pixels=DestroyPixelTLS(source_info.pixels);
1510 transform=DestroyTransformTLS(transform);
1511 if ((status != MagickFalse) &&
1512 (cmsGetDeviceClass(source_info.profile) != cmsSigLinkClass))
1513 status=SetImageProfilePrivate(image,profile,exception);
1515 profile=DestroyStringInfo(profile);
1516 if (target_info.profile != (cmsHPROFILE) NULL)
1517 (void) cmsCloseProfile(target_info.profile);
1519 (void) cmsCloseProfile(source_info.profile);
1520 cmsDeleteContext(cms_context);
1552MagickExport StringInfo *RemoveImageProfile(Image *image,
const char *name)
1557 assert(image != (Image *) NULL);
1558 assert(image->signature == MagickCoreSignature);
1559 if (IsEventLogging() != MagickFalse)
1560 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1561 if (image->profiles == (SplayTreeInfo *) NULL)
1562 return((StringInfo *) NULL);
1563 WriteTo8BimProfile(image,name,(StringInfo *) NULL);
1564 profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
1565 image->profiles,name);
1593MagickExport
void ResetImageProfileIterator(
const Image *image)
1595 assert(image != (Image *) NULL);
1596 assert(image->signature == MagickCoreSignature);
1597 if (IsEventLogging() != MagickFalse)
1598 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1599 if (image->profiles == (SplayTreeInfo *) NULL)
1601 ResetSplayTreeIterator((SplayTreeInfo *) image->profiles);
1635static void *DestroyProfile(
void *profile)
1637 return((
void *) DestroyStringInfo((StringInfo *) profile));
1640static inline const unsigned char *ReadResourceByte(
const unsigned char *p,
1641 unsigned char *quantum)
1647static inline const unsigned char *ReadResourceLong(
const unsigned char *p,
1648 unsigned int *quantum)
1650 *quantum=(
unsigned int) (*p++) << 24;
1651 *quantum|=(
unsigned int) (*p++) << 16;
1652 *quantum|=(
unsigned int) (*p++) << 8;
1653 *quantum|=(
unsigned int) (*p++);
1657static inline const unsigned char *ReadResourceShort(
const unsigned char *p,
1658 unsigned short *quantum)
1660 *quantum=(
unsigned short) (*p++) << 8;
1661 *quantum|=(
unsigned short) (*p++);
1665static inline void WriteResourceLong(
unsigned char *p,
1666 const unsigned int quantum)
1671 buffer[0]=(
unsigned char) (quantum >> 24);
1672 buffer[1]=(
unsigned char) (quantum >> 16);
1673 buffer[2]=(
unsigned char) (quantum >> 8);
1674 buffer[3]=(
unsigned char) quantum;
1675 (void) memcpy(p,buffer,4);
1678static void WriteTo8BimProfile(Image *image,
const char *name,
1679 const StringInfo *profile)
1707 if (LocaleCompare(name,
"icc") == 0)
1710 if (LocaleCompare(name,
"iptc") == 0)
1713 if (LocaleCompare(name,
"xmp") == 0)
1717 profile_8bim=(StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
1718 image->profiles,
"8bim");
1719 if (profile_8bim == (StringInfo *) NULL)
1721 datum=GetStringInfoDatum(profile_8bim);
1722 length=GetStringInfoLength(profile_8bim);
1723 for (p=datum; p < (datum+length-16); )
1726 if (LocaleNCompare((
char *) p,
"8BIM",4) != 0)
1729 p=ReadResourceShort(p,&
id);
1730 p=ReadResourceByte(p,&length_byte);
1731 p+=(ptrdiff_t) length_byte;
1732 if (((length_byte+1) & 0x01) != 0)
1734 if (p > (datum+length-4))
1736 p=ReadResourceLong(p,&value);
1737 count=(ssize_t) value;
1738 if ((count & 0x01) != 0)
1740 if ((count < 0) || (p > (datum+length-count)) || (count > (ssize_t) length))
1742 if (
id != profile_id)
1743 p+=(ptrdiff_t) count;
1757 extent=(size_t) ((datum+length)-(p+count));
1758 if (profile == (StringInfo *) NULL)
1760 offset=(size_t) (q-datum);
1761 extract_profile=AcquireStringInfo(offset+extent);
1762 (void) memcpy(extract_profile->datum,datum,offset);
1766 offset=(size_t) (p-datum);
1767 extract_extent=(ssize_t) profile->length;
1768 if ((extract_extent & 0x01) != 0)
1770 extract_profile=AcquireStringInfo(offset+(
size_t) extract_extent+
1772 (void) memcpy(extract_profile->datum,datum,offset-4);
1773 WriteResourceLong(extract_profile->datum+offset-4,(
unsigned int)
1775 (void) memcpy(extract_profile->datum+offset,
1776 profile->datum,profile->length);
1778 (void) memcpy(extract_profile->datum+offset+extract_extent,
1780 (void) AddValueToSplayTree((SplayTreeInfo *) image->profiles,
1781 ConstantString(
"8bim"),CloneStringInfo(extract_profile));
1782 extract_profile=DestroyStringInfo(extract_profile);
1788static void GetProfilesFromResourceBlock(Image *image,
1789 const StringInfo *resource_block,ExceptionInfo *exception)
1815 datum=GetStringInfoDatum(resource_block);
1816 length=GetStringInfoLength(resource_block);
1817 for (p=datum; p < (datum+length-16); )
1819 if (LocaleNCompare((
char *) p,
"8BIM",4) != 0)
1822 p=ReadResourceShort(p,&
id);
1823 p=ReadResourceByte(p,&length_byte);
1824 p+=(ptrdiff_t) length_byte;
1825 if (((length_byte+1) & 0x01) != 0)
1827 if (p > (datum+length-4))
1829 p=ReadResourceLong(p,&value);
1830 count=(ssize_t) value;
1831 if ((p > (datum+length-count)) || (count > (ssize_t) length) ||
1849 p=ReadResourceLong(p,&resolution);
1850 image->resolution.x=((double) resolution)/65536.0;
1851 p=ReadResourceShort(p,&units)+2;
1852 p=ReadResourceLong(p,&resolution)+4;
1853 image->resolution.y=((double) resolution)/65536.0;
1857 if ((ResolutionType) units != PixelsPerCentimeterResolution)
1858 image->units=PixelsPerInchResolution;
1861 image->units=PixelsPerCentimeterResolution;
1862 image->resolution.x/=2.54;
1863 image->resolution.y/=2.54;
1872 profile=BlobToProfileStringInfo(
"iptc",p,(
size_t) count,exception);
1873 if (profile != (StringInfo *) NULL)
1874 (void) SetImageProfileInternal(image,GetStringInfoName(profile),
1875 profile,MagickTrue,exception);
1876 p+=(ptrdiff_t) count;
1884 p+=(ptrdiff_t) count;
1892 profile=BlobToProfileStringInfo(
"icc",p,(
size_t) count,exception);
1893 if (profile != (StringInfo *) NULL)
1894 (void) SetImageProfileInternal(image,GetStringInfoName(profile),
1895 profile,MagickTrue,exception);
1896 p+=(ptrdiff_t) count;
1904 profile=BlobToProfileStringInfo(
"exif",p,(
size_t) count,exception);
1905 if (profile != (StringInfo *) NULL)
1906 (void) SetImageProfileInternal(image,GetStringInfoName(profile),
1907 profile,MagickTrue,exception);
1908 p+=(ptrdiff_t) count;
1916 profile=BlobToProfileStringInfo(
"xmp",p,(
size_t) count,exception);
1917 if (profile != (StringInfo *) NULL)
1918 (void) SetImageProfileInternal(image,GetStringInfoName(profile),
1919 profile,MagickTrue,exception);
1920 p+=(ptrdiff_t) count;
1925 p+=(ptrdiff_t) count;
1929 if ((count & 0x01) != 0)
1934static void PatchCorruptProfile(
const char *name,StringInfo *profile)
1945 if (LocaleCompare(name,
"xmp") == 0)
1950 p=GetStringInfoDatum(profile);
1951 p=(
unsigned char *) strstr((
const char *) p,
"<?xpacket end=\"w\"?>");
1952 if (p != (
unsigned char *) NULL)
1955 length=(size_t) (p-GetStringInfoDatum(profile));
1956 if (length != GetStringInfoLength(profile))
1959 SetStringInfoLength(profile,length);
1964 if (((LocaleCompare(name,
"exif") == 0) || (LocaleCompare(name,
"app1") == 0)) &&
1965 (GetStringInfoLength(profile) > 2))
1970 p=GetStringInfoDatum(profile);
1971 if ((LocaleNCompare((
const char *) p,
"MM",2) == 0) ||
1972 (LocaleNCompare((
const char *) p,
"II",2) == 0))
1975 profile_start[] =
"Exif\0\0";
1980 exif_profile=AcquireStringInfo(6);
1981 if (exif_profile != (StringInfo *) NULL)
1983 SetStringInfoDatum(exif_profile,profile_start);
1984 ConcatenateStringInfo(exif_profile,profile);
1985 SetStringInfoLength(profile,GetStringInfoLength(exif_profile));
1986 SetStringInfo(profile,exif_profile);
1987 exif_profile=DestroyStringInfo(exif_profile);
1993static MagickBooleanType ValidateXMPProfile(Image *image,
1994 const StringInfo *profile,ExceptionInfo *exception)
1996#if defined(MAGICKCORE_XML_DELEGATE)
2003 const char *artifact=GetImageArtifact(image,
"xmp:validate");
2004 if (IsStringTrue(artifact) == MagickFalse)
2006 document=xmlReadMemory((
const char *) GetStringInfoDatum(profile),(
int)
2007 GetStringInfoLength(profile),
"xmp.xml",NULL,XML_PARSE_NOERROR |
2008 XML_PARSE_NOWARNING);
2009 if (document == (xmlDocPtr) NULL)
2011 (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
2012 "CorruptImageProfile",
"`%s' (XMP)",image->filename);
2013 return(MagickFalse);
2015 xmlFreeDoc(document);
2019 (void) ThrowMagickException(exception,GetMagickModule(),
2020 MissingDelegateWarning,
"DelegateLibrarySupportNotBuiltIn",
"`%s' (XML)",
2022 return(MagickFalse);
2026static MagickBooleanType SetImageProfileInternal(Image *image,
const char *name,
2027 StringInfo *profile,
const MagickBooleanType recursive,
2028 ExceptionInfo *exception)
2031 key[MagickPathExtent];
2039 assert(image != (Image *) NULL);
2040 assert(image->signature == MagickCoreSignature);
2041 assert(profile != (StringInfo *) NULL);
2042 assert(name != (
const char *) NULL);
2043 if (IsEventLogging() != MagickFalse)
2044 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2045 length=GetStringInfoLength(profile);
2046 if ((length == 0) || (length > GetMaxProfileSize()))
2049 (void) ThrowMagickException(exception,GetMagickModule(),
2050 ResourceLimitWarning,
"ProfileSizeExceedsLimit",
"`%llu'",
2051 (
unsigned long long) length);
2052 profile=DestroyStringInfo(profile);
2055 PatchCorruptProfile(name,profile);
2056 if ((LocaleCompare(name,
"xmp") == 0) &&
2057 (ValidateXMPProfile(image,profile,exception) == MagickFalse))
2059 profile=DestroyStringInfo(profile);
2062 if (image->profiles == (SplayTreeInfo *) NULL)
2063 image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
2065 (void) CopyMagickString(key,name,MagickPathExtent);
2071 if ((length > 4) && (LocaleCompare(key,
"app1") == 0) &&
2072 (LocaleNCompare((
const char *) GetStringInfoDatum(profile),
"exif",4) == 0))
2073 (void) CopyMagickString(key,
"exif",MagickPathExtent);
2076 status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
2077 ConstantString(key),profile);
2078 if (status == MagickFalse)
2079 profile=DestroyStringInfo(profile);
2082 if (LocaleCompare(key,
"8bim") == 0)
2083 GetProfilesFromResourceBlock(image,profile,exception);
2085 if (recursive == MagickFalse)
2086 WriteTo8BimProfile(image,key,profile);
2091MagickExport StringInfo *AcquireProfileStringInfo(
const char *name,
2092 const size_t length,ExceptionInfo *exception)
2095 *profile = (StringInfo *) NULL;
2097 if (length > GetMaxProfileSize())
2098 (void) ThrowMagickException(exception,GetMagickModule(),
2099 ResourceLimitWarning,
"ProfileSizeExceedsLimit",
"`%llu'",
2100 (
unsigned long long) length);
2103 profile=AcquireStringInfo(length);
2104 SetStringInfoName(profile,name);
2109MagickExport StringInfo *BlobToProfileStringInfo(
const char *name,
2110 const void *blob,
const size_t length,ExceptionInfo *exception)
2115 profile=AcquireProfileStringInfo(name,length,exception);
2116 if (profile != (
const StringInfo *) NULL)
2117 (void) memcpy(profile->datum,blob,length);
2121MagickExport MagickBooleanType SetImageProfile(Image *image,
const char *name,
2122 const StringInfo *profile,ExceptionInfo *exception)
2127 if (profile == (
const StringInfo *) NULL)
2128 return(MagickFalse);
2129 clone_profile=CloneStringInfo(profile);
2130 return(SetImageProfileInternal(image,name,clone_profile,MagickFalse,
2134MagickExport MagickBooleanType SetImageProfilePrivate(Image *image,
2135 StringInfo *profile,ExceptionInfo *exception)
2137 if (profile == (
const StringInfo *) NULL)
2138 return(MagickFalse);
2139 return(SetImageProfileInternal(image,GetStringInfoName(profile),profile,
2140 MagickFalse,exception));
2166static inline int ReadProfileByte(
unsigned char **p,
size_t *length)
2178static inline signed short ReadProfileShort(
const EndianType endian,
2179 unsigned char *buffer)
2193 if (endian == LSBEndian)
2195 value=(
unsigned short) buffer[1] << 8;
2196 value|=(
unsigned short) buffer[0];
2197 quantum.unsigned_value=value & 0xffff;
2198 return((
signed short) quantum.signed_value);
2200 value=(
unsigned short) buffer[0] << 8;
2201 value|=(
unsigned short) buffer[1];
2202 quantum.unsigned_value=value & 0xffff;
2203 return((
signed short) quantum.signed_value);
2206static inline signed int ReadProfileLong(
const EndianType endian,
2207 unsigned char *buffer)
2221 if (endian == LSBEndian)
2223 value=(
unsigned int) buffer[3] << 24;
2224 value|=(
unsigned int) buffer[2] << 16;
2225 value|=(
unsigned int) buffer[1] << 8;
2226 value|=(
unsigned int) buffer[0];
2227 quantum.unsigned_value=value & 0xffffffff;
2228 return(quantum.signed_value);
2230 value=(
unsigned int) buffer[0] << 24;
2231 value|=(
unsigned int) buffer[1] << 16;
2232 value|=(
unsigned int) buffer[2] << 8;
2233 value|=(
unsigned int) buffer[3];
2234 quantum.unsigned_value=value & 0xffffffff;
2235 return(quantum.signed_value);
2238static inline signed int ReadProfileMSBLong(
unsigned char **p,
size_t *length)
2245 value=ReadProfileLong(MSBEndian,*p);
2251static inline signed short ReadProfileMSBShort(
unsigned char **p,
2259 value=ReadProfileShort(MSBEndian,*p);
2265static inline void WriteProfileLong(
const EndianType endian,
2266 const size_t value,
unsigned char *p)
2271 if (endian == LSBEndian)
2273 buffer[0]=(
unsigned char) value;
2274 buffer[1]=(
unsigned char) (value >> 8);
2275 buffer[2]=(
unsigned char) (value >> 16);
2276 buffer[3]=(
unsigned char) (value >> 24);
2277 (void) memcpy(p,buffer,4);
2280 buffer[0]=(
unsigned char) (value >> 24);
2281 buffer[1]=(
unsigned char) (value >> 16);
2282 buffer[2]=(
unsigned char) (value >> 8);
2283 buffer[3]=(
unsigned char) value;
2284 (void) memcpy(p,buffer,4);
2287static void WriteProfileShort(
const EndianType endian,
2288 const unsigned short value,
unsigned char *p)
2293 if (endian == LSBEndian)
2295 buffer[0]=(
unsigned char) value;
2296 buffer[1]=(
unsigned char) (value >> 8);
2297 (void) memcpy(p,buffer,2);
2300 buffer[0]=(
unsigned char) (value >> 8);
2301 buffer[1]=(
unsigned char) value;
2302 (void) memcpy(p,buffer,2);
2305static void SyncExifProfile(
const Image *image,
unsigned char *exif,
2308#define MaxDirectoryStack 16
2309#define EXIF_DELIMITER "\n"
2310#define EXIF_NUM_FORMATS 12
2311#define TAG_EXIF_OFFSET 0x8769
2312#define TAG_INTEROP_OFFSET 0xa005
2314 typedef struct _DirectoryInfo
2324 directory_stack[MaxDirectoryStack] = { { 0, 0 } };
2342 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
2349 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2350 if ((
id != 0x4949) && (
id != 0x4D4D))
2354 if (ReadProfileByte(&exif,&length) != 0x45)
2356 if (ReadProfileByte(&exif,&length) != 0x78)
2358 if (ReadProfileByte(&exif,&length) != 0x69)
2360 if (ReadProfileByte(&exif,&length) != 0x66)
2362 if (ReadProfileByte(&exif,&length) != 0x00)
2364 if (ReadProfileByte(&exif,&length) != 0x00)
2370 id=(ssize_t) ReadProfileShort(LSBEndian,exif);
2380 if (ReadProfileShort(endian,exif+2) != 0x002a)
2385 offset=(ssize_t) ReadProfileLong(endian,exif+4);
2386 if ((offset < 0) || ((
size_t) offset >= length))
2388 directory=exif+offset;
2391 exif_resources=NewSplayTree((
int (*)(
const void *,
const void *)) NULL,
2392 (
void *(*)(
void *)) NULL,(
void *(*)(
void *)) NULL);
2398 directory=directory_stack[level].directory;
2399 entry=directory_stack[level].entry;
2401 if ((directory < exif) || (directory > (exif+length-2)))
2406 number_entries=(size_t) ReadProfileShort(endian,directory);
2407 for ( ; entry < number_entries; entry++)
2423 q=(
unsigned char *) (directory+2+(12*entry));
2424 if (q > (exif+length-12))
2426 if (GetValueFromSplayTree(exif_resources,q) == q)
2428 (void) AddValueToSplayTree(exif_resources,q,q);
2429 tag_value=(ssize_t) ReadProfileShort(endian,q);
2430 format=(ssize_t) ReadProfileShort(endian,q+2);
2431 if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
2433 components=(int) ReadProfileLong(endian,q+4);
2436 number_bytes=(size_t) components*(
size_t) format_bytes[format];
2437 if ((ssize_t) number_bytes < components)
2439 if (number_bytes <= 4)
2446 offset=(ssize_t) ReadProfileLong(endian,q+8);
2448 ((
size_t) (offset+(ssize_t) number_bytes) > length))
2450 if (~length < number_bytes)
2452 p=(
unsigned char *) (exif+offset);
2458 (void) WriteProfileLong(endian,(
size_t) (image->resolution.x+0.5),p);
2459 if (number_bytes == 8)
2460 (void) WriteProfileLong(endian,1UL,p+4);
2465 (void) WriteProfileLong(endian,(
size_t) (image->resolution.y+0.5),p);
2466 if (number_bytes == 8)
2467 (void) WriteProfileLong(endian,1UL,p+4);
2472 if (number_bytes == 4)
2474 (void) WriteProfileLong(endian,(
size_t) image->orientation,p);
2477 (void) WriteProfileShort(endian,(
unsigned short) image->orientation,
2483 if (number_bytes == 4)
2485 (void) WriteProfileLong(endian,((
size_t) image->units)+1,p);
2488 (void) WriteProfileShort(endian,(
unsigned short) (image->units+1),p);
2494 if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
2496 offset=(ssize_t) ReadProfileLong(endian,p);
2497 if (((
size_t) offset < length) && (level < (MaxDirectoryStack-2)))
2499 directory_stack[level].directory=directory;
2501 directory_stack[level].entry=entry;
2503 directory_stack[level].directory=exif+offset;
2504 directory_stack[level].entry=0;
2506 if ((directory+2+(12*number_entries)) > (exif+length))
2508 offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
2510 if ((offset != 0) && ((
size_t) offset < length) &&
2511 (level < (MaxDirectoryStack-2)))
2513 directory_stack[level].directory=exif+offset;
2514 directory_stack[level].entry=0;
2521 }
while (level > 0);
2522 exif_resources=DestroySplayTree(exif_resources);
2526static void Sync8BimProfile(
const Image *image,
const StringInfo *profile)
2540 length=GetStringInfoLength(profile);
2541 p=GetStringInfoDatum(profile);
2544 if (ReadProfileByte(&p,&length) != 0x38)
2546 if (ReadProfileByte(&p,&length) != 0x42)
2548 if (ReadProfileByte(&p,&length) != 0x49)
2550 if (ReadProfileByte(&p,&length) != 0x4D)
2554 id=(
unsigned short) ReadProfileMSBShort(&p,&length);
2555 count=(ssize_t) ReadProfileByte(&p,&length);
2556 if ((count >= (ssize_t) length) || (count < 0))
2558 p+=(ptrdiff_t) count;
2559 length-=(size_t) count;
2560 if ((*p & 0x01) == 0)
2561 (void) ReadProfileByte(&p,&length);
2562 count=(ssize_t) ReadProfileMSBLong(&p,&length);
2563 if ((count > (ssize_t) length) || (count < 0))
2565 if ((
id == 0x3ED) && (count == 16))
2567 if (image->units == PixelsPerCentimeterResolution)
2568 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToSsizeT(
2569 image->resolution.x*2.54*65536.0),p);
2571 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToSsizeT(
2572 image->resolution.x*65536.0),p);
2573 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+4);
2574 if (image->units == PixelsPerCentimeterResolution)
2575 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToSsizeT(
2576 image->resolution.y*2.54*65536.0),p+8);
2578 WriteProfileLong(MSBEndian,(
unsigned int) CastDoubleToSsizeT(
2579 image->resolution.y*65536.0),p+8);
2580 WriteProfileShort(MSBEndian,(
unsigned short) image->units,p+12);
2583 SyncExifProfile(image,p,(
size_t) count);
2584 p+=(ptrdiff_t) count;
2585 length-=(size_t) count;
2590static void ReplaceXmpValue(StringInfo *profile,
size_t start,
size_t end,
2601 length=GetStringInfoLength(profile);
2602 value_length=strlen(value);
2603 new_length=length-(end-start)+value_length;
2604 if (new_length > length)
2605 SetStringInfoLength(profile,new_length);
2606 datum=(
char *) GetStringInfoDatum(profile);
2607 (void) memmove(datum+start+value_length,datum+end,length-end);
2608 (void) memcpy(datum+start,value,value_length);
2609 if (new_length < length)
2611 SetStringInfoLength(profile,new_length);
2612 datum=(
char *) GetStringInfoDatum(profile);
2613 *(datum+new_length)=
'\0';
2617static MagickBooleanType GetXmpOffsets(
const StringInfo *profile,
2618 const char *tag,
size_t *start,
size_t *end)
2628 datum=(
char *) GetStringInfoDatum(profile);
2629 length=GetStringInfoLength(profile);
2630 pos=strstr(datum,tag);
2631 tag_length=strlen(tag);
2632 if ((pos == (
char *) NULL) || ((pos-datum) < 1) || (*(pos-1) !=
'<') ||
2633 (((
size_t) (pos-datum)+tag_length) > length) ||
2634 (*(pos+tag_length) !=
'>'))
2635 return(MagickFalse);
2636 *start=(size_t) (pos-datum)+tag_length+1;
2637 pos=strstr(datum+*start,
"<");
2638 if (pos == (
char *) NULL)
2639 return(MagickFalse);
2640 *end=(size_t) (pos-datum);
2644static void GetXmpNumeratorAndDenominator(
double value,
2645 unsigned long *numerator,
unsigned long *denominator)
2652 if (value <= MagickEpsilon)
2654 if (value > (
double) MAGICK_ULONG_MAX)
2656 *numerator = MAGICK_ULONG_MAX;
2660 if (floor(value) == value)
2662 *numerator = (
unsigned long) value;
2668 while(fabs(df - value) > MagickEpsilon)
2675 *numerator=(
unsigned long) (value*(*denominator));
2677 df=*numerator/(double)*denominator;
2681static void SyncXmpProfile(
const Image *image,StringInfo *profile)
2684 value[MagickPathExtent];
2695 if (GetXmpOffsets(profile,
"tiff:XResolution",&start,&end) != MagickFalse)
2697 GetXmpNumeratorAndDenominator(image->resolution.x,&numerator,
2699 (void) FormatLocaleString(value,MagickPathExtent,
"%lu/%lu",numerator,
2701 ReplaceXmpValue(profile,start,end,value);
2703 if (GetXmpOffsets(profile,
"tiff:YResolution",&start,&end) != MagickFalse)
2705 if ((fabs(image->resolution.x-image->resolution.y) > MagickEpsilon) ||
2708 GetXmpNumeratorAndDenominator(image->resolution.y,&numerator,
2710 (void) FormatLocaleString(value,MagickPathExtent,
"%lu/%lu",
2711 numerator,denominator);
2713 ReplaceXmpValue(profile,start,end,value);
2715 if (GetXmpOffsets(profile,
"tiff:ResolutionUnit",&start,&end) != MagickFalse)
2717 (void) FormatLocaleString(value,MagickPathExtent,
"%d",
2718 ((
int) image->units)+1);
2719 ReplaceXmpValue(profile,start,end,value);
2721 if (GetXmpOffsets(profile,
"tiff:Orientation",&start,&end) != MagickFalse)
2723 (void) FormatLocaleString(value,MagickPathExtent,
"%d",
2724 (
int) image->orientation);
2725 ReplaceXmpValue(profile,start,end,value);
2729MagickPrivate
void SyncImageProfiles(Image *image)
2734 profile=(StringInfo *) GetImageProfile(image,
"8BIM");
2735 if (profile != (StringInfo *) NULL)
2736 Sync8BimProfile(image,profile);
2737 profile=(StringInfo *) GetImageProfile(image,
"EXIF");
2738 if (profile != (StringInfo *) NULL)
2739 SyncExifProfile(image,GetStringInfoDatum(profile),GetStringInfoLength(
2741 profile=(StringInfo *) GetImageProfile(image,
"XMP");
2742 if (profile != (StringInfo *) NULL)
2743 SyncXmpProfile(image,profile);
2746static void UpdateClipPath(
unsigned char *blob,
size_t length,
2747 const size_t old_columns,
const size_t old_rows,
2748 const RectangleInfo *new_geometry)
2758 selector=(ssize_t) ReadProfileMSBShort(&blob,&length);
2764 if (knot_count != 0)
2767 length-=(size_t) MagickMin(length,24U);
2773 knot_count=(ssize_t) ReadProfileMSBShort(&blob,&length);
2775 length-=(size_t) MagickMin(length,22);
2783 if (knot_count == 0)
2789 length-=(size_t) MagickMin(length,24);
2795 for (i=0; i < 3; i++)
2805 y=(double) ReadProfileMSBLong(&blob,&length);
2806 y=y*old_rows/4096.0/4096.0;
2808 yy=(
signed int) ((y*4096*4096)/new_geometry->height);
2809 WriteProfileLong(MSBEndian,(
size_t) yy,blob-4);
2810 x=(double) ReadProfileMSBLong(&blob,&length);
2811 x=x*old_columns/4096.0/4096.0;
2813 xx=(
signed int) ((x*4096*4096)/new_geometry->width);
2814 WriteProfileLong(MSBEndian,(
size_t) xx,blob-4);
2825 length-=(size_t) MagickMin(length,24);
2832MagickPrivate
void Update8BIMClipPath(
const Image *image,
2833 const size_t old_columns,
const size_t old_rows,
2834 const RectangleInfo *new_geometry)
2849 assert(image != (Image *) NULL);
2850 assert(new_geometry != (RectangleInfo *) NULL);
2851 profile=GetImageProfile(image,
"8bim");
2852 if (profile == (StringInfo *) NULL)
2854 length=GetStringInfoLength(profile);
2855 info=GetStringInfoDatum(profile);
2858 if (ReadProfileByte(&info,&length) != (
unsigned char)
'8')
2860 if (ReadProfileByte(&info,&length) != (
unsigned char)
'B')
2862 if (ReadProfileByte(&info,&length) != (
unsigned char)
'I')
2864 if (ReadProfileByte(&info,&length) != (
unsigned char)
'M')
2866 id=(ssize_t) ReadProfileMSBShort(&info,&length);
2867 count=(ssize_t) ReadProfileByte(&info,&length);
2868 if ((count != 0) && ((
size_t) count <= length))
2871 length-=(size_t) count;
2873 if ((count & 0x01) == 0)
2874 (void) ReadProfileByte(&info,&length);
2875 count=(ssize_t) ReadProfileMSBLong(&info,&length);
2876 if ((count < 0) || ((
size_t) count > length))
2881 if ((
id > 1999) && (
id < 2999))
2882 UpdateClipPath(info,(
size_t) count,old_columns,old_rows,new_geometry);
2884 length-=(size_t) MagickMin(length,(
size_t) count);