[tracker] Change structure of the JPEG, XMP, TIFF and PDF extractors



commit 198b22516f8007bd49e7b5ba0620640ec3b7f84e
Author: Philip Van Hoof <philip codeminded be>
Date:   Wed Sep 2 17:31:51 2009 +0200

    Change structure of the JPEG, XMP, TIFF and PDF extractors
    
    Cleaning up of the Exif, XMP and IPTC extraction in the JPEG, XMP, TIFF and
    PDF extractors. Added proper usage of tracker_coalesce to merge fields
    together.

 src/tracker-extract/Makefile.am            |    9 +-
 src/tracker-extract/tracker-exif.c         |  386 ++++++++++++++
 src/tracker-extract/tracker-exif.h         |   40 ++
 src/tracker-extract/tracker-extract-jpeg.c |  606 ++++++++++------------
 src/tracker-extract/tracker-extract-pdf.c  |  258 ++++++++--
 src/tracker-extract/tracker-extract-tiff.c |  770 +++++++++++++++-------------
 src/tracker-extract/tracker-extract-xmp.c  |  282 +++++++++--
 src/tracker-extract/tracker-iptc.c         |  116 ++---
 src/tracker-extract/tracker-iptc.h         |   31 +-
 src/tracker-extract/tracker-xmp.c          |  262 +++-------
 src/tracker-extract/tracker-xmp.h          |   23 +-
 11 files changed, 1741 insertions(+), 1042 deletions(-)
---
diff --git a/src/tracker-extract/Makefile.am b/src/tracker-extract/Makefile.am
index 8c68c3c..5e6f457 100644
--- a/src/tracker-extract/Makefile.am
+++ b/src/tracker-extract/Makefile.am
@@ -100,6 +100,11 @@ xmp_sources = 								\
 	tracker-xmp.c							\
 	tracker-xmp.h
 
+# Common exif Sources
+exif_sources =								\
+	tracker-exif.c							\
+	tracker-exif.h
+
 # Common iptc Sources
 iptc_sources =								\
 	tracker-iptc.c							\
@@ -202,7 +207,7 @@ libextract_xine_la_LIBADD = $(GLIB2_LIBS) $(XINE_LIBS) $(GCOV_LIBS) \
 	$(top_builddir)/src/libtracker-common/libtracker-common.la
 
 # JPEG
-libextract_jpeg_la_SOURCES = tracker-extract-jpeg.c $(xmp_sources) $(iptc_sources)
+libextract_jpeg_la_SOURCES = tracker-extract-jpeg.c $(xmp_sources) $(iptc_sources) $(exif_sources)
 libextract_jpeg_la_LDFLAGS = $(module_flags)
 libextract_jpeg_la_LIBADD = $(GLIB2_LIBS) $(LIBJPEG_LIBS) $(LIBEXIF_LIBS) $(LIBIPTCDATA_LIBS) $(EXEMPI_LIBS) $(GCOV_LIBS) \
 	$(top_builddir)/src/libtracker-common/libtracker-common.la
@@ -286,4 +291,4 @@ BUILT_SOURCES = 							\
 
 CLEANFILES = $(BUILT_SOURCES)
 
-EXTRA_DIST = tracker-marshal.list
\ No newline at end of file
+EXTRA_DIST = tracker-marshal.list
diff --git a/src/tracker-extract/tracker-exif.c b/src/tracker-extract/tracker-exif.c
new file mode 100644
index 0000000..e67aefa
--- /dev/null
+++ b/src/tracker-extract/tracker-exif.c
@@ -0,0 +1,386 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* Tracker Exif - Exif helper functions
+ * Copyright (C) 2008, Nokia
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Author: Philip Van Hoof <philip codeminded be>
+ */
+
+#include "config.h"
+
+#include <locale.h>
+#include <string.h>
+#include <ctype.h>
+#include <glib.h>
+
+#include "tracker-main.h"
+#include "tracker-exif.h"
+
+#include <libtracker-common/tracker-type-utils.h>
+#include <libtracker-common/tracker-utils.h>
+
+
+#ifdef HAVE_LIBEXIF
+
+#include <libexif/exif-data.h>
+
+#define EXIF_DATE_FORMAT "%Y:%m:%d %H:%M:%S"
+
+#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 *
+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 localtime */
+		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];
+		exif_entry_get_value (entry, buf, 1024);
+		return g_strndup (buf, strstr (buf, " mm") - buf);
+	}
+
+	return NULL;
+}
+
+static gchar *
+get_flash (ExifData *exif, ExifTag tag)
+{
+	ExifEntry *entry = exif_data_get_entry (exif, tag);
+
+	if (entry) {
+		gchar buf[1024];
+
+		exif_entry_get_value (entry, buf, 1024);
+
+		if (strcasestr (buf, "flash fired")) {
+			return g_strdup ("nmm:flash-on");
+		}
+
+		return g_strdup ("nmm:flash-off");
+	}
+
+	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);
+	guint i;
+
+	if (entry) {
+		gchar buf[1024];
+		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"
+		};
+
+		exif_entry_get_value (entry, buf, 1024);
+
+		for (i=0; i < 8; i++) {
+			if (g_strcmp0 (buf, ostr[i]) == 0) {
+				switch (i) {
+					case 0:
+					return g_strdup ("nfo:orientation-top");
+					case 1:
+					return g_strdup ("nfo:orientation-top-mirror");
+					case 2:
+					return g_strdup ("nfo:orientation-bottom");
+					case 3:
+					return g_strdup ("nfo:orientation-bottom-mirror");
+					case 4:
+					return g_strdup ("nfo:orientation-left-mirror");
+					case 5:
+					return g_strdup ("nfo:orientation-right");
+					case 6:
+					return g_strdup ("nfo:orientation-right-mirror");
+					case 7:
+					return g_strdup ("nfo:orientation-left");
+					default:
+					break;
+				}
+			}
+		}
+
+		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) {
+		gchar buf[1024];
+
+		exif_entry_get_value (entry, buf, 1024);
+
+		if (strcasestr (buf, "center")) {
+			return g_strdup ("nmm:meteringMode-center-weighted-average");
+		}
+
+		if (strcasestr (buf, "average")) {
+			return g_strdup ("nmm:meteringMode-average");
+		}
+
+		if (strcasestr (buf, "spot")) {
+			return g_strdup ("nmm:meteringMode-spot");
+		}
+
+		if (strcasestr (buf, "multispot")) {
+			return g_strdup ("nmm:meteringMode-multispot");
+		}
+
+		if (strcasestr (buf, "pattern")) {
+			return g_strdup ("nmm:meteringMode-pattern");
+		}
+
+		if (strcasestr (buf, "partial")) {
+			return g_strdup ("nmm:meteringMode-partial");
+		}
+
+		return g_strdup ("nmm:meteringMode-other");
+	}
+
+	return NULL;
+}
+
+
+static gchar *
+get_white_balance (ExifData *exif, ExifTag tag)
+{
+	ExifEntry *entry = exif_data_get_entry (exif, tag);
+
+	if (entry) {
+		gchar buf[1024];
+		exif_entry_get_value (entry, buf, 1024);
+
+		if (strcasestr (buf, "auto")) {
+			return g_strdup ("nmm:whiteBalance-auto");
+		}
+
+		/* Found in the field: sunny, fluorescent, incandescent, cloudy.
+		 * These will this way also yield as manual. */
+
+		return g_strdup ("nmm:whiteBalance-manual");
+	}
+
+	return NULL;
+}
+
+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 */
+
+void
+tracker_read_exif (const unsigned char *buffer,
+                   size_t		len,
+                   const gchar         *uri,
+                   TrackerExifData     *data)
+{
+#ifdef HAVE_LIBEXIF
+	ExifData *exif;
+
+	exif = exif_data_new();
+
+	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)
+		data->copyright = get_value (exif, EXIF_TAG_COPYRIGHT);
+
+	exif_data_free (exif);
+
+#endif /* HAVE_LIBEXIF */
+}
+
diff --git a/src/tracker-extract/tracker-exif.h b/src/tracker-extract/tracker-exif.h
new file mode 100644
index 0000000..934c2e9
--- /dev/null
+++ b/src/tracker-extract/tracker-exif.h
@@ -0,0 +1,40 @@
+/* Tracker Xmp - Xmp helper functions
+ * Copyright (C) 2008, Nokia
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Author: Philip Van Hoof <philip codeminded be>
+ */
+
+#ifndef _TRACKER_EXIF_H_
+#define _TRACKER_EXIF_H_
+
+#include <glib.h>
+
+typedef struct {
+	gchar *y_dimension, *x_dimension, *image_width, *document_name, *time, *time_original,
+	      *artist, *user_comment, *description, *make, *model, *orientation,
+	      *exposure_time, *fnumber, *flash, *focal_length, *iso_speed_ratings,
+	      *metering_mode, *white_balance, *copyright;
+} TrackerExifData;
+
+void tracker_read_exif (const unsigned char *buffer,
+                        size_t               len,
+                        const gchar         *uri,
+                        TrackerExifData     *data);
+
+#endif /* _TRACKER_EXIF_H_ */
+
diff --git a/src/tracker-extract/tracker-extract-jpeg.c b/src/tracker-extract/tracker-extract-jpeg.c
index 725abaa..c94416e 100644
--- a/src/tracker-extract/tracker-extract-jpeg.c
+++ b/src/tracker-extract/tracker-extract-jpeg.c
@@ -54,32 +54,38 @@
 #include "tracker-main.h"
 #include "tracker-xmp.h"
 #include "tracker-iptc.h"
+#include "tracker-exif.h"
 
+#define RDF_PREFIX TRACKER_RDF_PREFIX
 #define NMM_PREFIX TRACKER_NMM_PREFIX
 #define NFO_PREFIX TRACKER_NFO_PREFIX
 #define NIE_PREFIX TRACKER_NIE_PREFIX
 #define DC_PREFIX TRACKER_DC_PREFIX
 #define NCO_PREFIX TRACKER_NCO_PREFIX
 
-#define RDF_PREFIX TRACKER_RDF_PREFIX
-#define RDF_TYPE RDF_PREFIX "type"
+#ifdef HAVE_LIBEXIF
+#define EXIF_NAMESPACE		"Exif"
+#define EXIF_NAMESPACE_LENGTH	4
+#endif /* HAVE_LIBEXIF */
 
 #ifdef HAVE_EXEMPI
-#define XMP_NAMESPACE	     "http://ns.adobe.com/xap/1.0/\x00";
-#define XMP_NAMESPACE_LENGTH 29
+#define XMP_NAMESPACE		"http://ns.adobe.com/xap/1.0/\x00";
+#define XMP_NAMESPACE_LENGTH	29
 #endif /* HAVE_EXEMPI */
 
-#ifdef HAVE_LIBEXIF
-#include <libexif/exif-data.h>
-#define EXIF_DATE_FORMAT "%Y:%m:%d %H:%M:%S"
-#endif /* HAVE_LIBEXIF */
-
 #ifdef HAVE_LIBIPTCDATA
-#define PS3_NAMESPACE	     "Photoshop 3.0\0"
-#define PS3_NAMESPACE_LENGTH 14
+#define PS3_NAMESPACE		"Photoshop 3.0\0"
+#define PS3_NAMESPACE_LENGTH	14
 #include <libiptcdata/iptc-jpeg.h>
 #endif /* HAVE_LIBIPTCDATA */
 
+typedef struct {
+	gchar *camera, *title, *orientation, *copyright, *white_balance, 
+	      *fnumber, *flash, *focal_length, *artist, 
+	      *exposure_time, *iso_speed_ratings, *date, *description,
+	      *metering_mode, *creator;
+} JpegNeedsMergeData;
+
 static void extract_jpeg (const gchar *filename,
 			  TrackerSparqlBuilder   *metadata);
 
