summaryrefslogtreecommitdiff
path: root/src/jpeg-utils.cpp
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@users.sourceforge.net>2012-04-15 21:44:31 +0200
committerTomas Bzatek <tbzatek@users.sourceforge.net>2012-04-15 21:44:31 +0200
commit713c2d86d9335a9c681357254d4bc4f817626259 (patch)
treec4cabe1b7dcf1d2f192fdcfc68d35e242305c949 /src/jpeg-utils.cpp
parentc5f23c17a14bbe07042f46be90fe2b2e465436c7 (diff)
downloadcataract-713c2d86d9335a9c681357254d4bc4f817626259.tar.xz
Change EXIF metadata handling into a registered function
This allows much greater flexibility from templates regarding EXIF metadata handling, no more hardcoded symbols. It's possible to display essentially any attribute known to Exiv2. Please see http://exiv2.org/metadata.html This brings two new functions that can be called from templates: * get_exif_value (exiv2_attribute) * get_exif_value_fixed (exiv2_attribute) Both functions take a string argument of metadata attribute name from Exiv2 namespace. The difference is that get_exif_value_fixed() does some extra formatting for several basic attributes (e.g. datetime format).
Diffstat (limited to 'src/jpeg-utils.cpp')
-rw-r--r--src/jpeg-utils.cpp320
1 files changed, 145 insertions, 175 deletions
diff --git a/src/jpeg-utils.cpp b/src/jpeg-utils.cpp
index 34d3997..031ecc0 100644
--- a/src/jpeg-utils.cpp
+++ b/src/jpeg-utils.cpp
@@ -30,204 +30,174 @@
#include "gallery-utils.h"
+struct ExifData {
+ Exiv2::Image::AutoPtr image;
+};
+
/*
- * get_exif: retrieve EXIF informations from a JPEG image
+ * EXIF and IPTC info retrieval, keeps the source file open until freed
*/
-TExifData *
-get_exif (const gchar *filename)
+ExifData *
+read_exif (const gchar *filename)
{
- TExifData *data;
+ ExifData *data;
- data = (TExifData*) g_malloc0 (sizeof (TExifData));
+ data = (ExifData*) g_malloc0 (sizeof (ExifData));
- try
- {
- Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open (filename);
- g_assert (image.get() != 0);
- image->readMetadata();
-
- Exiv2::ExifData &exifData = image->exifData();
- if (! exifData.empty()) {
- /* EXIF::Aperture */
- try {
- float val = exifData["Exif.Photo.FNumber"].toFloat();
- if (val >= 0)
- data->aperture = g_strdup_printf ("f/%.1f", val);
- } catch (...) { }
-
- /* EXIF::Camera model */
- try {
- data->camera_model = g_strdup (exifData["Exif.Image.Model"].toString().c_str());
- } catch (...) { }
-
- /* EXIF::DateTime */
- try {
- const char *val = NULL;
- try {
- val = exifData["Exif.Photo.DateTimeOriginal"].toString().c_str();
- } catch (...) { }
- if (! val || strlen (val) == 0)
- try {
- val = exifData["Exif.Image.DateTime"].toString().c_str();
- } catch (...) { }
-
- if (val && strlen (val) > 0) {
- struct tm tt;
- char conv[1024];
-
- memset (&conv, 0, sizeof (conv));
- memset (&tt, 0, sizeof (struct tm));
-
- if (sscanf (val, "%d:%d:%d %d:%d:%d", &tt.tm_year, &tt.tm_mon, &tt.tm_mday, &tt.tm_hour, &tt.tm_min, &tt.tm_sec) == 6)
- {
- tt.tm_year -= 1900;
- tt.tm_mon--;
- mktime (&tt);
- if (strftime (&conv[0], sizeof (conv), "%c", &tt))
- data->datetime = g_strdup (&conv[0]);
- }
- }
- } catch (...) { }
-
- /* EXIF::Shutter speed */
- try {
- float val = exifData["Exif.Photo.ExposureTime"].toFloat();
- if (val > 0) {
- if (val < 0.5)
- data->exposure = g_strdup_printf ("1/%.0f s", 1/val);
- else
- data->exposure = g_strdup_printf ("%.1f s", val);
- }
- } catch (...) { }
-
- /* EXIF::Flash */
- try {
- long int val = exifData["Exif.Photo.Flash"].toLong();
- if (val > 0 && (val & 1) == 1)
- data->flash = g_strdup ("Flash fired");
- else
- data->flash = g_strdup ("--");
- } catch (...) { }
-
- /* EXIF::Focal length */
- try {
- float val = exifData["Exif.Photo.FocalLength"].toFloat();
- if (val >= 0)
- data->focal_length = g_strdup_printf ("%.0f mm", val);
- } catch (...) { }
-
- /* EXIF::ISO */
- try {
- long int val = exifData["Exif.Photo.ISOSpeedRatings"].toLong();
- if (val > 0)
- data->iso = g_strdup_printf ("%ld", val);
- } catch (...) { }
-
- /* EXIF::Software */
- try {
- data->exif_software = g_strdup (exifData["Exif.Image.Software"].toString().c_str());
- } catch (...) { }
-
- /* EXIF::Image description */
- try {
- data->exif_imgdesc = g_strdup (exifData["Exif.Image.ImageDescription"].toString().c_str());
- } catch (...) { }
-
- /* EXIF::Artist */
- try {
- data->exif_artist = g_strdup (exifData["Exif.Image.Artist"].toString().c_str());
- } catch (...) { }
-
- /* EXIF::Copyright */
- try {
- data->exif_copyright = g_strdup (exifData["Exif.Image.Copyright"].toString().c_str());
- } catch (...) { }
-
- /* EXIF::User comment */
- try {
- data->exif_usercomment = g_strdup (exifData["Exif.Photo.UserComment"].toString().c_str());
- } catch (...) { }
- }
-
- Exiv2::IptcData &iptcData = image->iptcData();
- if (! iptcData.empty()) {
- /* IPTC::Object name */
- try {
- data->iptc_objectname = g_strdup (iptcData["Iptc.Application2.ObjectName"].toString().c_str());
- } catch (...) { }
-
- /* IPTC::Copyright */
- try {
- data->iptc_copyright = g_strdup (iptcData["Iptc.Application2.Copyright"].toString().c_str());
- } catch (...) { }
-
- /* IPTC::Credit */
- try {
- data->iptc_credit = g_strdup (iptcData["Iptc.Application2.Credit"].toString().c_str());
- } catch (...) { }
-
- /* IPTC::Caption */
- try {
- data->iptc_caption = g_strdup (iptcData["Iptc.Application2.Caption"].toString().c_str());
- } catch (...) { }
-
- /* IPTC::Author */
- try {
- data->iptc_author = g_strdup (iptcData["Iptc.Application2.Byline"].toString().c_str());
- } catch (...) { }
- }
-
- /* JPEG::Comment */
- try {
- data->jpeg_comment = g_strdup (image->comment().c_str());
- } catch (...) { }
+ try {
+ data->image = Exiv2::ImageFactory::open (filename);
+ g_assert (data->image.get() != 0);
+ data->image->readMetadata();
}
catch (Exiv2::AnyError& e)
{
- log_error ("get_exif: Caught Exiv2 exception: '%s'\n", e.what());
- free_exif_data (data);
+ log_error ("read_exif: Caught Exiv2 exception: '%s'\n", e.what());
+ exif_data_free (data);
return NULL;
}
return data;
}
-/*
- * free_exif_struct: free allocated structure
- */
void
-free_exif_data (TExifData *data)
+exif_data_free (ExifData *data)
{
if (data) {
- g_free (data->aperture);
- g_free (data->camera_model);
- g_free (data->datetime);
- g_free (data->exposure);
- g_free (data->flash);
- g_free (data->focal_length);
- g_free (data->focal_length_35mm);
- g_free (data->iso);
-
- g_free (data->exif_software);
- g_free (data->exif_imgdesc);
- g_free (data->exif_artist);
- g_free (data->exif_copyright);
- g_free (data->exif_usercomment);
-
- g_free (data->iptc_objectname);
- g_free (data->iptc_copyright);
- g_free (data->iptc_credit);
- g_free (data->iptc_caption);
- g_free (data->iptc_author);
-
- g_free (data->jpeg_comment);
-
+ /* FIXME: free data->image */
g_free (data);
}
}
+/*
+ * Retrieves value of the specified key or NULL if the key does not exist.
+ * The key argument belongs to Exiv2 namespace - see http://exiv2.org/tags.html
+ */
+gchar *
+get_exif_data (ExifData *exif, const gchar *key)
+{
+ try {
+ if (g_strcmp0 (key, JPEG_COMMENT) == 0) {
+ return g_strdup (exif->image->comment().c_str());
+ }
+
+ if (g_str_has_prefix (key, "Exif.")) {
+ Exiv2::ExifData &exifData = exif->image->exifData();
+ if (! exifData.empty()) {
+ return g_strdup (exifData[key].toString().c_str());
+ }
+ }
+
+ if (g_str_has_prefix (key, "Iptc.")) {
+ Exiv2::IptcData &iptcData = exif->image->iptcData();
+ if (! iptcData.empty()) {
+ return g_strdup (iptcData[key].toString().c_str());
+ }
+ }
+
+ return NULL;
+ }
+ catch (...) {
+ return NULL;
+ }
+}
+
+gchar *
+get_exif_data_fixed (ExifData *exif, const gchar *key)
+{
+ try
+ {
+ if (g_str_has_prefix (key, EXIF_APERTURE)) {
+ Exiv2::ExifData &exifData = exif->image->exifData();
+ if (! exifData.empty()) {
+ float val = exifData["Exif.Photo.FNumber"].toFloat();
+ if (val >= 0)
+ return g_strdup_printf ("f/%.1f", val);
+ }
+ }
+
+ if (g_str_has_prefix (key, EXIF_DATETIME)) {
+ Exiv2::ExifData &exifData = exif->image->exifData();
+ if (! exifData.empty()) {
+ const char *val = NULL;
+ try {
+ val = exifData["Exif.Photo.DateTimeOriginal"].toString().c_str();
+ } catch (...) { }
+ if (! val || strlen (val) == 0)
+ try {
+ val = exifData["Exif.Image.DateTime"].toString().c_str();
+ } catch (...) { }
+
+ if (val && strlen (val) > 0) {
+ struct tm tt;
+ char conv[1024];
+
+ memset (&conv, 0, sizeof (conv));
+ memset (&tt, 0, sizeof (struct tm));
+
+ if (sscanf (val, "%d:%d:%d %d:%d:%d", &tt.tm_year, &tt.tm_mon, &tt.tm_mday, &tt.tm_hour, &tt.tm_min, &tt.tm_sec) == 6)
+ {
+ tt.tm_year -= 1900;
+ tt.tm_mon--;
+ mktime (&tt);
+ if (strftime (&conv[0], sizeof (conv), "%c", &tt))
+ return g_strdup (&conv[0]);
+ }
+ }
+ }
+ }
+
+ if (g_str_has_prefix (key, EXIF_EXPOSURE)) {
+ Exiv2::ExifData &exifData = exif->image->exifData();
+ if (! exifData.empty()) {
+ float val = exifData["Exif.Photo.ExposureTime"].toFloat();
+ if (val > 0) {
+ if (val < 0.5)
+ return g_strdup_printf ("1/%.0f s", 1/val);
+ else
+ return g_strdup_printf ("%.1f s", val);
+ }
+ }
+ }
+
+ if (g_str_has_prefix (key, EXIF_FLASH)) {
+ Exiv2::ExifData &exifData = exif->image->exifData();
+ if (! exifData.empty()) {
+ long int val = exifData["Exif.Photo.Flash"].toLong();
+ if (val > 0 && (val & 1) == 1)
+ return g_strdup ("Flash fired");
+ else
+ return g_strdup ("--");
+ }
+ }
+
+ if (g_str_has_prefix (key, EXIF_FOCAL_LENGTH)) {
+ Exiv2::ExifData &exifData = exif->image->exifData();
+ if (! exifData.empty()) {
+ float val = exifData["Exif.Photo.FocalLength"].toFloat();
+ if (val >= 0)
+ return g_strdup_printf ("%.0f mm", val);
+ }
+ }
+
+ if (g_str_has_prefix (key, EXIF_ISO)) {
+ Exiv2::ExifData &exifData = exif->image->exifData();
+ if (! exifData.empty()) {
+ long int val = exifData["Exif.Photo.ISOSpeedRatings"].toLong();
+ if (val > 0)
+ return g_strdup_printf ("%ld", val);
+ }
+ }
+ }
+ catch (...) {
+ return NULL;
+ }
+
+ return get_exif_data (exif, key);
+}
+
+
static void
autorotate_image (MagickWand *magick_wand)
{