diff options
author | Richard Hughes <richard@hughsie.com> | 2013-08-01 15:48:48 +0100 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2013-08-01 15:51:58 +0100 |
commit | a1fc8cb8ff29bb57c6b987fcffe5963c6b7e80e0 (patch) | |
tree | dbfaec68fd586e07b7211bbafe1ffb699e1eb5b1 | |
parent | 5c222de9bdf00eb31793868f9e45ddeb61ca659e (diff) | |
download | colord-a1fc8cb8ff29bb57c6b987fcffe5963c6b7e80e0.tar.gz |
libcolord: Export cd_icc_utils_get_coverage() for comparing two profiles
-rw-r--r-- | doc/api/colord-docs.xml | 1 | ||||
-rw-r--r-- | lib/colord/Makefile.am | 2 | ||||
-rw-r--r-- | lib/colord/cd-icc-utils.c | 144 | ||||
-rw-r--r-- | lib/colord/cd-icc-utils.h | 43 | ||||
-rw-r--r-- | lib/colord/cd-test-private.c | 35 | ||||
-rw-r--r-- | lib/colord/colord-private.h | 1 | ||||
-rw-r--r-- | lib/colord/colord.h | 1 |
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> |