[gnome-color-manager] Switch around to the profile generating the clut, not the clut being loaded from the profile.



commit c534c25ce8631b6e05e9042114e78321834bb556
Author: Richard Hughes <richard hughsie com>
Date:   Thu Dec 10 09:28:14 2009 +0000

    Switch around to the profile generating the clut, not the clut being loaded from the profile.
    
    This should help startup speed (as the profile is only being parsed once) and also make the core more maintainable

 src/gcm-clut.c       |   57 +++++++-----------
 src/gcm-clut.h       |    5 +-
 src/gcm-profile.c    |  161 +++++++++++++++++++++++++------------------------
 src/gcm-profile.h    |    2 +-
 src/gcm-trc-widget.c |   12 ++--
 src/gcm-utils.c      |   46 ++++++++------
 6 files changed, 139 insertions(+), 144 deletions(-)
---
diff --git a/src/gcm-clut.c b/src/gcm-clut.c
index 28bf25b..0deae8c 100644
--- a/src/gcm-clut.c
+++ b/src/gcm-clut.c
@@ -36,7 +36,6 @@
 
 #include "gcm-clut.h"
 #include "gcm-utils.h"
-#include "gcm-profile.h"
 
 #include "egg-debug.h"
 
@@ -73,11 +72,12 @@ enum {
 
 G_DEFINE_TYPE (GcmClut, gcm_clut, G_TYPE_OBJECT)
 
+#if 0
 /**
- * gcm_clut_set_from_data:
+ * gcm_clut_set_source_data:
  **/
 static gboolean
-gcm_clut_set_from_data (GcmClut *clut, const GcmClutData *data, guint size)
+gcm_clut_set_source_data (GcmClut *clut, const GcmClutData *data, guint size)
 {
 	guint i;
 	GcmClutData *tmp;
@@ -96,55 +96,40 @@ gcm_clut_set_from_data (GcmClut *clut, const GcmClutData *data, guint size)
 
 	return TRUE;
 }
+#endif
 
 /**
- * gcm_clut_reset:
+ * gcm_clut_set_source_array:
  **/
 gboolean
-gcm_clut_reset (GcmClut *clut)
+gcm_clut_set_source_array (GcmClut *clut, GPtrArray *array)
 {
 	g_return_val_if_fail (GCM_IS_CLUT (clut), FALSE);
+	g_return_val_if_fail (array != NULL, FALSE);
 
-	/* setup nothing */
-	g_ptr_array_set_size (clut->priv->array, 0);
+	/* just take a reference */
+	if (clut->priv->array != NULL)
+		g_ptr_array_unref (clut->priv->array);
+	clut->priv->array = g_ptr_array_ref (array);
+
+	/* set size from input array */
+	clut->priv->size = array->len;
+
+	/* all okay */
 	return TRUE;
 }
 
 /**
- * gcm_clut_load_from_profile:
+ * gcm_clut_reset:
  **/
 gboolean
-gcm_clut_load_from_profile (GcmClut *clut, const gchar *filename, GError **error)
+gcm_clut_reset (GcmClut *clut)
 {
-	gboolean ret = TRUE;
-	GcmProfile *profile = NULL;
-	GcmClutData *data = NULL;
-	GError *error_local = NULL;
-
 	g_return_val_if_fail (GCM_IS_CLUT (clut), FALSE);
-	g_return_val_if_fail (filename != NULL, FALSE);
-
-	/* create new profile instance */
-	profile = gcm_profile_new ();
-
-	/* load the profile */
-	ret = gcm_profile_parse (profile, filename, &error_local);
-	if (!ret) {
-		if (error != NULL)
-			*error = g_error_new (1, 0, "failed to set from profile: %s", error_local->message);
-		g_error_free (error_local);
-		goto out;
-	}
 
-	/* generate the data */
-	data = gcm_profile_generate (profile, clut->priv->size);
-	if (data != NULL)
-		gcm_clut_set_from_data (clut, data, clut->priv->size);
-out:
-	if (profile != NULL)
-		g_object_unref (profile);
-	g_free (data);
-	return ret;
+	/* setup nothing */
+	g_ptr_array_set_size (clut->priv->array, 0);
+	return TRUE;
 }
 
 /**
diff --git a/src/gcm-clut.h b/src/gcm-clut.h
index 7f7a0ef..771c493 100644
--- a/src/gcm-clut.h
+++ b/src/gcm-clut.h
@@ -62,10 +62,9 @@ typedef struct {
 
 GType		 gcm_clut_get_type		  	(void);
 GcmClut		*gcm_clut_new				(void);
-gboolean	 gcm_clut_load_from_profile		(GcmClut		*clut,
-							 const gchar		*filename,
-							 GError			**error);
 GPtrArray	*gcm_clut_get_array			(GcmClut		*clut);
+gboolean	 gcm_clut_set_source_array		(GcmClut		*clut,
+							 GPtrArray		*array);
 gboolean	 gcm_clut_reset				(GcmClut		*clut);
 void		 gcm_clut_print				(GcmClut		*clut);
 
diff --git a/src/gcm-profile.c b/src/gcm-profile.c
index 22ed75c..3c60f58 100644
--- a/src/gcm-profile.c
+++ b/src/gcm-profile.c
@@ -1205,12 +1205,12 @@ out:
  *
  * Free with g_free();
  **/
-GcmClutData *
+GcmClut *
 gcm_profile_generate (GcmProfile *profile, guint size)
 {
-	guint i, j;
+	guint i;
 	guint ratio;
-	GcmClutData *gamma_data = NULL;
+	GcmClutData *tmp;
 	GcmClutData *vcgt_data;
 	GcmClutData *mlut_data;
 	GcmClutData *trc_data;
@@ -1218,6 +1218,11 @@ gcm_profile_generate (GcmProfile *profile, guint size)
 	gfloat gamma_green, min_green, max_green;
 	gfloat gamma_blue, min_blue, max_blue;
 	guint num_entries;
+	GcmClut *clut;
+	GPtrArray *array;
+	gfloat inverse_ratio;
+	guint idx;
+	gfloat frac;
 
 	g_return_val_if_fail (GCM_IS_PROFILE (profile), NULL);
 	g_return_val_if_fail (size != 0, FALSE);
@@ -1227,13 +1232,50 @@ gcm_profile_generate (GcmProfile *profile, guint size)
 	mlut_data = profile->priv->mlut_data;
 	trc_data = profile->priv->trc_data;
 
-	if (profile->priv->has_vcgt_formula) {
+	/* create new output array */
+	clut = gcm_clut_new ();
+	array = g_ptr_array_new_with_free_func (g_free);
+
+	if (profile->priv->has_vcgt_table) {
 
-		/* create new output array */
-		gamma_data = g_new0 (GcmClutData, size);
+		/* simply subsample if the LUT is smaller than the number of entries in the file */
+		num_entries = profile->priv->vcgt_data_size;
+		if (num_entries >= size) {
+			ratio = (guint) (num_entries / size);
+			for (i=0; i<size; i++) {
+				/* add a point */
+				tmp = g_new0 (GcmClutData, 1);
+				tmp->red = vcgt_data[ratio*i].red;
+				tmp->green = vcgt_data[ratio*i].green;
+				tmp->blue = vcgt_data[ratio*i].blue;
+				g_ptr_array_add (array, tmp);
+			}
+			goto out;
+		}
+
+		/* LUT is bigger than number of entries, so interpolate */
+		inverse_ratio = (gfloat) num_entries / size;
+		vcgt_data[num_entries].red = 0xffff;
+		vcgt_data[num_entries].green = 0xffff;
+		vcgt_data[num_entries].blue = 0xffff;
+
+		/* interpolate */
+		for (i=0; i<size; i++) {
+			idx = floor(i*inverse_ratio);
+			frac = (i*inverse_ratio) - idx;
+			tmp = g_new0 (GcmClutData, 1);
+			tmp->red = vcgt_data[idx].red * (1.0f-frac) + vcgt_data[idx + 1].red * frac;
+			tmp->green = vcgt_data[idx].green * (1.0f-frac) + vcgt_data[idx + 1].green * frac;
+			tmp->blue = vcgt_data[idx].blue * (1.0f-frac) + vcgt_data[idx + 1].blue * frac;
+			g_ptr_array_add (array, tmp);
+		}
+		goto out;
+	}
+
+	if (profile->priv->has_vcgt_formula) {
 
 		/* create mapping of desired size */
-		for (i = 0; i<size; i++) {
+		for (i=0; i<size; i++) {
 			gamma_red = (gfloat) vcgt_data[0].red / 65536.0;
 			gamma_green = (gfloat) vcgt_data[0].green / 65536.0;
 			gamma_blue = (gfloat) vcgt_data[0].blue / 65536.0;
@@ -1244,86 +1286,43 @@ gcm_profile_generate (GcmProfile *profile, guint size)
 			max_green = (gfloat) vcgt_data[2].green / 65536.0;
 			max_blue = (gfloat) vcgt_data[2].blue / 65536.0;
 
-			gamma_data[i].red = 65536.0 * ((gdouble) pow ((gdouble) i / (gdouble) size, gamma_red) * (max_red - min_red) + min_red);
-			gamma_data[i].green = 65536.0 * ((gdouble) pow ((gdouble) i / (gdouble) size, gamma_green) * (max_green - min_green) + min_green);
-			gamma_data[i].blue = 65536.0 * ((gdouble) pow ((gdouble) i / (gdouble) size, gamma_blue) * (max_blue - min_blue) + min_blue);
+			/* add a point */
+			tmp = g_new0 (GcmClutData, 1);
+			tmp->red = 65536.0 * ((gdouble) pow ((gdouble) i / (gdouble) size, gamma_red) * (max_red - min_red) + min_red);
+			tmp->green = 65536.0 * ((gdouble) pow ((gdouble) i / (gdouble) size, gamma_green) * (max_green - min_green) + min_green);
+			tmp->blue = 65536.0 * ((gdouble) pow ((gdouble) i / (gdouble) size, gamma_blue) * (max_blue - min_blue) + min_blue);
+			g_ptr_array_add (array, tmp);
 		}
 	}
 
 	if (profile->priv->has_mlut) {
 
-		/* create new output array */
-		gamma_data = g_new0 (GcmClutData, size);
-
 		/* roughly interpolate table */
 		ratio = (guint) (256 / (size));
-		for (i = 0; i<size; i++) {
-			gamma_data[i].red = mlut_data[ratio*i].red;
-			gamma_data[i].green = mlut_data[ratio*i].green;
-			gamma_data[i].blue = mlut_data[ratio*i].blue;
-		}
-		goto out;
-	}
-
-	if (profile->priv->has_vcgt_table) {
-
-		/* create new output array */
-		gamma_data = g_new0 (GcmClutData, size);
-
-		/* simply subsample if the LUT is smaller than the number of entries in the file */
-		num_entries = profile->priv->vcgt_data_size;
-		if (num_entries >= size) {
-			ratio = (guint) (num_entries / size);
-			for (i=0; i<size; i++) {
-				gamma_data[i].red = vcgt_data[ratio*i].red;
-				gamma_data[i].green = vcgt_data[ratio*i].green;
-				gamma_data[i].blue = vcgt_data[ratio*i].blue;
-			}
-			goto out;
-		}
-
-		/* add extrapolated upper limit to the arrays - handle overflow */
-		ratio = (guint) (size / num_entries);
-		vcgt_data[num_entries].red = (vcgt_data[num_entries-1].red + (vcgt_data[num_entries-1].red - vcgt_data[num_entries-2].red)) & 0xffff;
-		if (vcgt_data[num_entries].red < 0x4000)
-			vcgt_data[num_entries].red = 0xffff;
-
-		vcgt_data[num_entries].green = (vcgt_data[num_entries-1].green + (vcgt_data[num_entries-1].green - vcgt_data[num_entries-2].green)) & 0xffff;
-		if (vcgt_data[num_entries].green < 0x4000)
-			vcgt_data[num_entries].green = 0xffff;
-
-		vcgt_data[num_entries].blue = (vcgt_data[num_entries-1].blue + (vcgt_data[num_entries-1].blue - vcgt_data[num_entries-2].blue)) & 0xffff;
-		if (vcgt_data[num_entries].blue < 0x4000)
-			vcgt_data[num_entries].blue = 0xffff;
-
-		/* interpolate */
-		for (i=0; i<num_entries; i++) {
-			for (j = 0; j<ratio; j++) {
-				gamma_data[i*ratio + j].red = (vcgt_data[i].red * (ratio-j) + vcgt_data[i + 1].red * j) / ratio;
-				gamma_data[i*ratio + j].green = (vcgt_data[i].green * (ratio-j) + vcgt_data[i + 1].green * j) / ratio;
-				gamma_data[i*ratio + j].blue = (vcgt_data[i].blue * (ratio-j) + vcgt_data[i + 1].blue * j) / ratio;
-			}
+		for (i=0; i<size; i++) {
+			/* add a point */
+			tmp = g_new0 (GcmClutData, 1);
+			tmp->red = mlut_data[ratio*i].red;
+			tmp->green = mlut_data[ratio*i].green;
+			tmp->blue = mlut_data[ratio*i].blue;
+			g_ptr_array_add (array, tmp);
 		}
 		goto out;
 	}
 
 	if (profile->priv->has_curve_table) {
 
-		gfloat inverse_ratio;
-		guint idx;
-		gfloat frac;
-
-		/* create new output array */
-		gamma_data = g_new0 (GcmClutData, size);
-
 		/* simply subsample if the LUT is smaller than the number of entries in the file */
 		num_entries = profile->priv->trc_data_size;
 		if (num_entries >= size) {
 			ratio = (guint) (num_entries / size);
 			for (i=0; i<size; i++) {
-				gamma_data[i].red = trc_data[ratio*i].red;
-				gamma_data[i].green = trc_data[ratio*i].green;
-				gamma_data[i].blue = trc_data[ratio*i].blue;
+				/* add a point */
+				tmp = g_new0 (GcmClutData, 1);
+				tmp->red = trc_data[ratio*i].red;
+				tmp->green = trc_data[ratio*i].green;
+				tmp->blue = trc_data[ratio*i].blue;
+				g_ptr_array_add (array, tmp);
 			}
 			goto out;
 		}
@@ -1338,25 +1337,27 @@ gcm_profile_generate (GcmProfile *profile, guint size)
 		for (i=0; i<size; i++) {
 			idx = floor(i*inverse_ratio);
 			frac = (i*inverse_ratio) - idx;
-			gamma_data[i].red = trc_data[idx].red * (1.0f-frac) + trc_data[idx + 1].red * frac;
-			gamma_data[i].green = trc_data[idx].green * (1.0f-frac) + trc_data[idx + 1].green * frac;
-			gamma_data[i].blue = trc_data[idx].blue * (1.0f-frac) + trc_data[idx + 1].blue * frac;
+			tmp = g_new0 (GcmClutData, 1);
+			tmp->red = trc_data[idx].red * (1.0f-frac) + trc_data[idx + 1].red * frac;
+			tmp->green = trc_data[idx].green * (1.0f-frac) + trc_data[idx + 1].green * frac;
+			tmp->blue = trc_data[idx].blue * (1.0f-frac) + trc_data[idx + 1].blue * frac;
+			g_ptr_array_add (array, tmp);
 		}
 		goto out;
 	}
 
 	if (profile->priv->has_curve_fixed) {
 
-		/* create new output array */
-		gamma_data = g_new0 (GcmClutData, size);
-
 		/* use a simple y=x^gamma formula */
 		for (i=0; i<size; i++) {
 			gfloat part;
 			part = (gfloat) i / (gfloat) size;
-			gamma_data[i].red = pow (part, (gfloat) trc_data[0].red / 256.0f) * 65000.f;
-			gamma_data[i].green = pow (part, (gfloat) trc_data[0].green / 256.0f) * 65000.f;
-			gamma_data[i].blue = pow (part, (gfloat) trc_data[0].blue / 256.0f) * 65000.f;
+			/* add a point */
+			tmp = g_new0 (GcmClutData, 1);
+			tmp->red = pow (part, (gfloat) trc_data[0].red / 256.0f) * 65000.f;
+			tmp->green = pow (part, (gfloat) trc_data[0].green / 256.0f) * 65000.f;
+			tmp->blue = pow (part, (gfloat) trc_data[0].blue / 256.0f) * 65000.f;
+			g_ptr_array_add (array, tmp);
 		}
 		goto out;
 	}
@@ -1364,7 +1365,9 @@ gcm_profile_generate (GcmProfile *profile, guint size)
 	/* bugger */
 	egg_warning ("no LUT to generate");
 out:
-	return gamma_data;
+	gcm_clut_set_source_array (clut, array);
+	g_ptr_array_unref (array);
+	return clut;
 }
 
 /**
diff --git a/src/gcm-profile.h b/src/gcm-profile.h
index d165dc8..c539274 100644
--- a/src/gcm-profile.h
+++ b/src/gcm-profile.h
@@ -89,7 +89,7 @@ gboolean	 gcm_profile_parse_data			(GcmProfile	*profile,
 							 const gchar	*data,
 							 gsize		 length,
 							 GError		**error);
-GcmClutData	*gcm_profile_generate			(GcmProfile	*profile,
+GcmClut		*gcm_profile_generate			(GcmProfile	*profile,
 							 guint		 size);
 const gchar	*gcm_profile_type_to_text		(GcmProfileType	 type);
 const gchar	*gcm_profile_colorspace_to_text		(GcmProfileColorspace type);
diff --git a/src/gcm-trc-widget.c b/src/gcm-trc-widget.c
index 2aa6b33..5d073ed 100644
--- a/src/gcm-trc-widget.c
+++ b/src/gcm-trc-widget.c
@@ -26,6 +26,7 @@
 #include <math.h>
 
 #include "gcm-clut.h"
+#include "gcm-profile.h"
 #include "gcm-trc-widget.h"
 
 #include "egg-debug.h"
@@ -403,6 +404,7 @@ gcm_trc_widget_test (EggTest *test)
 	gboolean ret;
 	GError *error = NULL;
 	GcmClut *clut;
+	GcmProfile *profile;
 	gint response;
 	gchar *filename_profile;
 	gchar *filename_image;
@@ -426,12 +428,9 @@ gcm_trc_widget_test (EggTest *test)
 	filename_profile = egg_test_get_data_file ("AdobeGammaTest.icm");
 	egg_test_assert (test, (filename_profile != NULL));
 
-	clut = gcm_clut_new ();
-	g_object_set (clut,
-		      "size", 256,
-		      NULL);
-
-	gcm_clut_load_from_profile (clut, filename_profile, NULL);
+	profile = gcm_profile_new ();
+	gcm_profile_parse (profile, filename_profile, NULL);
+	clut = gcm_profile_generate (profile, 256);
 	g_object_set (widget,
 		      "clut", clut,
 		      NULL);
@@ -456,6 +455,7 @@ gcm_trc_widget_test (EggTest *test)
 	gtk_widget_destroy (dialog);
 
 	g_object_unref (clut);
+	g_object_unref (profile);
 	g_free (filename_profile);
 	g_free (filename_image);
 
diff --git a/src/gcm-utils.c b/src/gcm-utils.c
index a7e9adf..89f1dc3 100644
--- a/src/gcm-utils.c
+++ b/src/gcm-utils.c
@@ -215,11 +215,12 @@ gcm_utils_set_gamma_for_device (GcmDevice *device, GError **error)
 {
 	gboolean ret = FALSE;
 	GcmClut *clut = NULL;
+	GcmProfile *profile = NULL;
 	GcmXserver *xserver = NULL;
 	GnomeRRCrtc *crtc;
 	GnomeRROutput *output;
 	gint x, y;
-	gchar *profile = NULL;
+	gchar *filename = NULL;
 	gfloat gamma;
 	gfloat brightness;
 	gfloat contrast;
@@ -240,7 +241,7 @@ gcm_utils_set_gamma_for_device (GcmDevice *device, GError **error)
 	g_object_get (device,
 		      "id", &id,
 		      "type", &type,
-		      "profile-filename", &profile,
+		      "profile-filename", &filename,
 		      "gamma", &gamma,
 		      "brightness", &brightness,
 		      "contrast", &contrast,
@@ -285,27 +286,32 @@ gcm_utils_set_gamma_for_device (GcmDevice *device, GError **error)
 	if (size == 0)
 		goto out;
 
-	/* create CLUT */
-	clut = gcm_clut_new ();
-	g_object_set (clut,
-		      "size", size,
-		      NULL);
-
 	/* only set the CLUT if we're not seting the atom */
 	use_global = gconf_client_get_bool (gconf_client, GCM_SETTINGS_GLOBAL_DISPLAY_CORRECTION, NULL);
+	if (use_global && filename != NULL) {
+		/* create dummy CLUT */
+		profile = gcm_profile_new ();
+		ret = gcm_profile_parse (profile, filename, error);
+		if (!ret)
+			goto out;
+
+		/* create a CLUT from the profile */
+		clut = gcm_profile_generate (profile, size);
+	} else {
+		/* create dummy CLUT */
+		clut = gcm_clut_new ();
+		g_object_set (clut,
+			      "size", size,
+			      NULL);
+	}
+
+	/* do fine adjustment */
 	if (use_global) {
 		g_object_set (clut,
 			      "gamma", gamma,
 			      "brightness", brightness,
 			      "contrast", contrast,
 			      NULL);
-
-		/* load this new profile */
-		if (profile != NULL) {
-			ret = gcm_clut_load_from_profile (clut, profile, error);
-			if (!ret)
-				goto out;
-		}
 	}
 
 	/* actually set the gamma */
@@ -322,7 +328,7 @@ gcm_utils_set_gamma_for_device (GcmDevice *device, GError **error)
 
 	/* either remove the atoms or set them */
 	use_atom = gconf_client_get_bool (gconf_client, GCM_SETTINGS_SET_ICC_PROFILE_ATOM, NULL);
-	if (!use_atom || profile == NULL) {
+	if (!use_atom || filename == NULL) {
 
 		/* remove the output atom if there's nothing to show */
 		ret = gcm_xserver_remove_output_profile (xserver, output_name, error);
@@ -337,20 +343,20 @@ gcm_utils_set_gamma_for_device (GcmDevice *device, GError **error)
 		}
 	} else {
 		/* set the per-output and per screen profile atoms */
-		ret = gcm_xserver_set_output_profile (xserver, output_name, profile, error);
+		ret = gcm_xserver_set_output_profile (xserver, output_name, filename, error);
 		if (!ret)
 			goto out;
 
 		/* primary screen */
 		if (leftmost_screen) {
-			ret = gcm_xserver_set_root_window_profile (xserver, profile, error);
+			ret = gcm_xserver_set_root_window_profile (xserver, filename, error);
 			if (!ret)
 				goto out;
 		}
 	}
 out:
 	g_free (id);
-	g_free (profile);
+	g_free (filename);
 	g_free (output_name);
 	if (gconf_client != NULL)
 		g_object_unref (gconf_client);
@@ -358,6 +364,8 @@ out:
 		gnome_rr_screen_destroy (rr_screen);
 	if (clut != NULL)
 		g_object_unref (clut);
+	if (profile != NULL)
+		g_object_unref (profile);
 	if (xserver != NULL)
 		g_object_unref (xserver);
 	return ret;



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