]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/property.c
(no commit message)
[imagemagick] / MagickCore / property.c
index 973ca89206316cc1e6bf4d51a6869bceaa869f00..9868e822caf2b5b2c1b0e4197b4dace34c2b62bd 100644 (file)
 %                         MagickCore Property Methods                         %
 %                                                                             %
 %                              Software Design                                %
-%                                John Cristy                                  %
+%                                   Cristy                                    %
 %                                 March 2000                                  %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2014 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  %
@@ -36,7 +36,8 @@
 %
 %
 */
-\f
+
+
 /*
   Include declarations.
 */
 #include "MagickCore/version.h"
 #include "MagickCore/xml-tree.h"
 #include "MagickCore/xml-tree-private.h"
+#if defined(MAGICKCORE_LCMS_DELEGATE)
+#if defined(MAGICKCORE_HAVE_LCMS_LCMS2_H)
+#include <lcms/lcms2.h>
+#elif defined(MAGICKCORE_HAVE_LCMS2_H)
+#include "lcms2.h"
+#elif defined(MAGICKCORE_HAVE_LCMS_LCMS_H)
+#include <lcms/lcms.h>
+#else
+#include "lcms.h"
+#endif
+#endif
+\f
+/*
+  Define declarations.
+*/
+#if defined(MAGICKCORE_LCMS_DELEGATE)
+#if defined(LCMS_VERSION) && (LCMS_VERSION < 2000)
+#define cmsUInt32Number  DWORD
+#endif
+#endif
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -539,7 +560,7 @@ static inline unsigned short ReadPropertyMSBShort(const unsigned char **p,
     value;
 
   if (*length < 2)
-    return((unsigned short) ~0U);
+    return((unsigned short) ~0);
   for (i=0; i < 2; i++)
   {
     c=(int) (*(*p)++);
@@ -1532,6 +1553,63 @@ static MagickBooleanType GetEXIFProperty(const Image *image,
   return(status);
 }
 
+static MagickBooleanType GetICCProperty(const Image *image,const char *property,
+  ExceptionInfo *exception)
+{
+  const StringInfo
+    *profile;
+
+  magick_unreferenced(property);
+
+  profile=GetImageProfile(image,"icc");
+  if (profile == (StringInfo *) NULL)
+    profile=GetImageProfile(image,"icm");
+  if (profile == (StringInfo *) NULL)
+    return(MagickFalse);
+  if (GetStringInfoLength(profile) < 128)
+    return(MagickFalse);  /* minimum ICC profile length */
+#if defined(MAGICKCORE_LCMS_DELEGATE)
+  {
+    cmsHPROFILE
+      icc_profile;
+
+    icc_profile=cmsOpenProfileFromMem(GetStringInfoDatum(profile),
+      (cmsUInt32Number) GetStringInfoLength(profile));
+    if (icc_profile != (cmsHPROFILE *) NULL)
+      {
+#if defined(LCMS_VERSION) && (LCMS_VERSION < 2000)
+        const char
+          *name;
+
+        name=cmsTakeProductName(icc_profile);
+        if (name != (const char *) NULL)
+          (void) SetImageProperty((Image *) image,"icc:name",name,exception);
+#else
+        char
+          info[MaxTextExtent];
+
+        (void) cmsGetProfileInfoASCII(icc_profile,cmsInfoDescription,
+          "en","US",info,MaxTextExtent);
+        (void) SetImageProperty((Image *) image,"icc:description",info,
+          exception);
+        (void) cmsGetProfileInfoASCII(icc_profile,cmsInfoManufacturer,
+          "en","US",info,MaxTextExtent);
+        (void) SetImageProperty((Image *) image,"icc:manufacturer",info,
+          exception);
+        (void) cmsGetProfileInfoASCII(icc_profile,cmsInfoModel,"en",
+          "US",info,MaxTextExtent);
+        (void) SetImageProperty((Image *) image,"icc:model",info,exception);
+        (void) cmsGetProfileInfoASCII(icc_profile,cmsInfoCopyright,
+          "en","US",info,MaxTextExtent);
+        (void) SetImageProperty((Image *) image,"icc:copyright",info,exception);
+#endif
+        (void) cmsCloseProfile(icc_profile);
+      }
+  }
+#endif
+  return(MagickTrue);
+}
+
 static MagickBooleanType GetXMPProperty(const Image *image,const char *property)
 {
   char
@@ -1919,9 +1997,9 @@ static char *TraceSVGClippath(const unsigned char *blob,size_t length,
           point[i].x=(double) x*columns/4096/4096;
           point[i].y=(double) y*rows/4096/4096;
         }
-        if( IfMagickFalse(in_subpath) )
+        if (in_subpath == MagickFalse)
           {
-            (void) FormatLocaleString(message,MaxTextExtent,"M %g,%g\n",
+            (void) FormatLocaleString(message,MaxTextExtent,"M %g %g\n",
               point[1].x,point[1].y);
             for (i=0; i < 3; i++)
             {
@@ -1931,14 +2009,28 @@ static char *TraceSVGClippath(const unsigned char *blob,size_t length,
           }
         else
           {
+            /*
+              Handle special cases when Bezier curves are used to describe
+              corners and straight lines.
+            */
             if ((last[1].x == last[2].x) && (last[1].y == last[2].y) &&
                 (point[0].x == point[1].x) && (point[0].y == point[1].y))
-              (void) FormatLocaleString(message,MaxTextExtent,"L %g,%g\n",
-                point[1].x,point[1].y);
-            else
               (void) FormatLocaleString(message,MaxTextExtent,
-                "C %g,%g %g,%g %g,%g\n",last[2].x,last[2].y,
-                point[0].x,point[0].y,point[1].x,point[1].y);
+                "L %g %g\n",point[1].x,point[1].y);
+            else
+              if ((last[1].x == last[2].x) && (last[1].y == last[2].y))
+                (void) FormatLocaleString(message,MaxTextExtent,
+                  "V %g %g %g %g\n",point[0].x,point[0].y,
+                  point[1].x,point[1].y);
+              else
+                if ((point[0].x == point[1].x) && (point[0].y == point[1].y))
+                  (void) FormatLocaleString(message,MaxTextExtent,
+                    "Y %g %g %g %g\n",last[2].x,last[2].y,
+                    point[1].x,point[1].y);
+                else
+                  (void) FormatLocaleString(message,MaxTextExtent,
+                    "C %g %g %g %g %g %g\n",last[2].x,
+                    last[2].y,point[0].x,point[0].y,point[1].x,point[1].y);
             for (i=0; i < 3; i++)
               last[i]=point[i];
           }
@@ -1950,17 +2042,29 @@ static char *TraceSVGClippath(const unsigned char *blob,size_t length,
         */
         if (knot_count == 0)
           {
+           /*
+              Same special handling as above except we compare to the
+              first point in the path and close the path.
+            */
             if ((last[1].x == last[2].x) && (last[1].y == last[2].y) &&
                 (first[0].x == first[1].x) && (first[0].y == first[1].y))
               (void) FormatLocaleString(message,MaxTextExtent,
-                "L %g,%g Z\n",first[1].x,first[1].y);
+                "L %g %g Z\n",first[1].x,first[1].y);
             else
-              {
+              if ((last[1].x == last[2].x) && (last[1].y == last[2].y))
                 (void) FormatLocaleString(message,MaxTextExtent,
-                  "C %g,%g %g,%g %g,%g Z\n",last[2].x,
-                  last[2].y,first[0].x,first[0].y,first[1].x,first[1].y);
-                (void) ConcatenateString(&path,message);
-              }
+                  "V %g %g %g %g Z\n",first[0].x,first[0].y,
+                  first[1].x,first[1].y);
+              else
+                if ((first[0].x == first[1].x) && (first[0].y == first[1].y))
+                  (void) FormatLocaleString(message,MaxTextExtent,
+                    "Y %g %g %g %g Z\n",last[2].x,last[2].y,
+                    first[1].x,first[1].y);
+                else
+                  (void) FormatLocaleString(message,MaxTextExtent,
+                    "C %g %g %g %g %g %g Z\n",last[2].x,
+                    last[2].y,first[0].x,first[0].y,first[1].x,first[1].y);
+            (void) ConcatenateString(&path,message);
             in_subpath=MagickFalse;
           }
         break;
@@ -1997,11 +2101,9 @@ MagickExport const char *GetImageProperty(const Image *image,
 
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
-  if( IfMagickTrue(image->debug) )
+  if (IfMagickTrue(image->debug))
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-
   p=(const char *) NULL;
-  /* if property is in splay tree - return it and we are done */
   if (image->properties != (void *) NULL)
     {
       if (property == (const char *) NULL)
@@ -2025,13 +2127,8 @@ MagickExport const char *GetImageProperty(const Image *image,
     {
       if (LocaleNCompare("8bim:",property,5) == 0)
         {
-          if( IfMagickTrue(Get8BIMProperty(image,property,exception)) &&
-              (image->properties != (void *) NULL))
-            {
-              p=(const char *) GetValueFromSplayTree((SplayTreeInfo *)
-                image->properties,property);
-              return(p);
-            }
+          (void) Get8BIMProperty(image,property,exception);
+          break;
         }
       break;
     }
@@ -2040,28 +2137,24 @@ MagickExport const char *GetImageProperty(const Image *image,
     {
       if (LocaleNCompare("exif:",property,5) == 0)
         {
-          if( IfMagickTrue(GetEXIFProperty(image,property,exception)) &&
-              (image->properties != (void *) NULL))
-            {
-              p=(const char *) GetValueFromSplayTree((SplayTreeInfo *)
-                image->properties,property);
-              return(p);
-            }
+          (void) GetEXIFProperty(image,property,exception);
+          break;
         }
       break;
     }
     case 'I':
     case 'i':
     {
+      if ((LocaleNCompare("icc:",property,4) == 0) ||
+          (LocaleNCompare("icm:",property,4) == 0))
+        {
+          (void) GetICCProperty(image,property,exception);
+          break;
+        }
       if (LocaleNCompare("iptc:",property,5) == 0)
         {
-          if( IfMagickTrue(GetIPTCProperty(image,property,exception)) &&
-              (image->properties != (void *) NULL))
-            {
-              p=(const char *) GetValueFromSplayTree((SplayTreeInfo *)
-                image->properties,property);
-              return(p);
-            }
+          (void) GetIPTCProperty(image,property,exception);
+          break;
         }
       break;
     }
@@ -2070,20 +2163,21 @@ MagickExport const char *GetImageProperty(const Image *image,
     {
       if (LocaleNCompare("xmp:",property,4) == 0)
         {
-          if( IfMagickTrue(GetXMPProperty(image,property)) &&
-              (image->properties != (void *) NULL))
-            {
-              p=(const char *) GetValueFromSplayTree((SplayTreeInfo *)
-                image->properties,property);
-              return(p);
-            }
+          (void) GetXMPProperty(image,property);
+          break;
         }
       break;
     }
     default:
       break;
   }
-  return(p);
+  if (image->properties != (void *) NULL)
+    {
+      p=(const char *) GetValueFromSplayTree((SplayTreeInfo *)
+        image->properties,property);
+      return(p);
+    }
+  return((const char *) NULL);
 }
 \f
 /*
@@ -2135,7 +2229,7 @@ MagickExport const char *GetImageProperty(const Image *image,
     return((const char *)NULL); \
   }
 #define WarnNoImageInfoReturn(format,arg) \
-  if (image == (Image *) NULL ) { \
+  if (image_info == (ImageInfo *) NULL ) { \
     (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning, \
         "NoImageInfoForProperty",format,arg); \
     return((const char *)NULL); \
@@ -2431,6 +2525,13 @@ static const char *GetMagickPropertyLetter(ImageInfo *image_info,
         image->delay);
       break;
     }
+    case 'U': /* Image resolution units. */
+    {
+      WarnNoImageReturn("\"%%%c\"",letter);
+      string=CommandOptionToMnemonic(MagickResolutionOptions,
+        (ssize_t) image->units);
+      break;
+    }
     case 'W': /* layer canvas width */
     {
       WarnNoImageReturn("\"%%%c\"",letter);
@@ -2471,8 +2572,11 @@ static const char *GetMagickPropertyLetter(ImageInfo *image_info,
         page.y);
       break;
     }
-    case '#': /* Image signature */
+    case '#':
     {
+      /*
+        Image signature.
+      */
       WarnNoImageReturn("\"%%%c\"",letter);
       (void) SignatureImage(image,exception);
       string=GetImageProperty(image,"signature",exception);
@@ -2482,19 +2586,21 @@ static const char *GetMagickPropertyLetter(ImageInfo *image_info,
   if (string != (char *) NULL)
     return(string);
   if (*value != '\0')
-  {
-    /* create a cloned copy of result, that will get cleaned up, eventually */
-    if (image != (Image *)NULL)
-      {
-        (void) SetImageArtifact(image,"get-property",value);
-        return(GetImageArtifact(image,"get-property"));
-      }
-    else
-      {
-        (void) SetImageOption(image_info,"get-property",value);
-        return(GetImageOption(image_info,"get-property"));
-      }
-  }
+    {
+      /*
+        Create a cloned copy of result.
+      */
+      if (image != (Image *)NULL)
+        {
+          (void) SetImageArtifact(image,"get-property",value);
+          return(GetImageArtifact(image,"get-property"));
+        }
+      else
+        {
+          (void) SetImageOption(image_info,"get-property",value);
+          return(GetImageOption(image_info,"get-property"));
+        }
+    }
   return((char *)NULL);
 }
 
@@ -2532,6 +2638,12 @@ MagickExport const char *GetMagickProperty(ImageInfo *image_info,
           if (*value == '\0') string="";
           break;
         }
+      if (LocaleCompare("bit-depth",property) == 0)
+        {
+          (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
+            GetImageDepth(image, exception));
+          break;
+        }
       break;
     }
     case 'c':
@@ -2717,20 +2829,62 @@ MagickExport const char *GetMagickProperty(ImageInfo *image_info,
         }
      break;
     }
-/*  OBSOLETE  The 'page' of a image, is just the images index
-    This conficts with the -set page option that sets virtual canvas info
     case 'p':
     {
-      if (LocaleCompare("page",property) == 0)
+#if defined(MAGICKCORE_LCMS_DELEGATE)
+      if (LocaleCompare("profile:icc",property) == 0 ||
+          LocaleCompare("profile:icm",property) == 0)
         {
-          WarnNoImageReturn("\"%%[%s]\"",property);
-          (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
-            GetImageIndexInList(image)+1);
+#if !defined(LCMS_VERSION) || (LCMS_VERSION < 2000)
+#define cmsUInt32Number  DWORD
+#endif
+
+          const StringInfo
+            *profile;
+
+          cmsHPROFILE
+            icc_profile;
+
+          profile=GetImageProfile(image,property+8);
+          if (profile == (StringInfo *) NULL)
+            break;
+
+          icc_profile=cmsOpenProfileFromMem(GetStringInfoDatum(profile),
+            (cmsUInt32Number) GetStringInfoLength(profile));
+          if (icc_profile != (cmsHPROFILE *) NULL)
+            {
+#if defined(LCMS_VERSION) && (LCMS_VERSION < 2000)
+              string=cmsTakeProductName(icc_profile);
+#else
+              (void) cmsGetProfileInfoASCII(icc_profile,cmsInfoDescription,
+                "en","US",value,MaxTextExtent);
+#endif
+              (void) cmsCloseProfile(icc_profile);
+            }
+      }
+#endif
+      if (LocaleCompare("profiles",property) == 0)
+        {
+          const char
+            *name;
+
+          ResetImageProfileIterator(image);
+          name=GetNextImageProfile(image);
+          if (name != (char *) NULL)
+            {
+              (void) CopyMagickString(value,name,MaxTextExtent);
+              name=GetNextImageProfile(image);
+              while (name != (char *) NULL)
+              {
+                ConcatenateMagickString(value,",",MaxTextExtent);
+                ConcatenateMagickString(value,name,MaxTextExtent);
+                name=GetNextImageProfile(image);
+              }
+            }
           break;
         }
       break;
     }
-*/
     case 'r':
     {
       if (LocaleCompare("resolution.x",property) == 0)
@@ -2794,7 +2948,8 @@ MagickExport const char *GetMagickProperty(ImageInfo *image_info,
             GetMagickPrecision(),skewness);
           break;
         }
-      if (LocaleCompare("standard-deviation",property) == 0)
+      if ((LocaleCompare("standard-deviation",property) == 0) ||
+          (LocaleCompare("standard_deviation",property) == 0))
         {
           double
             mean,
@@ -2910,7 +3065,7 @@ MagickExport const char *GetMagickProperty(ImageInfo *image_info,
   }
   return((char *)NULL);
 }
-#undef WarnNoImageRteurn
+#undef WarnNoImageReturn
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -3003,6 +3158,7 @@ MagickExport char *GetNextImageProperty(const Image *image)
 
 /* common inline code to expand the interpreted text string */
 #define ExtendInterpretText(string_length)  do { \
+DisableMSCWarning(4127) \
     size_t length=(string_length); \
     if ((size_t) (q-interpret_text+length+1) >= extent) \
      { extent+=length; \
@@ -3011,10 +3167,12 @@ MagickExport char *GetNextImageProperty(const Image *image)
        if (interpret_text == (char *) NULL) \
          return((char *)NULL); \
        q=interpret_text+strlen(interpret_text); \
-   } } while (0)  /* no trailing ; */
+   } } while (0)  /* no trailing ; */ \
+RestoreMSCWarning
 
 /* same but append the given string */
 #define AppendString2Text(string)  do { \
+DisableMSCWarning(4127) \
     size_t length=strlen((string)); \
     if ((size_t) (q-interpret_text+length+1) >= extent) \
      { extent+=length; \
@@ -3026,10 +3184,12 @@ MagickExport char *GetNextImageProperty(const Image *image)
       } \
      (void) CopyMagickString(q,(string),extent); \
      q+=length; \
-   } while (0)  /* no trailing ; */
+   } while (0)  /* no trailing ; */ \
+RestoreMSCWarning
 
 /* same but append a 'key' and 'string' pair */
 #define AppendKeyValue2Text(key,string)  do { \
+DisableMSCWarning(4127) \
     size_t length=strlen(key)+strlen(string)+2; \
     if ((size_t) (q-interpret_text+length+1) >= extent) \
      { extent+=length; \
@@ -3040,7 +3200,8 @@ MagickExport char *GetNextImageProperty(const Image *image)
       q=interpret_text+strlen(interpret_text); \
      } \
      q+=FormatLocaleString(q,extent,"%s=%s\n",(key),(string)); \
-   } while (0)  /* no trailing ; */
+   } while (0)  /* no trailing ; */ \
+RestoreMSCWarning
 
 MagickExport char *InterpretImageProperties(ImageInfo *image_info,
   Image *image,const char *embed_text,ExceptionInfo *exception)