@@ -88,37 +94,6 @@ static TrackerExtractData data[] = {
 	{ 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 */
-
 struct tej_error_mgr 
 {
 	struct jpeg_error_mgr jpeg;
@@ -132,289 +107,31 @@ static void tracker_extract_jpeg_error_exit (j_common_ptr cinfo)
     longjmp(h->setjmp_buffer, 1);
 }
 
-#ifdef HAVE_LIBEXIF
-
-typedef gchar * (*PostProcessor) (const gchar*, gboolean *free_it);
-
-typedef struct {
-	ExifTag       tag;
-	const gchar  *name;
-	PostProcessor post;
-	const gchar  *rdf_class;
-	const gchar  *rdf_property;
-	const gchar  *urn_prefix;
-} TagType;
-
-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 TagType tags[] = {
-	{ EXIF_TAG_PIXEL_Y_DIMENSION, NFO_PREFIX "height", NULL, NULL, NULL, NULL },
-	{ EXIF_TAG_PIXEL_X_DIMENSION, NFO_PREFIX "width", NULL, NULL, NULL, NULL },
-	{ EXIF_TAG_RELATED_IMAGE_WIDTH, NFO_PREFIX "width", NULL, NULL, NULL, NULL },
-	{ EXIF_TAG_DOCUMENT_NAME, NIE_PREFIX "title", NULL, NULL, NULL, NULL },
-	/* { -1, "Image:Album", NULL }, */
-	{ EXIF_TAG_DATE_TIME, NIE_PREFIX "contentCreated", date_to_iso8601, NULL, NULL, NULL },
-	{ EXIF_TAG_DATE_TIME_ORIGINAL, NIE_PREFIX "contentCreated", date_to_iso8601, NULL, NULL, NULL },
-	/* { -1, "Image:Keywords", NULL }, */
-	{ EXIF_TAG_ARTIST, NCO_PREFIX "creator", NULL, NCO_PREFIX "Contact", NCO_PREFIX "fullname", "urn:artist:%s"},
-	{ EXIF_TAG_USER_COMMENT, NIE_PREFIX "comment", NULL, NULL, NULL, NULL },
-	{ EXIF_TAG_IMAGE_DESCRIPTION, NIE_PREFIX "description", NULL, NULL, NULL, NULL },
-	/* { EXIF_TAG_SOFTWARE, "Image:Software", NULL }, */
-	{ EXIF_TAG_MAKE, NMM_PREFIX "camera", NULL, NULL, NULL, NULL },
-	{ EXIF_TAG_MODEL, NMM_PREFIX "camera", NULL, NULL, NULL, NULL },
-	{ EXIF_TAG_ORIENTATION, NFO_PREFIX "orientation", fix_orientation, NULL, NULL, NULL },
-	/* { EXIF_TAG_EXPOSURE_PROGRAM, "Image:ExposureProgram", NULL }, */
-	{ EXIF_TAG_EXPOSURE_TIME, NMM_PREFIX "exposureTime", fix_exposure_time, NULL, NULL, NULL },
-	{ EXIF_TAG_FNUMBER, NMM_PREFIX "fnumber", fix_fnumber, NULL, NULL, NULL },
-	{ EXIF_TAG_FLASH, NMM_PREFIX "flash", fix_flash, NULL, NULL, NULL },
-	{ EXIF_TAG_FOCAL_LENGTH, NMM_PREFIX "focalLength", fix_focal_length, NULL, NULL, NULL },
-	{ EXIF_TAG_ISO_SPEED_RATINGS, NMM_PREFIX "isoSpeed", NULL, NULL, NULL, NULL },
-	{ EXIF_TAG_METERING_MODE, NMM_PREFIX "meteringMode", fix_metering_mode, NULL, NULL, NULL },
-	{ EXIF_TAG_WHITE_BALANCE, NMM_PREFIX "whiteBalance", fix_white_balance, NULL, NULL, NULL },
-	{ EXIF_TAG_COPYRIGHT, NIE_PREFIX "copyright", NULL, NULL, NULL, NULL },
-	{ -1, NULL, NULL }
-};
-
-#endif /* HAVE_EXIF */
-
-#ifdef HAVE_LIBEXIF
-
-static gchar *
-date_to_iso8601 (const gchar *date, gboolean *free_it)
-{
-	/* From: ex; date "2007:04:15 15:35:58"
-	 * To  : ex. "2007-04-15T17:35:58+0200 where +0200 is localtime */
-	*free_it = TRUE;
-	return tracker_date_format_to_iso8601 (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)
-{
-	*free_it = FALSE;
-	
-	if (strcasestr (flash, "flash fired")) {
-		return (gchar *) "nmm:flash-on";
-	} else {
-		return (gchar *) "nmm:flash-off";
-	}
-}
-
-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) {
-				case 0:
-				return (gchar *) "nfo:orientation-top";
-				case 1:
-				return (gchar *) "nfo:orientation-top-mirror";
-				case 2:
-				return (gchar *) "nfo:orientation-bottom";
-				case 3:
-				return (gchar *) "nfo:orientation-bottom-mirror";
-				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";
-				default:
-				break;
-			}
-		}
-	}
-
-	return (gchar *) "nfo:orientation-top";
-}
-
-
-static gchar *
-fix_metering_mode (const gchar *metering_mode, gboolean *free_it)
-{
-	*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
-read_exif (const unsigned char *buffer,
-	   size_t		len,
-	   const gchar         *uri,
-	   TrackerSparqlBuilder	       *metadata)
+insert_keywords (TrackerSparqlBuilder *metadata, const gchar *uri, gchar *keywords)
 {
-	ExifData *exif;
-	TagType  *p;
-
-	tracker_statement_list_insert (metadata, uri,
-	                               RDF_TYPE,
-	                               NMM_PREFIX "Photo");
-
-	exif = exif_data_new();
-	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);
-
-	for (p = tags; p->name; ++p) {
-		ExifEntry *entry = exif_data_get_entry (exif, p->tag);
-
-		if (entry) {
-			gchar buffer_[1024];
-			gchar *what_i_need;
-			gboolean free_it = FALSE;
-
-			exif_entry_get_value (entry, buffer_, 1024);
-
-			if (p->post) {
-				what_i_need = (*p->post) (buffer_, &free_it);
-			} else {
-				what_i_need = buffer_;
-			}
-
-			if (p->urn_prefix) {
-				gchar *canonical_uri = tracker_uri_printf_escaped (p->urn_prefix, what_i_need);
-				tracker_statement_list_insert (metadata, canonical_uri, RDF_TYPE, p->rdf_class);
-				tracker_statement_list_insert (metadata, canonical_uri, p->rdf_property, what_i_need);
-				tracker_statement_list_insert (metadata, uri, p->name, canonical_uri);
-				g_free (canonical_uri);
-			} else {
-				tracker_statement_list_insert (metadata, uri, p->name, what_i_need);
-			}
-
-			if (free_it)
-				g_free (what_i_need);
-		}
+	char *lasts, *keyw;
+	size_t len;
+
+	keyw = keywords;
+	keywords = strchr (keywords, '"');
+	if (keywords)
+		keywords++;
+	else 
+		keywords = keyw;
+
+	len = strlen (keywords);
+	if (keywords[len - 1] == '"')
+		keywords[len - 1] = '\0';
+
+	for (keyw = strtok_r (keywords, ",; ", &lasts); keyw; 
+	     keyw = strtok_r (NULL, ",; ", &lasts)) {
+		tracker_statement_list_insert (metadata, uri, 
+		                               NIE_PREFIX "keyword", 
+		                               (const gchar*) keyw);
 	}
-	
-	exif_data_free (exif);
 }
 
-#endif /* HAVE_LIBEXIF */
-
-
 static void
 extract_jpeg (const gchar *uri,
 	      TrackerSparqlBuilder   *metadata)
@@ -437,6 +154,10 @@ extract_jpeg (const gchar *uri,
 	f = tracker_file_open (filename, "rb", FALSE);
 
 	if (f) {
+		TrackerXmpData xmp_data = { 0 };
+		TrackerExifData exif_data = { 0 };
+		TrackerIptcData iptc_data = { 0 };
+		JpegNeedsMergeData merge_data = { 0 };
 		gchar *str;
 		gsize  len;
 #ifdef HAVE_LIBIPTCDATA
@@ -445,8 +166,12 @@ extract_jpeg (const gchar *uri,
 #endif /* HAVE_LIBIPTCDATA */
 
 		tracker_statement_list_insert (metadata, uri, 
-		                          RDF_TYPE, 
-		                          NFO_PREFIX "Image");
+		                               RDF_PREFIX "type", 
+		                               NFO_PREFIX "Image");
+
+		tracker_statement_list_insert (metadata, uri,
+		                               RDF_PREFIX "type",
+		                               NMM_PREFIX "Photo");
 
 		cinfo.err = jpeg_std_error (&tejerr.jpeg);
 		tejerr.jpeg.error_exit = tracker_extract_jpeg_error_exit;
@@ -482,32 +207,39 @@ extract_jpeg (const gchar *uri,
 				str = g_strndup ((gchar*) marker->data, len);
 
 				tracker_statement_list_insert (metadata, uri,
-							  NIE_PREFIX "comment",
-							  str);
+				                               NIE_PREFIX "comment",
+				                               str);
+
 				g_free (str);
+
 				break;
-				
+
 			case JPEG_APP0+1:
 				str = (gchar*) marker->data;
 				len = marker->data_length;
 
 #ifdef HAVE_LIBEXIF
-				if (strncmp ("Exif", (gchar*) (marker->data), 5) == 0) {
-					read_exif ((unsigned char*) marker->data,
-						   marker->data_length, uri,
-						   metadata);
+				if (strncmp (EXIF_NAMESPACE, (gchar*) (marker->data), EXIF_NAMESPACE_LENGTH) == 0) {
+
+					tracker_read_exif ((unsigned char*) marker->data,
+					                   marker->data_length, 
+					                   uri, &exif_data);
 				}
 #endif /* HAVE_LIBEXIF */
 
 #ifdef HAVE_EXEMPI
-
 				if (strncmp (XMP_NAMESPACE, str, XMP_NAMESPACE_LENGTH) == 0) {
+					TrackerXmpData xmp_data = { 0 };
+
 					tracker_read_xmp (str + XMP_NAMESPACE_LENGTH,
 							  len - XMP_NAMESPACE_LENGTH,
-							  uri, metadata);
+							  uri, &xmp_data);
+
 				}
 #endif /* HAVE_EXEMPI */
+
 				break;
+
 			case JPEG_APP0+13:
 				str = (gchar*) marker->data;
 				len = marker->data_length;
@@ -516,12 +248,14 @@ extract_jpeg (const gchar *uri,
 					offset = iptc_jpeg_ps3_find_iptc (str, len, &sublen);
 					if (offset>0) {
 						tracker_read_iptc (str + offset,
-								   sublen,
-								   uri, metadata);
+						                   sublen,
+						                   uri, &iptc_data);
 					}
 				}
 #endif /* HAVE_LIBIPTCDATA */
+
 				break;
+
 			default:
 				marker = marker->next;
 				continue;
@@ -530,13 +264,217 @@ extract_jpeg (const gchar *uri,
 			marker = marker->next;
 		}
 
-		/* We want native size to have priority over EXIF, XMP etc */
+		merge_data.camera = tracker_coalesce (4, xmp_data.Model, 
+		                                      xmp_data.Make,
+		                                      exif_data.model,
+		                                      exif_data.make);
+
+		merge_data.title = tracker_coalesce (2, xmp_data.title,
+		                                     exif_data.document_name);
+
+		merge_data.orientation = tracker_coalesce (3, exif_data.orientation,
+		                                           xmp_data.Orientation,
+		                                           iptc_data.image_orientation);
+
+		merge_data.copyright = tracker_coalesce (3, exif_data.copyright,
+		                                         xmp_data.rights,
+		                                         iptc_data.copyright_notice);
+
+		merge_data.white_balance = tracker_coalesce (2, exif_data.white_balance,
+		                                             xmp_data.WhiteBalance);
+		                                             
+
+		merge_data.fnumber =  tracker_coalesce (2, exif_data.fnumber,
+		                                        xmp_data.FNumber);
+
+		merge_data.flash =  tracker_coalesce (2, exif_data.flash,
+		                                      xmp_data.Flash);
+
+		merge_data.focal_length =  tracker_coalesce (2, exif_data.focal_length,
+		                                             xmp_data.FocalLength);
+
+		merge_data.artist =  tracker_coalesce (3, exif_data.artist,
+		                                       xmp_data.Artist,
+		                                       xmp_data.contributor);
+
+		merge_data.exposure_time =  tracker_coalesce (2, exif_data.exposure_time,
+		                                              xmp_data.ExposureTime);
+
+		merge_data.iso_speed_ratings =  tracker_coalesce (2, exif_data.iso_speed_ratings,
+		                                                  xmp_data.ISOSpeedRatings);
+
+		merge_data.date =  tracker_coalesce (5, exif_data.time, 
+		                                     xmp_data.date,
+		                                     iptc_data.date_created,
+		                                     exif_data.time_original,
+		                                     xmp_data.DateTimeOriginal);
+
+		merge_data.description = tracker_coalesce (2, exif_data.description,
+		                                           xmp_data.description);
+
+		merge_data.metering_mode =  tracker_coalesce (2, exif_data.metering_mode,
+		                                              xmp_data.MeteringMode);
+
+		merge_data.creator =  tracker_coalesce (3, iptc_data.byline,
+		                                        xmp_data.creator,
+		                                        iptc_data.credit);
+
+		if (exif_data.user_comment) {
+			tracker_statement_list_insert (metadata, uri, NIE_PREFIX "comment", exif_data.user_comment);
+			g_free (exif_data.user_comment);
+		}
+
+		/* Prioritize on native dimention in all cases */
 		tracker_statement_list_insert_with_int (metadata, uri,
 						   NFO_PREFIX "width",
 						   cinfo.image_width);
+		g_free (exif_data.x_dimension);
+
 		tracker_statement_list_insert_with_int (metadata, uri,
 						   NFO_PREFIX "height",
 						    cinfo.image_height);
+		g_free (exif_data.y_dimension);
+
+		if (xmp_data.keywords) {
+			insert_keywords (metadata, uri, xmp_data.keywords);
+			g_free (xmp_data.keywords);
+		}
+
+		if (xmp_data.subject) {
+			insert_keywords (metadata, uri, xmp_data.subject);
+			g_free (xmp_data.subject);
+		}
+
+		if (xmp_data.publisher) {
+			tracker_statement_list_insert (metadata, ":", RDF_PREFIX "type", NCO_PREFIX "Contact");
+			tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", xmp_data.publisher);
+			tracker_statement_list_insert (metadata, uri, NCO_PREFIX "publisher", ":");
+			g_free (xmp_data.publisher);
+		}
+
+		if (xmp_data.type) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "type", xmp_data.type);
+			g_free (xmp_data.type);
+		}
+
+		if (xmp_data.format) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "format", xmp_data.format);
+			g_free (xmp_data.format);
+		}
+
+		if (xmp_data.identifier) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "identifier", xmp_data.identifier);
+			g_free (xmp_data.identifier);
+		}
+
+		if (xmp_data.source) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "source", xmp_data.source);
+			g_free (xmp_data.source);
+		}
+
+		if (xmp_data.language) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "language", xmp_data.language);
+			g_free (xmp_data.language);
+		}
+
+		if (xmp_data.relation) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "relation", xmp_data.relation);
+			g_free (xmp_data.relation);
+		}
+
+		if (xmp_data.coverage) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "coverage", xmp_data.coverage);
+			g_free (xmp_data.coverage);
+		}
+
+		if (xmp_data.license) {
+			tracker_statement_list_insert (metadata, uri, NIE_PREFIX "license", xmp_data.license);
+			g_free (xmp_data.license);
+		}
+
+		if (iptc_data.keywords) {
+			insert_keywords (metadata, uri, iptc_data.keywords);
+			g_free (iptc_data.keywords);
+		}
+
+		if (merge_data.camera) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "camera", merge_data.camera);
+			g_free (merge_data.camera);
+		}
+
+		if (merge_data.title) {
+			tracker_statement_list_insert (metadata, uri, NIE_PREFIX "title", merge_data.title);
+			g_free (merge_data.title);
+		}
+
+		if (merge_data.orientation) {
+			tracker_statement_list_insert (metadata, uri, NFO_PREFIX "orientation", merge_data.orientation);
+			g_free (merge_data.orientation);
+		}
+
+		if (merge_data.copyright) {
+			tracker_statement_list_insert (metadata, uri, NIE_PREFIX "copyright", merge_data.copyright);
+			g_free (merge_data.copyright);
+		}
+
+		if (merge_data.white_balance) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "whiteBalance", merge_data.white_balance);
+			g_free (merge_data.white_balance);
+		}
+
+		if (merge_data.fnumber) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "fnumber", merge_data.fnumber);
+			g_free (merge_data.fnumber);
+		}
+
+		if (merge_data.flash) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "flash", merge_data.flash);
+			g_free (merge_data.flash);
+		}
+
+		if (merge_data.focal_length) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "focalLength", merge_data.focal_length);
+			g_free (merge_data.focal_length);
+		}
+
+		if (merge_data.artist) {
+			tracker_statement_list_insert (metadata, ":", RDF_PREFIX "type", NCO_PREFIX "Contact");
+			tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", merge_data.artist);
+			tracker_statement_list_insert (metadata, uri, NCO_PREFIX "contributor", ":");
+			g_free (merge_data.artist);
+		}
+
+		if (merge_data.exposure_time) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "exposureTime", merge_data.exposure_time);
+			g_free (merge_data.exposure_time);
+		}
+
+		if (merge_data.iso_speed_ratings) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "isoSpeed", merge_data.iso_speed_ratings);
+			g_free (merge_data.iso_speed_ratings);
+		}
+
+		if (merge_data.date) {
+			tracker_statement_list_insert (metadata, uri, NIE_PREFIX "contentCreated", merge_data.date);
+			g_free (merge_data.date);
+		}
+
+		if (merge_data.description) {
+			tracker_statement_list_insert (metadata, uri, NIE_PREFIX "description", merge_data.description);
+			g_free (merge_data.description);
+		}
+
+		if (merge_data.metering_mode) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "meteringMode", merge_data.metering_mode);
+			g_free (merge_data.metering_mode);
+		}
+
+		if (merge_data.creator) {
+			tracker_statement_list_insert (metadata, ":", RDF_PREFIX "type", NCO_PREFIX "Contact");
+			tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", merge_data.creator);
+			tracker_statement_list_insert (metadata, uri, NCO_PREFIX "creator", ":");
+			g_free (merge_data.creator);
+		}
 
 		jpeg_destroy_decompress (&cinfo);
 fail:
