diff options
| author | Tomas Bzatek <tbzatek@users.sourceforge.net> | 2013-03-10 19:08:58 +0100 |
|---|---|---|
| committer | Tomas Bzatek <tbzatek@users.sourceforge.net> | 2013-03-10 19:08:58 +0100 |
| commit | 13459096ccf173a4251b4e1ad6fdebaf61b33afd (patch) | |
| tree | c0f1176a93586bcae4d16bb6cb540967dff2cffa /src | |
| parent | 6468dd6da3764498fcabbf99603f50974f26c2c6 (diff) | |
| download | cataract-13459096ccf173a4251b4e1ad6fdebaf61b33afd.tar.xz | |
Add support for specifying custom date
This essentially means faking the datetime, e.g. when you want to mask
original picture date.
This commit also changes little bit of datetime conversion, hopefully
fixing DST issues. Needs more testing.
Diffstat (limited to 'src')
| -rw-r--r-- | src/generators.c | 3 | ||||
| -rw-r--r-- | src/items.c | 52 | ||||
| -rw-r--r-- | src/items.h | 2 | ||||
| -rw-r--r-- | src/jpeg-utils.cpp | 112 | ||||
| -rw-r--r-- | src/jpeg-utils.h | 1 |
5 files changed, 135 insertions, 35 deletions
diff --git a/src/generators.c b/src/generators.c index fe62b39..133c4c1 100644 --- a/src/generators.c +++ b/src/generators.c @@ -159,6 +159,9 @@ metadata_apply_overrides (ExifData *exif_data, exif_data->timezone_shift = item->metadata_tz_shift; if (exif_data->timezone_shift == 0) exif_data->timezone_shift = items->metadata_tz_shift; + exif_data->fake_datetime = item->metadata_fake_datetime; + if (exif_data->fake_datetime == (time_t) -1) + exif_data->fake_datetime = items->metadata_fake_datetime; } diff --git a/src/items.c b/src/items.c index 6ac7e56..85f0a26 100644 --- a/src/items.c +++ b/src/items.c @@ -15,9 +15,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#define _XOPEN_SOURCE 600 #include <stdio.h> #include <string.h> #include <stdlib.h> +#include <time.h> #include <libxml/xmlmemory.h> #include <libxml/parser.h> @@ -53,6 +55,36 @@ parse_timezone_string (const gchar *str) return hour * 60 + min; } +static time_t +parse_datetime_string (const gchar *str) +{ + struct tm tm; + char *res; + time_t rt; + + memset (&tm, 0, sizeof (struct tm)); + + res = strptime (str, "%Y-%m-%d %H:%M:%S", &tm); + if (res == NULL || *res != '\0') { + res = strptime (str, "%Y:%m:%d %H:%M:%S", &tm); + if (res == NULL || *res != '\0') { + res = strptime (str, "%Y-%m-%dT%H:%M:%S", &tm); + if (res == NULL || res < str + 19) { + log_error ("Invalid datetime string \"%s\", ignoring.\n", str); + return (time_t) -1; + } + } + } + + /* EXIF datetime carries no DST information while mktime() will correct + * the tm_isdst field resulting in unnecessary +- 1 hour shift. */ + rt = mktime (&tm); + if (tm.tm_isdst) + rt -= 60*60; + + return rt; +} + /* * parse_album_xml: XML parser for gallery index.xml files @@ -118,8 +150,15 @@ parse_album_xml (const gchar *filename, TPathInfo *path_info) s = xml_file_get_node_attribute (xml, "/gallery/general/metadata/timezone", "shift"); if (s != NULL) { - index->metadata_tz_shift = parse_timezone_string (s2); - g_free (s2); + index->metadata_tz_shift = parse_timezone_string (s); + g_free (s); + } + + index->metadata_fake_datetime = (time_t) -1; + s = xml_file_get_node_attribute (xml, "/gallery/general/metadata/fake", "date"); + if (s != NULL) { + index->metadata_fake_datetime = parse_datetime_string (s); + g_free (s); } @@ -258,6 +297,15 @@ parse_album_xml (const gchar *filename, TPathInfo *path_info) g_free (s2); } + item->metadata_fake_datetime = (time_t) -1; + s = g_strdup_printf ("/gallery/items/*[%d]/metadata/fake", i + 1); + s2 = xml_file_get_node_attribute (xml, s, "date"); + g_free (s); + if (s2 != NULL) { + item->metadata_fake_datetime = parse_datetime_string (s2); + g_free (s2); + } + if (item->path || item->preview) { g_ptr_array_add (index->items, item); } else { diff --git a/src/items.h b/src/items.h index 2b36927..331f29e 100644 --- a/src/items.h +++ b/src/items.h @@ -65,6 +65,7 @@ typedef struct { gchar *auth_passwd; TAuthType auth_type; int metadata_tz_shift; /* minutes */ + time_t metadata_fake_datetime; } TAlbum; typedef struct { @@ -83,6 +84,7 @@ typedef struct { gboolean hidden; gchar *metadata_external_exif; int metadata_tz_shift; /* minutes */ + time_t metadata_fake_datetime; } TIndexItem; typedef struct { diff --git a/src/jpeg-utils.cpp b/src/jpeg-utils.cpp index df3c94e..646763a 100644 --- a/src/jpeg-utils.cpp +++ b/src/jpeg-utils.cpp @@ -35,28 +35,6 @@ struct ExifDataPrivate { }; -static struct tm * -parse_exif_date (const char *str) -{ - struct tm *tm; - char *res; - - tm = (struct tm *) g_malloc0 (sizeof (struct tm)); - - res = strptime (str, "%Y:%m:%d %H:%M:%S", tm); - if (res == NULL || *res != '\0') - return NULL; - - /* FIXME: what was this used for? */ -#if 0 - tm->tm_year -= 1900; - tm->tm_mon--; -#endif - mktime (tm); - - return tm; -} - static void shift_time (struct tm *tm, int offset_min) { @@ -78,6 +56,37 @@ shift_time (struct tm *tm, int offset_min) } } +static struct tm * +parse_exif_date (const char *str) +{ + struct tm *tm; + char *res; + + tm = (struct tm *) g_malloc0 (sizeof (struct tm)); + + res = strptime (str, "%Y:%m:%d %H:%M:%S", tm); + if (res == NULL || *res != '\0') + return NULL; + + mktime (tm); + + if (tm->tm_isdst) + shift_time (tm, -60); + + return tm; +} + +static gchar * +format_exif_time (struct tm *tm) +{ + char conv[1024]; + + memset (&conv, 0, sizeof(conv)); + if (strftime (&conv[0], sizeof(conv), "%Y:%m:%d %H:%M:%S", tm)) + return g_strdup (&conv[0]); + + return NULL; +} /* * EXIF and IPTC info retrieval, keeps the source file open until freed @@ -203,7 +212,10 @@ get_exif_data_fixed (ExifData *exif, const gchar *key) return g_strdup_printf ("f/%.1f", val); } - if (g_str_equal (key, EXIF_DATETIME)) { + if (g_str_equal (key, EXIF_DATETIME) || + g_str_equal (key, "Exif.Photo.DateTimeOriginal") || + g_str_equal (key, "Exif.Photo.DateTimeDigitized") || + g_str_equal (key, "Exif.Image.DateTime")) { const char *val = NULL; try { val = exifData["Exif.Photo.DateTimeOriginal"].toString().c_str(); @@ -224,6 +236,12 @@ get_exif_data_fixed (ExifData *exif, const gchar *key) memset (&conv, 0, sizeof (conv)); + if (exif->fake_datetime != (time_t) -1) { + tt = localtime (&exif->fake_datetime); + if (strftime (&conv[0], sizeof (conv), "%c", tt)) + return g_strdup (&conv[0]); + } + tt = parse_exif_date (val); if (tt) { shift_time (tt, exif->timezone_shift); @@ -515,7 +533,9 @@ calculate_sizes (const unsigned long max_width, const unsigned long max_height, static gboolean shift_exif_time (Exiv2::ExifData& exifData, const char *key, int amount) { + struct tm *tt; const char *s; + gchar *st; gboolean res; res = FALSE; @@ -524,19 +544,15 @@ shift_exif_time (Exiv2::ExifData& exifData, const char *key, int amount) s = exifData[key].toString().c_str(); if (s && strlen (s) > 0) { - struct tm *tt; - char conv[1024]; - - memset (&conv, 0, sizeof (conv)); - tt = parse_exif_date (s); if (tt) { shift_time (tt, amount); - if (strftime (&conv[0], sizeof (conv), "%Y:%m:%d %H:%M:%S", tt)) { - exifData[key] = (const char *) &conv[0]; - res = TRUE; - } + st = format_exif_time (tt); + if (st) + exifData[key] = st; + g_free (st); g_free (tt); + res = TRUE; } } } @@ -545,6 +561,28 @@ shift_exif_time (Exiv2::ExifData& exifData, const char *key, int amount) return res; } +static gboolean +fake_exif_time (Exiv2::ExifData& exifData, const char *key, time_t datetime) +{ + struct tm *tt; + gchar *st; + gboolean res; + + res = FALSE; + try { + if (exifData[key].count() > 0) { + tt = localtime (&datetime); + st = format_exif_time (tt); + if (st) + exifData[key] = st; + g_free (st); + res = TRUE; + } + } catch (...) { } + + return res; +} + /* * modify_exif: - strip thumbnail stored in EXIF table * - write down overriden keys @@ -573,7 +611,7 @@ modify_exif (const gchar *filename, ExifData *exif, gboolean strip_thumbnail) modified = TRUE; } - if (exif->timezone_shift != 0 && !exifData.empty()) { + if (exif->timezone_shift != 0 && exif->fake_datetime != (time_t) -1 && !exifData.empty()) { /* need original data to calculate the shift from */ res = shift_exif_time (exifData, "Exif.Photo.DateTimeOriginal", exif->timezone_shift); res = shift_exif_time (exifData, "Exif.Photo.DateTimeDigitized", exif->timezone_shift) || res; @@ -582,6 +620,14 @@ modify_exif (const gchar *filename, ExifData *exif, gboolean strip_thumbnail) shift_exif_time (exifData, "Exif.Image.DateTime", exif->timezone_shift); modified = TRUE; } + + if (exif->fake_datetime != (time_t) -1 && !exifData.empty()) { + res = fake_exif_time (exifData, "Exif.Photo.DateTimeOriginal", exif->fake_datetime); + res = fake_exif_time (exifData, "Exif.Photo.DateTimeDigitized", exif->fake_datetime) || res; + if (! res) + fake_exif_time (exifData, "Exif.Image.DateTime", exif->fake_datetime); + modified = TRUE; + } } if (strip_thumbnail && ! exifData.empty()) { diff --git a/src/jpeg-utils.h b/src/jpeg-utils.h index 89a2cd4..cc6c5c7 100644 --- a/src/jpeg-utils.h +++ b/src/jpeg-utils.h @@ -52,6 +52,7 @@ typedef struct { gchar *override_copyright; int timezone_shift; + time_t fake_datetime; } ExifData; |
