[gnome-color-manager] Add whitepoint, rXYZ, and VCGT functionality to GcmCalibrateNative



commit be2207a739ab4eaef2aa071a52a0e54f267af666
Author: Richard Hughes <richard hughsie com>
Date:   Thu Oct 14 13:13:49 2010 +0100

    Add whitepoint, rXYZ, and VCGT functionality to GcmCalibrateNative

 src/gcm-calibrate-native.c |  482 ++++++++++++++++++++++++++++++++++++++------
 src/gcm-self-test.c        |   61 ++++++-
 2 files changed, 485 insertions(+), 58 deletions(-)
---
diff --git a/src/gcm-calibrate-native.c b/src/gcm-calibrate-native.c
index 62e66eb..6fa9e8c 100644
--- a/src/gcm-calibrate-native.c
+++ b/src/gcm-calibrate-native.c
@@ -32,6 +32,7 @@
 #include <gio/gio.h>
 #include <gtk/gtk.h>
 #include <lcms2.h>
+#include <math.h>
 
 #include "gcm-calibrate-native.h"
 #include "gcm-sensor-client.h"
@@ -160,7 +161,7 @@ gcm_calibrate_native_sample_write (GPtrArray *array, const gchar *filename)
  * gcm_calibrate_native_create_it8_file:
  **/
 static void
