[gnome-color-manager] Make GcmImage take a GcmProfile, not a base64 string for efficiency
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-color-manager] Make GcmImage take a GcmProfile, not a base64 string for efficiency
- Date: Thu, 24 Jun 2010 11:55:46 +0000 (UTC)
commit 91efd578106f7d160c3c6909bf15ca30fb893b03
Author: Richard Hughes <richard hughsie com>
Date: Thu Jun 24 12:54:47 2010 +0100
Make GcmImage take a GcmProfile, not a base64 string for efficiency
src/gcm-image.c | 259 +++++++++++++++++++++++++++------------------------
src/gcm-image.h | 10 ++
src/gcm-profile.c | 12 +++
src/gcm-profile.h | 1 +
src/gcm-self-test.c | 58 ++++--------
5 files changed, 180 insertions(+), 160 deletions(-)
---
diff --git a/src/gcm-image.c b/src/gcm-image.c
index 176052f..94cd788 100644
--- a/src/gcm-image.c
+++ b/src/gcm-image.c
@@ -46,89 +46,25 @@ static void gcm_image_finalize (GObject *object);
**/
struct _GcmImagePrivate
{
- gboolean has_embedded_icc_profile;
- gboolean use_embedded_icc_profile;
- gchar *output_icc_profile;
- gchar *input_icc_profile;
+ gboolean has_embedded_profile;
+ gboolean use_embedded_profile;
+ GcmProfile *output_profile;
+ GcmProfile *input_profile;
GdkPixbuf *original_pixbuf;
};
enum {
PROP_0,
- PROP_HAS_EMBEDDED_ICC_PROFILE,
- PROP_USE_EMBEDDED_ICC_PROFILE,
- PROP_OUTPUT_ICC_PROFILE,
- PROP_INPUT_ICC_PROFILE,
+ PROP_HAS_EMBEDDED_PROFILE,
+ PROP_USE_EMBEDDED_PROFILE,
+ PROP_OUTPUT_PROFILE,
+ PROP_INPUT_PROFILE,
PROP_LAST
};
G_DEFINE_TYPE (GcmImage, gcm_image, GTK_TYPE_IMAGE)
/**
- * gcm_image_get_profile_in:
- **/
-static cmsHPROFILE
-gcm_image_get_profile_in (GcmImage *image, const gchar *icc_profile_base64)
-{
- cmsHPROFILE profile = NULL;
- guchar *icc_profile = NULL;
- gsize icc_profile_size;
- GcmImagePrivate *priv = image->priv;
-
- /* ignore built-in */
- if (priv->use_embedded_icc_profile == FALSE) {
- egg_debug ("ignoring embedded ICC profile, assume sRGB");
- profile = cmsCreate_sRGBProfile ();
- goto out;
- }
-
- /* decode */
- icc_profile = g_base64_decode (icc_profile_base64, &icc_profile_size);
- if (icc_profile == NULL) {
- egg_warning ("failed to decode base64");
- goto out;
- }
-
- /* use embedded profile */
- profile = cmsOpenProfileFromMem (icc_profile, icc_profile_size);
-out:
- g_free (icc_profile);
- return profile;
-}
-
-/**
- * gcm_image_get_profile_out:
- **/
-static cmsHPROFILE
-gcm_image_get_profile_out (GcmImage *image)
-{
- cmsHPROFILE profile = NULL;
- guchar *icc_profile = NULL;
- gsize icc_profile_size;
- GcmImagePrivate *priv = image->priv;
-
- /* not set */
- if (priv->output_icc_profile == NULL) {
- egg_debug ("no output ICC profile, assume sRGB");
- profile = cmsCreate_sRGBProfile ();
- goto out;
- }
-
- /* decode */
- icc_profile = g_base64_decode (priv->output_icc_profile, &icc_profile_size);
- if (icc_profile == NULL) {
- egg_warning ("failed to decode base64");
- goto out;
- }
-
- /* use embedded profile */
- profile = cmsOpenProfileFromMem (icc_profile, icc_profile_size);
-out:
- g_free (icc_profile);
- return profile;
-}
-
-/**
* gcm_image_get_format:
**/
static cmsUInt32Number
@@ -175,7 +111,7 @@ out:
static void
gcm_image_cms_convert_pixbuf (GcmImage *image)
{
- const gchar *icc_profile_base64;
+ const gchar *profile_base64;
gint i;
cmsUInt32Number format;
gint width, height, rowstride;
@@ -185,6 +121,10 @@ gcm_image_cms_convert_pixbuf (GcmImage *image)
cmsHPROFILE profile_out;
cmsHTRANSFORM transform;
GdkPixbuf *pixbuf_cms;
+ guchar *profile_data = NULL;
+ gsize profile_size;
+ gboolean profile_close_input = FALSE;
+ gboolean profile_close_output = FALSE;
GcmImagePrivate *priv = image->priv;
/* not a pixbuf-backed image */
@@ -208,20 +148,47 @@ gcm_image_cms_convert_pixbuf (GcmImage *image)
/* get profile from pixbuf */
pixbuf_cms = gtk_image_get_pixbuf (GTK_IMAGE(image));
- icc_profile_base64 = gdk_pixbuf_get_option (pixbuf_cms, "icc-profile");
+ profile_base64 = gdk_pixbuf_get_option (pixbuf_cms, "profile");
/* set the boolean property */
- priv->use_embedded_icc_profile = (icc_profile_base64 != NULL);
+ priv->has_embedded_profile = (profile_base64 != NULL);
+
+ /* get input profile */
+ if (priv->use_embedded_profile && priv->has_embedded_profile) {
+
+ /* decode built-in */
+ profile_data = g_base64_decode (profile_base64, &profile_size);
+ if (profile_data == NULL) {
+ egg_warning ("failed to decode base64");
+ goto out;
+ }
- /* just exit, and have no color management done */
- if (icc_profile_base64 == NULL) {
- egg_debug ("not a color managed image");
+ /* use embedded profile */
+ profile_in = cmsOpenProfileFromMem (profile_data, profile_size);
+ profile_close_input = TRUE;
goto out;
+ } else if (priv->input_profile != NULL) {
+ /* use built-in */
+ profile_in = gcm_profile_get_handle (priv->input_profile);
+ profile_close_input = FALSE;
+ goto out;
+ } else {
+ egg_debug ("no profile, assume sRGB");
+ profile_in = cmsCreate_sRGBProfile ();
+ profile_close_input = TRUE;
}
- /* get profiles */
- profile_in = gcm_image_get_profile_in (image, icc_profile_base64);
- profile_out = gcm_image_get_profile_out (image);
+ /* get output profile */
+ if (priv->output_profile != NULL) {
+ /* use built-in */
+ profile_out = gcm_profile_get_handle (priv->output_profile);
+ profile_close_output = FALSE;
+ goto out;
+ } else {
+ egg_debug ("no profile, assume sRGB");
+ profile_out = cmsCreate_sRGBProfile ();
+ profile_close_output = TRUE;
+ }
/* create transform */
transform = cmsCreateTransform (profile_in, format, profile_out, format, INTENT_PERCEPTUAL, 0);
@@ -240,13 +207,16 @@ gcm_image_cms_convert_pixbuf (GcmImage *image)
/* destroy lcms state */
cmsDeleteTransform (transform);
- cmsCloseProfile (profile_in);
- cmsCloseProfile (profile_out);
+ if (profile_close_input)
+ cmsCloseProfile (profile_in);
+ if (profile_close_output)
+ cmsCloseProfile (profile_out);
/* refresh widget */
gtk_widget_set_visible (GTK_WIDGET(image), FALSE);
gtk_widget_set_visible (GTK_WIDGET(image), TRUE);
out:
+ g_free (profile_data);
return;
}
@@ -288,6 +258,57 @@ out:
}
/**
+ * gcm_image_set_input_profile:
+ **/
+void
+gcm_image_set_input_profile (GcmImage *image, GcmProfile *profile)
+{
+ GcmImagePrivate *priv = image->priv;
+ if (priv->input_profile != NULL) {
+ g_object_unref (priv->input_profile);
+ priv->input_profile = NULL;
+ }
+ if (profile != NULL)
+ priv->input_profile = g_object_ref (profile);
+ gcm_image_cms_convert_pixbuf (image);
+}
+
+/**
+ * gcm_image_set_output_profile:
+ **/
+void
+gcm_image_set_output_profile (GcmImage *image, GcmProfile *profile)
+{
+ GcmImagePrivate *priv = image->priv;
+ if (priv->output_profile != NULL) {
+ g_object_unref (priv->output_profile);
+ priv->output_profile = NULL;
+ }
+ if (profile != NULL)
+ priv->output_profile = g_object_ref (profile);
+ gcm_image_cms_convert_pixbuf (image);
+}
+
+/**
+ * gcm_image_has_embedded_profile:
+ **/
+gboolean
+gcm_image_has_embedded_profile (GcmImage *image)
+{
+ return image->priv->has_embedded_profile;
+}
+
+/**
+ * gcm_image_use_embedded_profile:
+ **/
+void
+gcm_image_use_embedded_profile (GcmImage *image, gboolean use_embedded_profile)
+{
+ image->priv->use_embedded_profile = use_embedded_profile;
+ gcm_image_cms_convert_pixbuf (image);
+}
+
+/**
* gcm_image_get_property:
**/
static void
@@ -297,17 +318,17 @@ gcm_image_get_property (GObject *object, guint prop_id, GValue *value, GParamSpe
GcmImagePrivate *priv = image->priv;
switch (prop_id) {
- case PROP_HAS_EMBEDDED_ICC_PROFILE:
- g_value_set_boolean (value, priv->has_embedded_icc_profile);
+ case PROP_HAS_EMBEDDED_PROFILE:
+ g_value_set_boolean (value, priv->has_embedded_profile);
break;
- case PROP_USE_EMBEDDED_ICC_PROFILE:
- g_value_set_boolean (value, priv->use_embedded_icc_profile);
+ case PROP_USE_EMBEDDED_PROFILE:
+ g_value_set_boolean (value, priv->use_embedded_profile);
break;
- case PROP_OUTPUT_ICC_PROFILE:
- g_value_set_string (value, priv->output_icc_profile);
+ case PROP_OUTPUT_PROFILE:
+ g_value_set_object (value, priv->output_profile);
break;
- case PROP_INPUT_ICC_PROFILE:
- g_value_set_string (value, priv->input_icc_profile);
+ case PROP_INPUT_PROFILE:
+ g_value_set_object (value, priv->input_profile);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -322,22 +343,16 @@ static void
gcm_image_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
GcmImage *image = GCM_IMAGE (object);
- GcmImagePrivate *priv = image->priv;
switch (prop_id) {
- case PROP_USE_EMBEDDED_ICC_PROFILE:
- priv->use_embedded_icc_profile = g_value_get_boolean (value);
- gcm_image_cms_convert_pixbuf (image);
+ case PROP_USE_EMBEDDED_PROFILE:
+ gcm_image_use_embedded_profile (image, g_value_get_boolean (value));
break;
- case PROP_OUTPUT_ICC_PROFILE:
- g_free (priv->output_icc_profile);
- priv->output_icc_profile = g_strdup (g_value_get_string (value));
- gcm_image_cms_convert_pixbuf (image);
+ case PROP_OUTPUT_PROFILE:
+ gcm_image_set_output_profile (image, g_value_get_object (value));
break;
- case PROP_INPUT_ICC_PROFILE:
- g_free (priv->input_icc_profile);
- priv->input_icc_profile = g_strdup (g_value_get_string (value));
- gcm_image_cms_convert_pixbuf (image);
+ case PROP_INPUT_PROFILE:
+ gcm_image_set_input_profile (image, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -358,36 +373,36 @@ gcm_image_class_init (GcmImageClass *klass)
object_class->set_property = gcm_image_set_property;
/**
- * GcmImage:has-embedded-icc-profile:
+ * GcmImage:has-embedded-profile:
*/
- pspec = g_param_spec_boolean ("has-embedded-icc-profile", NULL, NULL,
+ pspec = g_param_spec_boolean ("has-embedded-profile", NULL, NULL,
TRUE,
G_PARAM_READABLE);
- g_object_class_install_property (object_class, PROP_HAS_EMBEDDED_ICC_PROFILE, pspec);
+ g_object_class_install_property (object_class, PROP_HAS_EMBEDDED_PROFILE, pspec);
/**
- * GcmImage:use-embedded-icc-profile:
+ * GcmImage:use-embedded-profile:
*/
- pspec = g_param_spec_boolean ("use-embedded-icc-profile", NULL, NULL,
+ pspec = g_param_spec_boolean ("use-embedded-profile", NULL, NULL,
TRUE,
G_PARAM_READWRITE);
- g_object_class_install_property (object_class, PROP_USE_EMBEDDED_ICC_PROFILE, pspec);
+ g_object_class_install_property (object_class, PROP_USE_EMBEDDED_PROFILE, pspec);
/**
- * GcmImage:output-icc-profile:
+ * GcmImage:output-profile:
*/
- pspec = g_param_spec_string ("output-icc-profile", NULL, NULL,
- NULL,
+ pspec = g_param_spec_object ("output-profile", NULL, NULL,
+ GCM_TYPE_PROFILE,
G_PARAM_READWRITE);
- g_object_class_install_property (object_class, PROP_OUTPUT_ICC_PROFILE, pspec);
+ g_object_class_install_property (object_class, PROP_OUTPUT_PROFILE, pspec);
/**
- * GcmImage:input-icc-profile:
+ * GcmImage:input-profile:
*/
- pspec = g_param_spec_string ("input-icc-profile", NULL, NULL,
- NULL,
+ pspec = g_param_spec_object ("input-profile", NULL, NULL,
+ GCM_TYPE_PROFILE,
G_PARAM_READWRITE);
- g_object_class_install_property (object_class, PROP_INPUT_ICC_PROFILE, pspec);
+ g_object_class_install_property (object_class, PROP_INPUT_PROFILE, pspec);
g_type_class_add_private (klass, sizeof (GcmImagePrivate));
}
@@ -402,8 +417,8 @@ gcm_image_init (GcmImage *image)
priv = image->priv = GCM_IMAGE_GET_PRIVATE (image);
- priv->has_embedded_icc_profile = FALSE;
- priv->use_embedded_icc_profile = TRUE;
+ priv->has_embedded_profile = FALSE;
+ priv->use_embedded_profile = TRUE;
priv->original_pixbuf = NULL;
/* only convert pixbuf if the size changes */
@@ -422,8 +437,10 @@ gcm_image_finalize (GObject *object)
if (priv->original_pixbuf != NULL)
g_object_unref (priv->original_pixbuf);
- g_free (priv->output_icc_profile);
- g_free (priv->input_icc_profile);
+ if (priv->output_profile != NULL)
+ g_object_unref (priv->output_profile);
+ if (priv->input_profile != NULL)
+ g_object_unref (priv->input_profile);
G_OBJECT_CLASS (gcm_image_parent_class)->finalize (object);
}
diff --git a/src/gcm-image.h b/src/gcm-image.h
index fd033ff..412171f 100644
--- a/src/gcm-image.h
+++ b/src/gcm-image.h
@@ -25,6 +25,8 @@
#include <glib-object.h>
#include <gtk/gtk.h>
+#include "gcm-profile.h"
+
G_BEGIN_DECLS
#define GCM_TYPE_IMAGE (gcm_image_get_type ())
@@ -58,6 +60,14 @@ struct _GcmImageClass
GType gcm_image_get_type (void);
GcmImage *gcm_image_new (void);
+void gcm_image_set_input_profile (GcmImage *image,
+ GcmProfile *profile);
+void gcm_image_set_output_profile (GcmImage *image,
+ GcmProfile *profile);
+gboolean gcm_image_has_embedded_profile (GcmImage *image);
+void gcm_image_use_embedded_profile (GcmImage *image,
+ gboolean use_embedded_profile);
+
G_END_DECLS
#endif /* __GCM_IMAGE_H */
diff --git a/src/gcm-profile.c b/src/gcm-profile.c
index c690f8b..e3754fc 100644
--- a/src/gcm-profile.c
+++ b/src/gcm-profile.c
@@ -421,6 +421,18 @@ gcm_profile_set_has_vcgt (GcmProfile *profile, gboolean has_vcgt)
}
/**
+ * gcm_profile_get_handle:
+ *
+ * Return value: Do not call cmsCloseProfile() on this value!
+ **/
+gpointer
+gcm_profile_get_handle (GcmProfile *profile)
+{
+ g_return_val_if_fail (GCM_IS_PROFILE (profile), NULL);
+ return profile->priv->lcms_profile;
+}
+
+/**
* gcm_profile_get_can_delete:
**/
gboolean
diff --git a/src/gcm-profile.h b/src/gcm-profile.h
index dc20acd..98eefcd 100644
--- a/src/gcm-profile.h
+++ b/src/gcm-profile.h
@@ -72,6 +72,7 @@ gboolean gcm_profile_parse_data (GcmProfile *profile,
gboolean gcm_profile_save (GcmProfile *profile,
const gchar *filename,
GError **error);
+gpointer gcm_profile_get_handle (GcmProfile *profile);
const gchar *gcm_profile_get_checksum (GcmProfile *profile);
gboolean gcm_profile_get_can_delete (GcmProfile *profile);
GcmClut *gcm_profile_generate_vcgt (GcmProfile *profile,
diff --git a/src/gcm-self-test.c b/src/gcm-self-test.c
index 4807e92..a2a2cce 100644
--- a/src/gcm-self-test.c
+++ b/src/gcm-self-test.c
@@ -685,35 +685,6 @@ gcm_test_gamma_widget_func (void)
g_free (filename_image);
}
-static gchar *
-gcm_image_test_get_ibmt61_profile ()
-{
- gchar *filename;
- gchar *profile_base64 = NULL;
- gchar *contents = NULL;
- gboolean ret;
- gsize length;
- GError *error = NULL;
-
- /* get test file */
- filename = gcm_test_get_data_file ("ibm-t61.icc");
-
- /* get contents */
- ret = g_file_get_contents (filename, &contents, &length, &error);
- if (!ret) {
- g_warning ("failed to get contents: %s", error->message);
- g_error_free (error);
- goto out;
- }
-
- /* encode */
- profile_base64 = g_base64_encode ((const guchar *)contents, length);
-out:
- g_free (contents);
- g_free (filename);
- return profile_base64;
-}
-
static void
gcm_test_image_func (void)
{
@@ -724,7 +695,10 @@ gcm_test_image_func (void)
gint response;
gchar *filename_widget;
gchar *filename_test;
- gchar *profile_base64;
+ gchar *filename;
+ gboolean ret;
+ GcmProfile *profile;
+ GFile *file;
image = gcm_image_new ();
g_assert (image != NULL);
@@ -747,8 +721,8 @@ gcm_test_image_func (void)
gtk_widget_show (image_test);
g_object_set (image,
- "use-embedded-icc-profile", TRUE,
- "output-icc-profile", NULL,
+ "use-embedded-profile", TRUE,
+ "output-profile", NULL,
NULL);
response = gtk_dialog_run (GTK_DIALOG (dialog));
@@ -758,30 +732,36 @@ gcm_test_image_func (void)
filename_test = gcm_test_get_data_file ("image-widget-nonembed.png");
gtk_image_set_from_file (GTK_IMAGE(image_test), filename_test);
g_object_set (image,
- "use-embedded-icc-profile", FALSE,
+ "use-embedded-profile", FALSE,
NULL);
response = gtk_dialog_run (GTK_DIALOG (dialog));
g_assert ((response == GTK_RESPONSE_YES));
g_free (filename_test);
- profile_base64 = gcm_image_test_get_ibmt61_profile ();
- g_assert ((profile_base64 != NULL));
-
filename_test = gcm_test_get_data_file ("image-widget-output.png");
gtk_image_set_from_file (GTK_IMAGE(image_test), filename_test);
g_object_set (image,
- "use-embedded-icc-profile", TRUE,
- "output-icc-profile", profile_base64,
+ "use-embedded-profile", TRUE,
NULL);
+ /* get test file */
+ filename = gcm_test_get_data_file ("ibm-t61.icc");
+ profile = gcm_profile_new ();
+ file = g_file_new_for_path (filename);
+ ret = gcm_profile_parse (profile, file, NULL);
+ g_object_unref (file);
+ g_assert (ret);
+ gcm_image_set_output_profile (image, profile);
+ g_object_unref (profile);
+
response = gtk_dialog_run (GTK_DIALOG (dialog));
g_assert ((response == GTK_RESPONSE_YES));
g_free (filename_test);
gtk_widget_destroy (dialog);
- g_free (profile_base64);
+ g_free (filename);
g_free (filename_widget);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]