@@ -3083,7 +3244,7 @@ MagickExport char *InterpretImageProperties(ImageInfo *image_info,
            OptionError,"UnableToAccessPath","%s",p);
        return((char *) NULL);
      }
-     return(FileToString(p,~0,exception));
+     return(FileToString(p,~0UL,exception));
   }
 
   /*
@@ -3625,28 +3786,23 @@ MagickExport MagickBooleanType SetImageProperty(Image *image,
   assert(image->signature == MagickSignature);
   if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-
-  /* Create splay-tree */
   if (image->properties == (void *) NULL)
     image->properties=NewSplayTree(CompareSplayTreeString,
-      RelinquishMagickMemory,RelinquishMagickMemory);
-
-  /* Delete property if NULL --  empty string values are valid! */
+      RelinquishMagickMemory,RelinquishMagickMemory);  /* create splay-tree */
   if (value == (const char *) NULL)
-    return(DeleteImageProperty(image,property));
+    return(DeleteImageProperty(image,property));  /* delete if NULL */
   status=MagickTrue;
-
-  /* Do not 'set' single letter properties - read only shorthand */
   if (strlen(property) <= 1)
     {
-      (void) ThrowMagickException(exception,GetMagickModule(),
-          OptionError,"SetReadOnlyProperty","`%s'",property);
+      /*
+        Do not 'set' single letter properties - read only shorthand.
+       */
+      (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
+        "SetReadOnlyProperty","`%s'",property);
       return(MagickFalse);
     }
 
   /* FUTURE: binary chars or quotes in key should produce a error */