diff --git a/src/tracker-extract/tracker-extract-pdf.c b/src/tracker-extract/tracker-extract-pdf.c
index ca8f9ac..eb89cd1 100644
--- a/src/tracker-extract/tracker-extract-pdf.c
+++ b/src/tracker-extract/tracker-extract-pdf.c
@@ -36,12 +36,12 @@
 #include <libtracker-common/tracker-utils.h>
 #include <libtracker-common/tracker-type-utils.h>
 
+#define NMM_PREFIX TRACKER_NMM_PREFIX
+#define DC_PREFIX TRACKER_DC_PREFIX
 #define NIE_PREFIX TRACKER_NIE_PREFIX
 #define NFO_PREFIX TRACKER_NFO_PREFIX
 #define NCO_PREFIX TRACKER_NCO_PREFIX
-
 #define RDF_PREFIX TRACKER_RDF_PREFIX
-#define RDF_TYPE RDF_PREFIX "type"
 
 static void extract_pdf (const gchar *uri,
 			 TrackerSparqlBuilder   *metadata);
@@ -51,19 +51,55 @@ static TrackerExtractData data[] = {
 	{ NULL, NULL }
 };
 
+typedef struct {
+	gchar *author, *title, *creation_date, *subject;
+} PdfData;
+
+typedef struct {
+	gchar *creator, *title, *date;
+} PdfNeedsMergeData;
+
+
+static void
+insert_keywords (TrackerSparqlBuilder *metadata, const gchar *uri, gchar *keywords)
+{
+	char *lasts, *keyw;
+	size_t len;
+
+	keyw = keywords;
+	keywords = strchr (keywords, '"');
+	if (keywords)
+		keywords++;
+	else 
+		keywords = keyw;
+
+	len = strlen (keywords);
+	if (keywords[len - 1] == '"')
+		keywords[len - 1] = '\0';
+
+	for (keyw = strtok_r (keywords, ",; ", &lasts); keyw; 
+	     keyw = strtok_r (NULL, ",; ", &lasts)) {
+		tracker_statement_list_insert (metadata, uri, 
+		                               NIE_PREFIX "keyword", 
+		                               (const gchar*) keyw);
+	}
+}
+
+
 static void
 extract_pdf (const gchar *uri,
 	     TrackerSparqlBuilder  *metadata)
 {
+	PdfData pdf_data = { 0 };
+	PdfNeedsMergeData merge_data = { 0 };
+	TrackerXmpData xmp_data = { 0 };
 	PopplerDocument *document;
-	gchar		*title		= NULL;
-	gchar		*author		= NULL;
-	gchar		*subject	= NULL;
+	gchar		*author, *title, *subject;
 	gchar		*keywords	= NULL;
 	gchar		*metadata_xml	= NULL;
 	GTime		 creation_date;
 	GError		*error		= NULL;
-	gchar           *filename = g_filename_from_uri (uri, NULL, NULL);
+	gchar		*filename = g_filename_from_uri (uri, NULL, NULL);
 
 	g_type_init ();
 
@@ -75,16 +111,16 @@ extract_pdf (const gchar *uri,
 	}
 
 	tracker_statement_list_insert (metadata, uri, 
-	                          RDF_TYPE, 
-	                          NFO_PREFIX "PaginatedTextDocument");
+	                               RDF_PREFIX "type", 
+	                               NFO_PREFIX "PaginatedTextDocument");
 
 	g_object_get (document,
-		      "title", &title,
-		      "author", &author,
-		      "subject", &subject,
-		      "keywords", &keywords,
-		      "creation-date", &creation_date,
-		      NULL);
+	              "title", &title,
+	              "author", &author,
+	              "subject", &subject,
+	              "keywords", &keywords,
+	              "creation-date", &creation_date,
+	              NULL);
 
 	/* metadata property not present in older poppler versions */
 	if (g_object_class_find_property (G_OBJECT_GET_CLASS (document), "metadata")) {
@@ -92,21 +128,179 @@ extract_pdf (const gchar *uri,
 	}
 
 	if (!tracker_is_empty_string (title)) {
-		tracker_statement_list_insert (metadata, uri,
-					  NIE_PREFIX "title",
-					  title);
+		pdf_data.title = title;
 	}
+
 	if (!tracker_is_empty_string (author)) {
+		pdf_data.author = author;
+	}
 
-		tracker_statement_list_insert (metadata, ":", RDF_TYPE, NCO_PREFIX "Contact");
-		tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", author);
-		tracker_statement_list_insert (metadata, uri, NCO_PREFIX "creator", ":");
+	if (!tracker_is_empty_string (subject)) {
+		pdf_data.subject = subject;
+	}
 
+	if (creation_date > 0) {
+		pdf_data.creation_date = tracker_date_to_string ((time_t) creation_date);
 	}
-	if (!tracker_is_empty_string (subject)) {
-		tracker_statement_list_insert (metadata, uri,
-					  NIE_PREFIX "subject",
-					  subject);
+
+	if (metadata_xml) {
+
+		tracker_read_xmp (metadata_xml, strlen (metadata_xml), uri, &xmp_data);
+
+		merge_data.creator =  tracker_coalesce (2, pdf_data.author,
+		                                        xmp_data.creator);
+
+		merge_data.date =  tracker_coalesce (3, pdf_data.creation_date,
+		                                     xmp_data.date,
+		                                     xmp_data.DateTimeOriginal);
+
+		merge_data.title =  tracker_coalesce (2, pdf_data.title,
+		                                        xmp_data.title);
+
+
+		if (pdf_data.subject) {
+			insert_keywords (metadata, uri, pdf_data.subject);
+			g_free (pdf_data.subject);
+		}
+
+		if (merge_data.creator) {
+			tracker_statement_list_insert (metadata, ":", RDF_PREFIX "type", NCO_PREFIX "Contact");
+			tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", merge_data.creator);
+			tracker_statement_list_insert (metadata, uri, NCO_PREFIX "creator", ":");
+			g_free (merge_data.creator);
+		}
+
+		if (merge_data.date) {
+			tracker_statement_list_insert (metadata, uri, NIE_PREFIX "contentCreated", merge_data.date);
+			g_free (merge_data.date);
+		}
+
+		if (merge_data.title) {
+			tracker_statement_list_insert (metadata, uri, NIE_PREFIX "title", merge_data.title);
+			g_free (merge_data.title);
+		}
+
+		if (xmp_data.keywords) {
+			insert_keywords (metadata, uri, xmp_data.keywords);
+			g_free (xmp_data.keywords);
+		}
+
+		if (xmp_data.subject) {
+			insert_keywords (metadata, uri, xmp_data.subject);
+			g_free (xmp_data.subject);
+		}
+
+		if (xmp_data.publisher) {
+			tracker_statement_list_insert (metadata, ":", RDF_PREFIX "type", NCO_PREFIX "Contact");
+			tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", xmp_data.publisher);
+			tracker_statement_list_insert (metadata, uri, NCO_PREFIX "publisher", ":");
+			g_free (xmp_data.publisher);
+		}
+
+		if (xmp_data.type) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "type", xmp_data.type);
+			g_free (xmp_data.type);
+		}
+
+		if (xmp_data.format) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "format", xmp_data.format);
+			g_free (xmp_data.format);
+		}
+
+		if (xmp_data.identifier) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "identifier", xmp_data.identifier);
+			g_free (xmp_data.identifier);
+		}
+
+		if (xmp_data.source) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "source", xmp_data.source);
+			g_free (xmp_data.source);
+		}
+
+		if (xmp_data.language) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "language", xmp_data.language);
+			g_free (xmp_data.language);
+		}
+
+		if (xmp_data.relation) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "relation", xmp_data.relation);
+			g_free (xmp_data.relation);
+		}
+
+		if (xmp_data.coverage) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "coverage", xmp_data.coverage);
+			g_free (xmp_data.coverage);
+		}
+
+		if (xmp_data.license) {
+			tracker_statement_list_insert (metadata, uri, NIE_PREFIX "license", xmp_data.license);
+			g_free (xmp_data.license);
+		}
+
+		if (xmp_data.Make || xmp_data.Model) {
+			gchar *final_camera = tracker_coalesce (2, xmp_data.Make, xmp_data.Model); 
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "camera", final_camera);
+			g_free (final_camera);
+		}
+
+		if (xmp_data.Orientation) {
+			tracker_statement_list_insert (metadata, uri, NFO_PREFIX "orientation", xmp_data.Orientation);
+			g_free (xmp_data.Orientation);
+		}
+
+		if (xmp_data.rights) {
+			tracker_statement_list_insert (metadata, uri, NIE_PREFIX "copyright", xmp_data.rights);
+			g_free (xmp_data.rights);
+		}
+
+		if (xmp_data.WhiteBalance) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "whiteBalance", xmp_data.WhiteBalance);
+			g_free (xmp_data.WhiteBalance);
+		}
+
+		if (xmp_data.FNumber) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "fnumber", xmp_data.FNumber);
+			g_free (xmp_data.FNumber);
+		}
+
+		if (xmp_data.Flash) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "flash", xmp_data.Flash);
+			g_free (xmp_data.Flash);
+		}
+
+		if (xmp_data.FocalLength) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "focalLength", xmp_data.FocalLength);
+			g_free (xmp_data.FocalLength);
+		}
+
+		if (xmp_data.Artist || xmp_data.contributor) {
+			gchar *final_artist =  tracker_coalesce (2, xmp_data.Artist, xmp_data.contributor);
+			tracker_statement_list_insert (metadata, ":", RDF_PREFIX "type", NCO_PREFIX "Contact");
+			tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", final_artist);
+			tracker_statement_list_insert (metadata, uri, NCO_PREFIX "contributor", ":");
+			g_free (final_artist);
+		}
+
+		if (xmp_data.ExposureTime) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "exposureTime", xmp_data.ExposureTime);
+			g_free (xmp_data.ExposureTime);
+		}
+
+		if (xmp_data.ISOSpeedRatings) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "isoSpeed", xmp_data.ISOSpeedRatings);
+			g_free (xmp_data.ISOSpeedRatings);
+		}
+
+		if (xmp_data.description) {
+			tracker_statement_list_insert (metadata, uri, NIE_PREFIX "description", xmp_data.description);
+			g_free (xmp_data.description);
+		}
+
+		if (xmp_data.MeteringMode) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "meteringMode", xmp_data.MeteringMode);
+			g_free (xmp_data.MeteringMode);
+		}
+
 	}
 
 	if (!tracker_is_empty_string (keywords)) {
@@ -120,28 +314,12 @@ extract_pdf (const gchar *uri,
 		}
 	}
 
