diff --git a/MagickCore/profile.c b/MagickCore/profile.c
new file mode 100644
index 0000000..b3a747a
--- /dev/null
+++ b/MagickCore/profile.c
@@ -0,0 +1,1945 @@
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% PPPP RRRR OOO FFFFF IIIII L EEEEE %
+% P P R R O O F I L E %
+% PPPP RRRR O O FFF I L EEE %
+% P R R O O F I L E %
+% P R R OOO F IIIII LLLLL EEEEE %
+% %
+% %
+% MagickCore Image Profile Methods %
+% %
+% Software Design %
+% John Cristy %
+% July 1992 %
+% %
+% %
+% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
+% dedicated to making software imaging solutions freely available. %
+% %
+% You may not use this file except in compliance with the License. You may %
+% obtain a copy of the License at %
+% %
+% http://www.imagemagick.org/script/license.php %
+% %
+% Unless required by applicable law or agreed to in writing, software %
+% distributed under the License is distributed on an "AS IS" BASIS, %
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
+% See the License for the specific language governing permissions and %
+% limitations under the License. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%
+*/
+
+/*
+ Include declarations.
+*/
+#include "MagickCore/studio.h"
+#include "MagickCore/attribute.h"
+#include "MagickCore/cache.h"
+#include "MagickCore/color.h"
+#include "MagickCore/configure.h"
+#include "MagickCore/exception.h"
+#include "MagickCore/exception-private.h"
+#include "MagickCore/hashmap.h"
+#include "MagickCore/image.h"
+#include "MagickCore/memory_.h"
+#include "MagickCore/monitor.h"
+#include "MagickCore/monitor-private.h"
+#include "MagickCore/option.h"
+#include "MagickCore/pixel-accessor.h"
+#include "MagickCore/profile.h"
+#include "MagickCore/property.h"
+#include "MagickCore/quantum.h"
+#include "MagickCore/quantum-private.h"
+#include "MagickCore/splay-tree.h"
+#include "MagickCore/string_.h"
+#include "MagickCore/thread-private.h"
+#include "MagickCore/token.h"
+#include "MagickCore/utility.h"
+#if defined(MAGICKCORE_LCMS_DELEGATE)
+#if defined(MAGICKCORE_HAVE_LCMS_LCMS2_H)
+#include <wchar.h>
+#include <lcms/lcms2.h>
+#elif defined(MAGICKCORE_HAVE_LCMS2_H)
+#include <wchar.h>
+#include "lcms2.h"
+#elif defined(MAGICKCORE_HAVE_LCMS_LCMS_H)
+#include <lcms/lcms.h>
+#else
+#include "lcms.h"
+#endif
+#endif
+
+/*
+ Define declarations.
+*/
+#if !defined(LCMS_VERSION) || (LCMS_VERSION < 2000)
+#define cmsSigCmykData icSigCmykData
+#define cmsSigGrayData icSigGrayData
+#define cmsSigLabData icSigLabData
+#define cmsSigLuvData icSigLuvData
+#define cmsSigRgbData icSigRgbData
+#define cmsSigXYZData icSigXYZData
+#define cmsSigYCbCrData icSigYCbCrData
+#define cmsSigLinkClass icSigLinkClass
+#define cmsColorSpaceSignature icColorSpaceSignature
+#define cmsUInt32Number DWORD
+#define cmsSetLogErrorHandler(handler) cmsSetErrorHandler(handler)
+#define cmsCreateTransformTHR(context,source_profile,source_type, \
+ target_profile,target_type,intent,flags) cmsCreateTransform(source_profile, \
+ source_type,target_profile,target_type,intent,flags);
+#define cmsOpenProfileFromMemTHR(context,profile,length) \
+ cmsOpenProfileFromMem(profile,length)
+#endif
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% C l o n e I m a g e P r o f i l e s %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% CloneImageProfiles() clones one or more image profiles.
+%
+% The format of the CloneImageProfiles method is:
+%
+% MagickBooleanType CloneImageProfiles(Image *image,
+% const Image *clone_image)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+% o clone_image: the clone image.
+%
+*/
+MagickExport MagickBooleanType CloneImageProfiles(Image *image,
+ const Image *clone_image)
+{
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickSignature);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ assert(clone_image != (const Image *) NULL);
+ assert(clone_image->signature == MagickSignature);
+ image->color_profile.length=clone_image->color_profile.length;
+ image->color_profile.info=clone_image->color_profile.info;
+ image->iptc_profile.length=clone_image->iptc_profile.length;
+ image->iptc_profile.info=clone_image->iptc_profile.info;
+ if (clone_image->profiles != (void *) NULL)
+ image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
+ (void *(*)(void *)) ConstantString,(void *(*)(void *)) CloneStringInfo);
+ return(MagickTrue);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% D e l e t e I m a g e P r o f i l e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% DeleteImageProfile() deletes a profile from the image by its name.
+%
+% The format of the DeleteImageProfile method is:
+%
+% MagickBooleanTyupe DeleteImageProfile(Image *image,const char *name)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+% o name: the profile name.
+%
+*/
+MagickExport MagickBooleanType DeleteImageProfile(Image *image,const char *name)
+{
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickSignature);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ if (image->profiles == (SplayTreeInfo *) NULL)
+ return(MagickFalse);
+ return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->profiles,name));
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% D e s t r o y I m a g e P r o f i l e s %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% DestroyImageProfiles() releases memory associated with an image profile map.
+%
+% The format of the DestroyProfiles method is:
+%
+% void DestroyImageProfiles(Image *image)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+*/
+MagickExport void DestroyImageProfiles(Image *image)
+{
+ if (image->profiles != (SplayTreeInfo *) NULL)
+ image->profiles=DestroySplayTree((SplayTreeInfo *) image->profiles);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% G e t I m a g e P r o f i l e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% GetImageProfile() gets a profile associated with an image by name.
+%
+% The format of the GetImageProfile method is:
+%
+% const StringInfo *GetImageProfile(const Image *image,const char *name)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+% o name: the profile name.
+%
+*/
+MagickExport const StringInfo *GetImageProfile(const Image *image,
+ const char *name)
+{
+ char
+ key[MaxTextExtent];
+
+ const StringInfo
+ *profile;
+
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickSignature);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ if (image->profiles == (SplayTreeInfo *) NULL)
+ return((StringInfo *) NULL);
+ (void) CopyMagickString(key,name,MaxTextExtent);
+ profile=(const StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
+ image->profiles,key);
+ return(profile);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% G e t N e x t I m a g e P r o f i l e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% GetNextImageProfile() gets the next profile name for an image.
+%
+% The format of the GetNextImageProfile method is:
+%
+% char *GetNextImageProfile(const Image *image)
+%
+% A description of each parameter follows:
+%
+% o hash_info: the hash info.
+%
+*/
+MagickExport char *GetNextImageProfile(const Image *image)
+{
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickSignature);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ if (image->profiles == (SplayTreeInfo *) NULL)
+ return((char *) NULL);
+ return((char *) GetNextKeyInSplayTree((SplayTreeInfo *) image->profiles));
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% P r o f i l e I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ProfileImage() associates, applies, or removes an ICM, IPTC, or generic
+% profile with / to / from an image. If the profile is NULL, it is removed
+% from the image otherwise added or applied. Use a name of '*' and a profile
+% of NULL to remove all profiles from the image.
+%
+% ICC and ICM profiles are handled as follows: If the image does not have
+% an associated color profile, the one you provide is associated with the
+% image and the image pixels are not transformed. Otherwise, the colorspace
+% transform defined by the existing and new profile are applied to the image
+% pixels and the new profile is associated with the image.
+%
+% The format of the ProfileImage method is:
+%
+% MagickBooleanType ProfileImage(Image *image,const char *name,
+% const void *datum,const size_t length,const MagickBooleanType clone)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+% o name: Name of profile to add or remove: ICC, IPTC, or generic profile.
+%
+% o datum: the profile data.
+%
+% o length: the length of the profile.
+%
+% o clone: should be MagickFalse.
+%
+*/
+
+#if defined(MAGICKCORE_LCMS_DELEGATE)
+
+static unsigned short **DestroyPixelThreadSet(unsigned short **pixels)
+{
+ register ssize_t
+ i;
+
+ assert(pixels != (unsigned short **) NULL);
+ for (i=0; i < (ssize_t) GetOpenMPMaximumThreads(); i++)
+ if (pixels[i] != (unsigned short *) NULL)
+ pixels[i]=(unsigned short *) RelinquishMagickMemory(pixels[i]);
+ pixels=(unsigned short **) RelinquishMagickMemory(pixels);
+ return(pixels);
+}
+
+static unsigned short **AcquirePixelThreadSet(const size_t columns,
+ const size_t channels)
+{
+ register ssize_t
+ i;
+
+ unsigned short
+ **pixels;
+
+ size_t
+ number_threads;
+
+ number_threads=GetOpenMPMaximumThreads();
+ pixels=(unsigned short **) AcquireQuantumMemory(number_threads,
+ sizeof(*pixels));
+ if (pixels == (unsigned short **) NULL)
+ return((unsigned short **) NULL);
+ (void) ResetMagickMemory(pixels,0,number_threads*sizeof(*pixels));
+ for (i=0; i < (ssize_t) number_threads; i++)
+ {
+ pixels[i]=(unsigned short *) AcquireQuantumMemory(columns,channels*
+ sizeof(**pixels));
+ if (pixels[i] == (unsigned short *) NULL)
+ return(DestroyPixelThreadSet(pixels));
+ }
+ return(pixels);
+}
+
+static cmsHTRANSFORM *DestroyTransformThreadSet(cmsHTRANSFORM *transform)
+{
+ register ssize_t
+ i;
+
+ assert(transform != (cmsHTRANSFORM *) NULL);
+ for (i=0; i < (ssize_t) GetOpenMPMaximumThreads(); i++)
+ if (transform[i] != (cmsHTRANSFORM) NULL)
+ cmsDeleteTransform(transform[i]);
+ transform=(cmsHTRANSFORM *) RelinquishMagickMemory(transform);
+ return(transform);
+}
+
+static cmsHTRANSFORM *AcquireTransformThreadSet(Image *image,
+ const cmsHPROFILE source_profile,const cmsUInt32Number source_type,
+ const cmsHPROFILE target_profile,const cmsUInt32Number target_type,
+ const int intent,const cmsUInt32Number flags)
+{
+ cmsHTRANSFORM
+ *transform;
+
+ register ssize_t
+ i;
+
+ size_t
+ number_threads;
+
+ number_threads=GetOpenMPMaximumThreads();
+ transform=(cmsHTRANSFORM *) AcquireQuantumMemory(number_threads,
+ sizeof(*transform));
+ if (transform == (cmsHTRANSFORM *) NULL)
+ return((cmsHTRANSFORM *) NULL);
+ (void) ResetMagickMemory(transform,0,number_threads*sizeof(*transform));
+ for (i=0; i < (ssize_t) number_threads; i++)
+ {
+ transform[i]=cmsCreateTransformTHR(image,source_profile,source_type,
+ target_profile,target_type,intent,flags);
+ if (transform[i] == (cmsHTRANSFORM) NULL)
+ return(DestroyTransformThreadSet(transform));
+ }
+ return(transform);
+}
+#endif
+
+static MagickBooleanType SetAdobeRGB1998ImageProfile(Image *image)
+{
+ static unsigned char
+ AdobeRGB1998Profile[] =
+ {
+ 0x00, 0x00, 0x02, 0x30, 0x41, 0x44, 0x42, 0x45, 0x02, 0x10, 0x00,
+ 0x00, 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59,
+ 0x5a, 0x20, 0x07, 0xd0, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x13, 0x00,
+ 0x33, 0x00, 0x3b, 0x61, 0x63, 0x73, 0x70, 0x41, 0x50, 0x50, 0x4c,
+ 0x00, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0xd3, 0x2d, 0x41, 0x44, 0x42, 0x45, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
+ 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
+ 0x32, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00,
+ 0x00, 0x6b, 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x9c, 0x00,
+ 0x00, 0x00, 0x14, 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x01, 0xb0,
+ 0x00, 0x00, 0x00, 0x14, 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01,
+ 0xc4, 0x00, 0x00, 0x00, 0x0e, 0x67, 0x54, 0x52, 0x43, 0x00, 0x00,
+ 0x01, 0xd4, 0x00, 0x00, 0x00, 0x0e, 0x62, 0x54, 0x52, 0x43, 0x00,
+ 0x00, 0x01, 0xe4, 0x00, 0x00, 0x00, 0x0e, 0x72, 0x58, 0x59, 0x5a,
+ 0x00, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x00, 0x14, 0x67, 0x58, 0x59,
+ 0x5a, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x14, 0x62, 0x58,
+ 0x59, 0x5a, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x14, 0x74,
+ 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x70, 0x79,
+ 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x32, 0x30, 0x30, 0x30, 0x20,
+ 0x41, 0x64, 0x6f, 0x62, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65,
+ 0x6d, 0x73, 0x20, 0x49, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72,
+ 0x61, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x41, 0x64, 0x6f,
+ 0x62, 0x65, 0x20, 0x52, 0x47, 0x42, 0x20, 0x28, 0x31, 0x39, 0x39,
+ 0x38, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x02, 0x33, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x33, 0x00, 0x00,
+ 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x33, 0x00, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x9c, 0x18, 0x00, 0x00, 0x4f, 0xa5, 0x00,
+ 0x00, 0x04, 0xfc, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x34, 0x8d, 0x00, 0x00, 0xa0, 0x2c, 0x00, 0x00, 0x0f,
+ 0x95, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x26, 0x31, 0x00, 0x00, 0x10, 0x2f, 0x00, 0x00, 0xbe, 0x9c
+ };
+
+ StringInfo
+ *profile;
+
+ MagickBooleanType
+ status;
+
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickSignature);
+ if (GetImageProfile(image,"icm") != (const StringInfo *) NULL)
+ return(MagickFalse);
+ profile=AcquireStringInfo(sizeof(AdobeRGB1998Profile));
+ SetStringInfoDatum(profile,AdobeRGB1998Profile);
+ status=SetImageProfile(image,"icm",profile);
+ profile=DestroyStringInfo(profile);
+ return(status);
+}
+
+static MagickBooleanType SetsRGBImageProfile(Image *image)
+{
+ static unsigned char
+ sRGBProfile[] =
+ {
+ 0x00, 0x00, 0x0c, 0x48, 0x4c, 0x69, 0x6e, 0x6f, 0x02, 0x10, 0x00,
+ 0x00, 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59,
+ 0x5a, 0x20, 0x07, 0xce, 0x00, 0x02, 0x00, 0x09, 0x00, 0x06, 0x00,
+ 0x31, 0x00, 0x00, 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54,
+ 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47,
+ 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0xd3, 0x2d, 0x48, 0x50, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
+ 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00,
+ 0x33, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00,
+ 0x00, 0x6c, 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0xf0, 0x00,
+ 0x00, 0x00, 0x14, 0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x02, 0x04,
+ 0x00, 0x00, 0x00, 0x14, 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x02,
+ 0x18, 0x00, 0x00, 0x00, 0x14, 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00,
+ 0x02, 0x2c, 0x00, 0x00, 0x00, 0x14, 0x62, 0x58, 0x59, 0x5a, 0x00,
+ 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x14, 0x64, 0x6d, 0x6e, 0x64,
+ 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70, 0x64, 0x6d, 0x64,
+ 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88, 0x76, 0x75,
+ 0x65, 0x64, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x86, 0x76,
+ 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xd4, 0x00, 0x00, 0x00, 0x24,
+ 0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00,
+ 0x14, 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x04, 0x0c, 0x00, 0x00,
+ 0x00, 0x24, 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x04, 0x30, 0x00,
+ 0x00, 0x00, 0x0c, 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x3c,
+ 0x00, 0x00, 0x08, 0x0c, 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04,
+ 0x3c, 0x00, 0x00, 0x08, 0x0c, 0x62, 0x54, 0x52, 0x43, 0x00, 0x00,
+ 0x04, 0x3c, 0x00, 0x00, 0x08, 0x0c, 0x74, 0x65, 0x78, 0x74, 0x00,
+ 0x00, 0x00, 0x00, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, 0x39, 0x38, 0x20,
+ 0x48, 0x65, 0x77, 0x6c, 0x65, 0x74, 0x74, 0x2d, 0x50, 0x61, 0x63,
+ 0x6b, 0x61, 0x72, 0x64, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e,
+ 0x79, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x12, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45,
+ 0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+ 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39,
+ 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xcc, 0x58,
+ 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5a,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa2, 0x00, 0x00,
+ 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x99, 0x00, 0x00, 0xb7, 0x85,
+ 0x00, 0x00, 0x18, 0xda, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x24, 0xa0, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00,
+ 0xb6, 0xcf, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
+ 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x65, 0x63, 0x2e,
+ 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43, 0x20, 0x36, 0x31,
+ 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44, 0x65, 0x66,
+ 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
+ 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43, 0x20,
+ 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44,
+ 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63,
+ 0x65, 0x20, 0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73,
+ 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x52, 0x65,
+ 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65,
+ 0x77, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 0x43, 0x36,
+ 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x52, 0x65,
+ 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65,
+ 0x77, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 0x43, 0x36,
+ 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
+ 0xa4, 0xfe, 0x00, 0x14, 0x5f, 0x2e, 0x00, 0x10, 0xcf, 0x14, 0x00,
+ 0x03, 0xed, 0xcc, 0x00, 0x04, 0x13, 0x0b, 0x00, 0x03, 0x5c, 0x9e,
+ 0x00, 0x00, 0x00, 0x01, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x4c, 0x09, 0x56, 0x00, 0x50, 0x00, 0x00, 0x00, 0x57,
+ 0x1f, 0xe7, 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x8f, 0x00, 0x00, 0x00, 0x02, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x43, 0x52, 0x54, 0x20, 0x63, 0x75, 0x72, 0x76, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19, 0x00, 0x1e, 0x00,
+ 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37, 0x00, 0x3b,
+ 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54, 0x00,
+ 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
+ 0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00,
+ 0x90, 0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9,
+ 0x00, 0xae, 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00,
+ 0xc6, 0x00, 0xcb, 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0,
+ 0x00, 0xe5, 0x00, 0xeb, 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01,
+ 0x01, 0x01, 0x07, 0x01, 0x0d, 0x01, 0x13, 0x01, 0x19, 0x01, 0x1f,
+ 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32, 0x01, 0x38, 0x01, 0x3e, 0x01,
+ 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59, 0x01, 0x60, 0x01, 0x67,
+ 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83, 0x01, 0x8b, 0x01,
+ 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1, 0x01, 0xb9,
+ 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1, 0x01,
+ 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
+ 0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02,
+ 0x4b, 0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a,
+ 0x02, 0x84, 0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02,
+ 0xb6, 0x02, 0xc1, 0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb,
+ 0x02, 0xf5, 0x03, 0x00, 0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03,
+ 0x2d, 0x03, 0x38, 0x03, 0x43, 0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66,
+ 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a, 0x03, 0x96, 0x03, 0xa2, 0x03,
+ 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3, 0x03, 0xe0, 0x03, 0xec,
+ 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20, 0x04, 0x2d, 0x04,
+ 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71, 0x04, 0x7e,
+ 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4, 0x04,
+ 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
+ 0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05,
+ 0x77, 0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5,
+ 0x05, 0xd5, 0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06,
+ 0x27, 0x06, 0x37, 0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b,
+ 0x06, 0x8c, 0x06, 0x9d, 0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06,
+ 0xe3, 0x06, 0xf5, 0x07, 0x07, 0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d,
+ 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74, 0x07, 0x86, 0x07, 0x99, 0x07,
+ 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5, 0x07, 0xf8, 0x08, 0x0b,
+ 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a, 0x08, 0x6e, 0x08,
+ 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2, 0x08, 0xe7,
+ 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f, 0x09,
+ 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
+ 0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a,
+ 0x54, 0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5,
+ 0x0a, 0xdc, 0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b,
+ 0x51, 0x0b, 0x69, 0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8,
+ 0x0b, 0xe1, 0x0b, 0xf9, 0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c,
+ 0x5c, 0x0c, 0x75, 0x0c, 0x8e, 0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9,
+ 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26, 0x0d, 0x40, 0x0d, 0x5a, 0x0d,
+ 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3, 0x0d, 0xde, 0x0d, 0xf8,
+ 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64, 0x0e, 0x7f, 0x0e,
+ 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09, 0x0f, 0x25,
+ 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3, 0x0f,
+ 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
+ 0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11,
+ 0x13, 0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa,
+ 0x11, 0xc9, 0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12,
+ 0x64, 0x12, 0x84, 0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03,
+ 0x13, 0x23, 0x13, 0x43, 0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13,
+ 0xc5, 0x13, 0xe5, 0x14, 0x06, 0x14, 0x27, 0x14, 0x49, 0x14, 0x6a,
+ 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce, 0x14, 0xf0, 0x15, 0x12, 0x15,
+ 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b, 0x15, 0xbd, 0x15, 0xe0,
+ 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c, 0x16, 0x8f, 0x16,
+ 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41, 0x17, 0x65,
+ 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b, 0x18,
+ 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
+ 0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19,
+ 0xdd, 0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e,
+ 0x1a, 0xc5, 0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b,
+ 0x8a, 0x1b, 0xb2, 0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52,
+ 0x1c, 0x7b, 0x1c, 0xa3, 0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d,
+ 0x47, 0x1d, 0x70, 0x1d, 0x99, 0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16,
+ 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94, 0x1e, 0xbe, 0x1e, 0xe9, 0x1f,
+ 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94, 0x1f, 0xbf, 0x1f, 0xea,
+ 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98, 0x20, 0xc4, 0x20,
+ 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1, 0x21, 0xce,
+ 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf, 0x22,
+ 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
+ 0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24,
+ 0xda, 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7,
+ 0x25, 0xf7, 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26,
+ 0xe8, 0x27, 0x18, 0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc,
+ 0x28, 0x0d, 0x28, 0x3f, 0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29,
+ 0x06, 0x29, 0x38, 0x29, 0x6b, 0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02,
+ 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b, 0x2a, 0xcf, 0x2b, 0x02, 0x2b,
+ 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1, 0x2c, 0x05, 0x2c, 0x39,
+ 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c, 0x2d, 0x41, 0x2d,
+ 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c, 0x2e, 0x82,
+ 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91, 0x2f,
+ 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
+ 0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32,
+ 0x2a, 0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46,
+ 0x33, 0x7f, 0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34,
+ 0x9e, 0x34, 0xd8, 0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2,
+ 0x35, 0xfd, 0x36, 0x37, 0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37,
+ 0x24, 0x37, 0x60, 0x37, 0x9c, 0x37, 0xd7, 0x38, 0x14, 0x38, 0x50,
+ 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05, 0x39, 0x42, 0x39, 0x7f, 0x39,
+ 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74, 0x3a, 0xb2, 0x3a, 0xef,
+ 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8, 0x3c, 0x27, 0x3c,
+ 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61, 0x3d, 0xa1,
+ 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0, 0x3f,
+ 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
+ 0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41,
+ 0xee, 0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a,
+ 0x43, 0x7d, 0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44,
+ 0xce, 0x45, 0x12, 0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22,
+ 0x46, 0x67, 0x46, 0xab, 0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47,
+ 0xc0, 0x48, 0x05, 0x48, 0x4b, 0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d,
+ 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0, 0x4a, 0x37, 0x4a, 0x7d, 0x4a,
+ 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a, 0x4b, 0xe2, 0x4c, 0x2a,
+ 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a, 0x4d, 0x93, 0x4d,
+ 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00, 0x4f, 0x49,
+ 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb, 0x51,
+ 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
+ 0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54,
+ 0x42, 0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2,
+ 0x56, 0x0f, 0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57,
+ 0x92, 0x57, 0xe0, 0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a,
+ 0x59, 0x69, 0x59, 0xb8, 0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a,
+ 0xf5, 0x5b, 0x45, 0x5b, 0x95, 0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86,
+ 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78, 0x5d, 0xc9, 0x5e, 0x1a, 0x5e,
+ 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61, 0x5f, 0xb3, 0x60, 0x05,
+ 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f, 0x61, 0xa2, 0x61,
+ 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43, 0x63, 0x97,
+ 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d, 0x65,
+ 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
+ 0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69,
+ 0x43, 0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7,
+ 0x6b, 0x4f, 0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d,
+ 0x08, 0x6d, 0x60, 0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4,
+ 0x6f, 0x1e, 0x6f, 0x78, 0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70,
+ 0xe0, 0x71, 0x3a, 0x71, 0x95, 0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6,
+ 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8, 0x74, 0x14, 0x74, 0x70, 0x74,
+ 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1, 0x76, 0x3e, 0x76, 0x9b,
+ 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11, 0x78, 0x6e, 0x78,
+ 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46, 0x7a, 0xa5,
+ 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81, 0x7c,
+ 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
+ 0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81,
+ 0x0a, 0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4,
+ 0x83, 0x57, 0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85,
+ 0x47, 0x85, 0xab, 0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b,
+ 0x87, 0x9f, 0x88, 0x04, 0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89,
+ 0x99, 0x89, 0xfe, 0x8a, 0x64, 0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96,
+ 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca, 0x8d, 0x31, 0x8d, 0x98, 0x8d,
+ 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36, 0x8f, 0x9e, 0x90, 0x06,
+ 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8, 0x92, 0x11, 0x92,
+ 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20, 0x94, 0x8a,
+ 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f, 0x97,
+ 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
+ 0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b,
+ 0xaf, 0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2,
+ 0x9e, 0x40, 0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0,
+ 0x69, 0xa0, 0xd8, 0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96,
+ 0xa3, 0x06, 0xa3, 0x76, 0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5,
+ 0x38, 0xa5, 0xa9, 0xa6, 0x1a, 0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e,
+ 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4, 0xa9, 0x37, 0xa9, 0xa9, 0xaa,
+ 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75, 0xab, 0xe9, 0xac, 0x5c,
+ 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d, 0xae, 0xa1, 0xaf,
+ 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea, 0xb1, 0x60,
+ 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae, 0xb4,
+ 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
+ 0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9,
+ 0x4a, 0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7,
+ 0xbc, 0x21, 0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe,
+ 0x84, 0xbe, 0xff, 0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec,
+ 0xc1, 0x67, 0xc1, 0xe3, 0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3,
+ 0xd4, 0xc4, 0x51, 0xc4, 0xce, 0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46,
+ 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf, 0xc8, 0x3d, 0xc8, 0xbc, 0xc9,
+ 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7, 0xcb, 0x36, 0xcb, 0xb6,
+ 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5, 0xce, 0x36, 0xce,
+ 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba, 0xd1, 0x3c,
+ 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6, 0xd4,
+ 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
+ 0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9,
+ 0xf1, 0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a,
+ 0xdd, 0x10, 0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf,
+ 0xaf, 0xe0, 0x36, 0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53,
+ 0xe2, 0xdb, 0xe3, 0x63, 0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5,
+ 0x84, 0xe6, 0x0d, 0xe6, 0x96, 0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32,
+ 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0, 0xea, 0x5b, 0xea, 0xe5, 0xeb,
+ 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11, 0xed, 0x9c, 0xee, 0x28,
+ 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58, 0xf0, 0xe5, 0xf1,
+ 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7, 0xf4, 0x34,
+ 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb, 0xf7,
+ 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
+ 0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd,
+ 0xba, 0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff
+ };
+
+ StringInfo
+ *profile;
+
+ MagickBooleanType
+ status;
+
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickSignature);
+ if (GetImageProfile(image,"icm") != (const StringInfo *) NULL)
+ return(MagickFalse);
+ profile=AcquireStringInfo(sizeof(sRGBProfile));
+ SetStringInfoDatum(profile,sRGBProfile);
+ status=SetImageProfile(image,"icm",profile);
+ profile=DestroyStringInfo(profile);
+ return(status);
+}
+#if defined(MAGICKCORE_LCMS_DELEGATE)
+#if defined(LCMS_VERSION) && (LCMS_VERSION >= 2000)
+static void LCMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
+ const char *message)
+{
+ Image
+ *image;
+
+ (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%u, %s",
+ severity,message != (char *) NULL ? message : "no message");
+ image=(Image *) context;
+ if (image != (Image *) NULL)
+ (void) ThrowMagickException(&image->exception,GetMagickModule(),
+ ImageWarning,"UnableToTransformColorspace","`%s'",image->filename);
+
+}
+#else
+static int LCMSExceptionHandler(int severity,const char *message)
+{
+ (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%d, %s",
+ severity,message != (char *) NULL ? message : "no message");
+ return(1);
+}
+#endif
+#endif
+
+MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
+ const void *datum,const size_t length,
+ const MagickBooleanType magick_unused(clone))
+{
+#define ProfileImageTag "Profile/Image"
+#define ThrowProfileException(severity,tag,context) \
+{ \
+ if (source_profile != (cmsHPROFILE) NULL) \
+ (void) cmsCloseProfile(source_profile); \
+ if (target_profile != (cmsHPROFILE) NULL) \
+ (void) cmsCloseProfile(target_profile); \
+ ThrowBinaryException(severity,tag,context); \
+}
+
+ MagickBooleanType
+ status;
+
+ StringInfo
+ *profile;
+
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickSignature);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ assert(name != (const char *) NULL);
+ if ((datum == (const void *) NULL) || (length == 0))
+ {
+ char
+ **arguments,
+ *names;
+
+ int
+ number_arguments;
+
+ register ssize_t
+ i;
+
+ /*
+ Delete image profile(s).
+ */
+ names=ConstantString(name);
+ (void) SubstituteString(&names,","," ");
+ arguments=StringToArgv(names,&number_arguments);
+ names=DestroyString(names);
+ if (arguments == (char **) NULL)
+ return(MagickTrue);
+ ResetImageProfileIterator(image);
+ for (name=GetNextImageProfile(image); name != (const char *) NULL; )
+ {
+ for (i=1; i < (ssize_t) number_arguments; i++)
+ {
+ if ((*arguments[i] == '!') &&
+ (LocaleCompare(name,arguments[i]+1) == 0))
+ break;
+ if (GlobExpression(name,arguments[i],MagickTrue) != MagickFalse)
+ {
+ (void) DeleteImageProfile(image,name);
+ ResetImageProfileIterator(image);
+ break;
+ }
+ }
+ name=GetNextImageProfile(image);
+ }
+ for (i=0; i < (ssize_t) number_arguments; i++)
+ arguments[i]=DestroyString(arguments[i]);
+ arguments=(char **) RelinquishMagickMemory(arguments);
+ return(MagickTrue);
+ }
+ /*
+ Add a ICC, IPTC, or generic profile to the image.
+ */
+ status=MagickTrue;
+ profile=AcquireStringInfo((size_t) length);
+ SetStringInfoDatum(profile,(unsigned char *) datum);
+ if ((LocaleCompare(name,"icc") != 0) && (LocaleCompare(name,"icm") != 0))
+ status=SetImageProfile(image,name,profile);
+ else
+ {
+ const StringInfo
+ *icc_profile;
+
+ icc_profile=GetImageProfile(image,"icc");
+ if ((icc_profile != (const StringInfo *) NULL) &&
+ (CompareStringInfo(icc_profile,profile) == 0))
+ {
+ const char
+ *value;
+
+ value=GetImageProperty(image,"exif:ColorSpace");
+ if (LocaleCompare(value,"1") != 0)
+ (void) SetsRGBImageProfile(image);
+ value=GetImageProperty(image,"exif:InteroperabilityIndex");
+ if (LocaleCompare(value,"R98.") != 0)
+ (void) SetsRGBImageProfile(image);
+ value=GetImageProperty(image,"exif:InteroperabilityIndex");
+ if (LocaleCompare(value,"R03.") != 0)
+ (void) SetAdobeRGB1998ImageProfile(image);
+ icc_profile=GetImageProfile(image,"icc");
+ }
+ if ((icc_profile != (const StringInfo *) NULL) &&
+ (CompareStringInfo(icc_profile,profile) == 0))
+ {
+ profile=DestroyStringInfo(profile);
+ return(MagickTrue);
+ }
+#if !defined(MAGICKCORE_LCMS_DELEGATE)
+ (void) ThrowMagickException(&image->exception,GetMagickModule(),
+ MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn","`%s' (LCMS)",
+ image->filename);
+#else
+ {
+ cmsHPROFILE
+ source_profile;
+
+ /*
+ Transform pixel colors as defined by the color profiles.
+ */
+ cmsSetLogErrorHandler(LCMSExceptionHandler);
+ source_profile=cmsOpenProfileFromMemTHR(image,
+ GetStringInfoDatum(profile),(cmsUInt32Number)
+ GetStringInfoLength(profile));
+ if (source_profile == (cmsHPROFILE) NULL)
+ ThrowBinaryException(ResourceLimitError,
+ "ColorspaceColorProfileMismatch",name);
+ if ((cmsGetDeviceClass(source_profile) != cmsSigLinkClass) &&
+ (icc_profile == (StringInfo *) NULL))
+ status=SetImageProfile(image,name,profile);
+ else
+ {
+ CacheView
+ *image_view;
+
+ ColorspaceType
+ source_colorspace,
+ target_colorspace;
+
+ cmsColorSpaceSignature
+ signature;
+
+ cmsHPROFILE
+ target_profile;
+
+ cmsHTRANSFORM
+ *restrict transform;
+
+ cmsUInt32Number
+ flags,
+ source_type,
+ target_type;
+
+ ExceptionInfo
+ *exception;
+
+ int
+ intent;
+
+ MagickBooleanType
+ status;
+
+ MagickOffsetType
+ progress;
+
+ size_t
+ source_channels,
+ target_channels;
+
+ ssize_t
+ y;
+
+ unsigned short
+ **restrict source_pixels,
+ **restrict target_pixels;
+
+ exception=(&image->exception);
+ target_profile=(cmsHPROFILE) NULL;
+ if (icc_profile != (StringInfo *) NULL)
+ {
+ target_profile=source_profile;
+ source_profile=cmsOpenProfileFromMemTHR(image,
+ GetStringInfoDatum(icc_profile),(cmsUInt32Number)
+ GetStringInfoLength(icc_profile));
+ if (source_profile == (cmsHPROFILE) NULL)
+ ThrowProfileException(ResourceLimitError,
+ "ColorspaceColorProfileMismatch",name);
+ }
+ switch (cmsGetColorSpace(source_profile))
+ {
+ case cmsSigCmykData:
+ {
+ source_colorspace=CMYKColorspace;
+ source_type=(cmsUInt32Number) TYPE_CMYK_16;
+ source_channels=4;
+ break;
+ }
+ case cmsSigGrayData:
+ {
+ source_colorspace=GRAYColorspace;
+ source_type=(cmsUInt32Number) TYPE_GRAY_16;
+ source_channels=1;
+ break;
+ }
+ case cmsSigLabData:
+ {
+ source_colorspace=LabColorspace;
+ source_type=(cmsUInt32Number) TYPE_Lab_16;
+ source_channels=3;
+ break;
+ }
+ case cmsSigLuvData:
+ {
+ source_colorspace=YUVColorspace;
+ source_type=(cmsUInt32Number) TYPE_YUV_16;
+ source_channels=3;
+ break;
+ }
+ case cmsSigRgbData:
+ {
+ source_colorspace=RGBColorspace;
+ source_type=(cmsUInt32Number) TYPE_RGB_16;
+ source_channels=3;
+ break;
+ }
+ case cmsSigXYZData:
+ {
+ source_colorspace=XYZColorspace;
+ source_type=(cmsUInt32Number) TYPE_XYZ_16;
+ source_channels=3;
+ break;
+ }
+ case cmsSigYCbCrData:
+ {
+ source_colorspace=YCbCrColorspace;
+ source_type=(cmsUInt32Number) TYPE_YCbCr_16;
+ source_channels=3;
+ break;
+ }
+ default:
+ {
+ source_colorspace=UndefinedColorspace;
+ source_type=(cmsUInt32Number) TYPE_RGB_16;
+ source_channels=3;
+ break;
+ }
+ }
+ signature=cmsGetPCS(source_profile);
+ if (target_profile != (cmsHPROFILE) NULL)
+ signature=cmsGetColorSpace(target_profile);
+ switch (signature)
+ {
+ case cmsSigCmykData:
+ {
+ target_colorspace=CMYKColorspace;
+ target_type=(cmsUInt32Number) TYPE_CMYK_16;
+ target_channels=4;
+ break;
+ }
+ case cmsSigLabData:
+ {
+ target_colorspace=LabColorspace;
+ target_type=(cmsUInt32Number) TYPE_Lab_16;
+ target_channels=3;
+ break;
+ }
+ case cmsSigGrayData:
+ {
+ target_colorspace=GRAYColorspace;
+ target_type=(cmsUInt32Number) TYPE_GRAY_16;
+ target_channels=1;
+ break;
+ }
+ case cmsSigLuvData:
+ {
+ target_colorspace=YUVColorspace;
+ target_type=(cmsUInt32Number) TYPE_YUV_16;
+ target_channels=3;
+ break;
+ }
+ case cmsSigRgbData:
+ {
+ target_colorspace=RGBColorspace;
+ target_type=(cmsUInt32Number) TYPE_RGB_16;
+ target_channels=3;
+ break;
+ }
+ case cmsSigXYZData:
+ {
+ target_colorspace=XYZColorspace;
+ target_type=(cmsUInt32Number) TYPE_XYZ_16;
+ target_channels=3;
+ break;
+ }
+ case cmsSigYCbCrData:
+ {
+ target_colorspace=YCbCrColorspace;
+ target_type=(cmsUInt32Number) TYPE_YCbCr_16;
+ target_channels=3;
+ break;
+ }
+ default:
+ {
+ target_colorspace=UndefinedColorspace;
+ target_type=(cmsUInt32Number) TYPE_RGB_16;
+ target_channels=3;
+ break;
+ }
+ }
+ if ((source_colorspace == UndefinedColorspace) ||
+ (target_colorspace == UndefinedColorspace))
+ ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
+ name);
+ if ((source_colorspace == GRAYColorspace) &&
+ (IsImageGray(image,exception) == MagickFalse))
+ ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
+ name);
+ if ((source_colorspace == CMYKColorspace) &&
+ (image->colorspace != CMYKColorspace))
+ ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
+ name);
+ if ((source_colorspace == XYZColorspace) &&
+ (image->colorspace != XYZColorspace))
+ ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
+ name);
+ if ((source_colorspace == YCbCrColorspace) &&
+ (image->colorspace != YCbCrColorspace))
+ ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
+ name);
+ if ((source_colorspace != CMYKColorspace) &&
+ (source_colorspace != GRAYColorspace) &&
+ (source_colorspace != LabColorspace) &&
+ (source_colorspace != XYZColorspace) &&
+ (source_colorspace != YCbCrColorspace) &&
+ (image->colorspace != RGBColorspace))
+ ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
+ name);
+ switch (image->rendering_intent)
+ {
+ case AbsoluteIntent: intent=INTENT_ABSOLUTE_COLORIMETRIC; break;
+ case PerceptualIntent: intent=INTENT_PERCEPTUAL; break;
+ case RelativeIntent: intent=INTENT_RELATIVE_COLORIMETRIC; break;
+ case SaturationIntent: intent=INTENT_SATURATION; break;
+ default: intent=INTENT_PERCEPTUAL; break;
+ }
+ flags=cmsFLAGS_HIGHRESPRECALC;
+#if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
+ if (image->black_point_compensation != MagickFalse)
+ flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
+#endif
+ transform=AcquireTransformThreadSet(image,source_profile,
+ source_type,target_profile,target_type,intent,flags);
+ if (transform == (cmsHTRANSFORM *) NULL)
+ ThrowProfileException(ImageError,"UnableToCreateColorTransform",
+ name);
+ /*
+ Transform image as dictated by the source & target image profiles.
+ */
+ source_pixels=AcquirePixelThreadSet(image->columns,source_channels);
+ target_pixels=AcquirePixelThreadSet(image->columns,target_channels);
+ if ((source_pixels == (unsigned short **) NULL) ||
+ (target_pixels == (unsigned short **) NULL))
+ {
+ transform=DestroyTransformThreadSet(transform);
+ ThrowProfileException(ResourceLimitError,
+ "MemoryAllocationFailed",image->filename);
+ }
+ if (SetImageStorageClass(image,DirectClass) == MagickFalse)
+ {
+ target_pixels=DestroyPixelThreadSet(target_pixels);
+ source_pixels=DestroyPixelThreadSet(source_pixels);
+ transform=DestroyTransformThreadSet(transform);
+ if (source_profile != (cmsHPROFILE) NULL)
+ (void) cmsCloseProfile(source_profile);
+ if (target_profile != (cmsHPROFILE) NULL)
+ (void) cmsCloseProfile(target_profile);
+ return(MagickFalse);
+ }
+ if (target_colorspace == CMYKColorspace)
+ (void) SetImageColorspace(image,target_colorspace);
+ status=MagickTrue;
+ progress=0;
+ image_view=AcquireCacheView(image);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp parallel for schedule(dynamic,4) shared(status)
+#endif
+ for (y=0; y < (ssize_t) image->rows; y++)
+ {
+ const int
+ id = GetOpenMPThreadId();
+
+ MagickBooleanType
+ sync;
+
+ register ssize_t
+ x;
+
+ register Quantum
+ *restrict q;
+
+ register unsigned short
+ *p;
+
+ if (status == MagickFalse)
+ continue;
+ q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
+ exception);
+ if (q == (const Quantum *) NULL)
+ {
+ status=MagickFalse;
+ continue;
+ }
+ p=source_pixels[id];
+ for (x=0; x < (ssize_t) image->columns; x++)
+ {
+ *p++=ScaleQuantumToShort(GetPixelRed(image,q));
+ if (source_channels > 1)
+ {
+ *p++=ScaleQuantumToShort(GetPixelGreen(image,q));
+ *p++=ScaleQuantumToShort(GetPixelBlue(image,q));
+ }
+ if (source_channels > 3)
+ *p++=ScaleQuantumToShort(GetPixelBlack(image,q));
+ q+=GetPixelChannels(image);
+ }
+ cmsDoTransform(transform[id],source_pixels[id],target_pixels[id],
+ (unsigned int) image->columns);
+ p=target_pixels[id];
+ q-=image->columns;
+ for (x=0; x < (ssize_t) image->columns; x++)
+ {
+ SetPixelRed(image,ScaleShortToQuantum(*p),q);
+ SetPixelGreen(image,GetPixelRed(image,q),q);
+ SetPixelBlue(image,GetPixelRed(image,q),q);
+ p++;
+ if (target_channels > 1)
+ {
+ SetPixelGreen(image,ScaleShortToQuantum(*p),q);
+ p++;
+ SetPixelBlue(image,ScaleShortToQuantum(*p),q);
+ p++;
+ }
+ if (target_channels > 3)
+ {
+ SetPixelBlack(image,ScaleShortToQuantum(*p),q);
+ p++;
+ }
+ q+=GetPixelChannels(image);
+ }
+ sync=SyncCacheViewAuthenticPixels(image_view,exception);
+ if (sync == MagickFalse)
+ status=MagickFalse;
+ if (image->progress_monitor != (MagickProgressMonitor) NULL)
+ {
+ MagickBooleanType
+ proceed;
+
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+#pragma omp critical (MagickCore_ProfileImage)
+#endif
+ proceed=SetImageProgress(image,ProfileImageTag,progress++,
+ image->rows);
+ if (proceed == MagickFalse)
+ status=MagickFalse;
+ }
+ }
+ image_view=DestroyCacheView(image_view);
+ (void) SetImageColorspace(image,target_colorspace);
+ switch (signature)
+ {
+ case cmsSigRgbData:
+ {
+ image->type=image->matte == MagickFalse ? TrueColorType :
+ TrueColorMatteType;
+ break;
+ }
+ case cmsSigCmykData:
+ {
+ image->type=image->matte == MagickFalse ? ColorSeparationType :
+ ColorSeparationMatteType;
+ break;
+ }
+ case cmsSigGrayData:
+ {
+ image->type=image->matte == MagickFalse ? GrayscaleType :
+ GrayscaleMatteType;
+ break;
+ }
+ default:
+ break;
+ }
+ target_pixels=DestroyPixelThreadSet(target_pixels);
+ source_pixels=DestroyPixelThreadSet(source_pixels);
+ transform=DestroyTransformThreadSet(transform);
+ if (cmsGetDeviceClass(source_profile) != cmsSigLinkClass)
+ status=SetImageProfile(image,name,profile);
+ if (target_profile != (cmsHPROFILE) NULL)
+ (void) cmsCloseProfile(target_profile);
+ }
+ (void) cmsCloseProfile(source_profile);
+ }
+#endif
+ }
+ profile=DestroyStringInfo(profile);
+ return(status);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% R e m o v e I m a g e P r o f i l e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% RemoveImageProfile() removes a named profile from the image and returns its
+% value.
+%
+% The format of the RemoveImageProfile method is:
+%
+% void *RemoveImageProfile(Image *image,const char *name)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+% o name: the profile name.
+%
+*/
+MagickExport StringInfo *RemoveImageProfile(Image *image,const char *name)
+{
+ StringInfo
+ *profile;
+
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickSignature);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ if (image->profiles == (SplayTreeInfo *) NULL)
+ return((StringInfo *) NULL);
+ profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
+ image->profiles,name);
+ return(profile);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% R e s e t P r o f i l e I t e r a t o r %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ResetImageProfileIterator() resets the image profile iterator. Use it in
+% conjunction with GetNextImageProfile() to iterate over all the profiles
+% associated with an image.
+%
+% The format of the ResetImageProfileIterator method is:
+%
+% ResetImageProfileIterator(Image *image)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+*/
+MagickExport void ResetImageProfileIterator(const Image *image)
+{
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickSignature);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ if (image->profiles == (SplayTreeInfo *) NULL)
+ return;
+ ResetSplayTreeIterator((SplayTreeInfo *) image->profiles);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% S e t I m a g e P r o f i l e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% SetImageProfile() adds a named profile to the image. If a profile with the
+% same name already exists, it is replaced. This method differs from the
+% ProfileImage() method in that it does not apply CMS color profiles.
+%
+% The format of the SetImageProfile method is:
+%
+% MagickBooleanType SetImageProfile(Image *image,const char *name,
+% const StringInfo *profile)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+% o name: the profile name, for example icc, exif, and 8bim (8bim is the
+% Photoshop wrapper for iptc profiles).
+%
+% o profile: A StringInfo structure that contains the named profile.
+%
+*/
+
+static void *DestroyProfile(void *profile)
+{
+ return((void *) DestroyStringInfo((StringInfo *) profile));
+}
+
+static inline const unsigned char *ReadResourceByte(const unsigned char *p,
+ unsigned char *quantum)
+{
+ *quantum=(*p++);
+ return(p);
+}
+
+static inline const unsigned char *ReadResourceBytes(const unsigned char *p,
+ const ssize_t count,unsigned char *quantum)
+{
+ register ssize_t
+ i;
+
+ for (i=0; i < count; i++)
+ *quantum++=(*p++);
+ return(p);
+}
+
+static inline const unsigned char *ReadResourceLong(const unsigned char *p,
+ size_t *quantum)
+{
+ *quantum=(size_t) (*p++ << 24);
+ *quantum|=(size_t) (*p++ << 16);
+ *quantum|=(size_t) (*p++ << 8);
+ *quantum|=(size_t) (*p++ << 0);
+ return(p);
+}
+
+static inline const unsigned char *ReadResourceShort(const unsigned char *p,
+ unsigned short *quantum)
+{
+ *quantum=(unsigned short) (*p++ << 8);
+ *quantum|=(unsigned short) (*p++ << 0);
+ return(p);
+}
+
+static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
+ const StringInfo *resource_block)
+{
+ const unsigned char
+ *datum;
+
+ register const unsigned char
+ *p;
+
+ size_t
+ length;
+
+ StringInfo
+ *profile;
+
+ unsigned char
+ length_byte;
+
+ size_t
+ count;
+
+ unsigned short
+ id;
+
+ datum=GetStringInfoDatum(resource_block);
+ length=GetStringInfoLength(resource_block);
+ for (p=datum; p < (datum+length-16); )
+ {
+ if (LocaleNCompare((char *) p,"8BIM",4) != 0)
+ break;
+ p+=4;
+ p=ReadResourceShort(p,&id);
+ p=ReadResourceByte(p,&length_byte);
+ p+=length_byte;
+ if (((length_byte+1) & 0x01) != 0)
+ p++;
+ if (p > (datum+length-4))
+ break;
+ p=ReadResourceLong(p,&count);
+ if ((p > (datum+length-count)) || (count > length))
+ break;
+ switch (id)
+ {
+ case 0x03ed:
+ {
+ unsigned short
+ resolution;
+
+ /*
+ Resolution.
+ */
+ p=ReadResourceShort(p,&resolution)+6;
+ image->x_resolution=(double) resolution;
+ p=ReadResourceShort(p,&resolution)+6;
+ image->y_resolution=(double) resolution;
+ break;
+ }
+ case 0x0404:
+ {
+ /*
+ IPTC Profile
+ */
+ profile=AcquireStringInfo(count);
+ SetStringInfoDatum(profile,p);
+ (void) SetImageProfile(image,"iptc",profile);
+ profile=DestroyStringInfo(profile);
+ p+=count;
+ break;
+ }
+ case 0x040c:
+ {
+ /*
+ Thumbnail.
+ */
+ p+=count;
+ break;
+ }
+ case 0x040f:
+ {
+ /*
+ ICC Profile.
+ */
+ profile=AcquireStringInfo(count);
+ SetStringInfoDatum(profile,p);
+ (void) SetImageProfile(image,"icc",profile);
+ profile=DestroyStringInfo(profile);
+ p+=count;
+ break;
+ }
+ case 0x0422:
+ {
+ /*
+ EXIF Profile.
+ */
+ profile=AcquireStringInfo(count);
+ SetStringInfoDatum(profile,p);
+ (void) SetImageProfile(image,"exif",profile);
+ profile=DestroyStringInfo(profile);
+ p+=count;
+ break;
+ }
+ case 0x0424:
+ {
+ /*
+ XMP Profile.
+ */
+ profile=AcquireStringInfo(count);
+ SetStringInfoDatum(profile,p);
+ (void) SetImageProfile(image,"xmp",profile);
+ profile=DestroyStringInfo(profile);
+ p+=count;
+ break;
+ }
+ default:
+ {
+ p+=count;
+ break;
+ }
+ }
+ if ((count & 0x01) != 0)
+ p++;
+ }
+ return(MagickTrue);
+}
+
+MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name,
+ const StringInfo *profile)
+{
+ char
+ key[MaxTextExtent],
+ property[MaxTextExtent];
+
+ MagickBooleanType
+ status;
+
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickSignature);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ if (image->profiles == (SplayTreeInfo *) NULL)
+ image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
+ DestroyProfile);
+ (void) CopyMagickString(key,name,MaxTextExtent);
+ status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
+ ConstantString(key),CloneStringInfo(profile));
+ if ((status != MagickFalse) &&
+ ((LocaleCompare(name,"iptc") == 0) || (LocaleCompare(name,"8bim") == 0)))
+ (void) GetProfilesFromResourceBlock(image,profile);
+ /*
+ Inject profile into image properties.
+ */
+ (void) FormatLocaleString(property,MaxTextExtent,"%s:sans",name);
+ (void) GetImageProperty(image,property);
+ return(status);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% S y n c I m a g e P r o f i l e s %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% SyncImageProfiles() synchronizes image properties with the image profiles.
+% Currently we only support updating the EXIF resolution and orientation.
+%
+% The format of the SyncImageProfiles method is:
+%
+% MagickBooleanType SyncImageProfiles(Image *image)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+*/
+
+static inline int ReadProfileByte(unsigned char **p,size_t *length)
+{
+ int
+ c;
+
+ if (*length < 1)
+ return(EOF);
+ c=(int) (*(*p)++);
+ (*length)--;
+ return(c);
+}
+
+static inline unsigned short ReadProfileShort(const EndianType endian,
+ unsigned char *buffer)
+{
+ unsigned short
+ value;
+
+ if (endian == MSBEndian)
+ {
+ value=(unsigned short) ((((unsigned char *) buffer)[0] << 8) |
+ ((unsigned char *) buffer)[1]);
+ return((unsigned short) (value & 0xffff));
+ }
+ value=(unsigned short) ((buffer[1] << 8) | buffer[0]);
+ return((unsigned short) (value & 0xffff));
+}
+
+static inline size_t ReadProfileLong(const EndianType endian,
+ unsigned char *buffer)
+{
+ size_t
+ value;
+
+ if (endian == MSBEndian)
+ {
+ value=(size_t) ((buffer[0] << 24) | (buffer[1] << 16) |
+ (buffer[2] << 8) | buffer[3]);
+ return((size_t) (value & 0xffffffff));
+ }
+ value=(size_t) ((buffer[3] << 24) | (buffer[2] << 16) |
+ (buffer[1] << 8 ) | (buffer[0]));
+ return((size_t) (value & 0xffffffff));
+}
+
+static inline void WriteProfileLong(const EndianType endian,
+ const size_t value,unsigned char *p)
+{
+ unsigned char
+ buffer[4];
+
+ if (endian == MSBEndian)
+ {
+ buffer[0]=(unsigned char) (value >> 24);
+ buffer[1]=(unsigned char) (value >> 16);
+ buffer[2]=(unsigned char) (value >> 8);
+ buffer[3]=(unsigned char) value;
+ (void) CopyMagickMemory(p,buffer,4);
+ return;
+ }
+ buffer[0]=(unsigned char) value;
+ buffer[1]=(unsigned char) (value >> 8);
+ buffer[2]=(unsigned char) (value >> 16);
+ buffer[3]=(unsigned char) (value >> 24);
+ (void) CopyMagickMemory(p,buffer,4);
+}
+
+static void WriteProfileShort(const EndianType endian,
+ const unsigned short value,unsigned char *p)
+{
+ unsigned char
+ buffer[2];
+
+ if (endian == MSBEndian)
+ {
+ buffer[0]=(unsigned char) (value >> 8);
+ buffer[1]=(unsigned char) value;
+ (void) CopyMagickMemory(p,buffer,2);
+ return;
+ }
+ buffer[0]=(unsigned char) value;
+ buffer[1]=(unsigned char) (value >> 8);
+ (void) CopyMagickMemory(p,buffer,2);
+}
+
+MagickExport MagickBooleanType SyncImageProfiles(Image *image)
+{
+#define MaxDirectoryStack 16
+#define EXIF_DELIMITER "\n"
+#define EXIF_NUM_FORMATS 12
+#define TAG_EXIF_OFFSET 0x8769
+#define TAG_INTEROP_OFFSET 0xa005
+
+ typedef struct _DirectoryInfo
+ {
+ unsigned char
+ *directory;
+
+ size_t
+ entry;
+ } DirectoryInfo;
+
+ DirectoryInfo
+ directory_stack[MaxDirectoryStack];
+
+ EndianType
+ endian;
+
+ int
+ offset;
+
+ size_t
+ entry,
+ length,
+ number_entries;
+
+ ssize_t
+ id,
+ level;
+
+ static int
+ format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
+
+ StringInfo
+ *profile;
+
+ unsigned char
+ *directory,
+ *exif;
+
+ /*
+ Set EXIF resolution tag.
+ */
+ profile=(StringInfo *) GetImageProfile(image,"EXIF");
+ if (profile == (StringInfo *) NULL)
+ return(MagickTrue);
+ length=GetStringInfoLength(profile);
+ exif=GetStringInfoDatum(profile);
+ while (length != 0)
+ {
+ if (ReadProfileByte(&exif,&length) != 0x45)
+ continue;
+ if (ReadProfileByte(&exif,&length) != 0x78)
+ continue;
+ if (ReadProfileByte(&exif,&length) != 0x69)
+ continue;
+ if (ReadProfileByte(&exif,&length) != 0x66)
+ continue;
+ if (ReadProfileByte(&exif,&length) != 0x00)
+ continue;
+ if (ReadProfileByte(&exif,&length) != 0x00)
+ continue;
+ break;
+ }
+ if (length < 16)
+ return(MagickFalse);
+ id=(ssize_t) ReadProfileShort(LSBEndian,exif);
+ endian=LSBEndian;
+ if (id == 0x4949)
+ endian=LSBEndian;
+ else
+ if (id == 0x4D4D)
+ endian=MSBEndian;
+ else
+ return(MagickFalse);
+ if (ReadProfileShort(endian,exif+2) != 0x002a)
+ return(MagickFalse);
+ /*
+ This the offset to the first IFD.
+ */
+ offset=(int) ReadProfileLong(endian,exif+4);
+ if ((size_t) offset >= length)
+ return(MagickFalse);
+ directory=exif+offset;
+ level=0;
+ entry=0;
+ do
+ {
+ if (level > 0)
+ {
+ level--;
+ directory=directory_stack[level].directory;
+ entry=directory_stack[level].entry;
+ }
+ /*
+ Determine how many entries there are in the current IFD.
+ */
+ number_entries=ReadProfileShort(endian,directory);
+ for ( ; entry < number_entries; entry++)
+ {
+ int
+ components;
+
+ register unsigned char
+ *p,
+ *q;
+
+ size_t
+ number_bytes;
+
+ ssize_t
+ format,
+ tag_value;
+
+ q=(unsigned char *) (directory+2+(12*entry));
+ tag_value=(ssize_t) ReadProfileShort(endian,q);
+ format=(ssize_t) ReadProfileShort(endian,q+2);
+ if ((format-1) >= EXIF_NUM_FORMATS)
+ break;
+ components=(int) ReadProfileLong(endian,q+4);
+ number_bytes=(size_t) components*format_bytes[format];
+ if (number_bytes <= 4)
+ p=q+8;
+ else
+ {
+ int
+ offset;
+
+ /*
+ The directory entry contains an offset.
+ */
+ offset=(int) ReadProfileLong(endian,q+8);
+ if ((size_t) (offset+number_bytes) > length)
+ continue;
+ p=(unsigned char *) (exif+offset);
+ }
+ switch (tag_value)
+ {
+ case 0x011a:
+ {
+ (void) WriteProfileLong(endian,(size_t)
+ (image->x_resolution+0.5),p);
+ (void) WriteProfileLong(endian,1UL,p+4);
+ break;
+ }
+ case 0x011b:
+ {
+ (void) WriteProfileLong(endian,(size_t)
+ (image->y_resolution+0.5),p);
+ (void) WriteProfileLong(endian,1UL,p+4);
+ break;
+ }
+ case 0x0112:
+ {
+ (void) WriteProfileShort(endian,(unsigned short)
+ image->orientation,p);
+ break;
+ }
+ case 0x0128:
+ {
+ (void) WriteProfileShort(endian,(unsigned short)
+ (image->units+1),p);
+ break;
+ }
+ default:
+ break;
+ }
+ if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
+ {
+ size_t
+ offset;
+
+ offset=(size_t) ReadProfileLong(endian,p);
+ if ((offset < length) && (level < (MaxDirectoryStack-2)))
+ {
+ directory_stack[level].directory=directory;
+ entry++;
+ directory_stack[level].entry=entry;
+ level++;
+ directory_stack[level].directory=exif+offset;
+ directory_stack[level].entry=0;
+ level++;
+ if ((directory+2+(12*number_entries)) > (exif+length))
+ break;
+ offset=(size_t) ReadProfileLong(endian,directory+2+(12*
+ number_entries));
+ if ((offset != 0) && (offset < length) &&
+ (level < (MaxDirectoryStack-2)))
+ {
+ directory_stack[level].directory=exif+offset;
+ directory_stack[level].entry=0;
+ level++;
+ }
+ }
+ break;
+ }
+ }
+ } while (level > 0);
+ return(MagickTrue);
+}