]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/profile.c
Handle short months in png_write_iTIME()
[imagemagick] / MagickCore / profile.c
index 4309e81d8f437b8e2f9fed72071c417b051ec5d9..2204b162352708bd7330ff8707b38feeda0fb126 100644 (file)
 %                       MagickCore Image Profile Methods                      %
 %                                                                             %
 %                              Software Design                                %
-%                                John Cristy                                  %
+%                                   Cristy                                    %
 %                                 July 1992                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2017 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                            %
+%    https://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,          %
 #include "MagickCore/configure.h"
 #include "MagickCore/exception.h"
 #include "MagickCore/exception-private.h"
-#include "MagickCore/hashmap.h"
 #include "MagickCore/image.h"
+#include "MagickCore/linked-list.h"
 #include "MagickCore/memory_.h"
 #include "MagickCore/monitor.h"
 #include "MagickCore/monitor-private.h"
 #include "MagickCore/option.h"
+#include "MagickCore/option-private.h"
 #include "MagickCore/pixel-accessor.h"
 #include "MagickCore/profile.h"
 #include "MagickCore/profile-private.h"
 #if defined(MAGICKCORE_HAVE_LCMS_LCMS2_H)
 #include <wchar.h>
 #include <lcms/lcms2.h>
-#elif defined(MAGICKCORE_HAVE_LCMS2_H)
+#else
 #include <wchar.h>
 #include "lcms2.h"
-#elif defined(MAGICKCORE_HAVE_LCMS_LCMS_H)
-#include <lcms/lcms.h>
-#else
-#include "lcms.h"
 #endif
 #endif
 \f
 /*
-  Define declarations.
+  Forward 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
+static MagickBooleanType
+  SetImageProfileInternal(Image *,const char *,const StringInfo *,
+    const MagickBooleanType,ExceptionInfo *);
+
+static void
+  WriteTo8BimProfile(Image *,const char*,const StringInfo *);
 \f
 /*
   Typedef declarations
@@ -157,14 +142,18 @@ MagickExport MagickBooleanType CloneImageProfiles(Image *image,
   const Image *clone_image)
 {
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(clone_image != (const Image *) NULL);
-  assert(clone_image->signature == MagickSignature);
+  assert(clone_image->signature == MagickCoreSignature);
   if (clone_image->profiles != (void *) NULL)
-    image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
-      (void *(*)(void *)) ConstantString,(void *(*)(void *)) CloneStringInfo);
+    {
+      if (image->profiles != (void *) NULL)
+        DestroyImageProfiles(image);
+      image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
+        (void *(*)(void *)) ConstantString,(void *(*)(void *)) CloneStringInfo);
+    }
   return(MagickTrue);
 }
 \f
@@ -195,11 +184,12 @@ MagickExport MagickBooleanType CloneImageProfiles(Image *image,
 MagickExport MagickBooleanType DeleteImageProfile(Image *image,const char *name)
 {
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if (image->profiles == (SplayTreeInfo *) NULL)
     return(MagickFalse);
+  WriteTo8BimProfile(image,name,(StringInfo *) NULL);
   return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->profiles,name));
 }
 \f
@@ -258,21 +248,17 @@ MagickExport void DestroyImageProfiles(Image *image)
 MagickExport const StringInfo *GetImageProfile(const Image *image,
   const char *name)
 {
-  char
-    key[MaxTextExtent];
-
   const StringInfo
     *profile;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   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);
+    image->profiles,name);
   return(profile);
 }
 \f
@@ -301,7 +287,7 @@ MagickExport const StringInfo *GetImageProfile(const Image *image,
 MagickExport char *GetNextImageProfile(const Image *image)
 {
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if (image->profiles == (SplayTreeInfo *) NULL)
@@ -351,7 +337,6 @@ MagickExport char *GetNextImageProfile(const Image *image)
 */
 
 #if defined(MAGICKCORE_LCMS_DELEGATE)
