[tracker] Fixed the TIFF extractor for the new image ontology



commit 0e48339c88fe619e7020b827047f9af2a006eaf4
Author: Philip Van Hoof <philip codeminded be>
Date:   Thu Apr 16 16:08:01 2009 +0200

    Fixed the TIFF extractor for the new image ontology
---
 src/tracker-extract/tracker-extract-jpeg.c |    1 -
 src/tracker-extract/tracker-extract-tiff.c |  318 ++++++++++++++++++++++++----
 2 files changed, 280 insertions(+), 39 deletions(-)

diff --git a/src/tracker-extract/tracker-extract-jpeg.c b/src/tracker-extract/tracker-extract-jpeg.c
index e0062cb..89f0e16 100644
--- a/src/tracker-extract/tracker-extract-jpeg.c
+++ b/src/tracker-extract/tracker-extract-jpeg.c
@@ -35,7 +35,6 @@
 #include <string.h>
 #include <fcntl.h>
 
-#include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
diff --git a/src/tracker-extract/tracker-extract-tiff.c b/src/tracker-extract/tracker-extract-tiff.c
index 821cd22..cf1fc4b 100644
--- a/src/tracker-extract/tracker-extract-tiff.c
+++ b/src/tracker-extract/tracker-extract-tiff.c
@@ -21,6 +21,16 @@
 
 #include "config.h"
 
+#include <stdio.h>
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE /* strcasestr() */
+#endif
+
+#include <ctype.h>
+#include <string.h>
+#include <fcntl.h>
+
 #include <glib.h>
 #include <glib/gstdio.h>
 
@@ -31,6 +41,7 @@
 #include <libtracker-common/tracker-type-utils.h>
 #include <libtracker-common/tracker-statement-list.h>
 #include <libtracker-common/tracker-file-utils.h>
+#include <libtracker-common/tracker-utils.h>
 
 #include "tracker-main.h"
 #include "tracker-xmp.h"
@@ -47,7 +58,7 @@
 #define RDF_PREFIX TRACKER_RDF_PREFIX
 #define RDF_TYPE RDF_PREFIX "type"
 
