eog r4503 - in trunk: . src



Author: friemann
Date: Sun Mar 30 11:36:19 2008
New Revision: 4503
URL: http://svn.gnome.org/viewvc/eog?rev=4503&view=rev

Log:
2008-03-30  Felix Riemann  <friemann svn gnome org>

	* src/Makefile.am:
	* src/eog-image.c: (check_for_metadata_img_format),
	(eog_image_set_icc_data):
	* src/eog-metadata-reader-jpg.c:
	(eog_metadata_reader_jpg_get_icc_profile),
	(eog_metadata_reader_jpg_init_emr_iface):
	* src/eog-metadata-reader-jpg.h:
	* src/eog-metadata-reader-png.c: (eog_metadata_reader_png_dispose),
	(eog_metadata_reader_png_init),
	(eog_metadata_reader_png_class_init),
	(eog_metadata_reader_png_finished),
	(eog_metadata_reader_png_get_next_block),
	(eog_metadata_reader_png_consume),
	(eog_metadata_reader_png_get_xmp_data),
	(eog_metadata_reader_png_get_icc_profile),
	(eog_metadata_reader_png_init_emr_iface):
	* src/eog-metadata-reader-png.h:
	* src/eog-metadata-reader.c: (eog_metadata_reader_new),
	(eog_metadata_reader_get_exif_data),
	(eog_metadata_reader_get_icc_profile):
	* src/eog-metadata-reader.h:
	Add PNG metadata reader supporting embedded XMP and color profile
	data. This also moves the ICC profile generation using chromacity
	and gamma values from EogImage into the readers. Fixes bug #523856.


Added:
   trunk/src/eog-metadata-reader-png.c
   trunk/src/eog-metadata-reader-png.h
Modified:
   trunk/ChangeLog
   trunk/src/Makefile.am
   trunk/src/eog-image.c
   trunk/src/eog-metadata-reader-jpg.c
   trunk/src/eog-metadata-reader-jpg.h
   trunk/src/eog-metadata-reader.c
   trunk/src/eog-metadata-reader.h

Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am	(original)
+++ trunk/src/Makefile.am	Sun Mar 30 11:36:19 2008
@@ -32,6 +32,7 @@
 	eog-uri-converter.h		\
 	eog-metadata-reader.h		\
 	eog-metadata-reader-jpg.h	\
+	eog-metadata-reader-png.h	\
 	eog-save-as-dialog-helper.h	\
 	eog-print-image-setup.h         \
 	eog-print-preview.h             \
@@ -100,6 +101,7 @@
 	eog-uri-converter.c		\
 	eog-metadata-reader.c		\
 	eog-metadata-reader-jpg.c	\
+	eog-metadata-reader-png.c	\
 	eog-save-as-dialog-helper.c	\
 	eog-print-image-setup.c         \
 	eog-print-preview.c           	\

Modified: trunk/src/eog-image.c
==============================================================================
--- trunk/src/eog-image.c	(original)
+++ trunk/src/eog-image.c	Sun Mar 30 11:36:19 2008
@@ -490,6 +490,10 @@
 		if ((buffer[0] == 0xFF) && (buffer[1] == 0xD8)) {		
 			md_reader = eog_metadata_reader_new (EOG_METADATA_JPEG);
 		}
+		if (bytes_read >= 8 &&
+		    memcmp (buffer, "\x89PNG\x0D\x0A\x1a\x0A", 8) == 0) {
+			md_reader = eog_metadata_reader_new (EOG_METADATA_PNG);
+		}
 	}
 
 	return md_reader;
@@ -639,132 +643,10 @@
 eog_image_set_icc_data (EogImage *img, EogMetadataReader *md_reader)
 {
 	EogImagePrivate *priv = img->priv;
-	guchar *icc_chunk = NULL;
-	guint icc_chunk_len = 0;
-#ifdef HAVE_EXIF
-	ExifEntry *entry;
-	ExifByteOrder o;
-	gint color_space;
-#endif
-
-	/* TODO: switch on format to specialised functions */
-
-	eog_metadata_reader_get_icc_chunk (md_reader, &icc_chunk, &icc_chunk_len);
-
-	if (icc_chunk != NULL) {
-		cmsErrorAction (LCMS_ERROR_SHOW);
-
-		priv->profile = cmsOpenProfileFromMem(icc_chunk, icc_chunk_len);
-
-		if (priv->profile) {
-			eog_debug_message (DEBUG_LCMS, "JPEG has ICC profile");
-		} else {
-			eog_debug_message (DEBUG_LCMS, "JPEG has invalid ICC profile");
-		}
-
-		return;
-	}
-
-#ifdef HAVE_EXIF
-	if (priv->exif == NULL) return;
-
-	o = exif_data_get_byte_order (priv->exif);
-
-	entry = exif_data_get_entry (priv->exif, EXIF_TAG_COLOR_SPACE);
-
-	if (entry == NULL) return;
-
-	color_space = exif_get_short (entry->data, o);
-
-	switch (color_space) {
-	case 1:
-		eog_debug_message (DEBUG_LCMS, "JPEG is sRGB");
-
-		priv->profile = cmsCreate_sRGBProfile ();
 
-		break;
+	priv->profile = eog_metadata_reader_get_icc_profile (md_reader);
 
-	case 2:
-		eog_debug_message (DEBUG_LCMS, "JPEG is Adobe RGB (Disabled)");
 
-		/* TODO: create Adobe RGB profile */
-		//priv->profile = cmsCreate_Adobe1998Profile ();
-
-		break;
-
-	case 0xFFFF: 
-		{
-		cmsCIExyY whitepoint;
-		cmsCIExyYTRIPLE primaries;
-		LPGAMMATABLE gamma[3];
-		double gammaValue;
-		ExifRational r;
-
-		const int offset = exif_format_get_size (EXIF_FORMAT_RATIONAL);
-		
-		entry = exif_data_get_entry (priv->exif, EXIF_TAG_WHITE_POINT);
-
-		if (entry && entry->components == 2) {
-			r = exif_get_rational (entry->data, o);
-			whitepoint.x = (double) r.numerator / r.denominator;
-
-			r = exif_get_rational (entry->data + offset, o);
-			whitepoint.y = (double) r.numerator / r.denominator;
-			whitepoint.Y = 1.0;
-		} else {
-			eog_debug_message (DEBUG_LCMS, "No whitepoint found");
-			return;
-		}
-		    
-		entry = exif_data_get_entry (priv->exif, EXIF_TAG_PRIMARY_CHROMATICITIES);
-
-		if (entry && entry->components == 6) {
-			r = exif_get_rational (entry->data + 0 * offset, o);
-			primaries.Red.x = (double) r.numerator / r.denominator;
-
-			r = exif_get_rational (entry->data + 1 * offset, o);
-			primaries.Red.y = (double) r.numerator / r.denominator;
-		      
-			r = exif_get_rational (entry->data + 2 * offset, o);
-			primaries.Green.x = (double) r.numerator / r.denominator;
-
-			r = exif_get_rational (entry->data + 3 * offset, o);
-			primaries.Green.y = (double) r.numerator / r.denominator;
-		      
-			r = exif_get_rational (entry->data + 4 * offset, o);
-			primaries.Blue.x = (double) r.numerator / r.denominator;
-
-			r = exif_get_rational (entry->data + 5 * offset, o);
-			primaries.Blue.y = (double) r.numerator / r.denominator;		    
-		      
-			primaries.Red.Y = primaries.Green.Y = primaries.Blue.Y = 1.0;
-		} else {
-			eog_debug_message (DEBUG_LCMS, "No primary chromaticities found");
-			return;
-		}
-
-		entry = exif_data_get_entry (priv->exif, EXIF_TAG_GAMMA);
-
-		if (entry) {
-			r = exif_get_rational (entry->data, o);
-			gammaValue = (double) r.numerator / r.denominator;
-		} else {
-			eog_debug_message (DEBUG_LCMS, "No gamma found");
-			gammaValue = 2.2;
-		}
-		    
-		gamma[0] = gamma[1] = gamma[2] = cmsBuildGamma (256, gammaValue);
-		    
-		priv->profile = cmsCreateRGBProfile (&whitepoint, &primaries, gamma);
-
-		cmsFreeGamma(gamma[0]);
-
-		eog_debug_message (DEBUG_LCMS, "JPEG is calibrated");
-
-		break;
-		}
-	}
-#endif
 }
 #endif
 

