]> granicus.if.org Git - imagemagick/commitdiff
Fixed writing the values of the iptc profile reported in #149
authorDirk Lemstra <dirk@git.imagemagick.org>
Thu, 21 Sep 2017 15:04:36 +0000 (17:04 +0200)
committerDirk Lemstra <dirk@git.imagemagick.org>
Thu, 21 Sep 2017 15:05:19 +0000 (17:05 +0200)
coders/json.c

index 84313198e4dbbcc0ed4d88c5c383f6c0badf60de..87154589e65beca52a381786bb3e9672ce7a81f4 100644 (file)
 #include "MagickCore/utility.h"
 #include "MagickCore/version.h"
 #include "MagickCore/module.h"
+
+/*
+  Typedef declarations.
+*/
+typedef struct _IptcValue
+{
+  long
+    dataset,
+    record;
+
+  size_t
+    values_length;
+
+  char
+    tag[32],
+    ***values;
+} IptcValue;
 \f
 /*
   Forward declarations.
@@ -684,6 +701,182 @@ static ssize_t PrintChannelStatistics(FILE *file,const PixelChannel channel,
   return(n);
 }
 
+static void EncodeIptcProfile(FILE *file,const StringInfo *profile)
+{
+  char
+    *attribute,
+    **attribute_list;
+
+  const char
+    *tag;
+
+  IptcValue
+    *value,
+    **values;
+
+  long
+    dataset,
+    record,
+    sentinel;
+
+  register ssize_t
+    i,
+    j,
+    k;
+
+  size_t
+    count,
+    length,
+    profile_length;
+
+  values=(IptcValue **) NULL;
+  count=0;
+  profile_length=GetStringInfoLength(profile);
+  for (i=0; i < (ssize_t) profile_length; i+=(ssize_t) length)
+  {
+    length=1;
+    sentinel=GetStringInfoDatum(profile)[i++];
+    if (sentinel != 0x1c)
+      continue;
+    dataset=GetStringInfoDatum(profile)[i++];
+    record=GetStringInfoDatum(profile)[i++];
+    value=(IptcValue *) NULL;
+    for (j=0; j < count; j++)
+    {
+      if ((values[j]->record == record) && (values[j]->dataset == dataset))
+        value=values[j];
+    }
+    if (value == (IptcValue *) NULL)
+      {
+        values=(IptcValue **) ResizeQuantumMemory(values,count+1,
+          sizeof(*values));
+        if (values == (IptcValue **) NULL)
+          break;
+        value=AcquireMagickMemory(sizeof(*value));
+        if (value == (IptcValue *) NULL)
+          break;
+        /* Check the tag length in IptcValue when a new tag is added */
+        switch (record)
+        {
+          case 5: tag="Image Name"; break;
+          case 7: tag="Edit Status"; break;
+          case 10: tag="Priority"; break;
+          case 15: tag="Category"; break;
+          case 20: tag="Supplemental Category"; break;
+          case 22: tag="Fixture Identifier"; break;
+          case 25: tag="Keyword"; break;
+          case 30: tag="Release Date"; break;
+          case 35: tag="Release Time"; break;
+          case 40: tag="Special Instructions"; break;
+          case 45: tag="Reference Service"; break;
+          case 47: tag="Reference Date"; break;
+          case 50: tag="Reference Number"; break;
+          case 55: tag="Created Date"; break;
+          case 60: tag="Created Time"; break;
+          case 65: tag="Originating Program"; break;
+          case 70: tag="Program Version"; break;
+          case 75: tag="Object Cycle"; break;
+          case 80: tag="Byline"; break;
+          case 85: tag="Byline Title"; break;
+          case 90: tag="City"; break;
+          case 92: tag="Sub-Location"; break;
+          case 95: tag="Province State"; break;
+          case 100: tag="Country Code"; break;
+          case 101: tag="Country"; break;
+          case 103: tag="Original Transmission Reference"; break;
+          case 105: tag="Headline"; break;
+          case 110: tag="Credit"; break;
+          case 115: tag="Src"; break;
+          case 116: tag="Copyright String"; break;
+          case 120: tag="Caption"; break;
+          case 121: tag="Local Caption"; break;
+          case 122: tag="Caption Writer"; break;
+          case 200: tag="Custom Field 1"; break;
+          case 201: tag="Custom Field 2"; break;
+          case 202: tag="Custom Field 3"; break;
+          case 203: tag="Custom Field 4"; break;
+          case 204: tag="Custom Field 5"; break;
+          case 205: tag="Custom Field 6"; break;
+          case 206: tag="Custom Field 7"; break;
+          case 207: tag="Custom Field 8"; break;
+          case 208: tag="Custom Field 9"; break;
+          case 209: tag="Custom Field 10"; break;
+          case 210: tag="Custom Field 11"; break;
+          case 211: tag="Custom Field 12"; break;
+          case 212: tag="Custom Field 13"; break;
+          case 213: tag="Custom Field 14"; break;
+          case 214: tag="Custom Field 15"; break;
+          case 215: tag="Custom Field 16"; break;
+          case 216: tag="Custom Field 17"; break;
+          case 217: tag="Custom Field 18"; break;
+          case 218: tag="Custom Field 19"; break;
+          case 219: tag="Custom Field 20"; break;
+          default: tag="Unknown"; break;
+        }
+        (void) CopyMagickString(value->tag,tag,strlen(tag)+1);
+        value->record=record;
+        value->dataset=dataset;
+        value->values=(char ***) NULL;
+        value->values_length=0;
+        values[count++]=value;
+      }
+    length=(size_t) (GetStringInfoDatum(profile)[i++] << 8);
+    length|=GetStringInfoDatum(profile)[i++];
+    attribute=(char *) NULL;
+    if (~length >= (MagickPathExtent-1))
+      attribute=(char *) AcquireQuantumMemory(length+MagickPathExtent,
+        sizeof(*attribute));
+    if (attribute != (char *) NULL)
+      {
+        (void) CopyMagickString(attribute,(char *)
+          GetStringInfoDatum(profile)+i,length+1);
+        attribute_list=StringToList(attribute);
+        if (attribute_list != (char **) NULL)
+          {
+            value->values=(char ***) ResizeQuantumMemory(value->values,
+              value->values_length+1,
+              sizeof(*value->values));
+            if (value->values == (char ***) NULL)
+              break;
+            value->values[value->values_length++]=attribute_list;
+          }
+        attribute=DestroyString(attribute);
+      }
+  }
+  if (values != (IptcValue **) NULL)
+    {
+      for (i=0; i < count; i++)
+      {
+        value=values[i];
+        (void) FormatLocaleFile(file,"        \"%s[%.20g,%.20g]\": ",
+          value->tag,(double) value->dataset,(double) value->record);
+        if (value->values_length == 0)
+          (void) FormatLocaleFile(file,"null,");
+        else
+          {
+            (void) FormatLocaleFile(file,"[");
+            for (j=0; j < value->values_length; j++)
+            {
+              for (k=0; value->values[j][k] != (char *) NULL; k++)
+              {
+                if (j > 0 || k > 0)
+                  (void) FormatLocaleFile(file,",");
+                JsonFormatLocaleFile(file,"%s",value->values[j][k]);
+                value->values[j][k]=(char *) RelinquishMagickMemory(
+                  value->values[j][k]);
+              }
+              value->values[j]=(char **) RelinquishMagickMemory(
+                value->values[j]);
+            }
+            value->values=(char ***) RelinquishMagickMemory(value->values);
+            (void) FormatLocaleFile(file,"],\n");
+          }
+        values[i]=(IptcValue *) RelinquishMagickMemory(values[i]);
+      }
+      values=(IptcValue **) RelinquishMagickMemory(values);
+    }
+}
+
 static MagickBooleanType EncodeImageAttributes(Image *image,FILE *file,
   ExceptionInfo *exception)
 {
@@ -1378,128 +1571,7 @@ static MagickBooleanType EncodeImageAttributes(Image *image,FILE *file,
           (void) FormatLocaleFile(file,",\n");
         JsonFormatLocaleFile(file,"      %s: {\n",name);
         if (LocaleCompare(name,"iptc") == 0)
-          {
-            char
-              *attribute,
-              **attribute_list;
-
-            const char
-              *tag;
-
-            long
-              dataset,
-              record,
-              sentinel;
-
-            register ssize_t
-              j;
-
-            size_t
-              length,
-              profile_length;
-
-            profile_length=GetStringInfoLength(profile);
-            for (i=0; i < (ssize_t) profile_length; i+=(ssize_t) length)
-            {
-              length=1;
-              sentinel=GetStringInfoDatum(profile)[i++];
-              if (sentinel != 0x1c)
-                continue;
-              dataset=GetStringInfoDatum(profile)[i++];
-              record=GetStringInfoDatum(profile)[i++];
-              switch (record)
-              {
-                case 5: tag="Image Name"; break;
-                case 7: tag="Edit Status"; break;
-                case 10: tag="Priority"; break;
-                case 15: tag="Category"; break;
-                case 20: tag="Supplemental Category"; break;
-                case 22: tag="Fixture Identifier"; break;
-                case 25: tag="Keyword"; break;
-                case 30: tag="Release Date"; break;
-                case 35: tag="Release Time"; break;
-                case 40: tag="Special Instructions"; break;
-                case 45: tag="Reference Service"; break;
-                case 47: tag="Reference Date"; break;
-                case 50: tag="Reference Number"; break;
-                case 55: tag="Created Date"; break;
-                case 60: tag="Created Time"; break;
-                case 65: tag="Originating Program"; break;
-                case 70: tag="Program Version"; break;
-                case 75: tag="Object Cycle"; break;
-                case 80: tag="Byline"; break;
-                case 85: tag="Byline Title"; break;
-                case 90: tag="City"; break;
-                case 92: tag="Sub-Location"; break;
-                case 95: tag="Province State"; break;
-                case 100: tag="Country Code"; break;
-                case 101: tag="Country"; break;
-                case 103: tag="Original Transmission Reference"; break;
-                case 105: tag="Headline"; break;
-                case 110: tag="Credit"; break;
-                case 115: tag="Src"; break;
-                case 116: tag="Copyright String"; break;
-                case 120: tag="Caption"; break;
-                case 121: tag="Local Caption"; break;
-                case 122: tag="Caption Writer"; break;
-                case 200: tag="Custom Field 1"; break;
-                case 201: tag="Custom Field 2"; break;
-                case 202: tag="Custom Field 3"; break;
-                case 203: tag="Custom Field 4"; break;
-                case 204: tag="Custom Field 5"; break;
-                case 205: tag="Custom Field 6"; break;
-                case 206: tag="Custom Field 7"; break;
-                case 207: tag="Custom Field 8"; break;
-                case 208: tag="Custom Field 9"; break;
-                case 209: tag="Custom Field 10"; break;
-                case 210: tag="Custom Field 11"; break;
-                case 211: tag="Custom Field 12"; break;
-                case 212: tag="Custom Field 13"; break;
-                case 213: tag="Custom Field 14"; break;
-                case 214: tag="Custom Field 15"; break;
-                case 215: tag="Custom Field 16"; break;
-                case 216: tag="Custom Field 17"; break;
-                case 217: tag="Custom Field 18"; break;
-                case 218: tag="Custom Field 19"; break;
-                case 219: tag="Custom Field 20"; break;
-                default: tag="unknown"; break;
-              }
-              (void) FormatLocaleFile(file,"      \"%s[%.20g,%.20g]\": ",tag,
-                (double) dataset,(double) record);
-              length=(size_t) (GetStringInfoDatum(profile)[i++] << 8);
-              length|=GetStringInfoDatum(profile)[i++];
-              attribute=(char *) NULL;
-              if (~length >= (MagickPathExtent-1))
-                attribute=(char *) AcquireQuantumMemory(length+MagickPathExtent,
-                  sizeof(*attribute));
-              if (attribute != (char *) NULL)
-                {
-                  (void) CopyMagickString(attribute,(char *)
-                    GetStringInfoDatum(profile)+i,length+1);
-                  attribute_list=StringToList(attribute);
-                  if (attribute_list != (char **) NULL)
-                    {
-                     (void) FormatLocaleFile(file,"[");
-                      for (j=0; attribute_list[j] != (char *) NULL; j++)
-                      {
-                        if (j != 0)
-                          (void) FormatLocaleFile(file,",");
-                        JsonFormatLocaleFile(file,"%s",attribute_list[j]);
-                        attribute_list[j]=(char *) RelinquishMagickMemory(
-                          attribute_list[j]);
-                      }
-                      (void) FormatLocaleFile(file,"],");
-                      attribute_list=(char **) RelinquishMagickMemory(
-                        attribute_list);
-                    }
-                   else
-                    (void) FormatLocaleFile(file,"null,");
-                  attribute=DestroyString(attribute);
-                }
-              else
-                (void) FormatLocaleFile(file,"null,");
-            }
-          }
+          EncodeIptcProfile(file,profile);
         (void) FormatLocaleFile(file,"        \"length\": \"%.20g\"",(double)
           GetStringInfoLength(profile));
         (void) FormatLocaleFile(file,"\n      }");