-typedef gchar * (*PostProcessor) (gchar *);
+typedef gchar * (*PostProcessor) (const gchar *, gboolean *);
 
 typedef enum {
 	TIFF_TAGTYPE_UNDEFINED = 0,
@@ -63,56 +74,270 @@ typedef struct {
 	const gchar   *name;
 	TagType        type;
 	PostProcessor  post;
+	const gchar  *rdf_class;
+	const gchar  *rdf_property;
+	const gchar  *urn_prefix;
 } TiffTag;
  
 static void   extract_tiff    (const gchar *filename,
 			       GPtrArray   *metadata);
-static gchar *date_to_iso8601 (gchar       *date);
+
+static gchar *date_to_iso8601	(const gchar *exif_date, gboolean *free_it);
+static gchar *fix_focal_length	(const gchar *fl, gboolean *free_it);
+static gchar *fix_flash		(const gchar *flash, gboolean *free_it);
+static gchar *fix_fnumber	(const gchar *fn, gboolean *free_it);
+static gchar *fix_exposure_time (const gchar *et, gboolean *free_it);
+static gchar *fix_orientation   (const gchar *orientation, gboolean *free_it);
+static gchar *fix_metering_mode (const gchar *metering_mode, gboolean *free_it);
+static gchar *fix_white_balance (const gchar *white_balance, gboolean *free_it);
 
 static TrackerExtractData extract_data[] = {
 	{ "image/tiff", extract_tiff },
 	{ NULL, NULL }
 };
 
+
+
 /* FIXME: We are missing some */
 static TiffTag tags[] = {
-	{ TIFFTAG_ARTIST, NCO_PREFIX "creator", TIFF_TAGTYPE_STRING, NULL },
-	{ TIFFTAG_COPYRIGHT, NIE_PREFIX "copyright", TIFF_TAGTYPE_STRING, NULL },
-	{ TIFFTAG_DATETIME, NIE_PREFIX "contentCreated", TIFF_TAGTYPE_STRING, NULL },
-	{ TIFFTAG_DOCUMENTNAME, NIE_PREFIX "title", TIFF_TAGTYPE_STRING, NULL },
-	{ TIFFTAG_IMAGEDESCRIPTION, NIE_PREFIX "comment", TIFF_TAGTYPE_STRING, NULL },
-	{ TIFFTAG_IMAGEWIDTH, NFO_PREFIX "width", TIFF_TAGTYPE_UINT32, NULL },
-	{ TIFFTAG_IMAGELENGTH, NFO_PREFIX "height", TIFF_TAGTYPE_UINT32, NULL },
-	{ TIFFTAG_MAKE, "Image:CameraMake", TIFF_TAGTYPE_STRING, NULL },
-	{ TIFFTAG_MODEL, "Image:CameraModel", TIFF_TAGTYPE_STRING, NULL },
-	{ TIFFTAG_ORIENTATION, "Image:Orientation", TIFF_TAGTYPE_UINT16, NULL },
-	{ TIFFTAG_SOFTWARE, "Image:Software", TIFF_TAGTYPE_STRING, NULL },
-	{ -1, NULL, TIFF_TAGTYPE_UNDEFINED, NULL }
+	{ TIFFTAG_ARTIST, NCO_PREFIX "creator", TIFF_TAGTYPE_STRING, NULL, NCO_PREFIX "Contact", NCO_PREFIX "fullname" , ":"},
+	{ TIFFTAG_COPYRIGHT, NIE_PREFIX "copyright", TIFF_TAGTYPE_STRING, NULL, NULL, NULL, NULL },
+	{ TIFFTAG_DATETIME, NIE_PREFIX "contentCreated", TIFF_TAGTYPE_STRING, NULL, NULL, NULL, NULL },
+	{ TIFFTAG_DOCUMENTNAME, NIE_PREFIX "title", TIFF_TAGTYPE_STRING, NULL, NULL, NULL, NULL },
+	{ TIFFTAG_IMAGEDESCRIPTION, NIE_PREFIX "comment", TIFF_TAGTYPE_STRING, NULL, NULL, NULL, NULL },
+	{ TIFFTAG_IMAGEWIDTH, NFO_PREFIX "width", TIFF_TAGTYPE_UINT32, NULL, NULL, NULL, NULL },
+	{ TIFFTAG_IMAGELENGTH, NFO_PREFIX "height", TIFF_TAGTYPE_UINT32, NULL, NULL, NULL, NULL },
+	{ TIFFTAG_MAKE, NMM_PREFIX "camera", TIFF_TAGTYPE_STRING, NULL, NULL, NULL, NULL },
+	{ TIFFTAG_MODEL, NMM_PREFIX "camera", TIFF_TAGTYPE_STRING, NULL, NULL, NULL, NULL },
+	{ TIFFTAG_ORIENTATION, NFO_PREFIX "orientation", TIFF_TAGTYPE_UINT16, fix_orientation, NULL, NULL, NULL },
+	/* { TIFFTAG_SOFTWARE, "Image:Software", TIFF_TAGTYPE_STRING, NULL }, */
+	{ -1, NULL, TIFF_TAGTYPE_UNDEFINED, NULL, NULL, NULL, NULL }
 };
 
 static TiffTag exiftags[] = {
-	{ EXIFTAG_EXPOSURETIME, "Image:ExposureTime", TIFF_TAGTYPE_DOUBLE, NULL},
-	{ EXIFTAG_FNUMBER, "Image:FNumber", TIFF_TAGTYPE_DOUBLE, NULL},
-	{ EXIFTAG_EXPOSUREPROGRAM, "Image:ExposureProgram", TIFF_TAGTYPE_UINT16, NULL },
-	{ EXIFTAG_ISOSPEEDRATINGS, "Image:ISOSpeed", TIFF_TAGTYPE_C16_UINT16, NULL},
-	{ EXIFTAG_DATETIMEORIGINAL, NIE_PREFIX "contentCreated", TIFF_TAGTYPE_STRING, date_to_iso8601 },
-	{ EXIFTAG_METERINGMODE, "Image:MeteringMode", TIFF_TAGTYPE_UINT16, NULL},
-	{ EXIFTAG_FLASH, "Image:Flash", TIFF_TAGTYPE_UINT16, NULL},
-	{ EXIFTAG_FOCALLENGTH, "Image:FocalLength", TIFF_TAGTYPE_DOUBLE, NULL},
-	{ EXIFTAG_PIXELXDIMENSION, NFO_PREFIX "width", TIFF_TAGTYPE_UINT32, NULL},
-	{ EXIFTAG_PIXELYDIMENSION, NFO_PREFIX "height", TIFF_TAGTYPE_UINT32, NULL},
-	{ EXIFTAG_WHITEBALANCE, "Image:WhiteBalance", TIFF_TAGTYPE_UINT16, NULL},
-	{ -1, NULL, TIFF_TAGTYPE_UNDEFINED, NULL }
+	{ EXIFTAG_EXPOSURETIME, NMM_PREFIX "exposureTime", TIFF_TAGTYPE_DOUBLE, fix_exposure_time, NULL, NULL, NULL},
+	{ EXIFTAG_FNUMBER, NMM_PREFIX "fnumber", TIFF_TAGTYPE_DOUBLE, fix_fnumber, NULL, NULL, NULL},
+	/* { EXIFTAG_EXPOSUREPROGRAM, "Image:ExposureProgram", TIFF_TAGTYPE_UINT16, NULL, NULL, NULL, NULL }, */
+	{ EXIFTAG_ISOSPEEDRATINGS, NMM_PREFIX "isoSpeed", TIFF_TAGTYPE_C16_UINT16, NULL, NULL, NULL, NULL},
+	{ EXIFTAG_DATETIMEORIGINAL, NIE_PREFIX "contentCreated", TIFF_TAGTYPE_STRING, date_to_iso8601, NULL, NULL, NULL },
+	{ EXIFTAG_METERINGMODE, NMM_PREFIX "meteringMode", TIFF_TAGTYPE_UINT16, fix_metering_mode, NULL, NULL, NULL },
+	{ EXIFTAG_FLASH, NMM_PREFIX "flash", TIFF_TAGTYPE_UINT16, fix_flash, NULL, NULL, NULL },
+	{ EXIFTAG_FOCALLENGTH, NMM_PREFIX "focalLength", TIFF_TAGTYPE_DOUBLE, fix_focal_length, NULL, NULL, NULL},
+	{ EXIFTAG_PIXELXDIMENSION, NFO_PREFIX "width", TIFF_TAGTYPE_UINT32, NULL, NULL, NULL, NULL},
+	{ EXIFTAG_PIXELYDIMENSION, NFO_PREFIX "height", TIFF_TAGTYPE_UINT32, NULL, NULL, NULL, NULL},
+	{ EXIFTAG_WHITEBALANCE, NMM_PREFIX "whiteBalance", TIFF_TAGTYPE_UINT16, fix_white_balance, NULL, NULL, NULL },
+	{ -1, NULL, TIFF_TAGTYPE_UNDEFINED, NULL, NULL, NULL, NULL }
 };
 
+
+
+
+#ifndef HAVE_STRCASESTR
+
+static gchar *
+strcasestr (const gchar *haystack, 
+	    const gchar *needle)
+{
+	gchar *p;
+	gchar *startn = NULL;
+	gchar *np = NULL;
+
+	for (p = (gchar *) haystack; *p; p++) {
+		if (np) {
+			if (toupper (*p) == toupper (*np)) {
+				if (!*++np) {
+					return startn;
+				}
+			} else {
+				np = 0;
+			}
+		} else if (toupper (*p) == toupper (*needle)) {
+			np = (gchar *) needle + 1;
+			startn = p;
+		}
+	}
+
+	return NULL;
+}
+
+#endif /* HAVE_STRCASESTR */
+
 static gchar *
-date_to_iso8601 (gchar *date)
+date_to_iso8601	(const gchar *exif_date, gboolean *free_it)
 {
 	/* ex; date "2007:04:15 15:35:58"
 	 * To
 	 * ex. "2007-04-15T17:35:58+0200 where +0200 is localtime
 	 */
-	return tracker_date_format_to_iso8601 (date, EXIF_DATE_FORMAT);
+	*free_it = TRUE;
+	return tracker_date_format_to_iso8601 (exif_date, EXIF_DATE_FORMAT);
+}
+
+
+static gchar *
+fix_focal_length (const gchar *fl, gboolean *free_it)
+{
+	*free_it = TRUE;
+	return g_strndup (fl, strstr (fl, " mm") - fl);
+}
+
+static gchar *
+fix_flash (const gchar *flash, gboolean *free_it)
+{
+	/* Found in the field: Auto, Did not fire, Red-eye reduction */
+
+	*free_it = FALSE;
+	
+	if (strcasestr (flash, "not fire")) {
+		return (gchar *) "nmm:flash-off";
+	} else {
+		return (gchar *) "nmm:flash-on";
+	}
+}
+
+static gchar *
+fix_fnumber (const gchar *fn, gboolean *free_it)
+{
+	gchar *new_fn;
+
+	if (!fn) {
+		*free_it = FALSE;
+		return NULL;
+	}
+
+	new_fn = g_strdup (fn);
+
+	if (new_fn[0] == 'F') {
+		new_fn[0] = ' ';
+	} else if (fn[0] == 'f' && new_fn[1] == '/') {
+		new_fn[0] = new_fn[1] = ' ';
+	}
+
+	*free_it = TRUE;
+	return g_strstrip (new_fn);
+}
+
+static gchar *
+fix_exposure_time (const gchar *et, gboolean *free_it)
+{
+	gchar *sep;
+
+	sep = strchr (et, '/');
+
+	*free_it = TRUE;
+	
+	if (sep) {
+		gdouble fraction;
+
+		fraction = g_ascii_strtod (sep + 1, NULL);
+
+		if (fraction > 0.0) {
+			gdouble val;
+			gchar	buf[G_ASCII_DTOSTR_BUF_SIZE];
+
+			val = 1.0f / fraction;
+			g_ascii_dtostr (buf, sizeof(buf), val);
+
+			return g_strdup (buf);
+		}
+	}
+
+	return g_strdup (et);
+}
+
+static gchar *
+fix_orientation (const gchar *orientation, gboolean *free_it)
+{
+	guint i;
+	static const gchar *ostr[8] = {
+		/* 0 */ "top - left",
+		/* 1 */ "top - right",
+		/* 2 */ "bottom - right",
+		/* 3 */ "bottom - left",
+		/* 4 */ "left - top",
+		/* 5 */ "right - top",
+		/* 6 */ "right - bottom",
+		/* 7 */ "left - bottom"
+	};
+
+	*free_it = FALSE;
+	
+	for (i=0; i < 8; i++) {
+		if (g_strcmp0 (orientation,ostr[i]) == 0) {
+			switch (i) {
+				default:
+				case 0:
+				return (gchar *) "nfo:orientation-top";
+				case 1:
+				return (gchar *) "nfo:orientation-top-mirror"; // not sure
+				case 2:
+				return (gchar *) "nfo:orientation-bottom-mirror"; // not sure
+				case 3:
+				return (gchar *) "nfo:orientation-bottom";
+				case 4:
+				return (gchar *) "nfo:orientation-left-mirror";
+				case 5:
+				return (gchar *) "nfo:orientation-right";
+				case 6:
+				return (gchar *) "nfo:orientation-right-mirror";
+				case 7:
+				return (gchar *) "nfo:orientation-left";
+			}
+		}
+	}
+
+	return (gchar *) "nfo:orientation-top";
+}
+
+
+static gchar *
+fix_metering_mode (const gchar *metering_mode, gboolean *free_it)
+{
+	/* Found in the field: Multi-segment. These will yield as other */
+
+	*free_it = FALSE;
+	
+	if (strcasestr (metering_mode, "center")) {
+		return (gchar *) "nmm:meteringMode-center-weighted-average";
+	}
+
+	if (strcasestr (metering_mode, "average")) {
+		return (gchar *) "nmm:meteringMode-average";
+	}
+
+	if (strcasestr (metering_mode, "spot")) {
+		return (gchar *) "nmm:meteringMode-spot";
+	}
+
+	if (strcasestr (metering_mode, "multispot")) {
+		return (gchar *) "nmm:meteringMode-multispot";
+	}
+
+	if (strcasestr (metering_mode, "pattern")) {
+		return (gchar *) "nmm:meteringMode-pattern";
+	}
+
+	if (strcasestr (metering_mode, "partial")) {
+		return (gchar *) "nmm:meteringMode-partial";
+	}
+
+	return (gchar *) "nmm:meteringMode-other";
+}
+
+
+static gchar *
+fix_white_balance (const gchar *white_balance, gboolean *free_it)
+{
+	*free_it = FALSE;
+
+	if (strcasestr (white_balance, "auto")) {
+		return (gchar *) "nmm:whiteBalance-auto";
+	}
+
+	/* Found in the field: sunny, fluorescent, incandescent, cloudy. These
+	 * will this way also yield as manual. */
+
+	return (gchar *) "nmm:whiteBalance-manual";
 }
 
 static void
@@ -221,13 +446,17 @@ extract_tiff (const gchar *uri,
 				}
 
 				if (tag->post) {
+					gboolean free_it = FALSE;
+					gchar *value = (*tag->post) (buffer, &free_it);
 					tracker_statement_list_insert (metadata, uri,
-								  tag->name,
-								  (*tag->post) (buffer));
+								       tag->name,
+								       value);
+					if (free_it)
+						g_free (value);
 				} else {
 					tracker_statement_list_insert (metadata, uri,
-								  tag->name,
-							 	  buffer);
+								       tag->name,
+								       buffer);
 				}
 			}
 		}