Modified: trunk/src/eog-metadata-reader-jpg.c
==============================================================================
--- trunk/src/eog-metadata-reader-jpg.c	(original)
+++ trunk/src/eog-metadata-reader-jpg.c	Sun Mar 30 11:36:19 2008
@@ -150,17 +150,6 @@
 	g_type_class_add_private (klass, sizeof (EogMetadataReaderJpgPrivate));
 }
 
-EogMetadataReaderJpg*
-eog_metadata_reader_jpg_new (EogMetadataFileType type)
-{
-	EogMetadataReaderJpg *emr;
-	
-	/* CAUTION: check for type if we support more metadat-image-formats in the future */
-	
-	emr = g_object_new (EOG_TYPE_METADATA_READER_JPG, NULL);	
-	return emr;
-}
-
 static gboolean
 eog_metadata_reader_jpg_finished (EogMetadataReaderJpg *emr)
 {
@@ -503,20 +492,142 @@
  * parse the sections and construct a single memory chunk, or maybe even parse
  * the profile.
  */
-static void
-eog_metadata_reader_jpg_get_icc_chunk (EogMetadataReaderJpg *emr, guchar **data, guint *len)
+#ifdef HAVE_LCMS
+static gpointer
+eog_metadata_reader_jpg_get_icc_profile (EogMetadataReaderJpg *emr)
 {
 	EogMetadataReaderJpgPrivate *priv;
+	cmsHPROFILE profile = NULL;
 	
-	g_return_if_fail (EOG_IS_METADATA_READER (emr));
+	g_return_val_if_fail (EOG_IS_METADATA_READER (emr), NULL);
 
 	priv = emr->priv;
 
 	if (priv->icc_chunk) {	
-		*data = (guchar*) priv->icc_chunk + 14;
-		*len = priv->icc_len - 14;
+		cmsErrorAction (LCMS_ERROR_SHOW);
+
+		profile = cmsOpenProfileFromMem(priv->icc_chunk + 14, priv->icc_len - 14);
+
+		if (profile) {
+			eog_debug_message (DEBUG_LCMS, "JPEG has ICC profile");
+		} else {
+			eog_debug_message (DEBUG_LCMS, "JPEG has invalid ICC profile");
+		}
 	}
+
+#ifdef HAVE_EXIF
+	if (!profile && priv->exif_chunk != NULL) {
+		ExifEntry *entry;
+		ExifByteOrder o;
+		gint color_space;
+		ExifData *exif = eog_metadata_reader_jpg_get_exif_data (emr);
+
+		if (!exif) return NULL;
+
+		o = exif_data_get_byte_order (exif);
+
+		entry = exif_data_get_entry (exif, EXIF_TAG_COLOR_SPACE);
+
+		if (entry == NULL) {
+			exif_data_unref (exif);
+			return NULL;
+		}
+
+		color_space = exif_get_short (entry->data, o);
+
+		switch (color_space) {
+		case 1:
+			eog_debug_message (DEBUG_LCMS, "JPEG is sRGB");
+
+			profile = cmsCreate_sRGBProfile ();
+
+			break;
+		case 2:
+			eog_debug_message (DEBUG_LCMS, "JPEG is Adobe RGB (Disabled)");
+
+			/* TODO: create Adobe RGB profile */
+			//profile = cmsCreate_Adobe1998Profile ();
+
+			break;
+		case 0xFFFF: 
+		  	{
+			cmsCIExyY whitepoint;
+			cmsCIExyYTRIPLE primaries;
+			LPGAMMATABLE gamma[3];
+			double gammaValue;
+			ExifRational r;
+
+			const int offset = exif_format_get_size (EXIF_FORMAT_RATIONAL);
+		
+			entry = exif_data_get_entry (exif, EXIF_TAG_WHITE_POINT);
+
+			if (entry && entry->components == 2) {
+				r = exif_get_rational (entry->data, o);
+				whitepoint.x = (double) r.numerator / r.denominator;
+
+				r = exif_get_rational (entry->data + offset, o);
+				whitepoint.y = (double) r.numerator / r.denominator;
+				whitepoint.Y = 1.0;
+			} else {
+				eog_debug_message (DEBUG_LCMS, "No whitepoint found");
+				break;
+			}
+		    
+			entry = exif_data_get_entry (exif, EXIF_TAG_PRIMARY_CHROMATICITIES);
+
+			if (entry && entry->components == 6) {
+				r = exif_get_rational (entry->data + 0 * offset, o);
+				primaries.Red.x = (double) r.numerator / r.denominator;
+
+				r = exif_get_rational (entry->data + 1 * offset, o);
+				primaries.Red.y = (double) r.numerator / r.denominator;
+
+				r = exif_get_rational (entry->data + 2 * offset, o);
+				primaries.Green.x = (double) r.numerator / r.denominator;
+
+				r = exif_get_rational (entry->data + 3 * offset, o);
+				primaries.Green.y = (double) r.numerator / r.denominator;
+		      
+				r = exif_get_rational (entry->data + 4 * offset, o);
+				primaries.Blue.x = (double) r.numerator / r.denominator;
+
+				r = exif_get_rational (entry->data + 5 * offset, o);
+				primaries.Blue.y = (double) r.numerator / r.denominator;		    
+		      
+				primaries.Red.Y = primaries.Green.Y = primaries.Blue.Y = 1.0;
+			} else {
+				eog_debug_message (DEBUG_LCMS, "No primary chromaticities found");
+				break;
+			}
+
+			entry = exif_data_get_entry (exif, EXIF_TAG_GAMMA);
+
+			if (entry) {
+				r = exif_get_rational (entry->data, o);
+				gammaValue = (double) r.numerator / r.denominator;
+			} else {
+				eog_debug_message (DEBUG_LCMS, "No gamma found");
+				gammaValue = 2.2;
+			}
+		    
+			gamma[0] = gamma[1] = gamma[2] = cmsBuildGamma (256, gammaValue);
+		    
+			profile = cmsCreateRGBProfile (&whitepoint, &primaries, gamma);
+
+			cmsFreeGamma(gamma[0]);
+
+			eog_debug_message (DEBUG_LCMS, "JPEG is calibrated");
+
+			break;
+			}
+			
+			exif_data_unref (exif);
+		}
+	}
+#endif
+	return profile;
 }
+#endif
 
 static void
 eog_metadata_reader_jpg_init_emr_iface (gpointer g_iface, gpointer iface_data)
@@ -539,9 +650,11 @@
 		(gpointer (*) (EogMetadataReader *self)) 
 			eog_metadata_reader_jpg_get_exif_data;
 #endif
-	iface->get_icc_chunk = 
-		(void (*) (EogMetadataReader *self, guchar **buf, guint *len))
-			eog_metadata_reader_jpg_get_icc_chunk;
+#ifdef HAVE_LCMS
+	iface->get_icc_profile = 
+		(gpointer (*) (EogMetadataReader *self))
+			eog_metadata_reader_jpg_get_icc_profile;
+#endif
 #ifdef HAVE_EXEMPI
 	iface->get_xmp_ptr =
 		(gpointer (*) (EogMetadataReader *self))

Modified: trunk/src/eog-metadata-reader-jpg.h
==============================================================================
--- trunk/src/eog-metadata-reader-jpg.h	(original)
+++ trunk/src/eog-metadata-reader-jpg.h	Sun Mar 30 11:36:19 2008
@@ -26,12 +26,12 @@
 
 G_BEGIN_DECLS
 
-#define EOG_TYPE_METADATA_READER_JPG            (eog_metadata_reader_jpg_get_type ())
-#define EOG_METADATA_READER_JPG(o)         (G_TYPE_CHECK_INSTANCE_CAST ((o), EOG_TYPE_METADATA_READER_JPG, EogMetadataReaderJpg))
-#define EOG_METADATA_READER_JPG_CLASS(k)   (G_TYPE_CHECK_CLASS_CAST((k), EOG_TYPE_METADATA_READER_JPG, EogMetadataReaderJpgClass))
-#define EOG_IS_METADATA_READER_JPG(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), EOG_TYPE_METADATA_READER_JPG))
-#define EOG_IS_METADATA_READER_JPG_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), EOG_TYPE_METADATA_READER_JPG))
-#define EOG_METADATA_READER_JPG_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), EOG_TYPE_METADATA_READER_JPG, EogMetadataReaderJpgClass))
+#define EOG_TYPE_METADATA_READER_JPG		(eog_metadata_reader_jpg_get_type ())
+#define EOG_METADATA_READER_JPG(o)         	(G_TYPE_CHECK_INSTANCE_CAST ((o),EOG_TYPE_METADATA_READER_JPG, EogMetadataReaderJpg))
+#define EOG_METADATA_READER_JPG_CLASS(k)   	(G_TYPE_CHECK_CLASS_CAST((k), EOG_TYPE_METADATA_READER_JPG, EogMetadataReaderJpgClass))
+#define EOG_IS_METADATA_READER_JPG(o)      	(G_TYPE_CHECK_INSTANCE_TYPE ((o), EOG_TYPE_METADATA_READER_JPG))
+#define EOG_IS_METADATA_READER_JPG_CLASS(k)   	(G_TYPE_CHECK_CLASS_TYPE ((k), EOG_TYPE_METADATA_READER_JPG))
+#define EOG_METADATA_READER_JPG_GET_CLASS(o)  	(G_TYPE_INSTANCE_GET_CLASS ((o), EOG_TYPE_METADATA_READER_JPG, EogMetadataReaderJpgClass))
 
 typedef struct _EogMetadataReaderJpg EogMetadataReaderJpg;
 typedef struct _EogMetadataReaderJpgClass EogMetadataReaderJpgClass;
@@ -49,8 +49,6 @@
 
 GType		      eog_metadata_reader_jpg_get_type	(void) G_GNUC_CONST;
 
-EogMetadataReaderJpg* eog_metadata_reader_jpg_new	(EogMetadataFileType type);
-
 G_END_DECLS
 
 #endif /* _EOG_METADATA_READER_JPG_H_ */

Added: trunk/src/eog-metadata-reader-png.c
==============================================================================
--- (empty file)
+++ trunk/src/eog-metadata-reader-png.c	Sun Mar 30 11:36:19 2008
@@ -0,0 +1,647 @@
+/* Eye Of GNOME -- PNG Metadata Reader
+ *
+ * Copyright (C) 2008 The Free Software Foundation
+ *
+ * Author: Felix Riemann <friemann svn gnome org>
+ *
+ * Based on the old EogMetadataReader code.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <zlib.h>
+
+#include "eog-metadata-reader.h"
+#include "eog-metadata-reader-png.h"
+#include "eog-debug.h"
+
+typedef enum {
+	EMR_READ_MAGIC,
+	EMR_READ_SIZE_HIGH_HIGH_BYTE,
+	EMR_READ_SIZE_HIGH_LOW_BYTE,
+	EMR_READ_SIZE_LOW_HIGH_BYTE,
+	EMR_READ_SIZE_LOW_LOW_BYTE,
+	EMR_READ_CHUNK_NAME,
+	EMR_SKIP_BYTES,
+	EMR_CHECK_CRC,
+	EMR_SKIP_CRC,
+	EMR_READ_XMP_ITXT,
+	EMR_READ_ICCP,
+	EMR_READ_SRGB,
+	EMR_READ_CHRM,
+	EMR_READ_GAMA,
+	EMR_FINISHED
+} EogMetadataReaderPngState;
+
+#if 0
+#define IS_FINISHED(priv) (priv->icc_chunk  != NULL && \
+                           priv->xmp_chunk  != NULL)
+#endif
+
+struct _EogMetadataReaderPngPrivate {
+	EogMetadataReaderPngState  state;
+
+	/* data fields */
+	gpointer icc_chunk;
+	guint32  icc_len;
+
+	gpointer xmp_chunk;
+	guint32  xmp_len;
+
+	gpointer sRGB_chunk;
+	guint32	 sRGB_len;
+
+	gpointer cHRM_chunk;
+	guint32	 cHRM_len;
+
+	gpointer gAMA_chunk;
+	guint32	 gAMA_len;
+	
+	/* management fields */
+	gsize      size;
+	gsize      bytes_read;
+	guint	   sub_step;
+	guchar	   chunk_name[4];
+	guint32	   chunk_name_crc;
+	gpointer   *crc_chunk;
+	guint32	   *crc_len;
+	guint32    target_crc;
+	gboolean   hasIHDR;
+};
+
+#define EOG_METADATA_READER_PNG_GET_PRIVATE(object) \
+	(G_TYPE_INSTANCE_GET_PRIVATE ((object), EOG_TYPE_METADATA_READER_PNG, EogMetadataReaderPngPrivate))
+
+static void
+eog_metadata_reader_png_init_emr_iface (gpointer g_iface, gpointer iface_data);
+
+G_DEFINE_TYPE_WITH_CODE (EogMetadataReaderPng, eog_metadata_reader_png,
+			 G_TYPE_OBJECT,
+			 G_IMPLEMENT_INTERFACE (EOG_TYPE_METADATA_READER,
+			 		eog_metadata_reader_png_init_emr_iface))
+
+static void
+eog_metadata_reader_png_dispose (GObject *object)
+{
+	EogMetadataReaderPng *emr = EOG_METADATA_READER_PNG (object);
+	EogMetadataReaderPngPrivate *priv = emr->priv;
+	
+	g_free (priv->xmp_chunk);
+	priv->xmp_chunk = NULL;
+
+	g_free (priv->icc_chunk);
+	priv->icc_chunk = NULL;
+
+	g_free (priv->sRGB_chunk);
+	priv->sRGB_chunk = NULL;
+
+	g_free (priv->cHRM_chunk);
+	priv->cHRM_chunk = NULL;
+
+	g_free (priv->gAMA_chunk);
+	priv->gAMA_chunk = NULL;
+
+	G_OBJECT_CLASS (eog_metadata_reader_png_parent_class)->dispose (object);
+}
+
+static void
+eog_metadata_reader_png_init (EogMetadataReaderPng *obj)
+{
+	EogMetadataReaderPngPrivate *priv;
+
+	priv = obj->priv =  EOG_METADATA_READER_PNG_GET_PRIVATE (obj);
+	priv->icc_chunk = NULL;
+	priv->icc_len = 0;
+	priv->xmp_chunk = NULL;
+	priv->xmp_len = 0;
+	priv->sRGB_chunk = NULL;
+	priv->sRGB_len = 0;
+	priv->cHRM_chunk = NULL;
+	priv->cHRM_len = 0;
+	priv->gAMA_chunk = NULL;
+	priv->gAMA_len = 0;
+	
+	priv->sub_step = 0;
+	priv->state = EMR_READ_MAGIC;
+	priv->hasIHDR = FALSE;
+}
+
+static void 
+eog_metadata_reader_png_class_init (EogMetadataReaderPngClass *klass)
+{
+	GObjectClass *object_class = (GObjectClass*) klass;
+
+	object_class->dispose = eog_metadata_reader_png_dispose;
+
+	g_type_class_add_private (klass, sizeof (EogMetadataReaderPngPrivate));
+}
+
+static gboolean
+eog_metadata_reader_png_finished (EogMetadataReaderPng *emr)
+{
+	g_return_val_if_fail (EOG_IS_METADATA_READER_PNG (emr), TRUE);
+
+	return (emr->priv->state == EMR_FINISHED);
+}
+
+
+static void
+eog_metadata_reader_png_get_next_block (EogMetadataReaderPngPrivate* priv,
+				    	guchar *chunk,
+					int* i,
+					const guchar *buf,
+					int len,
+					EogMetadataReaderPngState state)
+{
+	if (*i + priv->size < len) {
+		/* read data in one block */
+		memcpy ((guchar*) (chunk) + priv->bytes_read, &buf[*i], priv->size);
+		priv->state = EMR_CHECK_CRC;
+		*i = *i + priv->size - 1; /* the for-loop consumes the other byte */
+		priv->size = 0;
+	} else {
+		int chunk_len = len - *i;
+		memcpy ((guchar*) (chunk) + priv->bytes_read, &buf[*i], chunk_len);
+		priv->bytes_read += chunk_len; /* bytes already read */
+		priv->size = (*i + priv->size) - len; /* remaining data to read */
+		*i = len - 1;
+		priv->state = state;
+	}
+}
+
+static void
+eog_metadata_reader_png_consume (EogMetadataReaderPng *emr, const guchar *buf, guint len)
+{
+	EogMetadataReaderPngPrivate *priv;
+ 	int i;
+	EogMetadataReaderPngState next_state;
+	guint32 chunk_crc;
+	static const gchar PNGMAGIC[8] = "\x89PNG\x0D\x0A\x1a\x0A";
+
+	g_return_if_fail (EOG_IS_METADATA_READER_PNG (emr));
+
+	priv = emr->priv;
+	
+	if (priv->state == EMR_FINISHED) return;
+
+	for (i = 0; (i < len) && (priv->state != EMR_FINISHED); i++) {
+
+		switch (priv->state) {
+		case EMR_READ_MAGIC:
+			/* Check PNG magic string */
+			if (priv->sub_step < 8 &&
+			    (gchar)buf[i] == PNGMAGIC[priv->sub_step]) {
+			    	if (priv->sub_step == 7)
+					priv->state = EMR_READ_SIZE_HIGH_HIGH_BYTE;
+				priv->sub_step++;
+			} else {
+				priv->state = EMR_FINISHED;
+			}
+			break;
+		case EMR_READ_SIZE_HIGH_HIGH_BYTE:
+			/* Read the high byte of the size's high word */
+			priv->size |= (buf[i] & 0xFF) << 24;
+			priv->state = EMR_READ_SIZE_HIGH_LOW_BYTE;
+			break;
+		case EMR_READ_SIZE_HIGH_LOW_BYTE:
+			/* Read the low byte of the size's high word */
+			priv->size |= (buf[i] & 0xFF) << 16;
+			priv->state = EMR_READ_SIZE_LOW_HIGH_BYTE;
+			break;
+		case EMR_READ_SIZE_LOW_HIGH_BYTE:
+			/* Read the high byte of the size's low word */
+			priv->size |= (buf [i] & 0xff) << 8;
+			priv->state = EMR_READ_SIZE_LOW_LOW_BYTE;
+			break;			
+		case EMR_READ_SIZE_LOW_LOW_BYTE:
+			/* Read the high byte of the size's low word */
+			priv->size |= (buf [i] & 0xff);			
+			priv->state = EMR_READ_CHUNK_NAME;
+			priv->sub_step = 0; /* Make sure sub_step is 0 before next step */
+			break;
+		case EMR_READ_CHUNK_NAME:
+			/* Read the 4-byte chunk name */
+			if (priv->sub_step > 3)
+				g_assert_not_reached ();
+
+			priv->chunk_name[priv->sub_step] = buf[i];
+
+			if (priv->sub_step++ == 3)
+				/* Take the CRC32 from the chunk name for later */
+				priv->chunk_name_crc = crc32 (crc32 (0L, Z_NULL, 0), priv->chunk_name, 4);
+			else
+				break;
+
+			if (G_UNLIKELY (!priv->hasIHDR)) {
+				/* IHDR should be the first chunk in a PNG */
+				if (priv->size == 13 
+				    && memcmp (priv->chunk_name, "IHDR", 4) == 0){
+					priv->hasIHDR = TRUE;
+				} else {
+					/* Stop parsing if it is not */
+					priv->state = EMR_FINISHED;
+				}
+			}
+
+			/* Try to identify the chunk by its name.
+			 * Already do some sanity checks where possible */
+			if (memcmp (priv->chunk_name, "iTXt", 4) == 0 &&
+			    priv->size > (22 + 54) && priv->xmp_chunk == NULL) {
+				priv->state = EMR_READ_XMP_ITXT;
+			} else if (memcmp (priv->chunk_name, "iCCP", 4) == 0 &&
+				   priv->icc_chunk == NULL) {
+				priv->state = EMR_READ_ICCP;
+			} else if (memcmp (priv->chunk_name, "sRGB", 4) == 0 &&
+				   priv->sRGB_chunk == NULL && priv->size == 1) {
+				priv->state = EMR_READ_SRGB;
+			} else if (memcmp (priv->chunk_name, "cHRM", 4) == 0 &&
+				   priv->cHRM_chunk == NULL && priv->size == 32) {
+				priv->state = EMR_READ_CHRM;
+			} else if (memcmp (priv->chunk_name, "gAMA", 4) == 0 &&
+				   priv->gAMA_chunk == NULL && priv->size == 4) {
+				priv->state = EMR_READ_GAMA;
+			} else if (memcmp (priv->chunk_name, "IEND", 4) == 0) {
+				priv->state = EMR_FINISHED;
+			} else {
+				/* Skip chunk + 4-byte CRC32 value */
+				priv->size += 4;
+				priv->state = EMR_SKIP_BYTES;
+			}
+			priv->sub_step = 0;
+			break;
+		case EMR_SKIP_CRC:
+			/* Skip the 4-byte CRC32 value following every chunk */
+			priv->size = 4;
+		case EMR_SKIP_BYTES:
+		/* Skip chunk and start reading the size of the next one */
+			eog_debug_message (DEBUG_IMAGE_DATA, "Skip bytes: %i", priv->size);
+
+			if (i + priv->size < len) { 
+				i = i + priv->size - 1; /* the for-loop consumes the other byte */
+				priv->size = 0;
+				priv->state = EMR_READ_SIZE_HIGH_HIGH_BYTE;
+			}
+			else {  
+				priv->size = (i + priv->size) - len;
+				i = len - 1;
+			}
+			break;
+		case EMR_CHECK_CRC:
+			/* Read the chunks CRC32 value from the file,... */
+			if (priv->sub_step == 0)
+				priv->target_crc = 0;
+
+			priv->target_crc |= buf[i] << ((3 - priv->sub_step) * 8);
+
+			if (priv->sub_step++ != 3)
+				break;
+
+			/* ...generate the chunks CRC32, merge it with the 
+			 * chunk name's CRC32 value... */
+			chunk_crc = crc32 (0L, Z_NULL, 0);
+			chunk_crc = crc32 (chunk_crc, *priv->crc_chunk, *priv->crc_len);
+			chunk_crc = crc32_combine (priv->chunk_name_crc, chunk_crc, *priv->crc_len);
+
+			eog_debug_message (DEBUG_IMAGE_DATA, "Checking CRC: Chunk: 0x%X - Target: 0x%X", chunk_crc, priv->target_crc);
+
+			/* ...and check if they match. If they don't throw
+			 * the chunk away and stop parsing. */
+			if (priv->target_crc == chunk_crc) {
+				priv->state = EMR_READ_SIZE_HIGH_HIGH_BYTE;
+			} else {
+				g_free (*priv->crc_chunk);
+				*priv->crc_chunk = NULL;
+				*priv->crc_len = 0;
+				/* Stop parsing for security reasons */
+				priv->state = EMR_FINISHED;
+			}
+			priv->sub_step = 0;
+			break;
+		case EMR_READ_XMP_ITXT:
+			/* Extract an iTXt chunk possibly containing
+			 * an XMP packet */
+			eog_debug_message (DEBUG_IMAGE_DATA,
+					   "Read XMP Chunk - size: %u",
+					   priv->size);
+
+			if (priv->xmp_chunk == NULL) { 
+				priv->xmp_chunk = g_new0 (guchar, priv->size);
+				priv->xmp_len = priv->size;
+				priv->crc_len = &priv->xmp_len;
+				priv->bytes_read = 0;
+				priv->crc_chunk = &priv->xmp_chunk;
+				next_state = EMR_READ_XMP_ITXT;
+			}
+			eog_metadata_reader_png_get_next_block (priv,
+							    priv->xmp_chunk,
+							    &i, buf, len,
+							    EMR_READ_XMP_ITXT);
+
+			if (priv->state == EMR_CHECK_CRC) {
+				/* Check if it is actually an XMP chunk.
+				 * Throw it away if not. */
+				if ((memcmp (priv->xmp_chunk, "XML:com.adobe.xmp\0", 18) != 0)
+				    || (*(guint32*)(priv->xmp_chunk+18)) != 0) {
+					priv->state = EMR_SKIP_CRC;
+					g_free (priv->xmp_chunk);
+					priv->xmp_chunk = NULL;
+					priv->xmp_len = 0;
+				}
+			}
+			break;
+		case EMR_READ_ICCP:
+			/* Extract an iCCP chunk containing a 
+			 * deflated ICC profile. */
+			eog_debug_message (DEBUG_IMAGE_DATA,
+					   "Read ICC Chunk - size: %u",
+					   priv->size);
+
+			if (priv->icc_chunk == NULL) { 
+				priv->icc_chunk = g_new0 (guchar, priv->size);
+				priv->icc_len = priv->size;
+				priv->crc_len = &priv->icc_len;
+				priv->bytes_read = 0;
+				priv->crc_chunk = &priv->icc_chunk;
+				next_state = EMR_READ_ICCP;
+			}
+
+			eog_metadata_reader_png_get_next_block (priv,
+							    priv->icc_chunk,
+							    &i, buf, len,
+							    EMR_READ_ICCP);
+			break;
+		case EMR_READ_SRGB:
+			/* Extract the sRGB chunk. Marks the image data as
+			 * being in sRGB colorspace. */
+			eog_debug_message (DEBUG_IMAGE_DATA,
+					   "Read sRGB Chunk - value: %u", *(buf+i));
+
+			if (priv->sRGB_chunk == NULL) { 
+				priv->sRGB_chunk = g_new0 (guchar, priv->size);
+				priv->sRGB_len = priv->size;
+				priv->crc_len = &priv->sRGB_len;
+				priv->bytes_read = 0;
+				priv->crc_chunk = &priv->sRGB_chunk;
+				next_state = EMR_READ_SRGB;
+			}
+
+			eog_metadata_reader_png_get_next_block (priv,
+							    priv->sRGB_chunk,
+							    &i, buf, len,
+							    EMR_READ_SRGB);
+			break;
+		case EMR_READ_CHRM:
+			/* Extract the cHRM chunk. Contains the coordinates of
+			 * the image's whitepoint and primary chromacities. */
+			eog_debug_message (DEBUG_IMAGE_DATA,
+					   "Read cHRM Chunk - size: %u",
+					   priv->size);
+
+			if (priv->cHRM_chunk == NULL) { 
+				priv->cHRM_chunk = g_new0 (guchar, priv->size);
+				priv->cHRM_len = priv->size;
+				priv->crc_len = &priv->cHRM_len;
+				priv->bytes_read = 0;
+				priv->crc_chunk = &priv->cHRM_chunk;
+				next_state = EMR_READ_CHRM;
+			}
+
+			eog_metadata_reader_png_get_next_block (priv,
+							    priv->cHRM_chunk,
+							    &i, buf, len,
+							    EMR_READ_ICCP);
+			break;
+		case EMR_READ_GAMA:
+			/* Extract the gAMA chunk containing the 
+			 * image's gamma value */
+			eog_debug_message (DEBUG_IMAGE_DATA,
+					   "Read gAMA-Chunk - size: %u",
+					   priv->size);
+
+			if (priv->gAMA_chunk == NULL) { 
+				priv->gAMA_chunk = g_new0 (guchar, priv->size);
+				priv->gAMA_len = priv->size;
+				priv->crc_len = &priv->gAMA_len;
+				priv->bytes_read = 0;
+				priv->crc_chunk = &priv->gAMA_chunk;
+				next_state = EMR_READ_CHRM;
+			}
+
+			eog_metadata_reader_png_get_next_block (priv,
+							    priv->gAMA_chunk,
+							    &i, buf, len,
+							    EMR_READ_ICCP);
+			break;
+		default:
+			g_assert_not_reached ();
+		}
+	}
+}
+
+#ifdef HAVE_EXEMPI
+
+/* skip the ID + packet */
+#define EOG_XMP_OFFSET (22 + 54)
+
+static gpointer 
+eog_metadata_reader_png_get_xmp_data (EogMetadataReaderPng *emr )
+{
+	EogMetadataReaderPngPrivate *priv;
+	XmpPtr xmp = NULL;
+
+	g_return_val_if_fail (EOG_IS_METADATA_READER_PNG (emr), NULL);
+
+	priv = emr->priv;
+
+	if (priv->xmp_chunk != NULL) {
+		xmp = xmp_new (priv->xmp_chunk+EOG_XMP_OFFSET,
+			       priv->xmp_len-EOG_XMP_OFFSET);
+	}
+
+	return (gpointer) xmp;
+}
+#endif
+
+#ifdef HAVE_LCMS
+
+#define EXTRACT_DOUBLE_UINT_BLOCK_OFFSET(chunk,offset,divider) \
+		(double)(GUINT32_FROM_BE(*((guint32*)((chunk)+((offset)*4))))/(double)(divider))
+
+/* This is the amount of memory the inflate output buffer gets increased by 
+ * while decompressing the ICC profile */
+#define EOG_ICC_INFLATE_BUFFER_STEP 1024
+
+/* I haven't seen ICC profiles larger than 1MB yet.
+ * A maximum output buffer of 5MB should be enough. */
+#define EOG_ICC_INFLATE_BUFFER_LIMIT (1024*1024*5)
+
+static gpointer
+eog_metadata_reader_png_get_icc_profile (EogMetadataReaderPng *emr)
+{
+	EogMetadataReaderPngPrivate *priv;
+	cmsHPROFILE profile = NULL;
+	
+	g_return_val_if_fail (EOG_IS_METADATA_READER_PNG (emr), NULL);
+
+	priv = emr->priv;
+
+	if (priv->icc_chunk) {
+		gpointer outbuf;
+		gsize offset = 0, chunk_len;
+		z_stream zstr;
+		int z_ret;
+
+		/* Use default allocation functions */
+		zstr.zalloc = Z_NULL;
+		zstr.zfree = Z_NULL;
+		zstr.opaque = Z_NULL;
+
+		/* Skip the name of the ICC profile */
+		while (*((guchar*)priv->icc_chunk+offset) != '\0')
+			offset++;
+		/* Ensure the compression method (deflate) */
+		if (*((guchar*)priv->icc_chunk+(++offset)) != '\0')
+			return NULL;
+		++offset; //offset now points to the start of the deflated data
+
+		/* Prepare the zlib data structure for decompression */
+		zstr.next_in = priv->icc_chunk + offset;
+		chunk_len = zstr.avail_in = priv->icc_len - offset;
+		if (inflateInit (&zstr) != Z_OK) {
+			return NULL;
+		}
+
+		/* Prepare output buffer and make zlib aware of it */
+		outbuf = g_malloc (EOG_ICC_INFLATE_BUFFER_STEP);
+		zstr.next_out = outbuf;
+		zstr.avail_out = EOG_ICC_INFLATE_BUFFER_STEP;
+
+		do {
+			if (zstr.avail_out == 0) {
+				/* The output buffer was not large enough to
+				 * hold all the decompressed data. Increase its
+				 * size and continue decompression. */
+				gsize new_size = zstr.total_out + EOG_ICC_INFLATE_BUFFER_STEP;
+
+				if (G_UNLIKELY (new_size > EOG_ICC_INFLATE_BUFFER_LIMIT)) {
+					/* Enforce a memory limit for the output
+					 * buffer to avoid possible OOM cases */
+					inflateEnd (&zstr);
+					g_free (outbuf);
+					eog_debug_message (DEBUG_IMAGE_DATA, "ICC profile is too large. Ignoring.");
+					return NULL;
+				}
+				outbuf = g_realloc(outbuf, new_size);
+				zstr.avail_out = EOG_ICC_INFLATE_BUFFER_STEP;
+				zstr.next_out = outbuf + zstr.total_out;
+			}
+			z_ret = inflate (&zstr, Z_SYNC_FLUSH);
+		} while (z_ret == Z_OK);
+
+		if (G_UNLIKELY (z_ret != Z_STREAM_END)) {
+			eog_debug_message (DEBUG_IMAGE_DATA, "Error while inflating ICC profile: %s (%d)\n", zstr.msg, z_ret);
+			inflateEnd (&zstr);
+			g_free (outbuf);
+			return NULL;
+		}
+
+		cmsErrorAction (LCMS_ERROR_SHOW);
+
+		profile = cmsOpenProfileFromMem(outbuf, zstr.total_out);
+		inflateEnd (&zstr);
+		g_free (outbuf);
+
+		eog_debug_message (DEBUG_LCMS, "PNG has %s ICC profile", profile ? "valid" : "invalid");
+	}
+
+	if (!profile && priv->sRGB_chunk) {
+		eog_debug_message (DEBUG_LCMS, "PNG is sRGB");
+		/* If the file has an sRGB chunk the image data is in the sRGB
+		 * colorspace. lcms has a built-in sRGB profile. */
+		
+		profile = cmsCreate_sRGBProfile ();
+	}
+
+	if (!profile && priv->cHRM_chunk) {
+		cmsCIExyY whitepoint;
+		cmsCIExyYTRIPLE primaries;
+		LPGAMMATABLE gamma[3];
+		double gammaValue = 2.2; // 2.2 should be a sane default gamma
+
+		/* This uglyness extracts the chromacity and whitepoint values 
+		 * from a PNG's cHRM chunk. These can be accurate up to the 
+		 * 5th decimal point. 
+		 * They are saved as integer values multiplied by 100000. */
+
+		eog_debug_message (DEBUG_LCMS, "Trying to calculate color profile");
+
+		whitepoint.x = EXTRACT_DOUBLE_UINT_BLOCK_OFFSET (priv->cHRM_chunk, 0, 100000);
+		whitepoint.y = EXTRACT_DOUBLE_UINT_BLOCK_OFFSET (priv->cHRM_chunk, 1, 100000);
+
+		primaries.Red.x = EXTRACT_DOUBLE_UINT_BLOCK_OFFSET (priv->cHRM_chunk, 2, 100000);
+		primaries.Red.y = EXTRACT_DOUBLE_UINT_BLOCK_OFFSET (priv->cHRM_chunk, 3, 100000);
+		primaries.Green.x = EXTRACT_DOUBLE_UINT_BLOCK_OFFSET (priv->cHRM_chunk, 4, 100000);
+		primaries.Green.y = EXTRACT_DOUBLE_UINT_BLOCK_OFFSET (priv->cHRM_chunk, 5, 100000);
+		primaries.Blue.x = EXTRACT_DOUBLE_UINT_BLOCK_OFFSET (priv->cHRM_chunk, 6, 100000);
+		primaries.Blue.y = EXTRACT_DOUBLE_UINT_BLOCK_OFFSET (priv->cHRM_chunk, 7, 100000);
+
+		primaries.Red.Y = primaries.Green.Y = primaries.Blue.Y = 1.0;
+
+		/* If the gAMA_chunk is present use its value which is saved 
+		 * the same way as the whitepoint. Use 2.2 as default value if
+		 * the chunk is not present. */
+		if (priv->gAMA_chunk)
+			gammaValue = (double) 1.0/EXTRACT_DOUBLE_UINT_BLOCK_OFFSET (priv->gAMA_chunk, 0, 100000);
+
+		gamma[0] = gamma[1] = gamma[2] = cmsBuildGamma (256, gammaValue);
+
+		profile = cmsCreateRGBProfile (&whitepoint, &primaries, gamma);
+
+		cmsFreeGamma(gamma[0]);
+	}
+
+	return profile;
+}
+#endif
+
+static void
+eog_metadata_reader_png_init_emr_iface (gpointer g_iface, gpointer iface_data)
+{
+	EogMetadataReaderInterface *iface;
+
+	iface = (EogMetadataReaderInterface*) g_iface;
+
+	iface->consume = 
+		(void (*) (EogMetadataReader *self, const guchar *buf, guint len))
+			eog_metadata_reader_png_consume;
+	iface->finished = 
+		(gboolean (*) (EogMetadataReader *self))
+			eog_metadata_reader_png_finished;
+#ifdef HAVE_LCMS
+	iface->get_icc_profile = 
+		(cmsHPROFILE (*) (EogMetadataReader *self))
+			eog_metadata_reader_png_get_icc_profile;
+#endif
+#ifdef HAVE_EXEMPI
+	iface->get_xmp_ptr =
+		(gpointer (*) (EogMetadataReader *self))
+			eog_metadata_reader_png_get_xmp_data;
+#endif
+}