-	if (creation_date > 0) {
-		gchar *date_string = tracker_date_to_string ((time_t) creation_date);
-		tracker_statement_list_insert (metadata, uri,
-				          NIE_PREFIX "created",
-				          date_string);
-		g_free (date_string);
-	}
-
 	tracker_statement_list_insert_with_int (metadata, uri,
 					   NFO_PREFIX "pageCount",
 					   poppler_document_get_n_pages (document));
 
-	if ( metadata_xml ) {
-		tracker_read_xmp (metadata_xml, strlen (metadata_xml), uri, metadata);
-	}
-
-	g_free (title);
-	g_free (author);
-	g_free (subject);
 	g_free (keywords);
 	g_free (metadata_xml);
-
 	g_object_unref (document);
 	g_free (filename);
 }
diff --git a/src/tracker-extract/tracker-extract-tiff.c b/src/tracker-extract/tracker-extract-tiff.c
index ac82428..af0b195 100644
--- a/src/tracker-extract/tracker-extract-tiff.c
+++ b/src/tracker-extract/tracker-extract-tiff.c
@@ -23,10 +23,6 @@
 
 #include <stdio.h>
 
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE /* strcasestr() */
-#endif
-
 #include <ctype.h>
 #include <string.h>
 #include <fcntl.h>
@@ -46,19 +42,16 @@
 #include "tracker-main.h"
 #include "tracker-xmp.h"
 #include "tracker-iptc.h"
+#include "tracker-exif.h"
 
-#define EXIF_DATE_FORMAT     "%Y:%m:%d %H:%M:%S"
+#define EXIF_DATE_FORMAT	"%Y:%m:%d %H:%M:%S"
 
 #define NMM_PREFIX TRACKER_NMM_PREFIX
 #define NFO_PREFIX TRACKER_NFO_PREFIX
 #define NIE_PREFIX TRACKER_NIE_PREFIX
 #define DC_PREFIX TRACKER_DC_PREFIX
 #define NCO_PREFIX TRACKER_NCO_PREFIX
-
 #define RDF_PREFIX TRACKER_RDF_PREFIX
-#define RDF_TYPE RDF_PREFIX "type"
-
-typedef gchar * (*PostProcessor) (const gchar *, gboolean *);
 
 typedef enum {
 	TIFF_TAGTYPE_UNDEFINED = 0,
@@ -70,289 +63,213 @@ typedef enum {
 } TagType;
 
 typedef struct {
-	guint          tag;
-	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,
-			       TrackerSparqlBuilder   *metadata);
-
-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);
+	gchar *camera, *title, *orientation, *copyright, *white_balance, 
+	      *fnumber, *flash, *focal_length, *artist, 
+	      *exposure_time, *iso_speed_ratings, *date, *description,
+	      *metering_mode, *creator, *x_dimension, *y_dimension;
+} TiffNeedsMergeData;
+
+typedef struct {
+	gchar *artist, *copyright, *datetime, *documentname, *imagedescription,
+	      *imagewidth, *imagelength, *make, *model, *orientation;
+} TiffData;
+
+static void extract_tiff (const gchar *filename,
+                          TrackerSparqlBuilder   *metadata);
 
 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, 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, 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)
+get_flash (TIFF *image)
 {
-	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;
+	guint16 varui16 = 0;
+
+	if (TIFFGetField (image, EXIFTAG_FLASH, &varui16)) {
+		switch (varui16) {
+			case 0x0001:
+			case 0x0009:
+			case 0x000D:
+			case 0x000F:
+			case 0x0019:
+			case 0x001D:
+			case 0x001F:
+			case 0x0041:
+			case 0x0045:
+			case 0x0047:
+			case 0x0049:
+			case 0x004D:
+			case 0x004F:
+			case 0x0059:
+			case 0x005F:
+			case 0x005D:
+			return g_strdup ("nmm:flash-on");
+			default:
+			return g_strdup ("nmm:flash-off");
 		}
 	}
 
 	return NULL;
 }
 
-#endif /* HAVE_STRCASESTR */
-
 static gchar *
-date_to_iso8601	(const gchar *exif_date, gboolean *free_it)
+get_orientation (TIFF *image)
 {
-	/* ex; date "2007:04:15 15:35:58"
-	 * To
-	 * ex. "2007-04-15T17:35:58+0200 where +0200 is localtime
-	 */
-	*free_it = TRUE;
-	return tracker_date_format_to_iso8601 (exif_date, EXIF_DATE_FORMAT);
-}
+	guint16 varui16 = 0;
 
+	if (TIFFGetField (image, TIFFTAG_ORIENTATION, &varui16)) {
+		switch (varui16) {
+			default:
+			case 0:
+			return  g_strdup ("nfo:orientation-top");
+			case 1:
+			return  g_strdup ("nfo:orientation-top-mirror");
+			case 2:
+			return  g_strdup ("nfo:orientation-bottom");
+			case 3:
+			return  g_strdup ("nfo:orientation-bottom-mirror");
+			case 4:
+			return  g_strdup ("nfo:orientation-left-mirror");
+			case 5:
+			return  g_strdup ("nfo:orientation-right");
+			case 6:
+			return  g_strdup ("nfo:orientation-right-mirror");
+			case 7:
+			return  g_strdup ("nfo:orientation-left");
+		}
+	}
 
-static gchar *
-fix_focal_length (const gchar *fl, gboolean *free_it)
-{
-	*free_it = TRUE;
-	return g_strndup (fl, strstr (fl, " mm") - fl);
+	return NULL;
 }
 
-static gchar *
-fix_flash (const gchar *flash, gboolean *free_it)
-{
-	*free_it = FALSE;
-	
-	if (strcasestr (flash, "flash fired")) {
-		return (gchar *) "nmm:flash-on";
-	} else {
-		return (gchar *) "nmm:flash-off";
-	}
-}
 
 static gchar *
-fix_fnumber (const gchar *fn, gboolean *free_it)
+get_metering_mode (TIFF *image)
 {
-	gchar *new_fn;
-
-	if (!fn) {
-		*free_it = FALSE;
-		return NULL;
-	}
-
-	new_fn = g_strdup (fn);
+	guint16 varui16 = 0;
 
-	if (new_fn[0] == 'F') {
-		new_fn[0] = ' ';
-	} else if (fn[0] == 'f' && new_fn[1] == '/') {
-		new_fn[0] = new_fn[1] = ' ';
+	if (TIFFGetField (image, EXIFTAG_METERINGMODE, &varui16)) {
+		switch (varui16) {
+			case 1:
+			return g_strdup ("nmm:meteringMode-average");
+			case 2:
+			return g_strdup ("nmm:meteringMode-center-weighted-average");
+			case 3:
+			return g_strdup ("nmm:meteringMode-spot");
+			case 4:
+			return g_strdup ("nmm:meteringMode-multispot");
+			case 5:
+			return g_strdup ("nmm:meteringMode-pattern");
+			case 6:
+			return g_strdup ("nmm:meteringMode-partial");
+			default:
+			return g_strdup ("nmm:meteringMode-other");
+		}
 	}
 
-	*free_it = TRUE;
-	return g_strstrip (new_fn);
+	return NULL;
 }
 
-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)
+get_white_balance (TIFF *image)
 {
-	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";
-				case 2:
-				return (gchar *) "nfo:orientation-bottom";
-				case 3:
-				return (gchar *) "nfo:orientation-bottom-mirror";
-				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";
-			}
+	guint16 varui16 = 0;
+
+	if (TIFFGetField (image, EXIFTAG_WHITEBALANCE, &varui16)) {
+		if (varui16 == 0) {
+			return g_strdup ("nmm:whiteBalance-auto");
 		}
+		return g_strdup ("nmm:whiteBalance-manual");
 	}
 
-	return (gchar *) "nfo:orientation-top";
+	return NULL;
 }
 
 
 static gchar *
-fix_metering_mode (const gchar *metering_mode, gboolean *free_it)
+get_value (TIFF *image, guint tag, guint type)
 {
-	*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";
-	}
+	guint16 count16 = 0;
+	gfloat vardouble = 0;
+	guint16 varui16 = 0;
+	guint32 varui32 = 0;
+	gchar *text = NULL;
+	void *data = NULL;
 
-	if (strcasestr (metering_mode, "partial")) {
-		return (gchar *) "nmm:meteringMode-partial";
+	switch (type) {
+		case TIFF_TAGTYPE_STRING:
+			if (TIFFGetField (image, tag, &text)) {
+				return g_strdup (text);
+			}
+			break;
+		case TIFF_TAGTYPE_UINT16:
+			if (TIFFGetField (image, tag, &varui16)) {
+				return g_strdup_printf ("%i", varui16);
+			}
+			break;
+		case TIFF_TAGTYPE_UINT32:
+			if (TIFFGetField (image, tag, &varui32)) {
+				return g_strdup_printf ("%i", varui32);
+			}
+			break;
+		case TIFF_TAGTYPE_DOUBLE:
+			if (TIFFGetField (image, tag, &vardouble)) {
+				return g_strdup_printf ("%f", vardouble);
+			}
+			break;
+		case TIFF_TAGTYPE_C16_UINT16:
+			if (TIFFGetField (image, tag, &count16, &data)) {
+				return g_strdup_printf ("%i", * (guint16 *) data);
+			}
+			break;
+		default:
+			break;
 	}
 
-	return (gchar *) "nmm:meteringMode-other";
+	return NULL;
 }
 
 
-static gchar *
-fix_white_balance (const gchar *white_balance, gboolean *free_it)
+static void
+insert_keywords (TrackerSparqlBuilder *metadata, const gchar *uri, gchar *keywords)
 {
-	*free_it = FALSE;
-
-	if (strcasestr (white_balance, "auto")) {
-		return (gchar *) "nmm:whiteBalance-auto";
+	char *lasts, *keyw;
+	size_t len;
+
+	keyw = keywords;
+	keywords = strchr (keywords, '"');
+	if (keywords)
+		keywords++;
+	else 
+		keywords = keyw;
+
+	len = strlen (keywords);
+	if (keywords[len - 1] == '"')
+		keywords[len - 1] = '\0';
+
+	for (keyw = strtok_r (keywords, ",; ", &lasts); keyw; 
+	     keyw = strtok_r (NULL, ",; ", &lasts)) {
+		tracker_statement_list_insert (metadata, uri, 
+		                               NIE_PREFIX "keyword", 
+		                               (const gchar*) keyw);
 	}
-
-	/* Found in the field: sunny, fluorescent, incandescent, cloudy. These
-	 * will this way also yield as manual. */
-
-	return (gchar *) "nmm:whiteBalance-manual";
 }
 
 static void
-extract_tiff (const gchar *uri, 
-	      TrackerSparqlBuilder   *metadata)
+extract_tiff (const gchar *uri, TrackerSparqlBuilder *metadata)
 {
 	TIFF *image;
 	glong exifOffset;
 	gchar *filename = g_filename_from_uri (uri, NULL, NULL);
-	TiffTag *tag;
-
-	gchar buffer[1024];
-	gchar *text;
-	guint16 varui16 = 0;
-	guint32 varui32 = 0;
-	void *data;
-	guint16 count16;
-
-	gfloat vardouble;
+	TrackerXmpData xmp_data = { 0 };
+	TrackerIptcData iptc_data = { 0 };
+	TrackerExifData exif_data = { 0 };
+	TiffNeedsMergeData merge_data = { 0 };
+	TiffData tiff_data = { 0 };
 
 #ifdef HAVE_LIBIPTCDATA
 	gchar   *iptcOffset;
@@ -371,8 +288,12 @@ extract_tiff (const gchar *uri,
 	}
 
 	tracker_statement_list_insert (metadata, uri, 
-	                          RDF_TYPE, 
-	                          NFO_PREFIX "Image");
+	                               RDF_PREFIX "type",
+	                               NFO_PREFIX "Image");
+
+	tracker_statement_list_insert (metadata, uri,
+	                               RDF_PREFIX "type",
+	                               NMM_PREFIX "Photo");
 
 #ifdef HAVE_LIBIPTCDATA
 	if (TIFFGetField (image, TIFFTAG_RICHTIFFIPTC, &iptcSize, &iptcOffset)) {
@@ -380,7 +301,7 @@ extract_tiff (const gchar *uri,
 			TIFFSwabArrayOfLong((uint32 *) iptcOffset,(unsigned long) iptcSize);
 		tracker_read_iptc (iptcOffset,
 				   4*iptcSize,
-				   uri, metadata);
+				   uri, &iptc_data);
 	}
 #endif /* HAVE_LIBIPTCDATA */
 
@@ -391,145 +312,274 @@ extract_tiff (const gchar *uri,
 		tracker_read_xmp (xmpOffset,
 				  size,
 				  uri,
-				  metadata);
+				  &xmp_data);
 	}
 #endif /* HAVE_EXEMPI */
 