-
 static unsigned short **DestroyPixelThreadSet(unsigned short **pixels)
 {
   register ssize_t
@@ -377,7 +362,7 @@ static unsigned short **AcquirePixelThreadSet(const size_t columns,
   size_t
     number_threads;
 
-  number_threads=GetMagickResourceLimit(ThreadResource);
+  number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
   pixels=(unsigned short **) AcquireQuantumMemory(number_threads,
     sizeof(*pixels));
   if (pixels == (unsigned short **) NULL)
@@ -420,7 +405,7 @@ static cmsHTRANSFORM *AcquireTransformThreadSet(Image *image,
   size_t
     number_threads;
 
-  number_threads=GetMagickResourceLimit(ThreadResource);
+  number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
   transform=(cmsHTRANSFORM *) AcquireQuantumMemory(number_threads,
     sizeof(*transform));
   if (transform == (cmsHTRANSFORM *) NULL)
@@ -428,8 +413,8 @@ static cmsHTRANSFORM *AcquireTransformThreadSet(Image *image,
   (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);
+    transform[i]=cmsCreateTransformTHR((cmsContext) image,source_profile,
+      source_type,target_profile,target_type,intent,flags);
     if (transform[i] == (cmsHTRANSFORM) NULL)
       return(DestroyTransformThreadSet(transform));
   }
@@ -438,7 +423,6 @@ static cmsHTRANSFORM *AcquireTransformThreadSet(Image *image,
 #endif
 
 #if defined(MAGICKCORE_LCMS_DELEGATE)
-#if defined(LCMS_VERSION) && (LCMS_VERSION >= 2000)
 static void CMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
   const char *message)
 {
@@ -452,29 +436,318 @@ static void CMSExceptionHandler(cmsContext context,cmsUInt32Number severity,
     *image;
 
   cms_exception=(CMSExceptionInfo *) context;
-  image=cms_exception->image;
+  if (cms_exception == (CMSExceptionInfo *) NULL)
+    return;
   exception=cms_exception->exception;
+  if (exception == (ExceptionInfo *) NULL)
+    return;
+  image=cms_exception->image;
   if (image == (Image *) NULL)
     {
       (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
-        "UnableToTransformColorspace","'%s'","unknown context");
+        "UnableToTransformColorspace","`%s'","unknown context");
       return;
     }
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%u, %s",
       severity,message != (char *) NULL ? message : "no message");
   (void) ThrowMagickException(exception,GetMagickModule(),ImageWarning,
-    "UnableToTransformColorspace","'%s'",image->filename);
+    "UnableToTransformColorspace","`%s'",image->filename);
 }
-#else
-static int CMSExceptionHandler(int severity,const char *message)
+#endif
+
+static MagickBooleanType SetsRGBImageProfile(Image *image,
+  ExceptionInfo *exception)
 {
-  (void) LogMagickEvent(TransformEvent,GetMagickModule(),"lcms: #%d, %s",
-    severity,message != (char *) NULL ? message : "no message");
-  return(1);
+  static unsigned char
+    sRGBProfile[] =
+    {
+      0x00, 0x00, 0x0c, 0x8c, 0x61, 0x72, 0x67, 0x6c, 0x02, 0x20, 0x00, 0x00,
+      0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
+      0x07, 0xde, 0x00, 0x01, 0x00, 0x06, 0x00, 0x16, 0x00, 0x0f, 0x00, 0x3a,
+      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, 0x61, 0x72, 0x67, 0x6c,
+      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,
+      0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x99,
+      0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0xec, 0x00, 0x00, 0x00, 0x67,
+      0x64, 0x6d, 0x6e, 0x64, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70,
+      0x64, 0x6d, 0x64, 0x64, 0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88,
+      0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x0c,
+      0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x00, 0x67,
+      0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x24,
+      0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xe4, 0x00, 0x00, 0x00, 0x14,
+      0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x24,
+      0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x14,
+      0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x14,
+      0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x14,
+      0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x58, 0x00, 0x00, 0x00, 0x14,
+      0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x04, 0x6c, 0x00, 0x00, 0x00, 0x14,
+      0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
+      0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
+      0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x08, 0x0c,
+      0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+      0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36,
+      0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75, 0x69, 0x76,
+      0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x77, 0x77,
+      0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x31, 0x39,
+      0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c,
+      0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x3f, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31,
+      0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x28, 0x45, 0x71, 0x75,
+      0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77,
+      0x77, 0x77, 0x2e, 0x73, 0x72, 0x67, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x20,
+      0x31, 0x39, 0x39, 0x38, 0x20, 0x48, 0x50, 0x20, 0x70, 0x72, 0x6f, 0x66,
+      0x69, 0x6c, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x72, 0x65, 0x61,
+      0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x72, 0x61, 0x65, 0x6d,
+      0x65, 0x20, 0x57, 0x2e, 0x20, 0x47, 0x69, 0x6c, 0x6c, 0x2e, 0x20, 0x52,
+      0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f,
+      0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
+      0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x4e, 0x6f, 0x20, 0x57,
+      0x61, 0x72, 0x72, 0x61, 0x6e, 0x74, 0x79, 0x2c, 0x20, 0x55, 0x73, 0x65,
+      0x20, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e,
+      0x20, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x00, 0x00, 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, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00,
+      0x43, 0x52, 0x54, 0x20, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x0d, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36,
+      0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x0d, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa4, 0x7c,
+      0x00, 0x14, 0x5f, 0x30, 0x00, 0x10, 0xce, 0x02, 0x00, 0x03, 0xed, 0xb2,
+      0x00, 0x04, 0x13, 0x0a, 0x00, 0x03, 0x5c, 0x67, 0x00, 0x00, 0x00, 0x01,
+      0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x0a, 0x3d,
+      0x00, 0x50, 0x00, 0x00, 0x00, 0x57, 0x1e, 0xb8, 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, 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, 0xa0,
+      0x00, 0x00, 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x97, 0x00, 0x00, 0xb7, 0x87,
+      0x00, 0x00, 0x18, 0xd9, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x24, 0x9f, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0xb6, 0xc4,
+      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 == MagickCoreSignature);
+  if (GetImageProfile(image,"icc") != (const StringInfo *) NULL)
+    return(MagickFalse);
+  profile=AcquireStringInfo(sizeof(sRGBProfile));
+  SetStringInfoDatum(profile,sRGBProfile);
+  status=SetImageProfile(image,"icc",profile,exception);
+  profile=DestroyStringInfo(profile);
+  return(status);
 }
-#endif
-#endif
 
 MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
   const void *datum,const size_t length,ExceptionInfo *exception)