-gcm_calibrate_native_create_it8_file (GcmCalibrateNative *calibrate_native, GcmSensor *sensor, guint precision)
+gcm_calibrate_native_create_it8_file (GcmCalibrateNative *calibrate_native, GcmSensor *sensor, const gchar *filename, guint steps)
 {
 	GcmCalibrateNativePrivate *priv = calibrate_native->priv;
 	guint i;
@@ -172,7 +173,7 @@ gcm_calibrate_native_create_it8_file (GcmCalibrateNative *calibrate_native, GcmS
 	gdouble divisions;
 
 	/* step size */
-	divisions = 1.0f / (gfloat) precision;
+	divisions = 1.0f / (gfloat) (steps - 1);
 
 	result.X = 0.1;
 	result.Y = 0.2;
@@ -187,7 +188,7 @@ gcm_calibrate_native_create_it8_file (GcmCalibrateNative *calibrate_native, GcmS
 	gcm_calibrate_native_sample_add (array, "CBL", &source);
 
 	/* blue ramp */
-	for (i=1; i<precision; i++) {
+	for (i=0; i<steps; i++) {
 		patch_name = g_strdup_printf ("BR%i", i+1);
 		source.B = 1.0f - (divisions * i);
 		gcm_calibrate_native_sample_add (array, patch_name, &source);
@@ -201,7 +202,7 @@ gcm_calibrate_native_create_it8_file (GcmCalibrateNative *calibrate_native, GcmS
 	gcm_calibrate_native_sample_add (array, "CGR", &source);
 
 	/* green ramp */
-	for (i=1; i<precision; i++) {
+	for (i=0; i<steps; i++) {
 		patch_name = g_strdup_printf ("GR%i", i+1);
 		source.G = 1.0f - (divisions * i);
 		gcm_calibrate_native_sample_add (array, patch_name, &source);
@@ -215,7 +216,7 @@ gcm_calibrate_native_create_it8_file (GcmCalibrateNative *calibrate_native, GcmS
 	gcm_calibrate_native_sample_add (array, "CRD", &source);
 
 	/* red ramp */
-	for (i=1; i<precision; i++) {
+	for (i=0; i<steps; i++) {
 		patch_name = g_strdup_printf ("RR%i", i+1);
 		source.R = 1.0f - (divisions * i);
 		gcm_calibrate_native_sample_add (array, patch_name, &source);
@@ -229,7 +230,7 @@ gcm_calibrate_native_create_it8_file (GcmCalibrateNative *calibrate_native, GcmS
 	gcm_calibrate_native_sample_add (array, "DMIN", &source);
 
 	/* grey ramp */
-	for (i=0; i<precision; i++) {
+	for (i=0; i<steps; i++) {
 		patch_name = g_strdup_printf ("GS%i", i+1);
 		source.R = divisions * i;
 		source.G = divisions * i;
@@ -259,71 +260,394 @@ gcm_calibrate_native_create_it8_file (GcmCalibrateNative *calibrate_native, GcmS
 	}
 
 	/* write to disk */
-	gcm_calibrate_native_sample_write (array, "./dave.it8");
+	gcm_calibrate_native_sample_write (array, filename);
 out:
 
 	g_ptr_array_unref (array);
 }
 
-/*
- * _cmsWriteTagTextAscii:
- */
-static cmsBool
-_cmsWriteTagTextAscii (cmsHPROFILE lcms_profile, cmsTagSignature sig, const gchar *text)
+/**
+ * gcm_calibrate_native_get_it8_patch_rgb_xyz:
+ **/
+static void
+gcm_calibrate_native_get_it8_patch_rgb_xyz (cmsHANDLE it8_handle, const gchar *patch, GcmColorRGB *rgb, GcmColorXYZ *xyz)
 {
-	cmsBool ret;
-	cmsMLU *mlu = cmsMLUalloc (0, 1);
-	cmsMLUsetASCII (mlu, "EN", "us", text);
-	ret = cmsWriteTag (lcms_profile, sig, mlu);
-	cmsMLUfree (mlu);
-	return ret;
+	if (rgb != NULL) {
+		rgb->R = cmsIT8GetDataDbl (it8_handle, patch, "RGB_R");
+		rgb->G = cmsIT8GetDataDbl (it8_handle, patch, "RGB_G");
+		rgb->B = cmsIT8GetDataDbl (it8_handle, patch, "RGB_B");
+	}
+	if (xyz != NULL) {
+		xyz->X = cmsIT8GetDataDbl (it8_handle, patch, "XYZ_X");
+		xyz->Y = cmsIT8GetDataDbl (it8_handle, patch, "XYZ_Y");
+		xyz->Z = cmsIT8GetDataDbl (it8_handle, patch, "XYZ_Z");
+	}
 }
 
 /**
- * gcm_calibrate_native_display:
+ * gcm_calibrate_native_get_it8_patch_xyY:
  **/
-static gboolean
-gcm_calibrate_native_display (GcmCalibrate *calibrate, GtkWindow *window, GError **error)
+static void
+gcm_calibrate_native_get_it8_patch_xyY (cmsHANDLE it8_handle, const gchar *patch, cmsCIExyY *result)
 {
-	GcmCalibrateNative *calibrate_native = GCM_CALIBRATE_NATIVE(calibrate);
-	GcmCalibrateNativePrivate *priv = calibrate_native->priv;
-	gboolean ret = TRUE;
-	GcmSensor *sensor;
-	const gchar *title;
-	const gchar *message;
-	const gchar *filename;
+	GcmColorXYZ sample;
+	gcm_calibrate_native_get_it8_patch_rgb_xyz (it8_handle, patch, NULL, &sample);
+	cmsXYZ2xyY (result, (cmsCIEXYZ*) &sample);
+}
 
+/**
+ * gcm_calibrate_native_interpolate_array:
+ *
+ * Linearly interpolate an array of data into a differently sized array.
+ **/
+static void
+gcm_calibrate_native_interpolate_array (gdouble *data, guint data_size, gdouble *new, guint new_size)
 {
-cmsHPROFILE profile;
-cmsViewingConditions PCS;
+	gdouble amount;
+	gdouble div;
+	guint i;
+	guint reg1, reg2;
+
+	/* gcm_calibrate_native_ */
+	for (i=0; i<new_size; i++) {
+		div = i * ((data_size - 1) / (gdouble) (new_size - 1));
+		reg1 = floor (div);
+		reg2 = ceil (div);
+		if (reg1 == reg2) {
+			/* no interpolation reqd */
+			new[i] = data[reg1];
+		} else {
+			amount = div - (gdouble) reg1;
+			new[i] = data[reg1] * (1.0f - amount) + data[reg2] * amount;
+		}
+	}
+}
+
+#if 0
+/**
+ * _gcm_color_normalize_XYZ:
+ *
+ * Return value: the Y value that was normalised
+ **/
+static gdouble
+_gcm_color_normalize_XYZ (GcmColorXYZ *xyz)
+{
+	gdouble Y;
+
+	g_return_val_if_fail (xyz != NULL, 0.0f);
+
+	/* return the value we used the scale */
+	Y = xyz->Y;
+
+	/* scale by luminance */
+	xyz->X /= Y;
+	xyz->Z /= Y;
+	xyz->Y = 1.0;
+	return Y;
+}
+#endif
+
+/**
+ * _gcm_color_scale_XYZ:
+ **/
+static void
+_gcm_color_scale_XYZ (GcmColorXYZ *xyz, gdouble scale)
+{
+	g_return_if_fail (xyz != NULL);
+
+	/* scale by factor */
+	xyz->X /= scale;
+	xyz->Y /= scale;
+	xyz->Z /= scale;
+}
+
+/**
+ * gcm_calibrate_native_create_profile_from_it8:
+ **/
+static gboolean
+gcm_calibrate_native_create_profile_from_it8 (GcmProfile *profile, const gchar *filename, guint vcgt_size, GError **error)
+{
+	gboolean ret = FALSE;
+	guint64 rampsize;
+	cmsHANDLE it8_handle;
+	cmsCIExyYTRIPLE primaries;
+	cmsCIExyY whitepoint;
+	GcmColorXYZ primary_red;
+	GcmColorXYZ primary_green;
+	GcmColorXYZ primary_blue;
+	guint i, j;
+	const gdouble gamma22 = 2.2f;
+	const gchar *patch_data;
+	gchar *patch_name;
+	gdouble div;
+	gdouble temperature;
+	gdouble whitepointY;
+	GcmColorXYZ patch_xyz;
+	GcmColorRGB patch_rgb;
+	GcmColorRGB actual_rgb;
+	GcmColorXYZ actual_xyz;
+	GcmColorRGB scale;
+	GcmColorRGB leakage;
+	cmsHPROFILE conversion_profile = NULL;
+	cmsHPROFILE xyz_profile = NULL;
+	cmsToneCurve *transfer_curve[3];
+	cmsHTRANSFORM conversion_transform = NULL;
+	gdouble *data_sampled[3] = { NULL, NULL, NULL};
+	gdouble *data_interpolated[3] = { NULL, NULL, NULL};
+	guint16 *data_vcgt[3] = { NULL, NULL, NULL};
+
+	/* load it8 file */
+	it8_handle = cmsIT8LoadFromFile(NULL, filename);
+	if (it8_handle == NULL)
+		goto out;
+
+	/* get the whitepoint */
+	gcm_calibrate_native_get_it8_patch_xyY (it8_handle, "DMAX", &whitepoint);
+	cmsTempFromWhitePoint (&temperature, &whitepoint);
+	egg_debug ("native whitepoint=%f,%f [scale:%f] (%fK)", whitepoint.x, whitepoint.y, whitepoint.Y, temperature);
+
+	/* we need to scale each reading by this value */
+	whitepointY = whitepoint.Y;
+//	_gcm_color_normalize_XYZ (&whitepoint);
+
+	/* optionally use a D50 target */
+//	cmsWhitePointFromTemp (&whitepoint, 5000);
+
+	/* normalize white point for CIECAM */
+	whitepoint.Y = 1.0f;
+
+	/* set white point */
+	cmsxyY2XYZ ((cmsCIEXYZ *) &actual_xyz, &whitepoint);
+	ret = gcm_profile_set_whitepoint (profile, &actual_xyz, error);
+	if (!ret)
+		goto out;
 
-/* take it8 file, and open */
-profile = cmsCreateProfilePlaceholder (NULL);
+	/* get the primaries */
+	gcm_calibrate_native_get_it8_patch_xyY (it8_handle, "CRD", &primaries.Red);
+	gcm_calibrate_native_get_it8_patch_xyY (it8_handle, "CGR", &primaries.Green);
+	gcm_calibrate_native_get_it8_patch_xyY (it8_handle, "CBL", &primaries.Blue);
+
+	egg_debug ("red=%f,%f green=%f,%f blue=%f,%f",
+		   primaries.Red.x, primaries.Red.y,
+		   primaries.Green.x, primaries.Green.y,
+		   primaries.Blue.x, primaries.Blue.y);
+
+	/* get the primaries */
+	gcm_calibrate_native_get_it8_patch_rgb_xyz (it8_handle, "CRD", NULL, &primary_red);
+	gcm_calibrate_native_get_it8_patch_rgb_xyz (it8_handle, "CGR", NULL, &primary_green);
+	gcm_calibrate_native_get_it8_patch_rgb_xyz (it8_handle, "CBL", NULL, &primary_blue);
+
+	/* scale the values */
+	_gcm_color_scale_XYZ (&primary_red, whitepointY);
+	_gcm_color_scale_XYZ (&primary_green, whitepointY);
+	_gcm_color_scale_XYZ (&primary_blue, whitepointY);
+
+	/* set the primaries */
+	ret = gcm_profile_set_primaries (profile, &primary_red, &primary_green, &primary_blue, error);
+	if (!ret)
+		goto out;
+
+	/* create our RGB conversion transform */
+	transfer_curve[0] = transfer_curve[1] = transfer_curve[2] = cmsBuildGamma (NULL, gamma22);
+	conversion_profile = cmsCreateRGBProfile (&whitepoint, &primaries, transfer_curve);
+	xyz_profile = cmsCreateXYZProfile ();
+	conversion_transform = cmsCreateTransform (xyz_profile, TYPE_XYZ_DBL,
+						   conversion_profile, TYPE_RGB_DBL,
+						   INTENT_ABSOLUTE_COLORIMETRIC, 0);
+
+	/* get the size of the gray ramp */
+	for (i=0; i<1024; i++) {
+		patch_name = g_strdup_printf ("GS%i", i+1);
+		patch_data = cmsIT8GetData (it8_handle, patch_name, "RGB_R");
+		g_free (patch_name);
+		if (patch_data == NULL)
+			break;
+	}
+	rampsize = i;
+	if (rampsize == 0) {
+		g_set_error_literal (error, 1, 0, "no gray ramp found");
+		goto out;
+	}
+	egg_debug ("rampsize = %li", rampsize);
+
+	/* create arrays for the sampled and processed data */
+	for (j=0; j<3; j++) {
+		data_sampled[j] = g_new0 (gdouble, rampsize);
+		data_interpolated[j] = g_new0 (gdouble, vcgt_size);
+		data_vcgt[j] = g_new0 (guint16, vcgt_size);
+	}
+
+	/* get the gray data */
+	for (i=0; i<rampsize; i++) {
+		patch_name = g_strdup_printf ("GS%i", i+1);
+		gcm_calibrate_native_get_it8_patch_rgb_xyz (it8_handle, patch_name, &patch_rgb, &patch_xyz);
+
+		/* scale the values */
+		_gcm_color_scale_XYZ (&patch_xyz, whitepointY);
+
+		cmsDoTransform (conversion_transform, &patch_xyz, &actual_rgb, 1);
+		egg_debug ("%s = %f,%f,%f -> %f,%f,%f", patch_name,
+			   patch_rgb.R, patch_rgb.G, patch_rgb.B,
+			   actual_rgb.R, actual_rgb.G, actual_rgb.B);
 
-cmsSetEncodedICCversion (profile, 0x2000000);
-cmsSetDeviceClass (profile, cmsSigDisplayClass);
-cmsSetColorSpace (profile, cmsSigRgbData);
-cmsSetPCS (profile, cmsSigLabData);
+		data_sampled[0][i] = actual_rgb.R;
+		data_sampled[1][i] = actual_rgb.G;
+		data_sampled[2][i] = actual_rgb.B;
+		g_free (patch_name);
+	}
+
+	for (i=0; i<rampsize; i++) {
+		egg_debug ("%i, %f,%f,%f", i,
+			   data_sampled[0][i],
+			   data_sampled[1][i],
+			   data_sampled[2][i]);
+	}
+
+	/* reverse the profile, as we want to correct the display, not profile it */
+	div = 1.0f / (gdouble) (rampsize - 1);
+	for (i=0; i<rampsize; i++) {
+		gdouble value = (div*i);
+		for (j=0; j<3; j++)
+			data_sampled[j][i] = value + (value - data_sampled[j][i]);
+	}
+
+	/* remove the backlight leakage */
+	gcm_color_set_RGB (&leakage, G_MAXDOUBLE, G_MAXDOUBLE, G_MAXDOUBLE);
+	for (i=0; i<rampsize; i++) {
+		if (data_sampled[0][i] < leakage.R)
+			leakage.R = data_sampled[0][i];
+		if (data_sampled[1][i] < leakage.G)
+			leakage.G = data_sampled[1][i];
+		if (data_sampled[2][i] < leakage.B)
+			leakage.B = data_sampled[2][i];
+	}
+	for (i=0; i<rampsize; i++) {
+		data_sampled[0][i] -= leakage.R;
+		data_sampled[1][i] -= leakage.G;
+		data_sampled[2][i] -= leakage.B;
+	}
+	egg_debug ("removed backlight leakage = %f,%f,%f", leakage.R, leakage.G, leakage.B);
+
+	/* scale all values to 1.0 */
+	gcm_color_set_RGB (&scale, 0.0, 0.0, 0.0);
+	for (i=0; i<rampsize; i++) {
+		if (data_sampled[0][i] > scale.R)
+			scale.R = data_sampled[0][i];
+		if (data_sampled[1][i] > scale.G)
+			scale.G = data_sampled[1][i];
+		if (data_sampled[1][i] > scale.B)
+			scale.B = data_sampled[2][i];
+	}
+	for (i=0; i<rampsize; i++) {
+		data_sampled[0][i] /= scale.R;
+		data_sampled[1][i] /= scale.G;
+		data_sampled[2][i] /= scale.B;
+	}
+	egg_debug ("scaled to 1.0 using = %f,%f,%f", scale.R, scale.G, scale.B);
 
-_cmsWriteTagTextAscii (profile, cmsSigProfileDescriptionTag, "cmsSigProfileDescriptionTag");
-_cmsWriteTagTextAscii (profile, cmsSigCopyrightTag, "cmsSigCopyrightTag");
-_cmsWriteTagTextAscii (profile, cmsSigDeviceModelDescTag, "cmsSigDeviceModelDescTag");
-_cmsWriteTagTextAscii (profile, cmsSigDeviceMfgDescTag, "cmsSigDeviceMfgDescTag");
+	for (i=0; i<rampsize; i++) {
+		egg_debug ("%i, %f,%f,%f", i,
+			   data_sampled[0][i],
+			   data_sampled[1][i],
+			   data_sampled[2][i]);
+	}
 
-PCS.whitePoint.X = cmsD50_XYZ()->X * 100.;
-PCS.whitePoint.Y = cmsD50_XYZ()->Y * 100.;
-PCS.whitePoint.Z = cmsD50_XYZ()->Z * 100.;
-PCS.Yb = 20;			/* 20% of surround */
-PCS.La = 20;			/* Adapting field luminance */
-PCS.surround = AVG_SURROUND;
-PCS.D_value  = 1.0;		/* Complete adaptation */
+	for (i=0; i<rampsize; i++) {
+		egg_debug ("%i, %f,%f,%f", i,
+			   data_sampled[0][i],
+			   data_sampled[1][i],
+			   data_sampled[2][i]);
+	}
 
+	/* linear interpolate the values */
+	for (j=0; j<3; j++)
+		gcm_calibrate_native_interpolate_array (data_sampled[j], rampsize, data_interpolated[j], vcgt_size);
 
-cmsSaveProfileToFile (profile, "dave.icc");
+	/* convert to uint16 type */
+	for (j=0; j<3; j++) {
+		for (i=0; i<vcgt_size; i++) {
+			data_vcgt[j][i] = data_interpolated[j][i] * 0xffff;
+		}
+	}
+
+	/* set this in the profile */
+	ret = gcm_profile_set_vcgt_from_data (profile, data_vcgt[0], data_vcgt[1], data_vcgt[2], vcgt_size, error);
+	if (!ret)
+		goto out;
+out:
+	cmsFreeToneCurve (*transfer_curve);
+	cmsCloseProfile (xyz_profile);
+	cmsCloseProfile (conversion_profile);
+	if (conversion_transform != NULL)
+		cmsDeleteTransform (conversion_transform);
+	for (j=0; j<3; j++) {
+		g_free (data_vcgt[j]);
+		g_free (data_interpolated[j]);
+		g_free (data_sampled[j]);
+	}
+	if (it8_handle != NULL)
+		cmsIT8Free (it8_handle);
+	return ret;
 
-egg_error ("moo");
 }
 
+/**
+ * gcm_calibrate_native_display:
+ **/
+static gboolean
+gcm_calibrate_native_display (GcmCalibrate *calibrate, GtkWindow *window, GError **error)
+{
+	GcmCalibrateNative *calibrate_native = GCM_CALIBRATE_NATIVE(calibrate);
+	GcmCalibrateNativePrivate *priv = calibrate_native->priv;
+	gboolean ret = TRUE;
+	GcmCalibratePrecision precision;
+	guint steps = 0;
+	GcmSensor *sensor;
+	gchar *copyright = NULL;
+	gchar *description = NULL;
+	gchar *manufacturer = NULL;
+	gchar *model = NULL;
+	const gchar *title;
+	const gchar *message;
+	const gchar *filename;
+	const gchar *basename;
+	gchar *filename_it8 = NULL;
+	gchar *filename_icc = NULL;
+	GcmProfile *profile;
+
+#if 0
+	cmsHPROFILE profile;
+	cmsViewingConditions PCS;
+	cmsViewingConditions device;
+
+	/* take it8 file, and open */
+	profile = cmsCreateProfilePlaceholder (NULL);
+
+	cmsSetEncodedICCversion (profile, 0x2000000);
+	cmsSetDeviceClass (profile, cmsSigDisplayClass);
+	cmsSetColorSpace (profile, cmsSigRgbData);
+	cmsSetPCS (profile, cmsSigLabData);
+
+	PCS.whitePoint.X = cmsD50_XYZ()->X * 100.;
+	PCS.whitePoint.Y = cmsD50_XYZ()->Y * 100.;
+	PCS.whitePoint.Z = cmsD50_XYZ()->Z * 100.;
+	PCS.La = 32;			/* Adapting field luminance */
+	PCS.Yb = 20;			/* 20% of surround */
+	PCS.surround = AVG_SURROUND;
+	PCS.D_value  = 1.0;		/* Complete adaptation */
+
+	device.Yb = 20;			/* sRGB VCs */
+	device.La = 4;
+	device.surround = DIM_SURROUND;
+	device.D_value  = 1.0;		/* Complete adaptation */
+
+	int PCSType = PT_Lab;
+	egg_warning ("%i", PCSType);
+
+	cmsSaveProfileToFile (profile, "dave.icc");
+#endif
+
+	/* TODO: get from GcmCalibrate */
 	sensor = gcm_sensor_huey_new ();
 
 	/* show window */
@@ -357,12 +681,8 @@ egg_error ("moo");
 	/* TRANSLATORS: button text */
 	gcm_calibrate_dialog_set_button_ok_id (priv->calibrate_dialog, _("Continue"));
 
-egg_warning ("moo");
-
-//	gtk_window_present (GTK_WINDOW (priv->calibrate_dialog));
-
-
 	/* wait for response */
+//	gtk_window_present (GTK_WINDOW (priv->calibrate_dialog));
 	g_main_loop_run (priv->loop);
 
 	/* is cancelled */
@@ -384,11 +704,59 @@ egg_warning ("moo");
 	gcm_calibrate_dialog_set_show_button_ok (priv->calibrate_dialog, FALSE);
 	gcm_calibrate_dialog_set_show_expander (priv->calibrate_dialog, FALSE);
 
-	gcm_calibrate_native_create_it8_file (calibrate_native, sensor, 10);
+	/* get filenames */
+	basename = gcm_calibrate_get_basename (calibrate);
+	filename_it8 = g_strdup_printf ("%s.it8", basename);
+	filename_icc = g_strdup_printf ("%s.icc", basename);
+
+	/* get the number of steps to use */
+	g_object_get (calibrate,
+		      "precision", &precision,
+		      NULL);
+	if (precision == GCM_CALIBRATE_PRECISION_SHORT)
+		steps = 10;
+	else if (precision == GCM_CALIBRATE_PRECISION_NORMAL)
+		steps = 20;
+	else if (precision == GCM_CALIBRATE_PRECISION_LONG)
+		steps = 30;
+
+	egg_debug ("creating %s", filename_it8);
+	gcm_calibrate_native_create_it8_file (calibrate_native, sensor, filename_it8, 10);
+
+	/* get profile text data */
+	copyright = gcm_calibrate_get_profile_copyright (calibrate);
+	description = gcm_calibrate_get_profile_description (calibrate);
+	model = gcm_calibrate_get_profile_model (calibrate);
+	manufacturer = gcm_calibrate_get_profile_manufacturer (calibrate);
+
+	/* create basic profile */
+	profile = gcm_profile_new ();
+	gcm_profile_set_colorspace (profile, GCM_COLORSPACE_RGB);
+	gcm_profile_set_kind (profile, GCM_PROFILE_KIND_DISPLAY_DEVICE);
+	gcm_profile_set_description (profile, description);
+	gcm_profile_set_copyright (profile, copyright);
+	gcm_profile_set_model (profile, model);
+	gcm_profile_set_manufacturer (profile, manufacturer);
+
+	/* convert sampled values to profile tables */
+	ret = gcm_calibrate_native_create_profile_from_it8 (profile, filename_it8, 256, error);
+	if (!ret)
+		goto out;
 
-	g_object_unref (sensor);
+	/* save */
+	egg_debug ("saving %s", filename_icc);
+	ret = gcm_profile_save (profile, filename_icc, error);
+	if (!ret)
+		goto out;
 
 out:
+	g_object_unref (sensor);
+	g_free (filename_it8);
+	g_free (filename_icc);
+	g_free (copyright);
+	g_free (description);
+	g_free (manufacturer);
+	g_free (model);
 	return ret;
 }
 
@@ -487,7 +855,7 @@ gcm_calibrate_native_finalize (GObject *object)
 	/* hide */
 	gcm_calibrate_dialog_hide (priv->calibrate_dialog);
 	g_object_unref (priv->calibrate_dialog);
-	g_object_unref (priv->sample_window);
+//	g_object_unref (priv->sample_window);
 	g_object_unref (priv->cancellable);
 	g_main_loop_unref (priv->loop);
 
diff --git a/src/gcm-self-test.c b/src/gcm-self-test.c
index 12204a0..c2b288f 100644
--- a/src/gcm-self-test.c
+++ b/src/gcm-self-test.c
@@ -163,18 +163,77 @@ gcm_test_calibrate_native_func (void)
 	gboolean ret;
 	GError *error = NULL;
 	GcmCalibrate *calibrate;
+	GcmClient *client;
+	GcmX11Screen *screen;
+	GcmDevice *device;
+	gchar *contents;
+	gchar *filename;
 
 	calibrate = gcm_calibrate_native_new ();
 	g_assert (calibrate != NULL);
 
 	g_object_set (calibrate,
-		      "output-name", "LVDS1",
+		      "output-name", "LVDS-1",
+		      NULL);
+
+	/* create a virtual device we can "calibrate" */
+	client = gcm_client_new ();
+	g_assert (client != NULL);
+	g_setenv ("GCM_TEST", "1", TRUE);
+	filename = gcm_utils_get_default_config_location ();
+	contents = g_strdup_printf ("[xrandr_hewlett_packard_hp_lp2480zx_3cm82200kv]\n"
+				    "serial=3CM82200KV\n"
+				    "model=HP LP2480zx\n"
+				    "manufacturer=Hewlett Packard\n"
+				    "title=Hewlett Packard - HP LP2480zx - 24\"\n"
+				    "type=display\n"
+				    "colorspace=rgb");
+	ret = g_file_set_contents (filename, contents, -1, &error);
+	g_assert_no_error (error);
+	g_assert (ret);
+
+	ret = gcm_client_coldplug (client, GCM_CLIENT_COLDPLUG_SAVED, &error);
+	g_assert_no_error (error);
+	g_assert (ret);
+
+	device = gcm_client_get_device_by_id (client, "xrandr_hewlett_packard_hp_lp2480zx_3cm82200kv");
+	g_assert (device != NULL);
+
+	/* set device */
+	g_object_set (device,
+		      "native-device", "LVDS-1",
 		      NULL);
+	ret = gcm_calibrate_set_from_device (calibrate, device, &error);
+	g_assert_no_error (error);
+	g_assert (ret);
 
+	/* use a screen */
+	screen = gcm_x11_screen_new ();
+	ret = gcm_x11_screen_assign (screen, NULL, &error);
+	g_assert_no_error (error);
+	g_assert (ret);
+
+	/* clear any VCGT */
+	ret = gcm_device_xrandr_reset (GCM_DEVICE_XRANDR (device), &error);
+	g_assert_no_error (error);
+	g_assert (ret);
+
+	/* do the calibration */
 	ret = gcm_calibrate_display (calibrate, NULL, &error);
 	g_assert_no_error (error);
 	g_assert (ret);
 
+	/* be good and restore the settings if they changed */
+	ret = g_spawn_command_line_sync (BINDIR "/gcm-apply", NULL, NULL, NULL, &error);
+	g_assert_no_error (error);
+	g_assert (ret);
+
+	g_object_unref (client);
+	g_object_unref (device);
+	g_unlink (filename);
+	g_free (contents);
+	g_free (filename);
+	g_object_unref (screen);
 	g_object_unref (calibrate);
 }
 



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