+	if (!tiff_data.artist)
+		tiff_data.artist = get_value (image, TIFFTAG_ARTIST, TIFF_TAGTYPE_STRING);
+	if (!tiff_data.copyright)
+		tiff_data.copyright = get_value (image, TIFFTAG_COPYRIGHT, TIFF_TAGTYPE_STRING);
+	if (!tiff_data.datetime) 
+		tiff_data.datetime = get_value (image, TIFFTAG_DATETIME, TIFF_TAGTYPE_STRING); 
+	if (!tiff_data.documentname) 
+		tiff_data.documentname = get_value (image, TIFFTAG_DOCUMENTNAME, TIFF_TAGTYPE_STRING); 
+	if (!tiff_data.imagedescription) 
+		tiff_data.imagedescription = get_value (image, TIFFTAG_IMAGEDESCRIPTION, TIFF_TAGTYPE_STRING); 
+	if (!tiff_data.make) 
+		tiff_data.make = get_value (image, TIFFTAG_MAKE, TIFF_TAGTYPE_STRING); 
+	if (!tiff_data.model) 
+		tiff_data.model = get_value (image, TIFFTAG_MODEL, TIFF_TAGTYPE_STRING); 
+	if (!tiff_data.orientation)
+		tiff_data.orientation = get_orientation (image); 
+
 	if (TIFFGetField (image, TIFFTAG_EXIFIFD, &exifOffset)) {
 		if (TIFFReadEXIFDirectory (image, exifOffset)) {
-			for (tag = exiftags; tag->name; ++tag) {
-				switch (tag->type) {
-				case TIFF_TAGTYPE_STRING:
-					if (!TIFFGetField (image, tag->tag, &text)) {
-						continue;
-					}
-
-					snprintf (buffer, sizeof (buffer), "%s",text);
-					break;
-				case TIFF_TAGTYPE_UINT16:						
-					if (!TIFFGetField (image, tag->tag, &varui16)) {
-						continue;
-					}
-
-					snprintf (buffer, sizeof (buffer), "%i",varui16);
-					break;
-				case TIFF_TAGTYPE_UINT32:
-					if (!TIFFGetField (image, tag->tag, &varui32)) {
-						continue;
-					}
-
-					snprintf(buffer, sizeof (buffer), "%i",varui32);
-					break;
-				case TIFF_TAGTYPE_DOUBLE:
-					if (!TIFFGetField (image, tag->tag, &vardouble)) {
-						continue;
-					}
-
-					snprintf (buffer, sizeof (buffer), "%f",vardouble);
-					break;
-				case TIFF_TAGTYPE_C16_UINT16:						
-					if (!TIFFGetField (image, tag->tag, &count16, &data)) {
-						continue;
-					}
-
-					/* We only take only the first for now */
-					snprintf (buffer, sizeof (buffer), "%i",*(guint16 *)data);
-					break;	
-
-				default:
-					continue;
-					break;
-				}
-
-				if (tag->post) {
-					gboolean free_it = FALSE;
-					gchar *value = (*tag->post) (buffer, &free_it);
-					tracker_statement_list_insert (metadata, uri,
-								       tag->name,
-								       value);
-					if (free_it)
-						g_free (value);
-				} else {
-					tracker_statement_list_insert (metadata, uri,
-								       tag->name,
-								       buffer);
-				}
-			}
+			if (!exif_data.exposure_time)
+				exif_data.exposure_time = get_value (image, EXIFTAG_EXPOSURETIME, TIFF_TAGTYPE_DOUBLE); 
+			if (!exif_data.fnumber)
+				exif_data.fnumber = get_value (image, EXIFTAG_FNUMBER, TIFF_TAGTYPE_DOUBLE); 
+			if (!exif_data.iso_speed_ratings)
+				exif_data.iso_speed_ratings = get_value (image, EXIFTAG_ISOSPEEDRATINGS, TIFF_TAGTYPE_C16_UINT16); 
+			if (!exif_data.time_original)
+				exif_data.time_original = get_value (image, EXIFTAG_DATETIMEORIGINAL, TIFF_TAGTYPE_STRING); 
+			if (!exif_data.metering_mode)
+				exif_data.metering_mode = get_metering_mode (image); 
+			if (!exif_data.flash)
+				exif_data.flash = get_flash (image); 
+			if (!exif_data.focal_length)
+				exif_data.focal_length = get_value (image, EXIFTAG_DATETIMEORIGINAL, TIFF_TAGTYPE_DOUBLE); 
+			if (!exif_data.white_balance) 
+				exif_data.white_balance = get_white_balance (image);
 		}
 	}
 
-	/* 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:
-				if (!TIFFGetField (image, tag->tag, &text)) {
-					continue;
-				}
-
-				snprintf (buffer, sizeof (buffer), "%s", text);
-				break;
-			case TIFF_TAGTYPE_UINT16:
-				if (!TIFFGetField (image, tag->tag, &varui16)) {
-					continue;
-				}
-
-				snprintf (buffer, sizeof (buffer), "%i",varui16);
-				break;
-			case TIFF_TAGTYPE_UINT32:
-				if (!TIFFGetField (image, tag->tag, &varui32)) {
-					continue;
-				}
-
-				snprintf(buffer, sizeof (buffer), "%i",varui32);
-				break;
-			case TIFF_TAGTYPE_DOUBLE:
-				if (!TIFFGetField (image, tag->tag, &vardouble)) {
-					continue;
-				}
-
-				snprintf (buffer, sizeof (buffer), "%f",vardouble);
-				break;
-			default:
-				continue;
-				break;
-			}
+	TIFFClose (image);
+	g_free (filename);
 
-		if (tag->post) {
-			what_i_need = (*tag->post) (buffer, &free_it);
-		} else {
-			what_i_need = buffer;
-		}
+	merge_data.camera = tracker_coalesce (6, tiff_data.model,
+	                                      tiff_data.make,
+	                                      xmp_data.Model, 
+	                                      xmp_data.Make,
+	                                      exif_data.model,
+	                                      exif_data.make);
+
+	merge_data.title = tracker_coalesce (3, tiff_data.documentname,
+	                                     xmp_data.title,
+	                                     exif_data.document_name);
+
+	merge_data.orientation = tracker_coalesce (4, tiff_data.orientation,
+	                                           exif_data.orientation,
+	                                           xmp_data.Orientation,
+	                                           iptc_data.image_orientation);
+
+	merge_data.copyright = tracker_coalesce (4, tiff_data.copyright,
+	                                         exif_data.copyright,
+	                                         xmp_data.rights,
+	                                         iptc_data.copyright_notice);
+
+	merge_data.white_balance = tracker_coalesce (2, exif_data.white_balance,
+	                                             xmp_data.WhiteBalance);
+	                                             
+
+	merge_data.fnumber =  tracker_coalesce (2, exif_data.fnumber,
+	                                        xmp_data.FNumber);
+
+	merge_data.flash =  tracker_coalesce (2, exif_data.flash,
+	                                      xmp_data.Flash);
+
+	merge_data.focal_length =  tracker_coalesce (2, exif_data.focal_length,
+	                                             xmp_data.FocalLength);
+
+	merge_data.artist =  tracker_coalesce (4, tiff_data.artist,
+	                                       exif_data.artist,
+	                                       xmp_data.Artist,
+	                                       xmp_data.contributor);
+
+	merge_data.exposure_time =  tracker_coalesce (2, exif_data.exposure_time,
+	                                              xmp_data.ExposureTime);
+
+	merge_data.iso_speed_ratings =  tracker_coalesce (2, exif_data.iso_speed_ratings,
+	                                                  xmp_data.ISOSpeedRatings);
+
+	merge_data.date =  tracker_coalesce (6, tiff_data.datetime,
+	                                     exif_data.time, 
+	                                     xmp_data.date,
+	                                     iptc_data.date_created,
+	                                     exif_data.time_original,
+	                                     xmp_data.DateTimeOriginal);
+
+	merge_data.description = tracker_coalesce (3, tiff_data.imagedescription,
+	                                           exif_data.description,
+	                                           xmp_data.description);
+
+	merge_data.metering_mode =  tracker_coalesce (2, exif_data.metering_mode,
+	                                              xmp_data.MeteringMode);
+
+	merge_data.creator =  tracker_coalesce (3, iptc_data.byline,
+	                                        xmp_data.creator,
+	                                        iptc_data.credit);
+
+	merge_data.x_dimension =  tracker_coalesce (2, tiff_data.imagewidth,
+	                                            exif_data.x_dimension);
+	merge_data.y_dimension =  tracker_coalesce (2, tiff_data.imagelength,
+	                                            exif_data.y_dimension);
+
+	if (exif_data.user_comment) {
+		tracker_statement_list_insert (metadata, uri, NIE_PREFIX "comment", exif_data.user_comment);
+		g_free (exif_data.user_comment);
+	}
 
+	if (merge_data.x_dimension) {
+		tracker_statement_list_insert (metadata, uri, NFO_PREFIX "width", merge_data.x_dimension);
+		g_free (merge_data.x_dimension);
+	}
 
-		if (tag->urn_prefix) {
-			gchar *canonical_uri;
+	if (merge_data.y_dimension) {
+		tracker_statement_list_insert (metadata, uri, NFO_PREFIX "height", merge_data.y_dimension);
+		g_free (merge_data.y_dimension);
+	}
 
-			if (tag->urn_prefix[0] == ':')
-				canonical_uri = tracker_uri_printf_escaped (tag->urn_prefix, what_i_need);
-			else
-				canonical_uri = (gchar *) tag->urn_prefix;
+	if (xmp_data.keywords) {
+		insert_keywords (metadata, uri, xmp_data.keywords);
+		g_free (xmp_data.keywords);
+	}
 
-			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 (xmp_data.subject) {
+		insert_keywords (metadata, uri, xmp_data.subject);
+		g_free (xmp_data.subject);
+	}
 
-			if (tag->urn_prefix[0] != ':')
-				g_free (canonical_uri);
-		} else {
-			tracker_statement_list_insert (metadata, uri, tag->name, what_i_need);
-		}
+	if (xmp_data.publisher) {
+		tracker_statement_list_insert (metadata, ":", RDF_PREFIX "type", NCO_PREFIX "Contact");
+		tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", xmp_data.publisher);
+		tracker_statement_list_insert (metadata, uri, NCO_PREFIX "publisher", ":");
+		g_free (xmp_data.publisher);
+	}
+
+	if (xmp_data.type) {
+		tracker_statement_list_insert (metadata, uri, DC_PREFIX "type", xmp_data.type);
+		g_free (xmp_data.type);
+	}
 
+	if (xmp_data.format) {
+		tracker_statement_list_insert (metadata, uri, DC_PREFIX "format", xmp_data.format);
+		g_free (xmp_data.format);
+	}
 
-		if (free_it) 
-			g_free (what_i_need);
+	if (xmp_data.identifier) {
+		tracker_statement_list_insert (metadata, uri, DC_PREFIX "identifier", xmp_data.identifier);
+		g_free (xmp_data.identifier);
 	}
 
-	TIFFClose (image);
+	if (xmp_data.source) {
+		tracker_statement_list_insert (metadata, uri, DC_PREFIX "source", xmp_data.source);
+		g_free (xmp_data.source);
+	}
 
-	g_free (filename);
+	if (xmp_data.language) {
+		tracker_statement_list_insert (metadata, uri, DC_PREFIX "language", xmp_data.language);
+		g_free (xmp_data.language);
+	}
+
+	if (xmp_data.relation) {
+		tracker_statement_list_insert (metadata, uri, DC_PREFIX "relation", xmp_data.relation);
+		g_free (xmp_data.relation);
+	}
+
+	if (xmp_data.coverage) {
+		tracker_statement_list_insert (metadata, uri, DC_PREFIX "coverage", xmp_data.coverage);
+		g_free (xmp_data.coverage);
+	}
+
+	if (xmp_data.license) {
+		tracker_statement_list_insert (metadata, uri, NIE_PREFIX "license", xmp_data.license);
+		g_free (xmp_data.license);
+	}
+
+	if (iptc_data.keywords) {
+		insert_keywords (metadata, uri, iptc_data.keywords);
+		g_free (iptc_data.keywords);
+	}
+
+	if (merge_data.camera) {
+		tracker_statement_list_insert (metadata, uri, NMM_PREFIX "camera", merge_data.camera);
+		g_free (merge_data.camera);
+	}
+
+	if (merge_data.title) {
+		tracker_statement_list_insert (metadata, uri, NIE_PREFIX "title", merge_data.title);
+		g_free (merge_data.title);
+	}
+
+	if (merge_data.orientation) {
+		tracker_statement_list_insert (metadata, uri, NFO_PREFIX "orientation", merge_data.orientation);
+		g_free (merge_data.orientation);
+	}
+
+	if (merge_data.copyright) {
+		tracker_statement_list_insert (metadata, uri, NIE_PREFIX "copyright", merge_data.copyright);
+		g_free (merge_data.copyright);
+	}
+
+	if (merge_data.white_balance) {
+		tracker_statement_list_insert (metadata, uri, NMM_PREFIX "whiteBalance", merge_data.white_balance);
+		g_free (merge_data.white_balance);
+	}
+
+	if (merge_data.fnumber) {
+		tracker_statement_list_insert (metadata, uri, NMM_PREFIX "fnumber", merge_data.fnumber);
+		g_free (merge_data.fnumber);
+	}
+
+	if (merge_data.flash) {
+		tracker_statement_list_insert (metadata, uri, NMM_PREFIX "flash", merge_data.flash);
+		g_free (merge_data.flash);
+	}
+
+	if (merge_data.focal_length) {
+		tracker_statement_list_insert (metadata, uri, NMM_PREFIX "focalLength", merge_data.focal_length);
+		g_free (merge_data.focal_length);
+	}
+
+	if (merge_data.artist) {
+		tracker_statement_list_insert (metadata, ":", RDF_PREFIX "type", NCO_PREFIX "Contact");
+		tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", merge_data.artist);
+		tracker_statement_list_insert (metadata, uri, NCO_PREFIX "contributor", ":");
+		g_free (merge_data.artist);
+	}
+
+	if (merge_data.exposure_time) {
+		tracker_statement_list_insert (metadata, uri, NMM_PREFIX "exposureTime", merge_data.exposure_time);
+		g_free (merge_data.exposure_time);
+	}
+
+	if (merge_data.iso_speed_ratings) {
+		tracker_statement_list_insert (metadata, uri, NMM_PREFIX "isoSpeed", merge_data.iso_speed_ratings);
+		g_free (merge_data.iso_speed_ratings);
+	}
+
+	if (merge_data.date) {
+		tracker_statement_list_insert (metadata, uri, NIE_PREFIX "contentCreated", merge_data.date);
+		g_free (merge_data.date);
+	}
+
+	if (merge_data.description) {
+		tracker_statement_list_insert (metadata, uri, NIE_PREFIX "description", merge_data.description);
+		g_free (merge_data.description);
+	}
+
+	if (merge_data.metering_mode) {
+		tracker_statement_list_insert (metadata, uri, NMM_PREFIX "meteringMode", merge_data.metering_mode);
+		g_free (merge_data.metering_mode);
+	}
+
+	if (merge_data.creator) {
+		tracker_statement_list_insert (metadata, ":", RDF_PREFIX "type", NCO_PREFIX "Contact");
+		tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", merge_data.creator);
+		tracker_statement_list_insert (metadata, uri, NCO_PREFIX "creator", ":");
+		g_free (merge_data.creator);
+	}
 }
 
 TrackerExtractData *
diff --git a/src/tracker-extract/tracker-extract-xmp.c b/src/tracker-extract/tracker-extract-xmp.c
index 299f60f..6fb61cd 100644
--- a/src/tracker-extract/tracker-extract-xmp.c
+++ b/src/tracker-extract/tracker-extract-xmp.c
@@ -23,10 +23,23 @@
 #include <gio/gio.h>
 
 #include <libtracker-common/tracker-statement-list.h>
+#include <libtracker-common/tracker-ontology.h>
+#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"
 
+
+#define NMM_PREFIX TRACKER_NMM_PREFIX
+#define NFO_PREFIX TRACKER_NFO_PREFIX
+#define NIE_PREFIX TRACKER_NIE_PREFIX
+#define DC_PREFIX TRACKER_DC_PREFIX
+#define NCO_PREFIX TRACKER_NCO_PREFIX
+#define RDF_PREFIX TRACKER_RDF_PREFIX
+
 static void extract_xmp (const gchar          *filename, 
                          TrackerSparqlBuilder *metadata);
 
@@ -48,74 +61,70 @@ find_orig_uri (const gchar *xmp_filename)
 	GFileEnumerator *iter;
 	GFileInfo *orig_info;
 	const gchar *filename_a;
-        gchar *found_file = NULL;
+	gchar *found_file = NULL;
 
-        file = g_file_new_for_path (xmp_filename);
-        dir = g_file_get_parent (file);
+	file = g_file_new_for_path (xmp_filename);
+	dir = g_file_get_parent (file);
 
-	orig_info = g_file_query_info (file, 
-                                       G_FILE_ATTRIBUTE_STANDARD_NAME,
-                                       G_FILE_QUERY_INFO_NONE, 
-                                       NULL, 
-                                       NULL);
+	orig_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_NAME,
+	                               G_FILE_QUERY_INFO_NONE, 
+	                               NULL, NULL);
 
 	filename_a = g_file_info_get_name (orig_info);
 
-	iter = g_file_enumerate_children (dir, 
-                                          G_FILE_ATTRIBUTE_STANDARD_NAME, 
-                                          G_FILE_QUERY_INFO_NONE, 
-                                          NULL, 
-                                          NULL);
+	iter = g_file_enumerate_children (dir, G_FILE_ATTRIBUTE_STANDARD_NAME, 
+	                                  G_FILE_QUERY_INFO_NONE, 
+	                                  NULL, NULL);
 
 	if (iter) {
 		GFileInfo *info;
 
 		while ((info = g_file_enumerator_next_file (iter, NULL, NULL)) && !found_file) {
 			const gchar *filename_b;
-                        const gchar *ext_a, *ext_b;
-                        gchar *casefold_a, *casefold_b;
-
-                        /* OK, important: 
-                         * 1. Files can't be the same.
-                         * 2. File names (without extension) must match
-                         * 3. Something else?
-                         */
+			const gchar *ext_a, *ext_b;
+			gchar *casefold_a, *casefold_b;
+
+			/* OK, important: 
+			 * 1. Files can't be the same.
+			 * 2. File names (without extension) must match
+			 * 3. Something else? */
+
 			filename_b = g_file_info_get_name (info);
 