@@ -496,50 +769,28 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
     *profile;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   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;
+        *next;
 
       /*
         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 (next=GetNextImageProfile(image); next != (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);
-              break;
-            }
-        }
-        name=GetNextImageProfile(image);
+        if (IsOptionMember(next,name) != MagickFalse)
+          {
+            (void) DeleteImageProfile(image,next);
+            ResetImageProfileIterator(image);
+          }
+        next=GetNextImageProfile(image);
       }
-      for (i=0; i < (ssize_t) number_arguments; i++)
-        arguments[i]=DestroyString(arguments[i]);
-      arguments=(char **) RelinquishMagickMemory(arguments);
       return(MagickTrue);
     }
   /*
@@ -564,12 +815,12 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
 
           value=GetImageProperty(image,"exif:ColorSpace",exception);
           (void) value;
-          /* Future.
           if (LocaleCompare(value,"1") != 0)
             (void) SetsRGBImageProfile(image,exception);
           value=GetImageProperty(image,"exif:InteroperabilityIndex",exception);
           if (LocaleCompare(value,"R98.") != 0)
             (void) SetsRGBImageProfile(image,exception);
+          /* Future.
           value=GetImageProperty(image,"exif:InteroperabilityIndex",exception);
           if (LocaleCompare(value,"R03.") != 0)
             (void) SetAdobeRGB1998ImageProfile(image,exception);
@@ -601,7 +852,7 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
         cms_exception.image=image;
         cms_exception.exception=exception;
         (void) cms_exception;
-        source_profile=cmsOpenProfileFromMemTHR(&cms_exception,
+        source_profile=cmsOpenProfileFromMemTHR((cmsContext) &cms_exception,
           GetStringInfoDatum(profile),(cmsUInt32Number)
           GetStringInfoLength(profile));
         if (source_profile == (cmsHPROFILE) NULL)
@@ -626,7 +877,7 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
               target_profile;
 
             cmsHTRANSFORM
-              *restrict transform;
+              *magick_restrict transform;
 
             cmsUInt32Number
               flags,
@@ -636,9 +887,6 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
             int
               intent;
 
-            MagickBooleanType
-              status;
-
             MagickOffsetType
               progress;
 
@@ -650,16 +898,16 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
               y;
 
             unsigned short
-              **restrict source_pixels,
-              **restrict target_pixels;
+              **magick_restrict source_pixels,
+              **magick_restrict target_pixels;
 
             target_profile=(cmsHPROFILE) NULL;
             if (icc_profile != (StringInfo *) NULL)
               {
                 target_profile=source_profile;
-                source_profile=cmsOpenProfileFromMemTHR(&cms_exception,
-                  GetStringInfoDatum(icc_profile),(cmsUInt32Number)
-                  GetStringInfoLength(icc_profile));
+                source_profile=cmsOpenProfileFromMemTHR((cmsContext)
+                  &cms_exception,GetStringInfoDatum(icc_profile),
+                  (cmsUInt32Number) GetStringInfoLength(icc_profile));
                 if (source_profile == (cmsHPROFILE) NULL)
                   ThrowProfileException(ResourceLimitError,
                     "ColorspaceColorProfileMismatch",name);
@@ -790,7 +1038,7 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
               ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
                 name);
              if ((source_colorspace == GRAYColorspace) &&
-                 (IsImageGray(image,exception) == MagickFalse))
+                 (SetImageGray(image,exception) == MagickFalse))
               ThrowProfileException(ImageError,"ColorspaceColorProfileMismatch",
                 name);
              if ((source_colorspace == CMYKColorspace) &&
@@ -855,12 +1103,11 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
               }
             if (target_colorspace == CMYKColorspace)
               (void) SetImageColorspace(image,target_colorspace,exception);
-            status=MagickTrue;
             progress=0;
             image_view=AcquireAuthenticCacheView(image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
             #pragma omp parallel for schedule(static,4) shared(status) \
-              dynamic_number_threads(image,image->columns,image->rows,1)
+              magick_threads(image,image,image->rows,1)
 #endif
             for (y=0; y < (ssize_t) image->rows; y++)
             {
@@ -874,7 +1121,7 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
                 x;
 
               register Quantum
-                *restrict q;
+                *magick_restrict q;
 
               register unsigned short
                 *p;
@@ -904,7 +1151,7 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
               cmsDoTransform(transform[id],source_pixels[id],target_pixels[id],
                 (unsigned int) image->columns);
               p=target_pixels[id];
-              q-=image->columns*GetPixelChannels(image);
+              q-=GetPixelChannels(image)*image->columns;
               for (x=0; x < (ssize_t) image->columns; x++)
               {
                 if (target_channels == 1)
@@ -949,20 +1196,20 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
             {
               case cmsSigRgbData:
               {
-                image->type=image->matte == MagickFalse ? TrueColorType :
-                  TrueColorMatteType;
+                image->type=image->alpha_trait == UndefinedPixelTrait ?
+                  TrueColorType : TrueColorAlphaType;
                 break;
               }
               case cmsSigCmykData:
               {
-                image->type=image->matte == MagickFalse ? ColorSeparationType :
-                  ColorSeparationMatteType;
+                image->type=image->alpha_trait == UndefinedPixelTrait ?
+                  ColorSeparationType : ColorSeparationAlphaType;
                 break;
               }
               case cmsSigGrayData:
               {
-                image->type=image->matte == MagickFalse ? GrayscaleType :
-                  GrayscaleMatteType;
+                image->type=image->alpha_trait == UndefinedPixelTrait ?
+                  GrayscaleType : GrayscaleAlphaType;
                 break;
               }
               default:
@@ -971,7 +1218,8 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
             target_pixels=DestroyPixelThreadSet(target_pixels);
             source_pixels=DestroyPixelThreadSet(source_pixels);
             transform=DestroyTransformThreadSet(transform);
-            if (cmsGetDeviceClass(source_profile) != cmsSigLinkClass)
+            if ((status != MagickFalse) &&
+                (cmsGetDeviceClass(source_profile) != cmsSigLinkClass))
               status=SetImageProfile(image,name,profile,exception);
             if (target_profile != (cmsHPROFILE) NULL)
               (void) cmsCloseProfile(target_profile);
@@ -1015,11 +1263,12 @@ MagickExport StringInfo *RemoveImageProfile(Image *image,const char *name)
     *profile;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if (image->profiles == (SplayTreeInfo *) NULL)
     return((StringInfo *) NULL);
+  WriteTo8BimProfile(image,name,(StringInfo *) NULL);
   profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *)
     image->profiles,name);
   return(profile);
@@ -1052,7 +1301,7 @@ MagickExport StringInfo *RemoveImageProfile(Image *image,const char *name)
 MagickExport void ResetImageProfileIterator(const Image *image)
 {
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if (image->profiles == (SplayTreeInfo *) NULL)
@@ -1103,36 +1352,148 @@ static inline const unsigned char *ReadResourceByte(const unsigned char *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)
+  unsigned int *quantum)
 {
-  *quantum=(size_t) (*p++ << 24);
-  *quantum|=(size_t) (*p++ << 16);
-  *quantum|=(size_t) (*p++ << 8);
-  *quantum|=(size_t) (*p++ << 0);
+  *quantum=(unsigned int) (*p++) << 24;
+  *quantum|=(unsigned int) (*p++) << 16;
+  *quantum|=(unsigned int) (*p++) << 8;
+  *quantum|=(unsigned int) (*p++);
   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);
+  *quantum=(unsigned short) (*p++) << 8;
+  *quantum|=(unsigned short) (*p++);
   return(p);
 }
 
-static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
+static inline void WriteResourceLong(unsigned char *p,
+  const unsigned int quantum)
+{
+  unsigned char
+    buffer[4];
+
+  buffer[0]=(unsigned char) (quantum >> 24);
+  buffer[1]=(unsigned char) (quantum >> 16);
+  buffer[2]=(unsigned char) (quantum >> 8);
+  buffer[3]=(unsigned char) quantum;
+  (void) CopyMagickMemory(p,buffer,4);
+}
+
+static void WriteTo8BimProfile(Image *image,const char *name,
+  const StringInfo *profile)
+{
+  const unsigned char
+    *datum,
+    *q;
+
+  register const unsigned char
+    *p;
+
+  size_t
+    length;
+
+  StringInfo
+    *profile_8bim;
+
+  ssize_t
+    count;
+
+  unsigned char
+    length_byte;
+
+  unsigned int
+    value;
+
+  unsigned short
+    id,
+    profile_id;
+
+  if (LocaleCompare(name,"icc") == 0)
+    profile_id=0x040f;
+  else
+    if (LocaleCompare(name,"iptc") == 0)
+      profile_id=0x0404;
+    else
+      if (LocaleCompare(name,"xmp") == 0)
+        profile_id=0x0424;
+      else
+        return;
+  profile_8bim=(StringInfo *) GetValueFromSplayTree((SplayTreeInfo *)
+    image->profiles,"8bim");
+  if (profile_8bim == (StringInfo *) NULL)
+    return;
+  datum=GetStringInfoDatum(profile_8bim);
+  length=GetStringInfoLength(profile_8bim);
+  for (p=datum; p < (datum+length-16); )
+  {
+    q=p;
+    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,&value);
+    count=(ssize_t) value;
+    if ((count & 0x01) != 0)
+      count++;
+    if ((count < 0) || (p > (datum+length-count)) ||
+        (count > (ssize_t) length))
+      break;
+    if (id != profile_id)
+      p+=count;
+    else
+      {
+        size_t
+          extent,
+          offset;
+
+        ssize_t
+          extract_extent;
+
+        StringInfo
+          *extract_profile;
+
+        extract_extent=0;
+        extent=(datum+length)-(p+count);
+        if (profile == (StringInfo *) NULL)
+          {
+            offset=(q-datum);
+            extract_profile=AcquireStringInfo(offset+extent);
+            (void) CopyMagickMemory(extract_profile->datum,datum,offset);
+          }
+        else
+          {
+            offset=(p-datum);
+            extract_extent=profile->length;
+            if ((extract_extent & 0x01) != 0)
+              extract_extent++;
+            extract_profile=AcquireStringInfo(offset+extract_extent+extent);
+            (void) CopyMagickMemory(extract_profile->datum,datum,offset-4);
+            WriteResourceLong(extract_profile->datum+offset-4,(unsigned int)
+              profile->length);
+            (void) CopyMagickMemory(extract_profile->datum+offset,
+              profile->datum,profile->length);
+          }
+        (void) CopyMagickMemory(extract_profile->datum+offset+extract_extent,
+          p+count,extent);
+        (void) AddValueToSplayTree((SplayTreeInfo *) image->profiles,
+          ConstantString("8bim"),CloneStringInfo(extract_profile));
+        extract_profile=DestroyStringInfo(extract_profile);
+        break;
+      }
+  }
+}
+
+static void GetProfilesFromResourceBlock(Image *image,
   const StringInfo *resource_block,ExceptionInfo *exception)
 {
   const unsigned char
@@ -1144,14 +1505,17 @@ static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
   size_t
     length;
 
+  ssize_t
+    count;
+
   StringInfo
     *profile;
 
   unsigned char
     length_byte;
 
-  size_t
-    count;
+  unsigned int
+    value;
 
   unsigned short
     id;
@@ -1170,23 +1534,40 @@ static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
       p++;
     if (p > (datum+length-4))
       break;
-    p=ReadResourceLong(p,&count);
-    if ((p > (datum+length-count)) || (count > length))
+    p=ReadResourceLong(p,&value);
+    count=(ssize_t) value;
+    if ((p > (datum+length-count)) || (count > (ssize_t) length) ||
+        (count < 0))
       break;
     switch (id)
     {
       case 0x03ed:
       {
-        unsigned short
+        unsigned int
           resolution;
 
+        unsigned short
+          units;
+
         /*
           Resolution.
         */
