From 5879c2a9aa8daf148d6ef7694f5e959c5207f40f Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Sat, 29 Aug 2015 16:09:11 +0200 Subject: 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). --- sample/src/setup.xml | 2 ++ src/jpeg-utils.cpp | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 82 insertions(+), 1 deletion(-) 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 @@ + + 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; } } -- cgit v1.2.3