]> granicus.if.org Git - imagemagick/commitdiff
Added support for reading/writing the tIME chunk.
authordirk <dirk@git.imagemagick.org>
Fri, 24 Oct 2014 21:10:08 +0000 (21:10 +0000)
committerdirk <dirk@git.imagemagick.org>
Fri, 24 Oct 2014 21:10:08 +0000 (21:10 +0000)
coders/png.c

index 9feb0888cb92a08cb6288da33a7237f904b291fa..70d8ebda8597a7260707b6facbfe6347345a16e0 100644 (file)
@@ -815,7 +815,9 @@ typedef struct _MngInfo
     ping_exclude_zTXt,
     ping_preserve_colormap,
   /* Added at version 6.8.5-7 */
-    ping_preserve_iCCP;
+    ping_preserve_iCCP,
+  /* Added at version 6.8.9-9 */
+    ping_exclude_tIME;
 
 } MngInfo;
 #endif /* VER */
@@ -1868,6 +1870,25 @@ static int read_vpag_chunk_callback(png_struct *ping, png_unknown_chunkp chunk)
 }
 #endif
 
+#if defined(PNG_tIME_SUPPORTED)
+static void read_tIME_chunk(Image *image,png_struct *ping,png_info *info,
+  ExceptionInfo *exception)
+{
+  png_timep
+    time;
+
+  if (png_get_tIME(ping,info,&time))
+    {
+      char
+        timestamp[21];
+
+      FormatLocaleString(timestamp,21,"%04d-%02d-%02dT%02d:%02d:%02dZ",
+        time->year,time->month,time->day,time->hour,time->minute,time->second);
+      SetImageProperty(image,"png:tIME",timestamp,exception);
+    }
+}
+#endif
+
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %                                                                             %
@@ -1903,7 +1924,6 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
 {
   /* Read one PNG image */
 
-  /* To do: Read the tIME chunk into the date:modify property */
   /* To do: Read the tEXt/Creation Time chunk into the date:create property */
 
   Image
@@ -2013,7 +2033,9 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
     112,  67,  65,  76, (png_byte) '\0',   /* pCAL */
     115,  67,  65,  76, (png_byte) '\0',   /* sCAL */
     115,  80,  76,  84, (png_byte) '\0',   /* sPLT */
+#if !defined(PNG_tIME_SUPPORTED)
     116,  73,  77,  69, (png_byte) '\0',   /* tIME */
+#endif
 #ifdef PNG_APNG_SUPPORTED /* libpng was built with APNG patch; */
                           /* ignore the APNG chunks */
      97,  99,  84,  76, (png_byte) '\0',   /* acTL */
@@ -3081,6 +3103,10 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
          (void) SetImageProperty(image,"png:PLTE.number_colors",msg,
             exception);
        }
+
+#if defined(PNG_tIME_SUPPORTED)
+     read_tIME_chunk(image,ping,ping_info,exception);
+#endif
    }
 
   /*
@@ -3658,8 +3684,8 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
             value=DestroyString(value);
           }
       }
-      num_text_total += num_text;
-    }
+    num_text_total += num_text;
+  }
 
 #ifdef MNG_OBJECT_BUFFERS
   /*
@@ -3871,6 +3897,10 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
        }
 #endif
 
+#if defined(PNG_tIME_SUPPORTED)
+     read_tIME_chunk(image,ping,end_info,exception);
+#endif
+
      if ((image->page.width != 0 && image->page.width != image->columns) ||
          (image->page.height != 0 && image->page.height != image->rows))
        {
@@ -7774,6 +7804,49 @@ static MagickBooleanType Magick_png_write_chunk_from_profile(Image *image,
    return(MagickTrue);
 }
 
+#if defined(PNG_tIME_SUPPORTED)
+static void write_tIME_chunk(Image *image,png_struct *ping,png_info *info,
+  const char *date,ExceptionInfo *exception)
+{
+  unsigned int
+    day,
+    hour,
+    minute,
+    month,
+    second,
+    year;
+
+  png_time
+    ptime;
+
+  time_t
+    ttime;
+
+  if (date != (const char *) NULL)
+    {
+      if (sscanf(date,"%d-%d-%dT%d:%d:%dZ",&year,&month,&day,&hour,&minute,
+          &second) != 6)
+        {
+          (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
+            "Invalid date format specified for png:tIME","`%s'",
+            image->filename);
+          return;
+        }
+      ptime.year=(png_uint_16) year;
+      ptime.month=(png_byte) month;
+      ptime.day=(png_byte) day;
+      ptime.hour=(png_byte) hour;
+      ptime.minute=(png_byte) minute;
+      ptime.second=(png_byte) second;
+    }
+  else
+  {
+    time(&ttime);
+    png_convert_from_time_t(&ptime,ttime);
+  }
+  png_set_tIME(ping,info,&ptime);
+}
+#endif
 
 /* Write one PNG image */
 static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