-        p=ReadResourceShort(p,&resolution)+6;
-        image->resolution.x=(double) resolution;
-        p=ReadResourceShort(p,&resolution)+6;
-        image->resolution.y=(double) resolution;
+        p=ReadResourceLong(p,&resolution);
+        image->resolution.x=((double) resolution)/65536.0;
+        p=ReadResourceShort(p,&units)+2;
+        p=ReadResourceLong(p,&resolution)+4;
+        image->resolution.y=((double) resolution)/65536.0;
+        /*
+          Values are always stored as pixels per inch.
+        */
+        if ((ResolutionType) units != PixelsPerCentimeterResolution)
+          image->units=PixelsPerInchResolution;
+        else
+          {
+            image->units=PixelsPerCentimeterResolution;
+            image->resolution.x/=2.54;
+            image->resolution.y/=2.54;
+          }
         break;
       }
       case 0x0404:
@@ -1196,7 +1577,8 @@ static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
         */
         profile=AcquireStringInfo(count);
         SetStringInfoDatum(profile,p);
-        (void) SetImageProfile(image,"iptc",profile,exception);
+        (void) SetImageProfileInternal(image,"iptc",profile,MagickTrue,
+          exception);
         profile=DestroyStringInfo(profile);
         p+=count;
         break;
@@ -1216,7 +1598,8 @@ static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
         */
         profile=AcquireStringInfo(count);
         SetStringInfoDatum(profile,p);
