summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2013-08-01 15:48:48 +0100
committerRichard Hughes <richard@hughsie.com>2013-08-01 15:51:58 +0100
commita1fc8cb8ff29bb57c6b987fcffe5963c6b7e80e0 (patch)
treedbfaec68fd586e07b7211bbafe1ffb699e1eb5b1
parent5c222de9bdf00eb31793868f9e45ddeb61ca659e (diff)
downloadcolord-a1fc8cb8ff29bb57c6b987fcffe5963c6b7e80e0.tar.gz
libcolord: Export cd_icc_utils_get_coverage() for comparing two profiles
-rw-r--r--doc/api/colord-docs.xml1
-rw-r--r--lib/colord/Makefile.am2
-rw-r--r--lib/colord/cd-icc-utils.c144
-rw-r--r--lib/colord/cd-icc-utils.h43
-rw-r--r--lib/colord/cd-test-private.c35
-rw-r--r--lib/colord/colord-private.h1
-rw-r--r--lib/colord/colord.h1
7 files changed, 227 insertions, 0 deletions
diff --git a/doc/api/colord-docs.xml b/doc/api/colord-docs.xml
index 9ecf2d4..80a1cdb 100644
--- a/doc/api/colord-docs.xml
+++ b/doc/api/colord-docs.xml
@@ -82,6 +82,7 @@
<xi:include href="xml/cd-dom.xml"/>
<xi:include href="xml/cd-icc.xml"/>
<xi:include href="xml/cd-icc-store.xml"/>
+ <xi:include href="xml/cd-icc-utils.xml"/>
<xi:include href="xml/cd-transform.xml"/>
<xi:include href="xml/cd-interp-akima.xml"/>
<xi:include href="xml/cd-interp-linear.xml"/>
diff --git a/lib/colord/Makefile.am b/lib/colord/Makefile.am
index bceaac1..88ad01f 100644
--- a/lib/colord/Makefile.am
+++ b/lib/colord/Makefile.am
@@ -38,6 +38,7 @@ libcolordbase_include_HEADERS = \
cd-enum.h \
cd-icc.h \
cd-icc-store.h \
+ cd-icc-utils.h \
cd-interp-akima.h \
cd-interp-linear.h \
cd-interp.h \
@@ -59,6 +60,7 @@ libcolordprivate_la_SOURCES = \
cd-enum.c \
cd-icc.c \
cd-icc-store.c \
+ cd-icc-utils.c \
cd-interp-akima.c \
cd-interp-linear.c \
cd-interp.c \
diff --git a/lib/colord/cd-icc-utils.c b/lib/colord/cd-icc-utils.c
new file mode 100644
index 0000000..7108143
--- /dev/null
+++ b/lib/colord/cd-icc-utils.c
@@ -0,0 +1,144 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU Lesser General Public License Version 2.1
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:cd-icc-utils
+ * @short_description: Utilities for working with CdIcc objects
+ *
+ * Functions to do unusual things with profiles.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <lcms2.h>
+
+#include "cd-icc-utils.h"
+
+typedef struct {
+ guint idx;
+ cmsFloat32Number *data;
+} CdIccUtilsGamutCheckHelper;
+
+/**
+ * cd_icc_utils_get_coverage_sample_cb:
+ **/
+static cmsInt32Number
+cd_icc_utils_get_coverage_sample_cb (const cmsFloat32Number in[],
+ cmsFloat32Number out[],
+ void *user_data)
+{
+ CdIccUtilsGamutCheckHelper *helper = (CdIccUtilsGamutCheckHelper *) user_data;
+ helper->data[helper->idx++] = in[0];
+ helper->data[helper->idx++] = in[1];
+ helper->data[helper->idx++] = in[2];
+ return 1;
+}
+
+/**
+ * cd_icc_utils_get_coverage:
+ * @icc: The profile to test
+ * @icc_reference: The reference profile, e.g. sRGB
+ * @coverage: The coverage of @icc on @icc_reference
+ * @error: A #GError, or %NULL
+ *
+ * Gets the gamut coverage of two profiles.
+ *
+ * Return value: TRUE for success
+ **/
+gboolean
+cd_icc_utils_get_coverage (CdIcc *icc,
+ CdIcc *icc_reference,
+ gdouble *coverage,
+ GError **error)
+{
+ const guint cube_size = 33;
+ cmsFloat32Number *data = NULL;
+ cmsHPROFILE profile_null = NULL;
+ cmsHTRANSFORM transform = NULL;
+ cmsUInt16Number *alarm_codes = NULL;
+ cmsUInt32Number dimensions[] = { cube_size, cube_size, cube_size };
+ CdIccUtilsGamutCheckHelper helper;
+ gboolean ret = TRUE;
+ guint cnt = 0;
+ guint data_len = cube_size * cube_size * cube_size;
+ guint i;
+
+ /* create a proofing transform with gamut check */
+ profile_null = cmsCreateNULLProfile ();
+ transform = cmsCreateProofingTransform (cd_icc_get_handle (icc),
+ TYPE_RGB_FLT,
+ profile_null,
+ TYPE_GRAY_FLT,
+ cd_icc_get_handle (icc_reference),
+ INTENT_ABSOLUTE_COLORIMETRIC,
+ INTENT_ABSOLUTE_COLORIMETRIC,
+ cmsFLAGS_GAMUTCHECK |
+ cmsFLAGS_SOFTPROOFING);
+ if (transform == NULL) {
+ ret = FALSE;
+ g_set_error (error,
+ CD_ICC_ERROR,
+ CD_ICC_ERROR_INVALID_COLORSPACE,
+ "Failed to setup transform for %s->%s",
+ cd_icc_get_filename (icc),
+ cd_icc_get_filename (icc_reference));
+ goto out;
+ }
+
+ /* set gamut alarm to 0xffff */
+ alarm_codes = g_new0 (cmsUInt16Number, cmsMAXCHANNELS);
+ alarm_codes[0] = 0xffff;
+ cmsSetAlarmCodes (alarm_codes);
+
+ /* slice profile in regular intevals */
+ data = g_new0 (cmsFloat32Number, data_len * 3);
+ helper.data = data;
+ helper.idx = 0;
+ ret = cmsSliceSpaceFloat (3, dimensions,
+ cd_icc_utils_get_coverage_sample_cb,
+ &helper);
+ if (!ret) {
+ g_set_error_literal (error,
+ CD_ICC_ERROR,
+ CD_ICC_ERROR_INTERNAL,
+ "Failed to slice data");
+ goto out;
+ }
+
+ /* transform each one of those nodes across the proofing transform */
+ cmsDoTransform (transform, helper.data, helper.data, data_len);
+
+ /* count the nodes that gives you zero and divide by total number */
+ for (i = 0; i < data_len; i++) {
+ if (helper.data[i] == 0.0)
+ cnt++;
+ }
+
+ /* success */
+ if (coverage != NULL)
+ *coverage = (gdouble) cnt / (gdouble) data_len;
+out:
+ g_free (data);
+ if (transform != NULL)
+ cmsDeleteTransform (transform);
+ return ret;
+}
diff --git a/lib/colord/cd-icc-utils.h b/lib/colord/cd-icc-utils.h
new file mode 100644
index 0000000..e46c0a6
--- /dev/null
+++ b/lib/colord/cd-icc-utils.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU Lesser General Public License Version 2.1
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if !defined (__COLORD_H_INSIDE__) && !defined (CD_COMPILATION)
+#error "Only <colord.h> can be included directly."
+#endif
+
+#ifndef __CD_ICC_UTILS_H__
+#define __CD_ICC_UTILS_H__
+
+#include <glib-object.h>
+
+#include "cd-icc.h"
+
+G_BEGIN_DECLS
+
+gboolean cd_icc_utils_get_coverage (CdIcc *icc,
+ CdIcc *icc_reference,
+ gdouble *coverage,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __CD_ICC_UTILS_H__ */
+
diff --git a/lib/colord/cd-test-private.c b/lib/colord/cd-test-private.c
index b43a5d9..b4770e7 100644
--- a/lib/colord/cd-test-private.c
+++ b/lib/colord/cd-test-private.c
@@ -31,6 +31,7 @@
#include "cd-dom.h"
#include "cd-icc.h"
#include "cd-icc-store.h"
+#include "cd-icc-utils.h"
#include "cd-interp-akima.h"
#include "cd-interp.h"
#include "cd-interp-linear.h"
@@ -1419,6 +1420,39 @@ colord_icc_store_func (void)
g_object_unref (store);
}
+static void
+colord_icc_util_func (void)
+{
+ CdIcc *icc_measured;
+ CdIcc *icc_reference;
+ gboolean ret;
+ gdouble coverage = 0;
+ GError *error = NULL;
+
+ icc_reference = cd_icc_new ();
+ ret = cd_icc_create_default (icc_reference, &error);
+ g_assert_no_error (error);
+ g_assert (ret);
+
+ icc_measured = cd_icc_new ();
+ ret = cd_icc_create_default (icc_measured, &error);
+ g_assert_no_error (error);
+ g_assert (ret);
+
+ /* get coverage of one vs. the other */
+ ret = cd_icc_utils_get_coverage (icc_reference,
+ icc_measured,
+ &coverage,
+ &error);
+ g_assert_no_error (error);
+ g_assert (ret);
+ g_assert_cmpfloat (coverage, >, 0.99);
+ g_assert_cmpfloat (coverage, <, 1.01);
+
+ g_object_unref (icc_reference);
+ g_object_unref (icc_measured);
+}
+
int
main (int argc, char **argv)
{
@@ -1430,6 +1464,7 @@ main (int argc, char **argv)
/* tests go here */
g_test_add_func ("/colord/transform", colord_transform_func);
g_test_add_func ("/colord/icc", colord_icc_func);
+ g_test_add_func ("/colord/icc{util}", colord_icc_util_func);
g_test_add_func ("/colord/icc{localized}", colord_icc_localized_func);
g_test_add_func ("/colord/icc{edid}", colord_icc_edid_func);
g_test_add_func ("/colord/icc{characterization}", colord_icc_characterization_func);
diff --git a/lib/colord/colord-private.h b/lib/colord/colord-private.h
index f06cc10..0ef27f6 100644
--- a/lib/colord/colord-private.h
+++ b/lib/colord/colord-private.h
@@ -40,6 +40,7 @@
#include <colord/cd-enum.h>
#include <colord/cd-icc.h>
#include <colord/cd-icc-store.h>
+#include <colord/cd-icc-utils.h>
#include <colord/cd-interp-akima.h>
#include <colord/cd-interp-linear.h>
#include <colord/cd-interp.h>
diff --git a/lib/colord/colord.h b/lib/colord/colord.h
index e7eff6a..88e18ca 100644
--- a/lib/colord/colord.h
+++ b/lib/colord/colord.h
@@ -44,6 +44,7 @@
#include <colord/cd-enum.h>
#include <colord/cd-icc.h>
#include <colord/cd-icc-store.h>
+#include <colord/cd-icc-utils.h>
#include <colord/cd-interp-akima.h>
#include <colord/cd-interp-linear.h>
#include <colord/cd-interp.h>