-
-
   /* Set attributes with known names or special prefixes
      return result is found, or break to set a free form properity
   */
@@ -3682,8 +3838,8 @@ MagickExport MagickBooleanType SetImageProperty(Image *image,
     {
       if (LocaleCompare("channels",property) == 0)
         {
-          (void) ThrowMagickException(exception,GetMagickModule(),
-               OptionError,"SetReadOnlyProperty","`%s'",property);
+          (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
+            "SetReadOnlyProperty","`%s'",property);
           return(MagickFalse);
         }
       if (LocaleCompare("colorspace",property) == 0)
@@ -3695,29 +3851,7 @@ MagickExport MagickBooleanType SetImageProperty(Image *image,
             value);
           if (colorspace < 0)
             return(MagickFalse); /* FUTURE: value exception?? */
-          image->colorspace=(ColorspaceType) colorspace;
-          image->rendering_intent=UndefinedIntent;
-          image->gamma=1.000f;
-          ResetMagickMemory(&image->chromaticity,0,sizeof(image->chromaticity));
-          if (IssRGBColorspace(image->colorspace) != MagickFalse)
-            {
-              image->rendering_intent=PerceptualIntent;
-              image->gamma=1.000f/2.200f;
-              image->chromaticity.red_primary.x=0.6400f;
-              image->chromaticity.red_primary.y=0.3300f;
-              image->chromaticity.red_primary.z=0.0300f;
-              image->chromaticity.green_primary.x=0.3000f;
-              image->chromaticity.green_primary.y=0.6000f;
-              image->chromaticity.green_primary.z=0.1000f;
-              image->chromaticity.blue_primary.x=0.1500f;
-              image->chromaticity.blue_primary.y=0.0600f;
-              image->chromaticity.blue_primary.z=0.7900f;
-              image->chromaticity.white_point.x=0.3127f;
-              image->chromaticity.white_point.y=0.3290f;
-              image->chromaticity.white_point.z=0.3583f;
-            }
-          return(SyncImagePixelCache(image,exception));
-          break;
+          return(SetImageColorspace(image,(ColorspaceType) colorspace,exception));
         }
       if (LocaleCompare("compose",property) == 0)
         {