Added: trunk/src/eog-metadata-reader-png.h
==============================================================================
--- (empty file)
+++ trunk/src/eog-metadata-reader-png.h	Sun Mar 30 11:36:19 2008
@@ -0,0 +1,54 @@
+/* Eye Of GNOME -- PNG Metadata Reader
+ *
+ * Copyright (C) 2008 The Free Software Foundation
+ *
+ * Author: Felix Riemann <friemann svn gnome org>
+ *
+ * Based on the old EogMetadataReader code.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _EOG_METADATA_READER_PNG_H_
+#define _EOG_METADATA_READER_PNG_H_
+
+G_BEGIN_DECLS
+
+#define EOG_TYPE_METADATA_READER_PNG		(eog_metadata_reader_png_get_type ())
+#define EOG_METADATA_READER_PNG(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), EOG_TYPE_METADATA_READER_PNG, EogMetadataReaderPng))
+#define EOG_METADATA_READER_PNG_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), EOG_TYPE_METADATA_READER_PNG, EogMetadataReaderPngClass))
+#define EOG_IS_METADATA_READER_PNG(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), EOG_TYPE_METADATA_READER_PNG))
+#define EOG_IS_METADATA_READER_PNG_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), EOG_TYPE_METADATA_READER_PNG))
+#define EOG_METADATA_READER_PNG_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), EOG_TYPE_METADATA_READER_PNG, EogMetadataReaderPngClass))
+
+typedef struct _EogMetadataReaderPng EogMetadataReaderPng;
+typedef struct _EogMetadataReaderPngClass EogMetadataReaderPngClass;
+typedef struct _EogMetadataReaderPngPrivate EogMetadataReaderPngPrivate;
+
+struct _EogMetadataReaderPng {
+	GObject parent;
+
+	EogMetadataReaderPngPrivate *priv;
+};
+
+struct _EogMetadataReaderPngClass {
+	GObjectClass parent_klass;
+};
+
+GType		      eog_metadata_reader_png_get_type	(void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* _EOG_METADATA_READER_PNG_H_ */

