summaryrefslogtreecommitdiff
path: root/src/libtracker-extract/tracker-exif.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libtracker-extract/tracker-exif.c')
-rw-r--r--src/libtracker-extract/tracker-exif.c643
1 files changed, 0 insertions, 643 deletions
diff --git a/src/libtracker-extract/tracker-exif.c b/src/libtracker-extract/tracker-exif.c
deleted file mode 100644
index 3e70169e1..000000000
--- a/src/libtracker-extract/tracker-exif.c
+++ /dev/null
@@ -1,643 +0,0 @@
-/*
- * Copyright (C) 2009, Nokia <ivan.frade@nokia.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-
-#include <string.h>
-#include <ctype.h>
-
-#include "tracker-exif.h"
-#include "tracker-utils.h"
-
-#ifdef HAVE_LIBEXIF
-
-#include <libexif/exif-data.h>
-
-#define EXIF_DATE_FORMAT "%Y:%m:%d %H:%M:%S"
-
-/**
- * SECTION:tracker-exif
- * @title: Exif
- * @short_description: Exchangeable Image File Format (EXIF)
- * @stability: Stable
- * @include: libtracker-extract/tracker-extract.h
- *
- * Exchangeable Image File Format (EXIF) is a specification for the
- * image file format used by digital cameras. The specification uses
- * the existing JPEG, TIFF Rev. 6.0, and RIFF WAV file formats, with
- * the addition of specific metadata tags. It is not supported in JPEG
- * 2000, PNG, or GIF.
- *
- * This API is provided to remove code duplication between extractors
- * using these standards.
- **/
-
-static gchar *
-get_date (ExifData *exif,
- ExifTag tag)
-{
- ExifEntry *entry = exif_data_get_entry (exif, tag);
-
- if (entry) {
- gchar buf[1024];
-
- exif_entry_get_value (entry, buf, 1024);
- /* From: ex; date "2007:04:15 15:35:58"
- * To : ex. "2007-04-15T17:35:58+0200 where +0200 is offset w.r.t gmt */
- return tracker_date_format_to_iso8601 (buf, EXIF_DATE_FORMAT);
- }
-
- return NULL;
-}
-
-static gchar *
-get_focal_length (ExifData *exif,
- ExifTag tag)
-{
- ExifEntry *entry = exif_data_get_entry (exif, tag);
-
- if (entry) {
- gchar buf[1024];
- const gchar *end;
- exif_entry_get_value (entry, buf, 1024);
- end = g_strstr_len (buf, 1024, " mm");
- if (end) {
- return g_strndup (buf, end - buf);
- } else {
- return NULL;
- }
- }
-
- return NULL;
-}
-
-static gchar *
-get_flash (ExifData *exif,
- ExifTag tag)
-{
- ExifEntry *entry = exif_data_get_entry (exif, tag);
-
- if (entry) {
- ExifByteOrder order;
- gushort flash;
-
- order = exif_data_get_byte_order (exif);
- flash = exif_get_short (entry->data, order);
-
- switch (flash) {
- case 0x0000: /* No flash */
- case 0x0005: /* Without strobe */
- case 0x0008: /* Flash did not fire */
- case 0x0010: /* Flash in compulsory mode, did not fire */
- case 0x0018: /* Flash in auto mode, did not fire */
- case 0x0058: /* Only red-eye reduction mode */
- return g_strdup ("nmm:flash-off");
- default:
- return g_strdup ("nmm:flash-on");
- }
- }
-
- return NULL;
-}
-
-static gchar *
-get_fnumber (ExifData *exif,
- ExifTag tag)
-{
- ExifEntry *entry = exif_data_get_entry (exif, tag);
-
- if (entry) {
- gchar buf[1024];
- gchar *new_fn;
-
- exif_entry_get_value (entry, buf, 1024);
-
- if (strlen (buf) <= 0) {
- return NULL;
- }
-
- new_fn = g_strdup (buf);
-
- if (new_fn[0] == 'F') {
- new_fn[0] = ' ';
- } else if (buf[0] == 'f' && new_fn[1] == '/') {
- new_fn[0] = new_fn[1] = ' ';
- }
-
- return g_strstrip (new_fn);
- }
-
- return NULL;
-}
-
-static gchar *
-get_exposure_time (ExifData *exif,
- ExifTag tag)
-{
- ExifEntry *entry = exif_data_get_entry (exif, tag);
-
- if (entry) {
- gchar buf[1024];
- gchar *sep;
-
- exif_entry_get_value (entry, buf, 1024);
-
- sep = strchr (buf, '/');
-
- if (sep) {
- gdouble fraction;
-
- fraction = g_ascii_strtod (sep + 1, NULL);
-
- if (fraction > 0.0) {
- gdouble val;
- gchar bufr[G_ASCII_DTOSTR_BUF_SIZE];
-
- val = 1.0f / fraction;
- g_ascii_dtostr (bufr, sizeof(bufr), val);
-
- return g_strdup (bufr);
- }
- }
-
- return g_strdup (buf);
- }
-
- return NULL;
-}
-
-static gchar *
-get_orientation (ExifData *exif,
- ExifTag tag)
-{
- ExifEntry *entry = exif_data_get_entry (exif, tag);
-
- if (entry) {
- ExifByteOrder order;
- gushort orientation;
-
- order = exif_data_get_byte_order (exif);
- orientation = exif_get_short (entry->data, order);
-
- switch (orientation) {
- case 1:
- return g_strdup ("nfo:orientation-top");
- case 2:
- return g_strdup ("nfo:orientation-top-mirror");
- case 3:
- return g_strdup ("nfo:orientation-bottom");
- case 4:
- return g_strdup ("nfo:orientation-bottom-mirror");
- case 5:
- return g_strdup ("nfo:orientation-left-mirror");
- case 6:
- return g_strdup ("nfo:orientation-right");
- case 7:
- return g_strdup ("nfo:orientation-right-mirror");
- case 8:
- return g_strdup ("nfo:orientation-left");
- default:
- return g_strdup ("nfo:orientation-top");
- }
- }
-
- return NULL;
-}
-
-static gchar *
-get_metering_mode (ExifData *exif,
- ExifTag tag)
-{
- ExifEntry *entry = exif_data_get_entry (exif, tag);
-
- if (entry) {
- ExifByteOrder order;
- gushort metering;
-
- order = exif_data_get_byte_order (exif);
- metering = exif_get_short (entry->data, order);
-
- switch (metering) {
- case 1:
- return g_strdup ("nmm:metering-mode-average");
- case 2:
- return g_strdup ("nmm:metering-mode-center-weighted-average");
- case 3:
- return g_strdup ("nmm:metering-mode-spot");
- case 4:
- return g_strdup ("nmm:metering-mode-multispot");
- case 5:
- return g_strdup ("nmm:metering-mode-pattern");
- case 6:
- return g_strdup ("nmm:metering-mode-partial");
- default:
- return g_strdup ("nmm:metering-mode-other");
- }
- }
-
- return NULL;
-}
-
-static gchar *
-get_white_balance (ExifData *exif,
- ExifTag tag)
-{
- ExifEntry *entry = exif_data_get_entry (exif, tag);
-
- if (entry) {
- ExifByteOrder order;
- gushort white_balance;
-
- order = exif_data_get_byte_order (exif);
- white_balance = exif_get_short (entry->data, order);
-
- if (white_balance == 0)
- return g_strdup ("nmm:white-balance-auto");
-
- /* Found in the field: sunny, fluorescent, incandescent, cloudy.
- * These will this way also yield as manual. */
- return g_strdup ("nmm:white-balance-manual");
- }
-
- return NULL;
-}
-
-static gchar *
-get_gps_coordinate (ExifData *exif,
- ExifTag tag,
- ExifTag reftag)
-{
- ExifEntry *entry = exif_data_get_entry (exif, tag);
- ExifEntry *refentry = exif_data_get_entry (exif, reftag);
-
- if (entry && refentry) {
- ExifByteOrder order;
- ExifRational degrees, minutes, seconds;
- gfloat f;
- gchar ref;
-
- if (entry->size == 24) {
- order = exif_data_get_byte_order (exif);
- degrees = exif_get_rational (entry->data, order);
- minutes = exif_get_rational (entry->data + 8, order);
- seconds = exif_get_rational (entry->data + 16, order);
- ref = exif_get_short (refentry->data, order);
-
- /* Avoid ridiculous values */
- if (degrees.denominator == 0 ||
- minutes.denominator == 0 ||
- seconds.denominator == 0) {
- return NULL;
- }
-
- f = (gdouble) degrees.numerator / degrees.denominator +
- (gdouble) minutes.numerator / (minutes.denominator * 60) +
- (gdouble) seconds.numerator / (seconds.denominator * 60 * 60);
-
- if (ref == 'S' || ref == 'W') {
- f = -1 * f;
- }
-
- return g_strdup_printf ("%f", f);
- } else {
- gchar buf[25] = { 0 };
-
- /* Incomplete data or it doesn't exist, fall
- * back to exif_entry_get_value() for safety.
- */
- exif_entry_get_value (entry, buf, sizeof (buf) - 1);
-
- if (buf[0] == '\0') {
- g_message ("EXIF GPS coordinate information is non-existent but EXIF tag '%s' was found, "
- "possible broken EXIF data?",
- exif_tag_get_name (tag));
- } else {
- g_message ("EXIF GPS coordinate information is partial, "
- "got EXIF tag '%s' with value '%s', "
- "expected with degrees, minutes and seconds",
- exif_tag_get_name (tag),
- buf);
- }
-
- g_message ("EXIF GPS coordinate information could not be extracted with tag '%s'",
- exif_tag_get_name (tag));
- }
- }
-
- return NULL;
-}
-
-static gchar *
-get_gps_altitude (ExifData *exif,
- ExifTag tag,
- ExifTag reftag)
-{
- ExifEntry *entry = exif_data_get_entry (exif, tag);
- ExifEntry *refentry = exif_data_get_entry (exif, reftag);
-
- if (entry) {
- ExifByteOrder order;
- ExifRational c;
- gfloat f;
-
- order = exif_data_get_byte_order (exif);
- c = exif_get_rational (entry->data, order);
-
- /* Avoid ridiculous values */
- if (c.denominator == 0) {
- return NULL;
- }
-
- f = (double)c.numerator/c.denominator;
-
- /* Strictly speaking it is invalid not to have this
- but.. let's try to cope here */
- if (refentry) {
- ExifShort ref;
- ref = exif_get_short (refentry->data, order);
- if (ref == 1) {
- f = -1 * f;
- }
- }
- return g_strdup_printf ("%f", f);
- }
-
- return NULL;
-}
-
-static gint
-get_int (ExifData *exif,
- ExifTag tag)
-{
- ExifEntry *entry = exif_data_get_entry (exif, tag);
-
- if (entry) {
- ExifByteOrder order;
-
- order = exif_data_get_byte_order (exif);
- return (gint) exif_get_short (entry->data, order);
- }
-
- return -1;
-}
-
-
-static gchar *
-get_value (ExifData *exif,
- ExifTag tag)
-{
- ExifEntry *entry = exif_data_get_entry (exif, tag);
-
- if (entry) {
- gchar buf[1024];
-
- exif_entry_get_value (entry, buf, 1024);
-
- return g_strdup (buf);
- }
-
- return NULL;
-}
-
-#endif /* HAVE_LIBEXIF */
-
-static gboolean
-parse_exif (const unsigned char *buffer,
- size_t len,
- const gchar *uri,
- TrackerExifData *data)
-{
-#ifdef HAVE_LIBEXIF
- ExifData *exif;
-#endif
-
- memset (data, 0, sizeof (TrackerExifData));
-
-#ifdef HAVE_LIBEXIF
-
- exif = exif_data_new ();
-
- g_return_val_if_fail (exif != NULL, FALSE);
-
- exif_data_set_option (exif, EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS);
- exif_data_unset_option (exif, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
- exif_data_set_option (exif, EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE);
-
- exif_data_load_data (exif, (unsigned char *) buffer, len);
-
- /* Unused in the current only user of this code (JPeg extractor)
- if (!data->y_dimension)
- data->y_dimension = get_value (exif, EXIF_TAG_PIXEL_Y_DIMENSION);
- if (!data->x_dimension)
- data->x_dimension = get_value (exif, EXIF_TAG_PIXEL_X_DIMENSION);
- if (!data->image_width)
- data->image_width = get_value (exif, EXIF_TAG_RELATED_IMAGE_WIDTH);
- */
-
- if (!data->document_name)
- data->document_name = get_value (exif, EXIF_TAG_DOCUMENT_NAME);
- if (!data->time)
- data->time = get_date (exif, EXIF_TAG_DATE_TIME);
- if (!data->time_original)
- data->time_original = get_date (exif, EXIF_TAG_DATE_TIME_ORIGINAL);
- if (!data->artist)
- data->artist = get_value (exif, EXIF_TAG_ARTIST);
- if (!data->user_comment)
- data->user_comment = get_value (exif, EXIF_TAG_USER_COMMENT);
- if (!data->description)
- data->description = get_value (exif, EXIF_TAG_IMAGE_DESCRIPTION);
- if (!data->make)
- data->make = get_value (exif, EXIF_TAG_MAKE);
- if (!data->model)
- data->model = get_value (exif, EXIF_TAG_MODEL);
- if (!data->orientation)
- data->orientation = get_orientation (exif, EXIF_TAG_ORIENTATION);
- if (!data->exposure_time)
- data->exposure_time = get_exposure_time (exif, EXIF_TAG_EXPOSURE_TIME);
- if (!data->fnumber)
- data->fnumber = get_fnumber (exif, EXIF_TAG_FNUMBER);
- if (!data->flash)
- data->flash = get_flash (exif, EXIF_TAG_FLASH);
- if (!data->focal_length)
- data->focal_length = get_focal_length (exif, EXIF_TAG_FOCAL_LENGTH);
- if (!data->iso_speed_ratings)
- data->iso_speed_ratings = get_value (exif, EXIF_TAG_ISO_SPEED_RATINGS);
- if (!data->metering_mode)
- data->metering_mode = get_metering_mode (exif, EXIF_TAG_METERING_MODE);
- if (!data->white_balance)
- data->white_balance = get_white_balance (exif, EXIF_TAG_WHITE_BALANCE);
- if (!data->copyright) {
- gchar *strip_off;
- data->copyright = get_value (exif, EXIF_TAG_COPYRIGHT);
- if (data->copyright) {
- /* Exif catenates this to the string, noticed the
- * string change from below in libexif 0.6.20 */
- strip_off = strstr (data->copyright, " (Photographer) - [None] (Editor)");
- if (strip_off) {
- *strip_off = '\0';
- } else {
- /* Fall back to old string */
- strip_off = strstr (data->copyright, " (Photographer) - (Editor)");
-
- if (strip_off) {
- *strip_off = '\0';
- }
- }
- }
- }
- if (!data->software)
- data->software = get_value (exif, EXIF_TAG_SOFTWARE);
-
- if (!data->resolution_unit)
- data->resolution_unit = get_int (exif, EXIF_TAG_RESOLUTION_UNIT);
- if (!data->x_resolution)
- data->x_resolution = get_value (exif, EXIF_TAG_X_RESOLUTION);
- if (!data->y_resolution)
- data->y_resolution = get_value (exif, EXIF_TAG_Y_RESOLUTION);
-
- if(!data->gps_altitude)
- data->gps_altitude = get_gps_altitude (exif, EXIF_TAG_GPS_ALTITUDE, EXIF_TAG_GPS_ALTITUDE_REF);
- if(!data->gps_latitude)
- data->gps_latitude = get_gps_coordinate (exif, EXIF_TAG_GPS_LATITUDE, EXIF_TAG_GPS_LATITUDE_REF);
- if(!data->gps_longitude)
- data->gps_longitude = get_gps_coordinate (exif, EXIF_TAG_GPS_LONGITUDE, EXIF_TAG_GPS_LONGITUDE_REF);
- if(!data->gps_direction)
- data->gps_direction = get_value (exif, EXIF_TAG_GPS_IMG_DIRECTION);
-
- exif_data_free (exif);
-#endif /* HAVE_LIBEXIF */
-
- return TRUE;
-}
-
-#ifndef TRACKER_DISABLE_DEPRECATED
-
-/**
- * tracker_exif_read:
- * @buffer: a chunk of data with exif data in it.
- * @len: the size of @buffer.
- * @uri: the URI this is related to.
- * @data: a pointer to a TrackerExifData struture to populate.
- *
- * This function takes @len bytes of @buffer and runs it through the
- * EXIF library. The result is that @data is populated with the EXIF
- * data found in @uri.
- *
- * Returns: %TRUE if the @data was populated successfully, otherwise
- * %FALSE is returned.
- *
- * Since: 0.8
- *
- * Deprecated: 0.9. Use tracker_exif_new() instead.
- **/
-gboolean
-tracker_exif_read (const unsigned char *buffer,
- size_t len,
- const gchar *uri,
- TrackerExifData *data)
-{
- g_return_val_if_fail (buffer != NULL, FALSE);
- g_return_val_if_fail (len > 0, FALSE);
- g_return_val_if_fail (uri != NULL, FALSE);
- g_return_val_if_fail (data != NULL, FALSE);
-
- return parse_exif (buffer, len, uri, data);
-}
-
-#endif /* TRACKER_DISABLE_DEPRECATED */
-
-/**
- * tracker_exif_new:
- * @buffer: a chunk of data with exif data in it.
- * @len: the size of @buffer.
- * @uri: the URI this is related to.
- *
- * This function takes @len bytes of @buffer and runs it through the
- * EXIF library.
- *
- * Returns: a newly allocated #TrackerExifData struct if EXIF data was
- * found, %NULL otherwise. Free the returned struct with tracker_exif_free().
- *
- * Since: 0.10
- **/
-TrackerExifData *
-tracker_exif_new (const guchar *buffer,
- size_t len,
- const gchar *uri)
-{
- TrackerExifData *data;
-
- g_return_val_if_fail (buffer != NULL, NULL);
- g_return_val_if_fail (len > 0, NULL);
- g_return_val_if_fail (uri != NULL, NULL);
-
- data = g_new0 (TrackerExifData, 1);
-
- if (!parse_exif (buffer, len, uri, data)) {
- tracker_exif_free (data);
- return NULL;
- }
-
- return data;
-}
-
-/**
- * tracker_exif_free:
- * @data: a #TrackerExifData
- *
- * Frees @data and all #TrackerExifData members. %NULL will produce a
- * a warning.
- *
- * Since: 0.10
- **/
-void
-tracker_exif_free (TrackerExifData *data)
-{
- g_return_if_fail (data != NULL);
-
- g_free (data->y_dimension);
- g_free (data->x_dimension);
- g_free (data->image_width);
- g_free (data->document_name);
- g_free (data->time);
- g_free (data->time_original);
- g_free (data->artist);
- g_free (data->user_comment);
- g_free (data->description);
- g_free (data->make);
- g_free (data->model);
- g_free (data->orientation);
- g_free (data->exposure_time);
- g_free (data->fnumber);
- g_free (data->flash);
- g_free (data->focal_length);
- g_free (data->iso_speed_ratings);
- g_free (data->metering_mode);
- g_free (data->white_balance);
- g_free (data->copyright);
- g_free (data->software);
- g_free (data->x_resolution);
- g_free (data->y_resolution);
- g_free (data->gps_altitude);
- g_free (data->gps_latitude);
- g_free (data->gps_longitude);
- g_free (data->gps_direction);
-
- g_free (data);
-}