-                        ext_a = g_utf8_strrchr (filename_a, -1, '.');
-                        ext_b = g_utf8_strrchr (filename_b, -1, '.');
-
-                        /* Look for extension */
-                        if (!ext_a || !ext_b) {
-                                g_object_unref (info);
-                                continue;
-                        }
-
-                        /* Name part is the same length */
-                        if ((ext_a - filename_a) != (ext_b - filename_b)) {
-                                g_object_unref (info);
-                                continue;
-                        }
-                        
-                        /* Check extensions are not the same (i.e. same len and ext) */
-                        if (g_strcmp0 (ext_a, ext_b) == 0) {
-                                g_object_unref (info);
-                                continue;
-                        }
+			ext_a = g_utf8_strrchr (filename_a, -1, '.');
+			ext_b = g_utf8_strrchr (filename_b, -1, '.');
+
+			/* Look for extension */
+			if (!ext_a || !ext_b) {
+				g_object_unref (info);
+				continue;
+			}
+
+			/* Name part is the same length */
+			if ((ext_a - filename_a) != (ext_b - filename_b)) {
+				g_object_unref (info);
+				continue;
+			}
+			
+			/* Check extensions are not the same (i.e. same len and ext) */
+			if (g_strcmp0 (ext_a, ext_b) == 0) {
+				g_object_unref (info);
+				continue;
+			}
 
 			/* Don't compare the ".xmp" with ".jpeg" and don't match the same file */
 
-                        /* Now compare name (without ext) and make
-                         * sure they are the same in a caseless
-                         * compare.
-                         */
-                        casefold_a = g_utf8_casefold (filename_a, (ext_a - filename_a));
-                        casefold_b = g_utf8_casefold (filename_b, (ext_b - filename_b));
-                        
+			/* Now compare name (without ext) and make
+			 * sure they are the same in a caseless
+			 * compare. */
+
+			casefold_a = g_utf8_casefold (filename_a, (ext_a - filename_a));
+			casefold_b = g_utf8_casefold (filename_b, (ext_b - filename_b));
+
 			if (g_strcmp0 (casefold_a, casefold_b) == 0) {
 				GFile *found;
-                                
-                                found = g_file_get_child (dir, filename_b);
+
+				found = g_file_get_child (dir, filename_b);
 				found_file = g_file_get_uri (found);
 				g_object_unref (found);
 			}
@@ -135,6 +144,32 @@ find_orig_uri (const gchar *xmp_filename)
 	return found_file;
 }
 
+
+static void
+insert_keywords (TrackerSparqlBuilder *metadata, const gchar *uri, gchar *keywords)
+{
+	char *lasts, *keyw;
+	size_t len;
+
+	keyw = keywords;
+	keywords = strchr (keywords, '"');
+	if (keywords)
+		keywords++;
+	else 
+		keywords = keyw;
+
+	len = strlen (keywords);
+	if (keywords[len - 1] == '"')
+		keywords[len - 1] = '\0';
+
+	for (keyw = strtok_r (keywords, ",; ", &lasts); keyw; 
+	     keyw = strtok_r (NULL, ",; ", &lasts)) {
+		tracker_statement_list_insert (metadata, uri, 
+		                               NIE_PREFIX "keyword", 
+		                               (const gchar*) keyw);
+	}
+}
+
 static void
 extract_xmp (const gchar          *uri, 
              TrackerSparqlBuilder *metadata)
@@ -143,16 +178,157 @@ extract_xmp (const gchar          *uri,
 	gsize length;
 	GError *error;
 	gchar *filename = g_filename_from_uri (uri, NULL, NULL);
+	TrackerXmpData xmp_data = { 0 };
 
 	if (g_file_get_contents (filename, &contents, &length, &error)) {
 		gchar *orig_uri = find_orig_uri (filename);
 
 		/* If no orig file is found for the sidekick, we use the sidekick to
 		 * describe itself instead, falling back to uri */
+
 		tracker_read_xmp (contents,
-                                  length, 
-                                  orig_uri ? orig_uri : uri, 
-                                  metadata);
+		                  length, 
+		                  orig_uri ? orig_uri : uri, 
+		                  &xmp_data);
+
+		if (xmp_data.keywords) {
+			insert_keywords (metadata, uri, xmp_data.keywords);
+			g_free (xmp_data.keywords);
+		}
+
+		if (xmp_data.subject) {
+			insert_keywords (metadata, uri, xmp_data.subject);
+			g_free (xmp_data.subject);
+		}
+
+		if (xmp_data.publisher) {
+			tracker_statement_list_insert (metadata, ":", RDF_PREFIX "type", NCO_PREFIX "Contact");
+			tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", xmp_data.publisher);
+			tracker_statement_list_insert (metadata, uri, NCO_PREFIX "publisher", ":");
+			g_free (xmp_data.publisher);
+		}
+
+		if (xmp_data.type) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "type", xmp_data.type);
+			g_free (xmp_data.type);
+		}
+
+		if (xmp_data.format) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "format", xmp_data.format);
+			g_free (xmp_data.format);
+		}
+
+		if (xmp_data.identifier) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "identifier", xmp_data.identifier);
+			g_free (xmp_data.identifier);
+		}
+
+		if (xmp_data.source) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "source", xmp_data.source);
+			g_free (xmp_data.source);
+		}
+
+		if (xmp_data.language) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "language", xmp_data.language);
+			g_free (xmp_data.language);
+		}
+
+		if (xmp_data.relation) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "relation", xmp_data.relation);
+			g_free (xmp_data.relation);
+		}
+
+		if (xmp_data.coverage) {
+			tracker_statement_list_insert (metadata, uri, DC_PREFIX "coverage", xmp_data.coverage);
+			g_free (xmp_data.coverage);
+		}
+
+		if (xmp_data.license) {
+			tracker_statement_list_insert (metadata, uri, NIE_PREFIX "license", xmp_data.license);
+			g_free (xmp_data.license);
+		}
+
+		if (xmp_data.Make || xmp_data.Model) {
+			gchar *final_camera = tracker_coalesce (2, xmp_data.Make, xmp_data.Model); 
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "camera", final_camera);
+			g_free (final_camera);
+		}
+
+		if (xmp_data.title) {
+			tracker_statement_list_insert (metadata, uri, NIE_PREFIX "title", xmp_data.title);
+			g_free (xmp_data.title);
+		}
+
+		if (xmp_data.Orientation) {
+			tracker_statement_list_insert (metadata, uri, NFO_PREFIX "orientation", xmp_data.Orientation);
+			g_free (xmp_data.Orientation);
+		}
+
+		if (xmp_data.rights) {
+			tracker_statement_list_insert (metadata, uri, NIE_PREFIX "copyright", xmp_data.rights);
+			g_free (xmp_data.rights);
+		}
+
+		if (xmp_data.WhiteBalance) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "whiteBalance", xmp_data.WhiteBalance);
+			g_free (xmp_data.WhiteBalance);
+		}
+
+		if (xmp_data.FNumber) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "fnumber", xmp_data.FNumber);
+			g_free (xmp_data.FNumber);
+		}
+
+		if (xmp_data.Flash) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "flash", xmp_data.Flash);
+			g_free (xmp_data.Flash);
+		}
+
+		if (xmp_data.FocalLength) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "focalLength", xmp_data.FocalLength);
+			g_free (xmp_data.FocalLength);
+		}
+
+		if (xmp_data.Artist || xmp_data.contributor) {
+			gchar *final_artist =  tracker_coalesce (2, xmp_data.Artist, xmp_data.contributor);
+			tracker_statement_list_insert (metadata, ":", RDF_PREFIX "type", NCO_PREFIX "Contact");
+			tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", final_artist);
+			tracker_statement_list_insert (metadata, uri, NCO_PREFIX "contributor", ":");
+			g_free (final_artist);
+		}
+
+		if (xmp_data.ExposureTime) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "exposureTime", xmp_data.ExposureTime);
+			g_free (xmp_data.ExposureTime);
+		}
+
+		if (xmp_data.ISOSpeedRatings) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "isoSpeed", xmp_data.ISOSpeedRatings);
+			g_free (xmp_data.ISOSpeedRatings);
+		}
+
+		if (xmp_data.date || xmp_data.DateTimeOriginal) {
+			gchar *final_date =  tracker_coalesce (2, xmp_data.date, xmp_data.DateTimeOriginal);
+			tracker_statement_list_insert (metadata, uri, NIE_PREFIX "contentCreated", final_date);
+			g_free (final_date);
+		}
+
+		if (xmp_data.description) {
+			tracker_statement_list_insert (metadata, uri, NIE_PREFIX "description", xmp_data.description);
+			g_free (xmp_data.description);
+		}
+
+		if (xmp_data.MeteringMode) {
+			tracker_statement_list_insert (metadata, uri, NMM_PREFIX "meteringMode", xmp_data.MeteringMode);
+			g_free (xmp_data.MeteringMode);
+		}
+
+		if (xmp_data.creator) {
+			tracker_statement_list_insert (metadata, ":", RDF_PREFIX "type", NCO_PREFIX "Contact");
+			tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", xmp_data.creator);
+			tracker_statement_list_insert (metadata, uri, NCO_PREFIX "creator", ":");
+			g_free (xmp_data.creator);
+		}
 
 		g_free (orig_uri);
 	}