Modified: trunk/src/eog-metadata-reader.c
==============================================================================
--- trunk/src/eog-metadata-reader.c	(original)
+++ trunk/src/eog-metadata-reader.c	Sun Mar 30 11:36:19 2008
@@ -27,6 +27,7 @@
 
 #include "eog-metadata-reader.h"
 #include "eog-metadata-reader-jpg.h"
+#include "eog-metadata-reader-png.h"
 #include "eog-debug.h"
 
 
@@ -48,11 +49,19 @@
 EogMetadataReader*
 eog_metadata_reader_new (EogMetadataFileType type)
 {
-	EogMetadataReader *emr = NULL;
+	EogMetadataReader *emr;
 	
-	/* CAUTION: check for type if we support more metadata-image-formats in the future */
-	if (type == EOG_METADATA_JPEG)
-		emr = EOG_METADATA_READER (eog_metadata_reader_jpg_new (type));
+	switch (type) {
+	case EOG_METADATA_JPEG:
+		emr = EOG_METADATA_READER (g_object_new (EOG_TYPE_METADATA_READER_JPG, NULL));
+		break;
+	case EOG_METADATA_PNG:
+		emr = EOG_METADATA_READER (g_object_new (EOG_TYPE_METADATA_READER_PNG, NULL));
+		break;
+	default:
+		emr = NULL;
+		break;
+	}
 
 	return emr;
 }