-        (void) SetImageProfile(image,"icc",profile,exception);
+        (void) SetImageProfileInternal(image,"icc",profile,MagickTrue,
+          exception);
         profile=DestroyStringInfo(profile);
         p+=count;
         break;
@@ -1228,7 +1611,8 @@ static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
         */
         profile=AcquireStringInfo(count);
         SetStringInfoDatum(profile,p);
-        (void) SetImageProfile(image,"exif",profile,exception);
+        (void) SetImageProfileInternal(image,"exif",profile,MagickTrue,
+          exception);
         profile=DestroyStringInfo(profile);
         p+=count;
         break;
@@ -1240,7 +1624,8 @@ static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
         */
         profile=AcquireStringInfo(count);
         SetStringInfoDatum(profile,p);
-        (void) SetImageProfile(image,"xmp",profile,exception);
+        (void) SetImageProfileInternal(image,"xmp",profile,MagickTrue,
+          exception);
         profile=DestroyStringInfo(profile);
         p+=count;
         break;
@@ -1254,39 +1639,51 @@ static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
     if ((count & 0x01) != 0)
       p++;
   }
-  return(MagickTrue);
 }
 
-MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name,
-  const StringInfo *profile,ExceptionInfo *exception)
+static MagickBooleanType SetImageProfileInternal(Image *image,const char *name,
+  const StringInfo *profile,const MagickBooleanType recursive,
+  ExceptionInfo *exception)
 {
   char
-    key[MaxTextExtent],
-    property[MaxTextExtent];
+    key[MagickPathExtent],
+    property[MagickPathExtent];
 
   MagickBooleanType
     status;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   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);
