summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@users.sourceforge.net>2015-08-29 16:09:11 +0200
committerTomas Bzatek <tbzatek@users.sourceforge.net>2015-08-29 16:09:11 +0200
commit5879c2a9aa8daf148d6ef7694f5e959c5207f40f (patch)
treea91e2e0a06a45ecb3748407402a1df1f51dada56
parent9f927315eb2536ac37d67ed304c02bcd4ea755c9 (diff)
downloadcataract-5879c2a9aa8daf148d6ef7694f5e959c5207f40f.tar.xz
jpeg-utils: Filter out certain tags from external EXIF file
Turned out that we shouldn't blindly copy all metadata from the supplied external EXIF file since they belong to a different image. This includes image size, JPEG compression parameters, rotation etc. This commit adds tag filtering so that not all tags are copied, retaining the important ones from the gallery image. The list of retained tags is by no means complete and is subject to future tweaks. For the moment this feature is recommended to be turned off (and is by default).
-rw-r--r--sample/src/setup.xml2
-rw-r--r--src/jpeg-utils.cpp81
2 files changed, 82 insertions, 1 deletions
diff --git a/sample/src/setup.xml b/sample/src/setup.xml
index 6b55c16..a2bb2b2 100644
--- a/sample/src/setup.xml
+++ b/sample/src/setup.xml
@@ -32,6 +32,8 @@
<!-- in case of supplied external EXIF data, shall these be written in generated images? -->
<!-- This will make image files carry the same data as used for pages -->
<!-- (allowed values: "yes", "no") default = "no" as this could overwrite important data -->
+ <!-- WARNING: this may possibly import mismatching metadata -->
+ <!-- (think of source RAW file vs. processed JPEG image differences) -->
<write_supplied_exif value="no" />
<!-- don't copy full size (original) images -->
diff --git a/src/jpeg-utils.cpp b/src/jpeg-utils.cpp
index e0c4fdf..965d751 100644
--- a/src/jpeg-utils.cpp
+++ b/src/jpeg-utils.cpp
@@ -722,6 +722,85 @@ override_iptc_time (Exiv2::IptcData &iptcData, const char *date_key, const char
return FALSE;
}
+
+/* List of tags we don't want to copy from external EXIF data since they are related to the RAW file,
+ * not the processed image. Note that this list is not by far complete.
+ */
+static const gchar * image_size_tags[] = {
+ "Exif.Image.ImageWidth",
+ "Exif.Image.ImageHeight",
+ "Exif.Image.ImageLength",
+ "Exif.Image.Orientation",
+ "Exif.Photo.PixelXDimension",
+ "Exif.Photo.PixelYDimension",
+ "Exif.Image.XResolution",
+ "Exif.Image.YResolution",
+ "Exif.Image.ResolutionUnit",
+ "Exif.Image.Compression",
+ "Exif.Image.BitsPerSample",
+ "Exif.Image.SamplesPerPixel",
+ "Exif.Photo.ComponentsConfiguration",
+ "Exif.Photo.CompressedBitsPerPixel",
+ "Exif.Image.JPEGTables",
+ "Exif.Image.JPEGProc",
+ "Exif.Image.JPEGInterchangeFormat",
+ "Exif.Image.JPEGInterchangeFormatLength",
+ "Exif.Image.JPEGRestartInterval",
+ "Exif.Image.JPEGLosslessPredictors",
+ "Exif.Image.JPEGPointTransforms",
+ "Exif.Image.JPEGQTables",
+ "Exif.Image.JPEGDCTables",
+ "Exif.Image.JPEGACTables",
+ "Exif.Image.YCbCrCoefficients",
+ "Exif.Image.YCbCrSubSampling",
+ "Exif.Image.YCbCrPositioning",
+ "Exif.Image.ReferenceBlackWhite",
+ "Exif.Image.PhotometricInterpretation",
+ "Exif.Image.PlanarConfiguration",
+};
+
+static gboolean
+is_image_size_tag (const gchar *s)
+{
+ unsigned int i;
+
+ for (i = 0; i < G_N_ELEMENTS (image_size_tags); i++)
+ if (g_str_equal (s, image_size_tags[i]))
+ return TRUE;
+ return FALSE;
+}
+
+static void
+copy_metadata (Exiv2::Image::AutoPtr &img, Exiv2::Image::AutoPtr &external_img)
+{
+ Exiv2::ExifData exifData;
+ Exiv2::ExifData &img_exifData = img->exifData();
+ Exiv2::ExifData &ext_exifData = external_img->exifData();
+
+ /* First copy metadata from the external image excluding size tags */
+ Exiv2::ExifData::const_iterator end = ext_exifData.end();
+ for (Exiv2::ExifData::const_iterator i = ext_exifData.begin(); i != end; ++i) {
+ gchar *s = g_strdup (i->key().c_str());
+ if (! is_image_size_tag (s))
+ exifData[s] = ext_exifData[s];
+ g_free (s);
+ }
+
+ /* Copy selected size tags from the processed image */
+ end = img_exifData.end();
+ for (Exiv2::ExifData::const_iterator i = img_exifData.begin(); i != end; ++i) {
+ gchar *s = g_strdup (i->key().c_str());
+ if (is_image_size_tag (s))
+ exifData[s] = img_exifData[s];
+ g_free (s);
+ }
+
+ img->setMetadata (*external_img);
+ img->setExifData (exifData);
+}
+
+
+
/*
* modify_exif: - strip thumbnail stored in EXIF table
* - write down overriden keys
@@ -750,7 +829,7 @@ modify_exif (const gchar *filename, ExifData *exif, gboolean strip_thumbnail, gb
if (ext_image.get() != 0) {
ext_image->clearMetadata();
ext_image->readMetadata();
- image->setMetadata (*ext_image);
+ copy_metadata (image, ext_image);
modified = TRUE;
}
}