summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/generators.c3
-rw-r--r--src/items.c52
-rw-r--r--src/items.h2
-rw-r--r--src/jpeg-utils.cpp112
-rw-r--r--src/jpeg-utils.h1
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;