]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/profile.c
(no commit message)
[imagemagick] / MagickCore / profile.c
index 48cb1b3ca4ab4ca188da2d639dd102dda1b637b7..60cdddc0bbe125ec25466e7889659292765c7943 100644 (file)
 #define cmsOpenProfileFromMemTHR(context,profile,length) \
   cmsOpenProfileFromMem(profile,length)
 #endif
+
+/*
+  Forward declarations
+*/
+static MagickBooleanType
+  SetImageProfileInternal(Image *,const char *,const StringInfo *,
+    const MagickBooleanType,ExceptionInfo *);
+
+static void
+  WriteTo8BimProfile(Image *,const char*,const StringInfo *);
 \f
 /*
   Typedef declarations
@@ -204,6 +214,7 @@ MagickExport MagickBooleanType DeleteImageProfile(Image *image,const char *name)
     (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
@@ -432,8 +443,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));
   }
@@ -605,7 +616,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)
@@ -661,9 +672,9 @@ MagickExport MagickBooleanType ProfileImage(Image *image,const char *name,
             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);
@@ -1024,6 +1035,7 @@ MagickExport StringInfo *RemoveImageProfile(Image *image,const char *name)
     (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);
@@ -1134,9 +1146,127 @@ static inline const unsigned char *ReadResourceShort(const unsigned char *p,
   *quantum=(unsigned short) (*p++ << 8);
   *quantum|=(unsigned short) (*p++ << 0);
   return(p);
+}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,
+    *s;
+
+  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); )
+  {
+    s=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 ((p > (datum+length-count)) || (count > length))
+      break;
+    if ((count & 0x01) != 0)
+      count++;
+    if (id == profile_id)
+      {
+        size_t
+          offset,
+          rest;
+
+        ssize_t
+          new_count;
+
+        StringInfo
+          *new_profile;
+
+        new_count=0;
+        rest=(datum+length)-(p+count);
+        if (profile == (StringInfo *) NULL)
+          {
+            offset=(s-datum);
+            new_profile=AcquireStringInfo(offset+rest);
+            (void) CopyMagickMemory(new_profile->datum,datum,offset);
+          }
+        else
+          {
+            offset=(p-datum);
+            new_count=profile->length;
+            if ((new_count & 0x01) != 0)
+              new_count++;
+            new_profile=AcquireStringInfo(offset+new_count+rest);
+            (void) CopyMagickMemory(new_profile->datum,datum,offset-4);
+            WriteResourceLong(new_profile->datum+offset-4,profile->length);
+            (void) CopyMagickMemory(new_profile->datum+offset,profile->datum,
+              profile->length);
+          }
+        (void) CopyMagickMemory(new_profile->datum+offset+new_count,p+count,
+          rest);
+        (void) AddValueToSplayTree((SplayTreeInfo *) image->profiles,
+          ConstantString("8bim"),CloneStringInfo(new_profile));
+        new_profile=DestroyStringInfo(new_profile);
+        break;
+      }
+    else
+      p+=count;
+  }
 }
 
-static MagickBooleanType GetProfilesFromResourceBlock(Image *image,
+static void GetProfilesFromResourceBlock(Image *image,
   const StringInfo *resource_block,ExceptionInfo *exception)
 {
   const unsigned char
@@ -1219,7 +1349,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;
@@ -1239,7 +1370,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;
@@ -1251,7 +1383,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;
@@ -1263,7 +1396,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;
@@ -1277,11 +1411,11 @@ 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],
@@ -1298,11 +1432,16 @@ MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name,
     image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
       DestroyProfile);
   (void) CopyMagickString(key,name,MaxTextExtent);
+  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.
   */
@@ -1310,6 +1449,12 @@ MagickExport MagickBooleanType SetImageProfile(Image *image,const char *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
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%