diff options
Diffstat (limited to 'src/jpeg-utils.cpp')
| -rw-r--r-- | src/jpeg-utils.cpp | 320 |
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) { |