@@ -102,6 +111,7 @@
 	EogMetadataReaderInterface *iface;
 
 	iface = EOG_METADATA_READER_GET_INTERFACE (emr);
+
 	if (iface->get_exif_data)
 		exif_data = iface->get_exif_data (emr);
 	
@@ -125,19 +135,18 @@
 }
 #endif
 
-void
-eog_metadata_reader_get_icc_chunk (EogMetadataReader *emr, guchar **data, guint *len)
+#ifdef HAVE_LCMS
+cmsHPROFILE
+eog_metadata_reader_get_icc_profile (EogMetadataReader *emr)
 {
 	EogMetadataReaderInterface *iface;
-
-	g_return_if_fail (data != NULL && len != NULL);
+	gpointer profile = NULL;
 
 	iface = EOG_METADATA_READER_GET_INTERFACE (emr);
-	
-	if (iface->get_icc_chunk)
-		iface->get_icc_chunk (emr, data, len);
-	else {
-		*data = NULL;
-		*len = 0;
-	}
+
+	if (iface->get_icc_profile)
+		profile = iface->get_icc_profile (emr);
+		
+	return profile;
 }
+#endif

Modified: trunk/src/eog-metadata-reader.h
==============================================================================
--- trunk/src/eog-metadata-reader.h	(original)
+++ trunk/src/eog-metadata-reader.h	Sun Mar 30 11:36:19 2008
@@ -29,6 +29,9 @@
 #if HAVE_EXEMPI
 #include <exempi/xmp.h>
 #endif
