summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLucas Rocha <lucasr@gnome.org>2007-03-17 22:19:09 +0000
committerLucas Almeida Rocha <lucasr@src.gnome.org>2007-03-17 22:19:09 +0000
commit9ac162fa8eddb77f2760a01b1b1315f202a8366c (patch)
tree450c0c5269b2befa452619293d801afdf0de9cc7
parent4aaab084893195f2c8232475fbbbf9e83082d276 (diff)
downloadeog-ng.tar.gz
Restabilished ICC profiling functionality with full code refactoring.eog-ng
2007-03-18 Lucas Rocha <lucasr@gnome.org> Restabilished ICC profiling functionality with full code refactoring. * src/eog-debug.[ch] (eog_debug_init): added EOG_DEBUG_LCMS for ICC profiles debugging. * src/eog-image.[ch] (eog_image_get_profile, eog_image_apply_display_profile, eog_image_set_icc_data, eog_image_real_load): load embedded ICC profile from the image if present. * src/eog-metadata-reader.[ch] (eog_metadata_reader_get_icc_chunk, eog_metadata_reader_get_icc_chunk_size): unify ICC functions for consistency. * src/eog-window.c (eog_job_load_cb, eog_window_init, eog_job_model_cb, eog_window_dispose, eog_window_get_display_profile): load and cache display profile to be applied on images just after they are successfully loaded. svn path=/branches/eog-ng/; revision=3650
-rw-r--r--ChangeLog18
-rw-r--r--src/eog-debug.c3
-rw-r--r--src/eog-debug.h4
-rw-r--r--src/eog-image.c167
-rw-r--r--src/eog-image.h7
-rw-r--r--src/eog-metadata-reader.c26
-rw-r--r--src/eog-metadata-reader.h3
-rw-r--r--src/eog-window.c94
8 files changed, 227 insertions, 95 deletions
diff --git a/ChangeLog b/ChangeLog
index 729d7eec..2091223d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2007-03-18 Lucas Rocha <lucasr@gnome.org>
+
+ Restabilished ICC profiling functionality with full code refactoring.
+
+ * src/eog-debug.[ch] (eog_debug_init): added EOG_DEBUG_LCMS for ICC
+ profiles debugging.
+ * src/eog-image.[ch] (eog_image_get_profile,
+ eog_image_apply_display_profile, eog_image_set_icc_data,
+ eog_image_real_load): load embedded ICC profile from the image if
+ present.
+ * src/eog-metadata-reader.[ch] (eog_metadata_reader_get_icc_chunk,
+ eog_metadata_reader_get_icc_chunk_size): unify ICC functions for
+ consistency.
+ * src/eog-window.c (eog_job_load_cb, eog_window_init,
+ eog_job_model_cb, eog_window_dispose,
+ eog_window_get_display_profile): load and cache display profile
+ to be applied on images just after they are successfully loaded.
+
2007-03-17 Lucas Rocha <lucasr@gnome.org>
Restabilished move to trash functionality. Patch from Javier Sánchez
diff --git a/src/eog-debug.c b/src/eog-debug.c
index e54b0890..e86cc26a 100644
--- a/src/eog-debug.c
+++ b/src/eog-debug.c
@@ -82,6 +82,9 @@ eog_debug_init ()
if (g_getenv ("EOG_DEBUG_PRINTING") != NULL)
debug = debug | EOG_DEBUG_PRINTING;
+ if (g_getenv ("EOG_DEBUG_LCMS") != NULL)
+ debug = debug | EOG_DEBUG_LCMS;
+
out:
#ifdef ENABLE_PROFILING
diff --git a/src/eog-debug.h b/src/eog-debug.h
index ccdcdcfe..232a7e87 100644
--- a/src/eog-debug.h
+++ b/src/eog-debug.h
@@ -41,7 +41,8 @@ typedef enum {
EOG_DEBUG_IMAGE_SAVE = 1 << 6,
EOG_DEBUG_LIST_STORE = 1 << 7,
EOG_DEBUG_PREFERENCES = 1 << 8,
- EOG_DEBUG_PRINTING = 1 << 9
+ EOG_DEBUG_PRINTING = 1 << 9,
+ EOG_DEBUG_LCMS = 1 << 10
} EogDebugSection;
#define DEBUG_WINDOW EOG_DEBUG_WINDOW, __FILE__, __LINE__, G_STRFUNC
@@ -54,6 +55,7 @@ typedef enum {
#define DEBUG_LIST_STORE EOG_DEBUG_LIST_STORE, __FILE__, __LINE__, G_STRFUNC
#define DEBUG_PREFERENCES EOG_DEBUG_PREFERENCES, __FILE__, __LINE__, G_STRFUNC
#define DEBUG_PRINTING EOG_DEBUG_PRINTING, __FILE__, __LINE__, G_STRFUNC
+#define DEBUG_LCMS EOG_DEBUG_LCMS, __FILE__, __LINE__, G_STRFUNC
void eog_debug_init (void);
diff --git a/src/eog-image.c b/src/eog-image.c
index 108a643b..20200d7f 100644
--- a/src/eog-image.c
+++ b/src/eog-image.c
@@ -512,131 +512,165 @@ eog_image_apply_display_profile (EogImage *img, cmsHPROFILE screen)
{
EogImagePrivate *priv;
cmsHTRANSFORM transform;
- int row, width, rows, stride;
+ gint row, width, rows, stride;
guchar *p;
g_return_if_fail (img != NULL);
- if (screen == NULL)
- return;
-
priv = img->priv;
- if (priv->profile == NULL)
- return;
-
- transform = cmsCreateTransform(priv->profile, TYPE_RGB_8, screen, TYPE_RGB_8, INTENT_PERCEPTUAL, 0);
+
+ if (screen == NULL || priv->profile == NULL) return;
+
+ transform = cmsCreateTransform (priv->profile,
+ TYPE_RGB_8,
+ screen,
+ TYPE_RGB_8,
+ INTENT_PERCEPTUAL,
+ 0);
rows = gdk_pixbuf_get_height(priv->image);
width = gdk_pixbuf_get_width (priv->image);
stride = gdk_pixbuf_get_rowstride (priv->image);
p = gdk_pixbuf_get_pixels (priv->image);
+
for (row = 0; row < rows; ++row) {
cmsDoTransform(transform, p, p, width);
p += stride;
}
- cmsDeleteTransform(transform);
- //cmsCloseProfile(screen);
+
+ cmsDeleteTransform (transform);
}
static void
-extract_profile (EogImage *img, EogMetadataReader *md_reader)
+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;
- const ExifByteOrder o = exif_data_get_byte_order (priv->exif);
+ ExifByteOrder o;
+ gint color_space;
#endif
+
/* TODO: switch on format to specialised functions */
- /* Embedded ICC profiles rule over anything else */
- {
- gpointer data = eog_metadata_reader_get_icc_chunk (md_reader);
- if (data != NULL) {
- cmsErrorAction (LCMS_ERROR_SHOW);
- priv->profile = cmsOpenProfileFromMem(data, eog_metadata_reader_get_icc_chunk_size (md_reader));
- if (priv->profile) {
- g_printerr("JPEG has ICC profile\n");
- } else {
- g_printerr("JPEG has invalid ICC profile\n");
- }
- return;
+ 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;
}
+
+ return;
+
#ifdef HAVE_EXIF
- /* No EXIF data, so can't do anything */
- if (priv->exif == NULL)
- return;
-
- entry = exif_content_get_entry (priv->exif->ifd [EXIF_IFD_EXIF], EXIF_TAG_COLOR_SPACE);
- if (entry == NULL)
- return;
+ 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");
- if (exif_get_short (entry->data, o) == 1) {
priv->profile = cmsCreate_sRGBProfile ();
- //g_printerr ("JPEG is sRGB\n");
- } else if (exif_get_short (entry->data, o) == 2) {
+
+ break;
+
+ case 2:
+ eog_debug_message (DEBUG_LCMS, "JPEG is Adobe RGB (Disabled)");
+
/* TODO: create Adobe RGB profile */
//priv->profile = cmsCreate_Adobe1998Profile ();
- //g_printerr ("JPEG is Adobe RGB (NOT correcting for now!)\n");
- } else if (exif_get_short (entry->data, o) == 0xFFFF) {
- double gammaValue;
+
+ break;
+
+ case 0xFFFF:
+ {
cmsCIExyY whitepoint;
cmsCIExyYTRIPLE primaries;
LPGAMMATABLE gamma[3];
-
- const int offset = exif_format_get_size (EXIF_FORMAT_RATIONAL);
+ double gammaValue;
ExifRational r;
+
+ const int offset = exif_format_get_size (EXIF_FORMAT_RATIONAL);
- entry = exif_content_get_entry (priv->exif->ifd [EXIF_IFD_0], EXIF_TAG_WHITE_POINT);
+ 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;
+ whitepoint.x = (double) r.numerator / r.denominator;
+
r = exif_get_rational (entry->data + offset, o);
- whitepoint.y = (double)r.numerator/r.denominator;
+ whitepoint.y = (double) r.numerator / r.denominator;
whitepoint.Y = 1.0;
} else {
- g_printerr("No whitepoint found\n");
+ eog_debug_message (DEBUG_LCMS, "No whitepoint found");
return;
}
- entry = exif_content_get_entry (priv->exif->ifd [EXIF_IFD_0], EXIF_TAG_PRIMARY_CHROMATICITIES);
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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.Blue.y = (double) r.numerator / r.denominator;
primaries.Red.Y = primaries.Green.Y = primaries.Blue.Y = 1.0;
} else {
- g_printerr("No primary chromaticities found\n");
+ eog_debug_message (DEBUG_LCMS, "No primary chromaticities found");
return;
}
- entry = exif_content_get_entry (priv->exif->ifd [EXIF_IFD_EXIF], EXIF_TAG_GAMMA);
+ 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;
+ gammaValue = (double) r.numerator / r.denominator;
} else {
- /* Assume 2.2 */
- g_printerr("No gamma found\n");
+ eog_debug_message (DEBUG_LCMS, "No gamma found");
gammaValue = 2.2;
}
- gamma[0] = gamma[1] = gamma[2] = cmsBuildGamma(256, gammaValue);
+ gamma[0] = gamma[1] = gamma[2] = cmsBuildGamma (256, gammaValue);
- priv->profile = cmsCreateRGBProfile(&whitepoint, &primaries, gamma);
- //g_printerr ("JPEG is calibrated\n");
+ priv->profile = cmsCreateRGBProfile (&whitepoint, &primaries, gamma);
+
cmsFreeGamma(gamma[0]);
+
+ eog_debug_message (DEBUG_LCMS, "JPEG is calibrated");
+
+ break;
+ }
}
#endif
}
@@ -654,6 +688,7 @@ eog_image_set_orientation (EogImage *img)
if (priv->exif != NULL) {
ExifByteOrder o = exif_data_get_byte_order (priv->exif);
+
ExifEntry *entry = exif_data_get_entry (priv->exif,
EXIF_TAG_ORIENTATION);
@@ -769,7 +804,7 @@ eog_image_real_load (EogImage *img,
guchar *buffer;
gboolean failed = FALSE;
gboolean first_run = TRUE;
- gboolean set_exif_data = TRUE;
+ gboolean set_metadata = TRUE;
gboolean read_image_data = (data2read & EOG_IMAGE_DATA_IMAGE);
g_assert (error == NULL || *error == NULL);
@@ -870,9 +905,13 @@ eog_image_real_load (EogImage *img,
eog_metadata_reader_consume (md_reader, buffer, bytes_read);
if (eog_metadata_reader_finished (md_reader)) {
- if (set_exif_data) {
+ if (set_metadata) {
eog_image_set_exif_data (img, md_reader);
- set_exif_data = FALSE;
+
+#ifdef HAVE_LCMS
+ eog_image_set_icc_data (img, md_reader);
+#endif
+ set_metadata = FALSE;
}
if (data2read == EOG_IMAGE_DATA_EXIF)
@@ -927,12 +966,6 @@ eog_image_real_load (EogImage *img,
priv->file_type = gdk_pixbuf_format_get_name (format);
}
}
-
-#ifdef HAVE_LCMS
- if (md_reader != NULL) {
- extract_profile (img, md_reader);
- }
-#endif
}
if (loader != NULL) {
diff --git a/src/eog-image.h b/src/eog-image.h
index 374b6d5f..0b145146 100644
--- a/src/eog-image.h
+++ b/src/eog-image.h
@@ -172,6 +172,13 @@ void eog_image_transform (EogImage *img,
void eog_image_autorotate (EogImage *img);
#endif
+#ifdef HAVE_LCMS
+cmsHPROFILE eog_image_get_profile (EogImage *img);
+
+void eog_image_apply_display_profile (EogImage *img,
+ cmsHPROFILE display_profile);
+#endif
+
void eog_image_undo (EogImage *img);
GList *eog_image_get_supported_mime_types (void);
diff --git a/src/eog-metadata-reader.c b/src/eog-metadata-reader.c
index b49d0b7c..c3223750 100644
--- a/src/eog-metadata-reader.c
+++ b/src/eog-metadata-reader.c
@@ -154,7 +154,7 @@ eog_metadata_reader_consume (EogMetadataReader *emr, guchar *buf, guint len)
priv->size = 0;
priv->state = EMR_READ_SIZE_HIGH_BYTE;
- eog_debug_message (DEBUG_IMAGE_DATA, "APPx Marker Found: %x\n", priv->last_marker);
+ eog_debug_message (DEBUG_IMAGE_DATA, "APPx Marker Found: %x", priv->last_marker);
}
else {
/* otherwise simply consume the byte */
@@ -342,20 +342,16 @@ eog_metadata_reader_get_exif_data (EogMetadataReader *emr)
* parse the sections and construct a single memory chunk, or maybe even parse
* the profile.
*/
-
-gpointer
-eog_metadata_reader_get_icc_chunk (EogMetadataReader *emr)
+void
+eog_metadata_reader_get_icc_chunk (EogMetadataReader *emr, guchar **data, guint *len)
{
- g_return_val_if_fail (EOG_IS_METADATA_READER (emr), NULL);
- if (emr->priv->icc_chunk)
- return emr->priv->icc_chunk + 14;
- else
- return NULL;
-}
+ EogMetadataReaderPrivate *priv;
+
+ g_return_if_fail (EOG_IS_METADATA_READER (emr));
+ priv = emr->priv;
-guint
-eog_metadata_reader_get_icc_chunk_size (EogMetadataReader *emr)
-{
- g_return_val_if_fail (EOG_IS_METADATA_READER (emr), -1);
- return emr->priv->icc_len - 14;
+ if (priv->icc_chunk) {
+ *data = (guchar*) priv->icc_chunk + 14;
+ *len = priv->icc_len - 14;
+ }
}
diff --git a/src/eog-metadata-reader.h b/src/eog-metadata-reader.h
index 406d1796..966e318d 100644
--- a/src/eog-metadata-reader.h
+++ b/src/eog-metadata-reader.h
@@ -49,8 +49,7 @@ gpointer eog_metadata_reader_get_iptc_chunk (EogMetadataReader *emr)
IptcData* eog_metadata_reader_get_iptc_data (EogMetadataReader *emr);
#endif
-gpointer eog_metadata_reader_get_icc_chunk (EogMetadataReader *emr);
-guint eog_metadata_reader_get_icc_chunk_size (EogMetadataReader *emr);
+void eog_metadata_reader_get_icc_chunk (EogMetadataReader *emr, guchar **data, guint *len);
G_END_DECLS
diff --git a/src/eog-window.c b/src/eog-window.c
index 7183bd68..33c91674 100644
--- a/src/eog-window.c
+++ b/src/eog-window.c
@@ -56,12 +56,21 @@
#include <glib-object.h>
#include <glib/gi18n.h>
#include <gdk/gdkkeysyms.h>
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#endif
#include <gtk/gtk.h>
#include <gtk/gtkprintunixdialog.h>
#include <libgnomevfs/gnome-vfs-mime.h>
#include <libgnomevfs/gnome-vfs-mime-handlers.h>
#include <gconf/gconf-client.h>
+#if HAVE_LCMS
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <lcms.h>
+#endif
+
#define EOG_WINDOW_GET_PRIVATE(object) \
(G_TYPE_INSTANCE_GET_PRIVATE ((object), EOG_TYPE_WINDOW, EogWindowPrivate))
@@ -155,6 +164,10 @@ struct _EogWindowPrivate {
guint open_with_menu_id;
GList* mime_application_list;
+
+#ifdef HAVE_LCMS
+ cmsHPROFILE *display_profile;
+#endif
};
static void eog_window_cmd_fullscreen (GtkAction *action, gpointer user_data);
@@ -484,6 +497,53 @@ eog_window_collection_mode_changed_cb (GConfClient *client,
}
}
+#ifdef HAVE_LCMS
+static cmsHPROFILE *
+eog_window_get_display_profile (GdkScreen *screen)
+{
+ Display *dpy;
+ Atom icc_atom, type;
+ int format;
+ gulong nitems;
+ gulong bytes_after;
+ guchar *str;
+ int result;
+ cmsHPROFILE *profile;
+
+ dpy = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen));
+
+ icc_atom = gdk_x11_get_xatom_by_name_for_display (gdk_screen_get_display (screen),
+ "_ICC_PROFILE");
+
+ result = XGetWindowProperty (dpy,
+ GDK_WINDOW_XID (gdk_screen_get_root_window (screen)),
+ icc_atom,
+ 0,
+ G_MAXLONG,
+ False,
+ XA_CARDINAL,
+ &type,
+ &format,
+ &nitems,
+ &bytes_after,
+ (guchar **)&str);
+
+ /* TODO: handle bytes_after != 0 */
+
+ if (nitems) {
+ profile = cmsOpenProfileFromMem(str, nitems);
+
+ XFree (str);
+
+ return profile;
+ } else {
+ eog_debug_message (DEBUG_LCMS, "No profile, not correcting");
+
+ return NULL;
+ }
+}
+#endif
+
static void
update_status_bar (EogWindow *window)
{
@@ -908,7 +968,8 @@ eog_window_update_openwith_menu (EogWindow *window, EogImage *image)
GnomeVFSMimeApplication *app = iter->data;
/* do not include eog itself */
- if (strcmp (gnome_vfs_mime_application_get_binary_name (app), g_get_prgname ()) == 0) {
+ if (g_ascii_strcasecmp (gnome_vfs_mime_application_get_binary_name (app),
+ g_get_prgname ()) == 0) {
apps = g_list_remove_link (apps, iter);
g_list_free1 (iter);
gnome_vfs_mime_application_free (app);
@@ -1159,6 +1220,11 @@ eog_job_load_cb (EogJobLoad *job, gpointer data)
priv->image = g_object_ref (job->image);
if (EOG_JOB (job)->error == NULL) {
+#ifdef HAVE_LCMS
+ eog_image_apply_display_profile (job->image,
+ priv->display_profile);
+#endif
+
eog_window_display_image (window, job->image);
} else {
GtkWidget *message_area;
@@ -3493,12 +3559,15 @@ static void
eog_window_init (EogWindow *window)
{
GdkGeometry hints;
+ GdkScreen *screen;
eog_debug (DEBUG_WINDOW);
hints.min_width = EOG_WINDOW_MIN_WIDTH;
hints.min_height = EOG_WINDOW_MIN_HEIGHT;
+ screen = gtk_widget_get_screen (GTK_WIDGET (window));
+
window->priv = EOG_WINDOW_GET_PRIVATE (window);
window->priv->client = gconf_client_get_default ();
@@ -3570,7 +3639,12 @@ eog_window_init (EogWindow *window)
window->priv->status = EOG_WINDOW_STATUS_UNKNOWN;
window->priv->recent_manager =
- gtk_recent_manager_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
+ gtk_recent_manager_get_for_screen (screen);
+
+#ifdef HAVE_LCMS
+ window->priv->display_profile =
+ eog_window_get_display_profile (screen);
+#endif
window->priv->recent_menu_id = 0;
@@ -3676,6 +3750,13 @@ eog_window_dispose (GObject *object)
priv->mime_application_list = NULL;
}
+#ifdef HAVE_LCMS
+ if (priv->display_profile != NULL) {
+ cmsCloseProfile (priv->display_profile);
+ priv->display_profile = NULL;
+ }
+#endif
+
G_OBJECT_CLASS (eog_window_parent_class)->dispose (object);
}
@@ -4045,7 +4126,7 @@ eog_job_model_cb (EogJobModel *job, gpointer data)
eog_debug (DEBUG_WINDOW);
-#if defined(HAVE_LCMS) || defined(HAVE_EXIF)
+#ifdef HAVE_EXIF
int i;
#endif
@@ -4063,13 +4144,6 @@ eog_job_model_cb (EogJobModel *job, gpointer data)
n_images = eog_list_store_length (EOG_LIST_STORE (priv->store));
-#ifdef HAVE_LCMS
- for (i = 0; i < n_images; i++) {
- //eog_image_apply_display_profile (eog_list_store_get_image_by_pos (priv->store, i),
- // get_screen_profile (window));
- }
-#endif
-
#ifdef HAVE_EXIF
if (gconf_client_get_bool (priv->client, EOG_CONF_VIEW_AUTOROTATE, NULL)) {
for (i = 0; i < n_images; i++) {