+  (void) CopyMagickString(key,name,MagickPathExtent);
+  LocaleLower(key);
   status=AddValueToSplayTree((SplayTreeInfo *) image->profiles,
     ConstantString(key),CloneStringInfo(profile));
-  if ((status != MagickFalse) &&
-      ((LocaleCompare(name,"iptc") == 0) || (LocaleCompare(name,"8bim") == 0)))
-    (void) GetProfilesFromResourceBlock(image,profile,exception);
+  if (status != MagickFalse)
+    {
+      if (LocaleCompare(name,"8bim") == 0)
+        GetProfilesFromResourceBlock(image,profile,exception);
+      else
+        if (recursive == MagickFalse)
+          WriteTo8BimProfile(image,name,profile);
+    }
   /*
     Inject profile into image properties.
   */
-  (void) FormatLocaleString(property,MaxTextExtent,"%s:sans",name);
+  (void) FormatLocaleString(property,MagickPathExtent,"%s:*",name);
   (void) GetImageProperty(image,property,exception);
   return(status);
 }
+
+MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name,
+  const StringInfo *profile,ExceptionInfo *exception)
+{
+  return(SetImageProfileInternal(image,name,profile,MagickFalse,exception));
+}
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1324,37 +1721,91 @@ static inline int ReadProfileByte(unsigned char **p,size_t *length)
   return(c);
 }
 