@@ -236,6 +465,7 @@ extract_tiff (const gchar *uri,
 	/* We want to give native tags priority over XMP/Exif */
 	for (tag = tags; tag->name; ++tag) {
 		gchar *what_i_need;
+		gboolean free_it = FALSE;
 
 		switch (tag->type) {
 			case TIFF_TAGTYPE_STRING:
@@ -272,20 +502,32 @@ extract_tiff (const gchar *uri,
 			}
 
 		if (tag->post) {
-			what_i_need = (*tag->post) (buffer);
+			what_i_need = (*tag->post) (buffer, &free_it);
 		} else {
 			what_i_need = buffer;
 		}
 
-		if (tag->tag == TIFFTAG_ARTIST) {
-			tracker_statement_list_insert (metadata, ":", RDF_TYPE, NCO_PREFIX "Contact");
-			tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", what_i_need);
-			tracker_statement_list_insert (metadata, uri, tag->name, ":");
+
+		if (tag->urn_prefix) {
+			gchar *canonical_uri;
+
+			if (tag->urn_prefix[0] == ':')
+				canonical_uri = tracker_uri_printf_escaped (tag->urn_prefix, what_i_need);
+			else
+				canonical_uri = (gchar *) tag->urn_prefix;
+
+			tracker_statement_list_insert (metadata, canonical_uri, RDF_TYPE, tag->rdf_class);
+			tracker_statement_list_insert (metadata, canonical_uri, tag->rdf_property, what_i_need);
+			tracker_statement_list_insert (metadata, uri, tag->name, canonical_uri);
+
+			if (tag->urn_prefix[0] != ':')
+				g_free (canonical_uri);
 		} else {
 			tracker_statement_list_insert (metadata, uri, tag->name, what_i_need);
 		}
 
-		if (tag->post) 
+
+		if (free_it) 
 			g_free (what_i_need);
 	}
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]