+#if HAVE_LCMS
+#include <lcms.h>
+#endif
 
 G_BEGIN_DECLS
 
@@ -43,51 +46,56 @@
 struct _EogMetadataReaderInterface {
 	GTypeInterface parent;
 
-	void		(*consume) 	(EogMetadataReader *self,
-					 const guchar *buf,
-					 guint len);
+	void		(*consume)		(EogMetadataReader *self,
+						 const guchar *buf,
+						 guint len);
 
-	gboolean	(*finished) 	(EogMetadataReader *self);
+	gboolean	(*finished)		(EogMetadataReader *self);
 
-	void		(*get_raw_exif) (EogMetadataReader *self,
-					 guchar **data,
-					 guint *len);
+	void		(*get_raw_exif)		(EogMetadataReader *self,
+						 guchar **data,
+						 guint *len);
 
-	gpointer	(*get_exif_data) (EogMetadataReader *self);
+	gpointer	(*get_exif_data)	(EogMetadataReader *self);
 
-	void		(*get_icc_chunk) (EogMetadataReader *self,
-					  guchar **data,
-					  guint *len);
+	gpointer	(*get_icc_profile)	(EogMetadataReader *self);
 
-	gpointer	(*get_xmp_ptr) 	(EogMetadataReader *self);
+	gpointer	(*get_xmp_ptr)		(EogMetadataReader *self);
 };
 
 typedef enum {
-	EOG_METADATA_JPEG
+	EOG_METADATA_JPEG,
+	EOG_METADATA_PNG
 } EogMetadataFileType;
 