-static inline unsigned short ReadProfileShort(const EndianType endian,
+static inline signed short ReadProfileShort(const EndianType endian,
   unsigned char *buffer)
 {
+  union
+  {
+    unsigned int
+      unsigned_value;
+
+    signed int
+      signed_value;
+  } quantum;
+
   unsigned short
     value;
 
-  if (endian == MSBEndian)
+  if (endian == LSBEndian)
     {
-      value=(unsigned short) ((((unsigned char *) buffer)[0] << 8) |
-        ((unsigned char *) buffer)[1]);
-      return((unsigned short) (value & 0xffff));
+      value=(unsigned short) buffer[1] << 8;
+      value|=(unsigned short) buffer[0];
+      quantum.unsigned_value=value & 0xffff;
+      return(quantum.signed_value);
     }
-  value=(unsigned short) ((buffer[1] << 8) | buffer[0]);
-  return((unsigned short) (value & 0xffff));
+  value=(unsigned short) buffer[0] << 8;
+  value|=(unsigned short) buffer[1];
+  quantum.unsigned_value=value & 0xffff;
+  return(quantum.signed_value);
 }
 
-static inline size_t ReadProfileLong(const EndianType endian,
+static inline signed int ReadProfileLong(const EndianType endian,
   unsigned char *buffer)
 {
-  size_t
+  union
+  {
+    unsigned int
+      unsigned_value;
+
+    signed int
+      signed_value;
+  } quantum;
+
+  unsigned int
     value;
 
-  if (endian == MSBEndian)
+  if (endian == LSBEndian)
     {
-      value=(size_t) ((buffer[0] << 24) | (buffer[1] << 16) |
-        (buffer[2] << 8) | buffer[3]);
-      return((size_t) (value & 0xffffffff));
+      value=(unsigned int) buffer[3] << 24;
+      value|=(unsigned int) buffer[2] << 16;
+      value|=(unsigned int) buffer[1] << 8;
+      value|=(unsigned int) buffer[0];
+      quantum.unsigned_value=value & 0xffffffff;
+      return(quantum.signed_value);
     }
-  value=(size_t) ((buffer[3] << 24) | (buffer[2] << 16) |
-    (buffer[1] << 8 ) | (buffer[0]));
-  return((size_t) (value & 0xffffffff));
+  value=(unsigned int) buffer[0] << 24;
+  value|=(unsigned int) buffer[1] << 16;
+  value|=(unsigned int) buffer[2] << 8;
+  value|=(unsigned int) buffer[3];
+  quantum.unsigned_value=value & 0xffffffff;
+  return(quantum.signed_value);
+}
+
+static inline signed int ReadProfileMSBLong(unsigned char **p,size_t *length)
+{
+  signed int
+    value;
+
+  if (*length < 4)
+    return(0);
+  value=ReadProfileLong(MSBEndian,*p);
+  (*length)-=4;
+  *p+=4;
+  return(value);
+}
+
+static inline signed short ReadProfileMSBShort(unsigned char **p,
+  size_t *length)
+{
+  signed short
+    value;
+
+  if (*length < 2)
+    return(0);
+  value=ReadProfileShort(MSBEndian,*p);
+  (*length)-=2;
+  *p+=2;
+  return(value);
 }
 
 static inline void WriteProfileLong(const EndianType endian,
@@ -1363,19 +1814,19 @@ static inline void WriteProfileLong(const EndianType endian,
   unsigned char
     buffer[4];
 
-  if (endian == MSBEndian)
+  if (endian == LSBEndian)
     {
-      buffer[0]=(unsigned char) (value >> 24);
-      buffer[1]=(unsigned char) (value >> 16);
-      buffer[2]=(unsigned char) (value >> 8);
-      buffer[3]=(unsigned char) value;
+      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);
       return;
     }
-  buffer[0]=(unsigned char) value;
-  buffer[1]=(unsigned char) (value >> 8);
-  buffer[2]=(unsigned char) (value >> 16);
-  buffer[3]=(unsigned char) (value >> 24);
+  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);
 }
 
@@ -1385,19 +1836,80 @@ static void WriteProfileShort(const EndianType endian,
   unsigned char
     buffer[2];
 
-  if (endian == MSBEndian)
+  if (endian == LSBEndian)
     {
-      buffer[0]=(unsigned char) (value >> 8);
-      buffer[1]=(unsigned char) value;
+      buffer[0]=(unsigned char) value;
+      buffer[1]=(unsigned char) (value >> 8);
       (void) CopyMagickMemory(p,buffer,2);
       return;
     }
-  buffer[0]=(unsigned char) value;
-  buffer[1]=(unsigned char) (value >> 8);
+  buffer[0]=(unsigned char) (value >> 8);
+  buffer[1]=(unsigned char) value;
   (void) CopyMagickMemory(p,buffer,2);
 }
 
-MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
+static MagickBooleanType Sync8BimProfile(Image *image,StringInfo *profile)
+{
+  size_t
+    length;
+
+  ssize_t
+    count;
+
+  unsigned char
+    *p;
+
+  unsigned short
+    id;
+
+  length=GetStringInfoLength(profile);
+  p=GetStringInfoDatum(profile);
+  while (length != 0)
+  {
+    if (ReadProfileByte(&p,&length) != 0x38)
+      continue;
+    if (ReadProfileByte(&p,&length) != 0x42)
+      continue;
+    if (ReadProfileByte(&p,&length) != 0x49)
+      continue;
+    if (ReadProfileByte(&p,&length) != 0x4D)
+      continue;
+    if (length < 7)
+      return(MagickFalse);
+    id=ReadProfileMSBShort(&p,&length);
+    count=(ssize_t) ReadProfileByte(&p,&length);
+    if ((count > (ssize_t) length) || (count < 0))
+      return(MagickFalse);
+    p+=count;
+    if ((*p & 0x01) == 0)
+      (void) ReadProfileByte(&p,&length);
+    count=(ssize_t) ReadProfileMSBLong(&p,&length);
+    if ((count > (ssize_t) length) || (count < 0))
+      return(MagickFalse);
+    if ((id == 0x3ED) && (count == 16))
+      {
+        if (image->units == PixelsPerCentimeterResolution)
+          WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.x*2.54*
+            65536.0),p);
+        else
+          WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.x*
+            65536.0),p);
+        WriteProfileShort(MSBEndian,(unsigned short) image->units,p+4);
+        if (image->units == PixelsPerCentimeterResolution)
+          WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.y*2.54*
+            65536.0),p+8);
+        else
+          WriteProfileLong(MSBEndian,(unsigned int) (image->resolution.y*
+            65536.0),p+8);
+        WriteProfileShort(MSBEndian,(unsigned short) image->units,p+12);
+      }
+    p+=count;
+    length-=count;
+  }
+  return(MagickTrue);
+}
+
+MagickBooleanType SyncExifProfile(Image *image,StringInfo *profile)
 {
 #define MaxDirectoryStack  16
 #define EXIF_DELIMITER  "\n"
@@ -1425,6 +1937,9 @@ MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
     length,
     number_entries;
 
+  SplayTreeInfo
+    *exif_resources;
+
   ssize_t
     id,
     level,
@@ -1433,9 +1948,6 @@ MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
   static int
     format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
 
-  StringInfo
-    *profile;
-
   unsigned char
     *directory,
     *exif;
@@ -1443,30 +1955,33 @@ MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
   /*
     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);
+  if ((id != 0x4949) && (id != 0x4D4D))
+    {
+      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;
@@ -1480,12 +1995,14 @@ MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
   /*
     This the offset to the first IFD.
   */
-  offset=(ssize_t) ((int) ReadProfileLong(endian,exif+4));
-  if ((offset < 0) || (size_t) offset >= length)
+  offset=(ssize_t) ReadProfileLong(endian,exif+4);
+  if ((offset < 0) || ((size_t) offset >= length))
     return(MagickFalse);
   directory=exif+offset;
   level=0;
   entry=0;
+  exif_resources=NewSplayTree((int (*)(const void *,const void *)) NULL,
+    (void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
   do
   {
     if (level > 0)
@@ -1494,6 +2011,8 @@ MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
         directory=directory_stack[level].directory;
         entry=directory_stack[level].entry;
       }
+    if ((directory < exif) || (directory > (exif+length-2)))
+      break;
     /*
       Determine how many entries there are in the current IFD.
     */
@@ -1515,11 +2034,18 @@ MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
         tag_value;
 
       q=(unsigned char *) (directory+2+(12*entry));
+      if (q > (exif+length-12))
+        break;  /* corrupt EXIF */
+      if (GetValueFromSplayTree(exif_resources,q) == q)
+        break;
+      (void) AddValueToSplayTree(exif_resources,q,q);
       tag_value=(ssize_t) ReadProfileShort(endian,q);
       format=(ssize_t) ReadProfileShort(endian,q+2);
-      if ((format-1) >= EXIF_NUM_FORMATS)
+      if ((format < 0) || ((format-1) >= EXIF_NUM_FORMATS))
         break;
-      components=(ssize_t) ((int) ReadProfileLong(endian,q+4));
+      components=(int) ReadProfileLong(endian,q+4);
+      if (components < 0)
+        break;  /* corrupt EXIF */
       number_bytes=(size_t) components*format_bytes[format];
       if ((ssize_t) number_bytes < components)
         break;  /* prevent overflow */
@@ -1527,14 +2053,11 @@ MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
         p=q+8;
       else
         {
-          ssize_t
-            offset;
-
           /*
             The directory entry contains an offset.
           */
-          offset=(ssize_t) ((int) ReadProfileLong(endian,q+8));
-          if ((size_t) (offset+number_bytes) > length)
+          offset=(ssize_t) ReadProfileLong(endian,q+8);
+          if ((offset < 0) || ((size_t) (offset+number_bytes) > length))
             continue;
           if (~length < number_bytes)
             continue;  /* prevent overflow */
@@ -1580,10 +2103,7 @@ MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
       }
       if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == TAG_INTEROP_OFFSET))
         {
-          ssize_t
-            offset;
-
-          offset=(ssize_t) ((int) ReadProfileLong(endian,p));
+          offset=(ssize_t) ReadProfileLong(endian,p);
           if (((size_t) offset < length) && (level < (MaxDirectoryStack-2)))
             {
               directory_stack[level].directory=directory;
@@ -1595,8 +2115,8 @@ MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
               level++;
               if ((directory+2+(12*number_entries)) > (exif+length))
                 break;
-              offset=(ssize_t) ((int) ReadProfileLong(endian,directory+2+(12*
-                number_entries)));
+              offset=(ssize_t) ReadProfileLong(endian,directory+2+(12*
+                number_entries));
               if ((offset != 0) && ((size_t) offset < length) &&
                   (level < (MaxDirectoryStack-2)))
                 {
@@ -1609,5 +2129,26 @@ MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
         }
     }
   } while (level > 0);
+  exif_resources=DestroySplayTree(exif_resources);
   return(MagickTrue);
 }
+
+MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
+{
+  MagickBooleanType
+    status;
+
+  StringInfo
+    *profile;
+
+  status=MagickTrue;
+  profile=(StringInfo *) GetImageProfile(image,"8BIM");
+  if (profile != (StringInfo *) NULL)
+    if (Sync8BimProfile(image,profile) == MagickFalse)
+      status=MagickFalse;
+  profile=(StringInfo *) GetImageProfile(image,"EXIF");
+  if (profile != (StringInfo *) NULL)
+    if (SyncExifProfile(image,profile) == MagickFalse)
+      status=MagickFalse;
+  return(status);
+}