@@ -7857,6 +7930,7 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
     ping_exclude_pHYs,
     ping_exclude_sRGB,
     ping_exclude_tEXt,
+    ping_exclude_tIME,
     /* ping_exclude_tRNS, */
     ping_exclude_vpAg,
     ping_exclude_zCCP, /* hex-encoded iCCP */
@@ -8013,6 +8087,7 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
   ping_exclude_pHYs=mng_info->ping_exclude_pHYs;
   ping_exclude_sRGB=mng_info->ping_exclude_sRGB;
   ping_exclude_tEXt=mng_info->ping_exclude_tEXt;
+  ping_exclude_tIME=mng_info->ping_exclude_tIME;
   /* ping_exclude_tRNS=mng_info->ping_exclude_tRNS; */
   ping_exclude_vpAg=mng_info->ping_exclude_vpAg;
   ping_exclude_zCCP=mng_info->ping_exclude_zCCP; /* hex-encoded iCCP in zTXt */
@@ -10609,6 +10684,24 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
     }
 #endif
 
+#if defined(PNG_tIME_SUPPORTED)
+  if (ping_exclude_tIME == MagickFalse)
+    {
+      const char
+        *timestamp;
+
+      timestamp=GetImageOption(image_info,"png:tIME");
+      if (timestamp != (const char *) NULL)
+        write_tIME_chunk(image,ping,ping_info,timestamp,exception);
+      else
+        {
+          if (image->taint == MagickFalse)
+            timestamp=GetImageProperty(image,"png:tIME",exception);
+          write_tIME_chunk(image,ping,ping_info,timestamp,exception);
+        }
+    }
+#endif
+
   if (mng_info->need_blob != MagickFalse)
   {
     if (OpenBlob(image_info,image,WriteBinaryBlobMode,exception) ==
@@ -11670,6 +11763,7 @@ static MagickBooleanType WritePNGImage(const ImageInfo *image_info,
   mng_info->ping_exclude_pHYs=MagickFalse;
   mng_info->ping_exclude_sRGB=MagickFalse;
   mng_info->ping_exclude_tEXt=MagickFalse;
+  mng_info->ping_exclude_tIME=MagickFalse;
   mng_info->ping_exclude_tRNS=MagickFalse;
   mng_info->ping_exclude_vpAg=MagickFalse;
   mng_info->ping_exclude_zCCP=MagickFalse; /* hex-encoded iCCP in zTXt */
@@ -11876,6 +11970,7 @@ static MagickBooleanType WritePNGImage(const ImageInfo *image_info,
         mng_info->ping_exclude_pHYs=excluding;
         mng_info->ping_exclude_sRGB=excluding;
         mng_info->ping_exclude_tEXt=excluding;
+        mng_info->ping_exclude_tIME=excluding;
         mng_info->ping_exclude_tRNS=excluding;
         mng_info->ping_exclude_vpAg=excluding;
         mng_info->ping_exclude_zCCP=excluding;
@@ -11905,6 +12000,8 @@ static MagickBooleanType WritePNGImage(const ImageInfo *image_info,
           MagickTrue;
         mng_info->ping_exclude_tEXt=excluding != MagickFalse ? MagickFalse :
           MagickTrue;
+        mng_info->ping_exclude_tIME=excluding != MagickFalse ? MagickFalse :
+          MagickTrue;
         mng_info->ping_exclude_tRNS=excluding != MagickFalse ? MagickFalse :
           MagickTrue;
         mng_info->ping_exclude_vpAg=excluding != MagickFalse ? MagickFalse :
@@ -11950,6 +12047,9 @@ static MagickBooleanType WritePNGImage(const ImageInfo *image_info,
     if (IsOptionMember("text",value) != MagickFalse)
       mng_info->ping_exclude_tEXt=excluding;
 
+    if (IsOptionMember("time",value) != MagickFalse)
+      mng_info->ping_exclude_tIME=excluding;
+
     if (IsOptionMember("trns",value) != MagickFalse)
       mng_info->ping_exclude_tRNS=excluding;
 
@@ -12003,6 +12103,9 @@ static MagickBooleanType WritePNGImage(const ImageInfo *image_info,
     if (mng_info->ping_exclude_tEXt != MagickFalse)
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
           "    tEXt");
+    if (mng_info->ping_exclude_tIME != MagickFalse)
+      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+          "    tIME");
     if (mng_info->ping_exclude_tRNS != MagickFalse)
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
           "    tRNS");