eog r4503 - in trunk: . src
- From: friemann svn gnome org
- To: svn-commits-list gnome org
- Subject: eog r4503 - in trunk: . src
- Date: Sun, 30 Mar 2008 11:36:19 +0100 (BST)
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]