-GType                eog_metadata_reader_get_type (void) G_GNUC_CONST;
-
-EogMetadataReader*   eog_metadata_reader_new (EogMetadataFileType type);
-void                 eog_metadata_reader_consume (EogMetadataReader *emr, const guchar *buf, guint len);
-gboolean             eog_metadata_reader_finished (EogMetadataReader *emr);
+GType                eog_metadata_reader_get_type	(void) G_GNUC_CONST;
 
-void                 eog_metadata_reader_get_exif_chunk (EogMetadataReader *emr, guchar **data, guint *len);
+EogMetadataReader*   eog_metadata_reader_new 		(EogMetadataFileType type);
+void                 eog_metadata_reader_consume	(EogMetadataReader *emr,
+							 const guchar *buf,
+							 guint len);
+gboolean             eog_metadata_reader_finished	(EogMetadataReader *emr);
+
+void                 eog_metadata_reader_get_exif_chunk (EogMetadataReader *emr,
+							 guchar **data,
+							 guint *len);
 
 #ifdef HAVE_EXIF
-ExifData*            eog_metadata_reader_get_exif_data (EogMetadataReader *emr);
+ExifData*            eog_metadata_reader_get_exif_data	(EogMetadataReader *emr);
 #endif
 
 #ifdef HAVE_EXEMPI
-XmpPtr	     	     eog_metadata_reader_get_xmp_data (EogMetadataReader *emr);
+XmpPtr	     	     eog_metadata_reader_get_xmp_data	(EogMetadataReader *emr);
 #endif
 
 #if 0
-gpointer             eog_metadata_reader_get_iptc_chunk (EogMetadataReader *emr);
-IptcData*            eog_metadata_reader_get_iptc_data (EogMetadataReader *emr);
+gpointer             eog_metadata_reader_get_iptc_chunk	(EogMetadataReader *emr);
+IptcData*            eog_metadata_reader_get_iptc_data	(EogMetadataReader *emr);
 #endif
 
-void                 eog_metadata_reader_get_icc_chunk (EogMetadataReader *emr, guchar **data, guint *len);
+#ifdef HAVE_LCMS
+cmsHPROFILE          eog_metadata_reader_get_icc_profile (EogMetadataReader *emr);
+#endif
 
 G_END_DECLS
 



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