diff --git a/src/tracker-extract/tracker-iptc.c b/src/tracker-extract/tracker-iptc.c
index 575b9d2..00de234 100644
--- a/src/tracker-extract/tracker-iptc.c
+++ b/src/tracker-extract/tracker-iptc.c
@@ -20,23 +20,13 @@
 
 #include "config.h"
 
-#include <libtracker-common/tracker-ontology.h>
-#include <libtracker-common/tracker-statement-list.h>
-
 #include "tracker-iptc.h"
 #include "tracker-main.h"
 
-#define RDF_PREFIX TRACKER_RDF_PREFIX
-#define RDF_TYPE RDF_PREFIX "type"
-#define NIE_PREFIX TRACKER_NIE_PREFIX
-#define NCO_PREFIX TRACKER_NCO_PREFIX
-#define NFO_PREFIX TRACKER_NFO_PREFIX
-
 #include <glib.h>
 #include <string.h>
 
 #include <libtracker-common/tracker-type-utils.h>
-#include <libtracker-common/tracker-file-utils.h>
 
 #ifdef HAVE_LIBIPTCDATA
 
@@ -45,44 +35,6 @@
 
 #define IPTC_DATE_FORMAT "%Y %m %d"
 
-typedef const gchar * (*IptcPostProcessor) (const gchar*);
-
-typedef struct {
-	IptcRecord        record;
-	IptcTag           tag;
-	const gchar      *name;
-	IptcPostProcessor post;
-	const gchar      *urn;
-	const gchar      *rdf_type;
-	const gchar      *predicate;
-} IptcTagType;
-
-static const gchar *fix_iptc_orientation (const gchar *orientation);
-
-static gchar *
-date_to_iso8601 (const gchar *date)
-{
-	/* From: 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, IPTC_DATE_FORMAT);
-}
-
-static IptcTagType iptctags[] = {
-        { 2, IPTC_TAG_KEYWORDS, NIE_PREFIX "keyword", NULL, NULL, NULL, NULL }, /* We might have to strtok_r this one? */
-	/*	{ 2, IPTC_TAG_CONTENT_LOC_NAME, "Image:Location", NULL, NULL, NULL, NULL }, */
-	/*{ 2, IPTC_TAG_SUBLOCATION, "Image:Location", NULL, NULL, NULL, NULL },*/
-        { 2, IPTC_TAG_DATE_CREATED, NIE_PREFIX "contentCreated", date_to_iso8601, NULL, NULL, NULL },
-        /*{ 2, IPTC_TAG_ORIGINATING_PROGRAM, "Image:Software", NULL, NULL, NULL, NULL },*/
-        { 2, IPTC_TAG_BYLINE, NCO_PREFIX "creator", NULL, ":", NCO_PREFIX "Contact", NCO_PREFIX "fullname" },
-        /*{ 2, IPTC_TAG_CITY, "Image:City", NULL, NULL, NULL, NULL },*/
-        /*{ 2, IPTC_TAG_COUNTRY_NAME, "Image:Country", NULL, NULL, NULL, NULL },*/
-	{ 2, IPTC_TAG_CREDIT, NCO_PREFIX "creator", NULL, ":", NCO_PREFIX "Contact", NCO_PREFIX "fullname" },
-        { 2, IPTC_TAG_COPYRIGHT_NOTICE, NIE_PREFIX "copyright", NULL, NULL, NULL, NULL },
-        { 2, IPTC_TAG_IMAGE_ORIENTATION, NFO_PREFIX "orientation", fix_iptc_orientation, NULL, NULL, NULL },
-	{ -1, -1, NULL, NULL, NULL, NULL, NULL }
-};
-
 static const gchar *
 fix_iptc_orientation (const gchar *orientation)
 {
@@ -100,45 +52,73 @@ void
 tracker_read_iptc (const unsigned char *buffer,
 		   size_t		len,
 		   const gchar         *uri,
-		   TrackerSparqlBuilder   *metadata)
+		   TrackerIptcData     *data)
 {
 #ifdef HAVE_LIBIPTCDATA
-	IptcData     *iptc = NULL;
-	IptcTagType  *p = NULL;
+	guint i;
+	IptcData *iptc = NULL;
+	IptcTag   p[6] = { IPTC_TAG_KEYWORDS, 
+	         /* 01 */  IPTC_TAG_DATE_CREATED,
+	         /* 02 */  IPTC_TAG_BYLINE,
+	         /* 03 */  IPTC_TAG_CREDIT,
+	         /* 04 */  IPTC_TAG_COPYRIGHT_NOTICE,
+	         /* 05 */  IPTC_TAG_IMAGE_ORIENTATION};
+
+	/* FIXME According to valgrind this is leaking (together with the unref).
+	 * Problem in libiptc */
 
-	/* FIXME According to valgrind this is leaking (together with the unref). Problem in libiptc */
 	iptc = iptc_data_new ();
-       	if (!iptc)
+
+	if (!iptc)
 		return;
+
 	if (iptc_data_load (iptc, buffer, len) < 0) {
 		iptc_data_unref (iptc);
 		return;
 	}
 
-	for (p = iptctags; p->name; ++p) {
+	for (i = 0; i < 6; i++) {
 		IptcDataSet *dataset = NULL;
 
-		while ( (dataset = iptc_data_get_next_dataset (iptc, dataset, p->record, p->tag) ) ) {
+		while ((dataset = iptc_data_get_next_dataset (iptc, dataset, 2, p[i]))) {
 			gchar mbuffer[1024];
-			const gchar *what_i_need;
 
 			iptc_dataset_get_as_str (dataset, mbuffer, 1024);
-			
-			if (p->post) {
-				what_i_need = (*p->post) (mbuffer);
-			} else {
-				what_i_need = mbuffer;
-			}
 
-			if (p->urn) {
-				tracker_statement_list_insert (metadata, p->urn, RDF_TYPE, p->rdf_type);
-				tracker_statement_list_insert (metadata, p->urn, p->predicate, what_i_need);
-				tracker_statement_list_insert (metadata, uri, p->name, p->urn);
-			} else {
-				tracker_statement_list_insert (metadata, uri, p->name, what_i_need);
+			switch (p[i]) {
+				case IPTC_TAG_KEYWORDS:
+					if (!data->keywords)
+						data->keywords = g_strdup (mbuffer);
+					break;
+				case IPTC_TAG_DATE_CREATED:
+					if (!data->date_created) {
+						/* From: ex; date "2007:04:15 15:35:58"
+						* To : ex. "2007-04-15T17:35:58+0200 where +0200 is localtime */
+						data->date_created = tracker_date_format_to_iso8601 (mbuffer, IPTC_DATE_FORMAT);
+					}
+					break;
+				case IPTC_TAG_BYLINE:
+					if (!data->byline)
+						data->byline = g_strdup (mbuffer);
+					break;
+				case IPTC_TAG_CREDIT:
+					if (!data->credit)
+						data->credit = g_strdup (mbuffer);
+					break;
+				case IPTC_TAG_COPYRIGHT_NOTICE:
+					if (!data->copyright_notice)
+						data->copyright_notice = g_strdup (mbuffer);
+					break;
+				case IPTC_TAG_IMAGE_ORIENTATION:
+					if (!data->image_orientation)
+						data->image_orientation = g_strdup (fix_iptc_orientation (mbuffer));
+					break;
+				default:
+					break;
 			}
 		}
 	}
+
 	iptc_data_unref (iptc);
 
 #endif
diff --git a/src/tracker-extract/tracker-iptc.h b/src/tracker-extract/tracker-iptc.h
index c688844..ac6a817 100644
--- a/src/tracker-extract/tracker-iptc.h
+++ b/src/tracker-extract/tracker-iptc.h
@@ -1,12 +1,37 @@
+/* Tracker IPTC - Iptc helper functions
+ * Copyright (C) 2008, Nokia
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Author: Philip Van Hoof <philip codeminded be>
+ */
 
 #ifndef _TRACKER_IPTC_H_
 #define _TRACKER_IPTC_H_
 
 #include <glib.h>
 
+typedef struct {
+	gchar *keywords, *date_created, *byline, *credit, *copyright_notice, 
+	      *image_orientation;
+} TrackerIptcData;
+
 void tracker_read_iptc (const unsigned char *buffer,
-			size_t		    len,
-			const gchar        *uri,
-			TrackerSparqlBuilder   *metadata);
+                        size_t               len,
+                        const gchar         *uri,
+                        TrackerIptcData     *data);
 
 #endif
diff --git a/src/tracker-extract/tracker-xmp.c b/src/tracker-extract/tracker-xmp.c
index 60c2cf6..ebfaa28 100644
--- a/src/tracker-extract/tracker-xmp.c
+++ b/src/tracker-extract/tracker-xmp.c
@@ -25,20 +25,10 @@
 
 #include <glib.h>
 
-#include <libtracker-common/tracker-ontology.h>
-#include <libtracker-common/tracker-statement-list.h>
-
 #include "tracker-main.h"
 #include "tracker-xmp.h"
 
-#define RDF_PREFIX TRACKER_RDF_PREFIX
-#define RDF_TYPE RDF_PREFIX "type"
-#define NIE_PREFIX TRACKER_NIE_PREFIX
-#define NFO_PREFIX TRACKER_NFO_PREFIX
-#define NCO_PREFIX TRACKER_NCO_PREFIX
-#define NMM_PREFIX TRACKER_NMM_PREFIX
-#define DC_PREFIX TRACKER_DC_PREFIX
-
+#include <libtracker-common/tracker-type-utils.h>
 #include <libtracker-common/tracker-utils.h>
 
 #ifdef HAVE_EXEMPI
@@ -49,10 +39,10 @@
 static void tracker_xmp_iter        (XmpPtr                xmp,
 				     XmpIteratorPtr        iter,
 				     const gchar          *uri,
-				     TrackerSparqlBuilder *metadata,
+				     TrackerXmpData       *data,
 				     gboolean              append);
 static void tracker_xmp_iter_simple (const gchar          *uri,
-				     TrackerSparqlBuilder *metadata,
+				     TrackerXmpData       *data,
 				     const gchar          *schema,
 				     const gchar          *path,
 				     const gchar          *value,
@@ -117,14 +107,14 @@ fix_white_balance (const gchar *wb)
 static void 
 tracker_xmp_iter_array (XmpPtr                xmp,
 			const gchar          *uri,
-			TrackerSparqlBuilder *metadata, 
+			TrackerXmpData       *data, 
 			const gchar          *schema, 
 			const gchar          *path)
 {
 	XmpIteratorPtr iter;
 
 	iter = xmp_iterator_new (xmp, schema, path, XMP_ITER_JUSTCHILDREN);
-	tracker_xmp_iter (xmp, iter, uri, metadata, TRUE);
+	tracker_xmp_iter (xmp, iter, uri, data, TRUE);
 	xmp_iterator_free (iter);
 }
 
@@ -133,14 +123,14 @@ tracker_xmp_iter_array (XmpPtr                xmp,
 static void
 tracker_xmp_iter_alt_text (XmpPtr                xmp, 
 			   const gchar          *uri,
-			   TrackerSparqlBuilder *metadata, 
+			   TrackerXmpData       *data, 
 			   const gchar          *schema, 
 			   const gchar          *path)
 {
 	XmpIteratorPtr iter;
 
 	iter = xmp_iterator_new (xmp, schema, path, XMP_ITER_JUSTCHILDREN);
-	tracker_xmp_iter (xmp, iter, uri, metadata, FALSE);
+	tracker_xmp_iter (xmp, iter, uri, data, FALSE);
 	xmp_iterator_free (iter);
 }
 
@@ -148,7 +138,7 @@ tracker_xmp_iter_alt_text (XmpPtr                xmp,
 static void
 tracker_xmp_iter_simple_qual (XmpPtr                xmp, 
 			      const gchar          *uri,
-			      TrackerSparqlBuilder *metadata,
+			      TrackerXmpData       *data,
 			      const gchar          *schema, 
 			      const gchar          *path, 
 			      const gchar          *value, 
@@ -194,7 +184,7 @@ tracker_xmp_iter_simple_qual (XmpPtr                xmp,
 	}
 
 	if (!ignore_element) {
-		tracker_xmp_iter_simple (uri, metadata, schema, path, value, append);
+		tracker_xmp_iter_simple (uri, data, schema, path, value, append);
 	}
 
 	xmp_string_free (the_prop);
@@ -247,12 +237,12 @@ fix_orientation (const gchar *orientation)
 }
 
 
-/* We have a simple element. Add any metadata we know about to the
+/* We have a simple element. Add any data we know about to the
  * hash table.
  */
 static void
 tracker_xmp_iter_simple (const gchar          *uri,
-			 TrackerSparqlBuilder *metadata,
+			 TrackerXmpData       *data,
 			 const gchar          *schema, 
 			 const gchar          *path, 
 			 const gchar          *value, 
@@ -270,203 +260,113 @@ tracker_xmp_iter_simple (const gchar          *uri,
 
 	/* Dublin Core */
 	if (strcmp (schema, NS_DC) == 0) {
-		if (strcmp (name, "title") == 0) {
-			tracker_statement_list_insert (metadata, uri, 
-						  NIE_PREFIX "title", value);
+		if (strcmp (name, "title") == 0 && !data->title) {
+			data->title = g_strdup (value);
 		}
-		else if (strcmp (name, "rights") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NIE_PREFIX "copyright", value);
+		else if (strcmp (name, "rights") == 0 && !data->rights) {
+			data->rights = g_strdup (value);
 		}
-		else if (strcmp (name, "creator") == 0) {
-
-			tracker_statement_list_insert (metadata, ":", RDF_TYPE, NCO_PREFIX "Contact");
-			tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", value);
-			tracker_statement_list_insert (metadata, uri, NCO_PREFIX "creator", ":");
-
+		else if (strcmp (name, "creator") == 0 && !data->creator) {
+			data->creator = g_strdup (value);
 		}
-		else if (strcmp (name, "description") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NIE_PREFIX "description", value);
+		else if (strcmp (name, "description") == 0 && !data->description) {
+			data->description = g_strdup (value);
 		}
-		else if (strcmp (name, "date") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NIE_PREFIX "contentCreated", value);
-		}
-		else if (strcmp (name, "keywords") == 0) {
-			gchar *keywords = g_strdup (value);
-			char *lasts, *keyw;
-			size_t len;
-
-			keyw = keywords;
-			keywords = strchr (keywords, '"');
-			if (keywords)
-				keywords++;
-			else 
-				keywords = keyw;
-
-			len = strlen (keywords);
-			if (keywords[len - 1] == '"')
-				keywords[len - 1] = '\0';
-
-			for (keyw = strtok_r (keywords, ",; ", &lasts); keyw; 
-			     keyw = strtok_r (NULL, ",; ", &lasts)) {
-				tracker_statement_list_insert (metadata,
-						  uri, NIE_PREFIX "keyword",
-						  (const gchar*) keyw);
-			}
-
-			g_free (keyw);
+		else if (strcmp (name, "date") == 0 && !data->date) {
+			data->date = g_strdup (value);
 		}
-		else if (strcmp (name, "subject") == 0) {
-			gchar *keywords = g_strdup (value);
-			char *lasts, *keyw;
-			size_t len;
-
-			tracker_statement_list_insert (metadata, uri, 
-						  NIE_PREFIX "subject", value);
-
-			/* The subject field may contain keywords as well */
-
-			keyw = keywords;
-			keywords = strchr (keywords, '"');
-			if (keywords)
-				keywords++;
-			else 
-				keywords = keyw;
-
-			len = strlen (keywords);
-			if (keywords[len - 1] == '"')
-				keywords[len - 1] = '\0';
-
-			for (keyw = strtok_r (keywords, ",; ", &lasts); keyw; 
-			     keyw = strtok_r (NULL, ",; ", &lasts)) {
-				tracker_statement_list_insert (metadata,
-						  uri, NIE_PREFIX "keyword",
-						  (const gchar*) keyw);
-			}
-
-			g_free (keyw);
-
+		else if (strcmp (name, "keywords") == 0 && !data->keywords) {
+			 data->keywords = g_strdup (value);
 		}
-		else if (strcmp (name, "publisher") == 0) {
-			tracker_statement_list_insert (metadata, ":", RDF_TYPE, NCO_PREFIX "Contact");
-			tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", value);
-			tracker_statement_list_insert (metadata, uri, NCO_PREFIX "publisher", ":");
+		else if (strcmp (name, "subject") == 0 && !data->subject) {
+			data->subject = g_strdup (value);
 		}
-		else if (strcmp (name, "contributor") == 0) {
-			tracker_statement_list_insert (metadata, ":", RDF_TYPE, NCO_PREFIX "Contact");
-			tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", value);
-			tracker_statement_list_insert (metadata, uri, NCO_PREFIX "contributor", ":");
+		else if (strcmp (name, "publisher") == 0 && !data->publisher) {
+			data->publisher = g_strdup (value);
 		}
-		else if (strcmp (name, "type") == 0) {
-			tracker_statement_list_insert (metadata, uri, 
-						  DC_PREFIX "type", value);
+		else if (strcmp (name, "contributor") == 0 && !data->contributor) {
+			data->contributor = g_strdup (value);
 		}
-		else if (strcmp (name, "format") == 0) {
-			tracker_statement_list_insert (metadata, uri, 
-						  DC_PREFIX "format", value);
+		else if (strcmp (name, "type") == 0 && !data->type) {
+			data->type = g_strdup (value);
 		}
-		else if (strcmp (name, "identifier") == 0) {
-			tracker_statement_list_insert (metadata, uri, 
-						  DC_PREFIX "identifier", value);
+		else if (strcmp (name, "format") == 0 && !data->format) {
+			data->format = g_strdup (value);
 		}
-		else if (strcmp (name, "source") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  DC_PREFIX "source", value);
+		else if (strcmp (name, "identifier") == 0 && !data->identifier) {
+			data->identifier = g_strdup (value);
 		}
-		else if (strcmp (name, "language") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  DC_PREFIX "language", value);
+		else if (strcmp (name, "source") == 0 && !data->source) {
+			data->source = g_strdup (value);
 		}
-		else if (strcmp (name, "relation") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  DC_PREFIX "relation", value);
+		else if (strcmp (name, "language") == 0 && !data->language) {
+			data->language = g_strdup (value);
 		}
-		else if (strcmp (name, "coverage") == 0) {
-			tracker_statement_list_insert (metadata, uri, 
-						  DC_PREFIX "coverage", value);
+		else if (strcmp (name, "relation") == 0 && !data->relation) {
+			data->relation = g_strdup (value);
+		}
+		else if (strcmp (name, "coverage") == 0 && !data->coverage) {
+			data->coverage = g_strdup (value);
 		}
 
 	}
 	/* Creative Commons */
 	else if (strcmp (schema, NS_CC) == 0) {
-		if (strcmp (name, "license") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NIE_PREFIX "license", value);
+		if (strcmp (name, "license") == 0 && !data->license) {
+			data->license = g_strdup (value);
 		}
 	}
 	/* Exif basic scheme */
 	else if (strcmp (schema, NS_EXIF) == 0) {
-		if (strcmp (name, "Title") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NFO_PREFIX "title", value);
+		if (strcmp (name, "Title") == 0 && !data->Title) {
+			data->Title = g_strdup (value);
 		}
-		else if (strcmp (name, "DateTimeOriginal") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NIE_PREFIX "contentCreated", value);
+		else if (strcmp (name, "DateTimeOriginal") == 0 && !data->DateTimeOriginal) {
+			data->DateTimeOriginal = g_strdup (value);
 		}
-		else if (strcmp (name, "Artist") == 0) {
-			tracker_statement_list_insert (metadata, ":", RDF_TYPE, NCO_PREFIX "Contact");
-			tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", value);
-			/* contributor is OK here? */
-			tracker_statement_list_insert (metadata, uri, NCO_PREFIX "contributor", ":");
+		else if (strcmp (name, "Artist") == 0 && !data->Artist) {
+			data->Artist = g_strdup (value);
 		}
 /*		else if (strcmp (name, "Software") == 0) {
 			tracker_statement_list_insert (metadata, uri,
 						  "Image:Software", value);
 		}*/
-		else if (strcmp (name, "Make") == 0) {
-			tracker_statement_list_insert (metadata, uri, 
-						  NMM_PREFIX "camera", value);
+		else if (strcmp (name, "Make") == 0 && !data->Make) {
+			data->Make = g_strdup (value);
 		}
-		else if (strcmp (name, "Model") == 0) {
-			tracker_statement_list_insert (metadata, uri, 
-						  NMM_PREFIX "camera", value);
+		else if (strcmp (name, "Model") == 0 && !data->Model) {
+			data->Model = g_strdup (value);
 		}
-		else if (strcmp (name, "Orientation") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NFO_PREFIX "orientation", 
-						  fix_orientation (value));
+		else if (strcmp (name, "Orientation") == 0 && !data->Orientation) {
+			data->Orientation = g_strdup (fix_orientation (value));
 		}
-		else if (strcmp (name, "Flash") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NMM_PREFIX "flash", 
-						  fix_flash (value));
+		else if (strcmp (name, "Flash") == 0 && !data->Flash) {
+			data->Flash = g_strdup (fix_flash (value));
 		}
-		else if (strcmp (name, "MeteringMode") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NMM_PREFIX "meteringMode", 
-						  fix_metering_mode (value));
+		else if (strcmp (name, "MeteringMode") == 0 && !data->MeteringMode) {
+			data->MeteringMode = g_strdup (fix_metering_mode (value));
 		}
 		/*else if (strcmp (name, "ExposureProgram") == 0) {
 			tracker_statement_list_insert (metadata, uri,
 						  "Image:ExposureProgram", value);
 		}*/
-		else if (strcmp (name, "ExposureTime") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NMM_PREFIX "exposureTime", value);
+		else if (strcmp (name, "ExposureTime") == 0 && !data->ExposureTime) {
+			data->ExposureTime = g_strdup (value);
 		}
-		else if (strcmp (name, "FNumber") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NMM_PREFIX "fnumber", value);
+		else if (strcmp (name, "FNumber") == 0 && !data->FNumber) {
+			data->FNumber = g_strdup (value);
 		}
-		else if (strcmp (name, "FocalLength") == 0) {
-			tracker_statement_list_insert (metadata, uri, 
-						  NMM_PREFIX "focalLength", value);
+		else if (strcmp (name, "FocalLength") == 0 && !data->FocalLength) {
+			data->FocalLength = g_strdup (value);
 		}
-		else if (strcmp (name, "ISOSpeedRatings") == 0) {
-			tracker_statement_list_insert (metadata, uri, 
-						  NMM_PREFIX "isoSpeed", value);
+		else if (strcmp (name, "ISOSpeedRatings") == 0 && !data->ISOSpeedRatings) {
+			data->ISOSpeedRatings = g_strdup (value);
 		}
-		else if (strcmp (name, "WhiteBalance") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						   NMM_PREFIX "whiteBalance",
-						   fix_white_balance (value));
+		else if (strcmp (name, "WhiteBalance") == 0 && !data->WhiteBalance) {
+			data->WhiteBalance = g_strdup (fix_white_balance (value));
 		}
-		else if (strcmp (name, "Copyright") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NIE_PREFIX "copyright", value);
+		else if (strcmp (name, "Copyright") == 0 && !data->Copyright) {
+			data->Copyright = g_strdup (value);
 		}
 	}
 	/* XAP (XMP)scheme */
@@ -534,7 +434,7 @@ void
 tracker_xmp_iter (XmpPtr                xmp, 
 		  XmpIteratorPtr        iter, 
 		  const gchar          *uri,
-		  TrackerSparqlBuilder *metadata, 
+		  TrackerXmpData       *data, 
 		  gboolean              append)
 {
 	XmpStringPtr the_schema = xmp_string_new ();
@@ -550,18 +450,18 @@ tracker_xmp_iter (XmpPtr                xmp,
 		if (XMP_IS_PROP_SIMPLE (opt)) {
 			if (!tracker_is_empty_string (path)) {
 				if (XMP_HAS_PROP_QUALIFIERS (opt)) {
-					tracker_xmp_iter_simple_qual (xmp, uri, metadata, schema, path, value, append);
+					tracker_xmp_iter_simple_qual (xmp, uri, data, schema, path, value, append);
 				} else {
-					tracker_xmp_iter_simple (uri, metadata, schema, path, value, append);
+					tracker_xmp_iter_simple (uri, data, schema, path, value, append);
 				}
 			}
 		}
 		else if (XMP_IS_PROP_ARRAY (opt)) {
 			if (XMP_IS_ARRAY_ALTTEXT (opt)) {
-				tracker_xmp_iter_alt_text (xmp, uri, metadata, schema, path);
+				tracker_xmp_iter_alt_text (xmp, uri, data, schema, path);
 				xmp_iterator_skip (iter, XMP_ITER_SKIPSUBTREE);
 			} else {
-				tracker_xmp_iter_array (xmp, uri, metadata, schema, path);
+				tracker_xmp_iter_array (xmp, uri, data, schema, path);
 				xmp_iterator_skip (iter, XMP_ITER_SKIPSUBTREE);
 			}
 		}
@@ -578,7 +478,7 @@ void
 tracker_read_xmp (const gchar          *buffer, 
 		  size_t                len, 
 		  const gchar          *uri,
-		  TrackerSparqlBuilder *metadata)
+		  TrackerXmpData       *data)
 {
 #ifdef HAVE_EXEMPI
 	XmpPtr xmp;
@@ -592,7 +492,7 @@ tracker_read_xmp (const gchar          *buffer,
 		XmpIteratorPtr iter;
 
 		iter = xmp_iterator_new (xmp, NULL, NULL, XMP_ITER_PROPERTIES);
-		tracker_xmp_iter (xmp, iter, uri, metadata, FALSE);
+		tracker_xmp_iter (xmp, iter, uri, data, FALSE);
 		xmp_iterator_free (iter);
 		xmp_free (xmp);
 	}
diff --git a/src/tracker-extract/tracker-xmp.h b/src/tracker-extract/tracker-xmp.h
index fd4d7c6..f14b2c3 100644
--- a/src/tracker-extract/tracker-xmp.h
+++ b/src/tracker-extract/tracker-xmp.h
@@ -22,9 +22,30 @@
 
 #include <glib.h>
 
+typedef struct {
+	/* NS_DC */
+	gchar *title, *rights, *creator, *description, *date, *keywords, *subject,
+	      *publisher, *contributor, *type, *format, *identifier, *source,
+	      *language, *relation, *coverage;
+
+	/* NS_CC */
+	gchar *license;
+
+	/* NS_EXIF */
+	gchar *Title, *DateTimeOriginal, *Artist, *Make, *Model, *Orientation,
+	      *Flash, *MeteringMode, *ExposureTime, *FNumber, *FocalLength,
+	      *ISOSpeedRatings, *WhiteBalance, *Copyright;
+
+	/* TODO NS_XAP*/
+	/* TODO NS_IPTC4XMP */
+	/* TODO NS_PHOTOSHOP */
+
+} TrackerXmpData;
+
+
 void tracker_read_xmp (const gchar          *buffer, 
                        size_t                len, 
                        const gchar          *uri,
-                       TrackerSparqlBuilder *metadata);
+                       TrackerXmpData       *data);
 
 #endif /* _TRACKER_XMP_H_ */



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