diff options
-rw-r--r-- | client/cd-create-profile.c | 80 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | lib/colord/Makefile.am | 2 | ||||
-rw-r--r-- | lib/colord/cd-context-lcms.c | 239 | ||||
-rw-r--r-- | lib/colord/cd-context-lcms.h | 45 | ||||
-rw-r--r-- | lib/colord/cd-icc-utils.c | 4 | ||||
-rw-r--r-- | lib/colord/cd-icc.c | 248 | ||||
-rw-r--r-- | lib/colord/cd-icc.h | 1 | ||||
-rw-r--r-- | lib/colord/cd-it8.c | 43 | ||||
-rw-r--r-- | lib/colord/cd-transform.c | 36 |
10 files changed, 459 insertions, 243 deletions
diff --git a/client/cd-create-profile.c b/client/cd-create-profile.c index 3a4235b..60587ce 100644 --- a/client/cd-create-profile.c +++ b/client/cd-create-profile.c @@ -25,33 +25,18 @@ #include <gio/gio.h> #include <locale.h> #include <lcms2.h> -#include <lcms2_plugin.h> #include <stdlib.h> #include <math.h> #include <colord-private.h> +#define LCMS_CURVE_PLUGIN_TYPE_REC709 1024 + typedef struct { GOptionContext *context; cmsHPROFILE lcms_profile; CdIcc *icc; } CdUtilPrivate; -static gint lcms_error_code = 0; - -/** - * cd_fix_profile_error_cb: - **/ -static void -cd_fix_profile_error_cb (cmsContext ContextID, - cmsUInt32Number errorcode, - const char *text) -{ - g_warning ("LCMS error %i: %s", errorcode, text); - - /* copy this sytemwide */ - lcms_error_code = errorcode; -} - static gboolean set_vcgt_from_data (cmsHPROFILE profile, const guint16 *red, @@ -267,7 +252,8 @@ cd_util_create_colprof (CdUtilPrivate *priv, goto out; /* open /tmp/$basename.icc as hProfile */ - priv->lcms_profile = cmsOpenProfileFromMemTHR (priv->icc, data, len); + priv->lcms_profile = cmsOpenProfileFromMemTHR (cd_icc_get_context (priv->icc), + data, len); if (priv->lcms_profile == NULL) { ret = FALSE; g_set_error (error, 1, 0, @@ -317,8 +303,8 @@ cd_util_create_named_color (CdUtilPrivate *priv, const GNode *tmp; gboolean ret = TRUE; - priv->lcms_profile = cmsCreateNULLProfileTHR (priv->icc); - if (priv->lcms_profile == NULL || lcms_error_code != 0) { + priv->lcms_profile = cmsCreateNULLProfileTHR (cd_icc_get_context (priv->icc)); + if (priv->lcms_profile == NULL) { ret = FALSE; g_set_error_literal (error, 1, 0, "failed to create NULL profile"); @@ -408,8 +394,8 @@ cd_util_create_x11_gamma (CdUtilPrivate *priv, points[2] = rgb.B; /* create a bog-standard sRGB profile */ - priv->lcms_profile = cmsCreate_sRGBProfileTHR (priv->icc); - if (priv->lcms_profile == NULL || lcms_error_code != 0) { + priv->lcms_profile = cmsCreate_sRGBProfileTHR (cd_icc_get_context (priv->icc)); + if (priv->lcms_profile == NULL) { ret = FALSE; g_set_error_literal (error, 1, 0, "failed to create profile"); @@ -470,45 +456,6 @@ cd_util_build_lstar_gamma (void) return cmsBuildParametricToneCurve (NULL, 4, params); } -#define LCMS_CURVE_PLUGIN_TYPE_REC709 1024 - -/** - * cd_util_lcms_rec709_trc_cb: - **/ -static double -cd_util_lcms_rec709_trc_cb (int type, const double params[], double x) -{ - gdouble val = 0.f; - - switch (type) { - case -LCMS_CURVE_PLUGIN_TYPE_REC709: - if (x < params[4]) - val = x * params[3]; - else - val = params[1] * pow (x, (1.f / params[0])) + params[2]; - break; - case LCMS_CURVE_PLUGIN_TYPE_REC709: - if (x <= (params[3] * params[4])) - val = x / params[3]; - else - val = pow (((x + params[2]) / params[1]), params[0]); - break; - } - return val; -} - -/* add Rec. 709 TRC curve type */ -cmsPluginParametricCurves cd_util_lcms_rec709_trc = { - { cmsPluginMagicNumber, /* 'acpp' */ - 2000, /* minimum version */ - cmsPluginParametricCurveSig, /* type */ - NULL }, /* no more plugins */ - 1, /* number functions */ - {LCMS_CURVE_PLUGIN_TYPE_REC709}, /* function types */ - {5}, /* parameter count */ - cd_util_lcms_rec709_trc_cb /* evaluator */ -}; - /** * cd_util_build_rec709_gamma: **/ @@ -652,7 +599,7 @@ cd_util_create_standard_space (CdUtilPrivate *priv, primaries.Blue.Y = yxy.Y; /* create profile */ - priv->lcms_profile = cmsCreateRGBProfileTHR (priv->icc, + priv->lcms_profile = cmsCreateRGBProfileTHR (cd_icc_get_context (priv->icc), &white, &primaries, transfer); @@ -681,8 +628,8 @@ cd_util_create_temperature (CdUtilPrivate *priv, guint temp; /* create a bog-standard sRGB profile */ - priv->lcms_profile = cmsCreate_sRGBProfileTHR (priv->icc); - if (priv->lcms_profile == NULL || lcms_error_code != 0) { + priv->lcms_profile = cmsCreate_sRGBProfileTHR (cd_icc_get_context (priv->icc)); + if (priv->lcms_profile == NULL) { ret = FALSE; g_set_error_literal (error, 1, 0, "failed to create profile"); @@ -929,11 +876,6 @@ main (int argc, char **argv) bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); - /* setup LCMS */ - cmsSetLogErrorHandler (cd_fix_profile_error_cb); - ret = cmsPlugin (&cd_util_lcms_rec709_trc); - g_assert (ret); - priv = g_new0 (CdUtilPrivate, 1); priv->icc = cd_icc_new (); priv->context = g_option_context_new (NULL); diff --git a/configure.ac b/configure.ac index 73eb467..296e98c 100644 --- a/configure.ac +++ b/configure.ac @@ -158,6 +158,10 @@ AC_CHECK_LIB(lcms2, cmsMLUtranslationsCount, have_lcms_mlu_translations_count=ye if test x$have_lcms_mlu_translations_count != x; then AC_DEFINE(HAVE_LCMS_MLU_TRANSLATIONS_COUNT,1,[cmsMLUtranslationsCount is available]) fi +AC_CHECK_LIB(lcms2, cmsCreateContext, have_lcms_create_context=yes) +if test x$have_lcms_create_context != x; then + AC_DEFINE(HAVE_LCMS_CREATE_CONTEXT,1,[cmsCreateContext is available]) +fi PKG_CHECK_MODULES(SQLITE, sqlite3) diff --git a/lib/colord/Makefile.am b/lib/colord/Makefile.am index 7ac18b5..33817e7 100644 --- a/lib/colord/Makefile.am +++ b/lib/colord/Makefile.am @@ -56,6 +56,8 @@ libcolordbase_include_HEADERS = \ cd-version.h libcolordprivate_la_SOURCES = \ + cd-context-lcms.c \ + cd-context-lcms.h \ cd-buffer.c \ cd-color.c \ cd-dom.c \ diff --git a/lib/colord/cd-context-lcms.c b/lib/colord/cd-context-lcms.c new file mode 100644 index 0000000..85d5574 --- /dev/null +++ b/lib/colord/cd-context-lcms.c @@ -0,0 +1,239 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2014 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-context-lcms + * @short_description: Functionality to save per-thread context data for LCMS2 + */ + +#include "config.h" + +#include <lcms2.h> +#include <lcms2_plugin.h> + +#include "cd-context-lcms.h" +#include "cd-icc.h" /* for the error codes */ + +/*< private >*/ +#define LCMS_CURVE_PLUGIN_TYPE_REC709 1024 + +/** + * cd_context_lcms_get_error: + **/ +static GError ** +cd_context_lcms_get_error (gpointer ctx) +{ + GError **error_ctx; +#ifdef HAVE_LCMS_CREATE_CONTEXT + error_ctx = cmsGetContextUserData (ctx); +#else + error_ctx = (GError **) ctx; +#endif + return error_ctx; +} + +/** + * cd_context_lcms2_error_cb: + **/ +static void +cd_context_lcms2_error_cb (cmsContext context_id, + cmsUInt32Number code, + const gchar *message) +{ + gint error_code; + GError **error_ctx; + + /* nothing set, must be pre-2.6 */ + if (context_id == NULL) { + g_warning ("Error handler called with no context: %s", message); + return; + } + + /* there's already one error pending */ + error_ctx = cd_context_lcms_get_error (context_id); + if (*error_ctx != NULL) { + g_prefix_error (error_ctx, "%s & ", message); + return; + } + + /* convert the first cmsERROR in into a CdIccError */ + switch (code) { + case cmsERROR_CORRUPTION_DETECTED: + error_code = CD_ICC_ERROR_CORRUPTION_DETECTED; + break; + case cmsERROR_FILE: + case cmsERROR_READ: + case cmsERROR_SEEK: + error_code = CD_ICC_ERROR_FAILED_TO_OPEN; + break; + case cmsERROR_WRITE: + error_code = CD_ICC_ERROR_FAILED_TO_SAVE; + break; + case cmsERROR_COLORSPACE_CHECK: + error_code = CD_ICC_ERROR_INVALID_COLORSPACE; + break; + case cmsERROR_BAD_SIGNATURE: + error_code = CD_ICC_ERROR_FAILED_TO_PARSE; + break; + case cmsERROR_ALREADY_DEFINED: + case cmsERROR_INTERNAL: + case cmsERROR_NOT_SUITABLE: + case cmsERROR_NULL: + case cmsERROR_RANGE: + case cmsERROR_UNDEFINED: + case cmsERROR_UNKNOWN_EXTENSION: + error_code = CD_ICC_ERROR_INTERNAL; + break; + default: + g_warning ("LCMS2 error code not recognised; please report"); + error_code = CD_ICC_ERROR_INTERNAL; + } + error_ctx = cd_context_lcms_get_error (context_id); + g_set_error_literal (error_ctx, CD_ICC_ERROR, error_code, message); +} + +/** + * cd_context_lcms_plugins_cb: + **/ +static double +cd_context_lcms_plugins_cb (int type, const double params[], double x) +{ + gdouble val = 0.f; + + switch (type) { + case -LCMS_CURVE_PLUGIN_TYPE_REC709: + if (x < params[4]) + val = x * params[3]; + else + val = params[1] * pow (x, (1.f / params[0])) + params[2]; + break; + case LCMS_CURVE_PLUGIN_TYPE_REC709: + if (x <= (params[3] * params[4])) + val = x / params[3]; + else + val = pow (((x + params[2]) / params[1]), params[0]); + break; + } + return val; +} + +cmsPluginParametricCurves cd_icc_lcms_plugins = { + { cmsPluginMagicNumber, /* 'acpp' */ + 2000, /* minimum version */ + cmsPluginParametricCurveSig, /* type */ + NULL }, /* no more plugins */ + 1, /* number functions */ + {LCMS_CURVE_PLUGIN_TYPE_REC709}, /* function types */ + {5}, /* parameter count */ + cd_context_lcms_plugins_cb /* evaluator */ +}; + +/** + * cd_context_lcms_new: + * + * Return value: (transfer full): A new LCMS context + **/ +gpointer +cd_context_lcms_new (void) +{ + cmsContext ctx; + GError **error_ctx; + error_ctx = g_new0 (GError *, 1); +#ifdef HAVE_LCMS_CREATE_CONTEXT + ctx = cmsCreateContext (NULL, error_ctx); + cmsSetLogErrorHandlerTHR (ctx, cd_context_lcms2_error_cb); + cmsPluginTHR (ctx, &cd_icc_lcms_plugins); +#else + ctx = (cmsContext) error_ctx; + cmsSetLogErrorHandler (cd_context_lcms2_error_cb); + /* we've disabled this as it's unreliable without a context */ + if(0) cmsPlugin (&cd_icc_lcms_plugins); +#endif + return ctx; +} + +/** + * _cd_context_lcms_pre26_start: + **/ +void +_cd_context_lcms_pre26_start (void) +{ +#ifndef HAVE_LCMS_CREATE_CONTEXT + cmsSetLogErrorHandler (cd_context_lcms2_error_cb); +#endif +} + +/** + * _cd_context_lcms_pre26_stop: + **/ +void +_cd_context_lcms_pre26_stop (void) +{ +#ifndef HAVE_LCMS_CREATE_CONTEXT + cmsSetLogErrorHandler (NULL); +#endif +} + +/** + * cd_context_lcms_free: + **/ +void +cd_context_lcms_free (gpointer ctx) +{ + GError **error_ctx; + +#ifdef HAVE_LCMS_CREATE_CONTEXT + error_ctx = cmsGetContextUserData (ctx); +#else + error_ctx = (GError **) ctx; +#endif + g_clear_error (error_ctx); + +#ifdef HAVE_LCMS_CREATE_CONTEXT + cmsUnregisterPluginsTHR (ctx); + cmsDeleteContext (ctx); +#endif +} + +/** + * cd_context_lcms_error_clear: + **/ +void +cd_context_lcms_error_clear (gpointer ctx) +{ + g_clear_error (cd_context_lcms_get_error (ctx)); +} + +/** + * cd_context_lcms_error_check: + **/ +gboolean +cd_context_lcms_error_check (gpointer ctx, GError **error) +{ + GError **error_ctx; + error_ctx = cd_context_lcms_get_error (ctx); + if (*error_ctx == NULL) + return TRUE; + g_propagate_error (error, *error_ctx); + *error_ctx = NULL; + return FALSE; +} diff --git a/lib/colord/cd-context-lcms.h b/lib/colord/cd-context-lcms.h new file mode 100644 index 0000000..0d03634 --- /dev/null +++ b/lib/colord/cd-context-lcms.h @@ -0,0 +1,45 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2014 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 (CD_COMPILATION) +#error "You cannot include this file externaly" +#endif + +#ifndef __CD_CONTEXT_PRIVATE_H +#define __CD_CONTEXT_PRIVATE_H + +#include <glib.h> + +gpointer cd_context_lcms_new (void); +void cd_context_lcms_free (gpointer ctx); +void cd_context_lcms_error_clear (gpointer ctx); +gboolean cd_context_lcms_error_check (gpointer ctx, + GError **error); + +/* not part of the API */ +void _cd_context_lcms_pre26_start (void); +void _cd_context_lcms_pre26_stop (void); + +G_END_DECLS + +#endif /* __CD_CONTEXT_PRIVATE_H */ + diff --git a/lib/colord/cd-icc-utils.c b/lib/colord/cd-icc-utils.c index b2d58df..8472a27 100644 --- a/lib/colord/cd-icc-utils.c +++ b/lib/colord/cd-icc-utils.c @@ -75,8 +75,8 @@ cd_icc_utils_get_coverage_calc (CdIcc *icc, guint i; /* create a proofing transform with gamut check */ - profile_null = cmsCreateNULLProfileTHR (icc); - transform = cmsCreateProofingTransformTHR (icc, + profile_null = cmsCreateNULLProfileTHR (cd_icc_get_context (icc)); + transform = cmsCreateProofingTransformTHR (cd_icc_get_context (icc), cd_icc_get_handle (icc), TYPE_RGB_FLT, profile_null, diff --git a/lib/colord/cd-icc.c b/lib/colord/cd-icc.c index f9ade3c..fcb697a 100644 --- a/lib/colord/cd-icc.c +++ b/lib/colord/cd-icc.c @@ -33,6 +33,7 @@ #include <stdlib.h> #include <math.h> +#include "cd-context-lcms.h" #include "cd-icc.h" static void cd_icc_class_init (CdIccClass *klass); @@ -63,6 +64,7 @@ struct _CdIccPrivate { CdColorspace colorspace; CdProfileKind kind; + cmsContext context_lcms; cmsHPROFILE lcms_profile; gboolean can_delete; gchar *checksum; @@ -78,7 +80,6 @@ struct _CdIccPrivate CdColorXYZ red; CdColorXYZ green; CdColorXYZ blue; - GError *error_lcms; }; G_DEFINE_TYPE (CdIcc, cd_icc, G_TYPE_OBJECT) @@ -160,60 +161,6 @@ cd_icc_uint32_to_str (guint32 id, gchar *str) } /** - * cd_icc_lcms2_error_cb: - **/ -static void -cd_icc_lcms2_error_cb (cmsContext context_id, - cmsUInt32Number code, - const gchar *message) -{ - CdIcc *icc = CD_ICC (context_id); - CdIccPrivate *priv = icc->priv; - gint error_code; - - /* there's already one error pending */ - if (priv->error_lcms != NULL) { - g_prefix_error (&priv->error_lcms, - "%s & ", message); - return; - } - - /* convert the first cmsERROR in into a CdIccError */ - switch (code) { - case cmsERROR_CORRUPTION_DETECTED: - error_code = CD_ICC_ERROR_CORRUPTION_DETECTED; - break; - case cmsERROR_FILE: - case cmsERROR_READ: - case cmsERROR_SEEK: - error_code = CD_ICC_ERROR_FAILED_TO_OPEN; - break; - case cmsERROR_WRITE: - error_code = CD_ICC_ERROR_FAILED_TO_SAVE; - break; - case cmsERROR_COLORSPACE_CHECK: - error_code = CD_ICC_ERROR_INVALID_COLORSPACE; - break; - case cmsERROR_BAD_SIGNATURE: - error_code = CD_ICC_ERROR_FAILED_TO_PARSE; - break; - case cmsERROR_ALREADY_DEFINED: - case cmsERROR_INTERNAL: - case cmsERROR_NOT_SUITABLE: - case cmsERROR_NULL: - case cmsERROR_RANGE: - case cmsERROR_UNDEFINED: - case cmsERROR_UNKNOWN_EXTENSION: - error_code = CD_ICC_ERROR_INTERNAL; - break; - default: - g_warning ("LCMS2 erorr code not recognised; please report"); - error_code = CD_ICC_ERROR_INTERNAL; - } - g_set_error_literal (&priv->error_lcms, CD_ICC_ERROR, error_code, message); -} - -/** * cd_icc_read_tag: **/ static gpointer @@ -221,10 +168,11 @@ cd_icc_read_tag (CdIcc *icc, cmsTagSignature sig, GError **error) { CdIccPrivate *priv = icc->priv; gchar sig_string[5]; + gboolean ret; gpointer tmp; /* ensure context error is not present to aid debugging */ - g_clear_error (&priv->error_lcms); + cd_context_lcms_error_clear (priv->context_lcms); /* read raw value */ tmp = cmsReadTag (priv->lcms_profile, sig); @@ -232,11 +180,9 @@ cd_icc_read_tag (CdIcc *icc, cmsTagSignature sig, GError **error) goto out; /* any context error? */ - if (priv->error_lcms != NULL) { - g_propagate_error (error, priv->error_lcms); - priv->error_lcms = NULL; + ret = cd_context_lcms_error_check (priv->context_lcms, error); + if (!ret) goto out; - } /* missing value */ cd_icc_uint32_to_str (GINT32_FROM_BE (sig), sig_string); @@ -259,7 +205,7 @@ cd_icc_write_tag (CdIcc *icc, cmsTagSignature sig, gpointer data, GError **error gchar sig_string[5]; /* ensure context error is not present to aid debugging */ - g_clear_error (&priv->error_lcms); + cd_context_lcms_error_clear (priv->context_lcms); /* read raw value */ ret = cmsWriteTag (priv->lcms_profile, sig, data); @@ -274,11 +220,9 @@ cd_icc_write_tag (CdIcc *icc, cmsTagSignature sig, gpointer data, GError **error } /* any context error? */ - if (priv->error_lcms != NULL) { - g_propagate_error (error, priv->error_lcms); - priv->error_lcms = NULL; + ret = cd_context_lcms_error_check (priv->context_lcms, error); + if (!ret) goto out; - } /* missing value */ cd_icc_uint32_to_str (GINT32_FROM_BE (sig), sig_string); @@ -323,7 +267,7 @@ cd_icc_to_string (CdIcc *icc) g_return_val_if_fail (CD_IS_ICC (icc), NULL); /* setup error handler */ - cmsSetLogErrorHandler (cd_icc_lcms2_error_cb); + _cd_context_lcms_pre26_start (); /* print header */ str = g_string_new ("icc:\nHeader:\n"); @@ -768,7 +712,7 @@ cd_icc_to_string (CdIcc *icc) if (str->len > 0) g_string_truncate (str, str->len - 1); - cmsSetLogErrorHandler (NULL); + _cd_context_lcms_pre26_stop (); return g_string_free (str, FALSE); } @@ -857,8 +801,8 @@ cd_icc_calc_whitepoint (CdIcc *icc, GError **error) /* do Lab to RGB transform to get primaries */ profiles[0] = priv->lcms_profile; - profiles[1] = cmsCreateXYZProfileTHR (icc); - transform = cmsCreateExtendedTransform (icc, + profiles[1] = cmsCreateXYZProfileTHR (priv->context_lcms); + transform = cmsCreateExtendedTransform (priv->context_lcms, 2, profiles, bpc, @@ -976,8 +920,8 @@ cd_icc_load_primaries (CdIcc *icc, GError **error) } /* get the illuminants by running it through the profile */ - xyz_profile = cmsCreateXYZProfileTHR (icc); - transform = cmsCreateTransformTHR (icc, + xyz_profile = cmsCreateXYZProfileTHR (priv->context_lcms); + transform = cmsCreateTransformTHR (priv->context_lcms, priv->lcms_profile, TYPE_RGB_DBL, xyz_profile, TYPE_XYZ_DBL, INTENT_PERCEPTUAL, 0); @@ -1116,8 +1060,7 @@ cd_icc_load (CdIcc *icc, CdIccLoadFlags flags, GError **error) gboolean ret = TRUE; guint i; - /* setup error handler */ - cmsSetLogErrorHandler (cd_icc_lcms2_error_cb); + _cd_context_lcms_pre26_start (); /* get version */ priv->version = cmsGetProfileVersion (priv->lcms_profile); @@ -1181,7 +1124,7 @@ cd_icc_load (CdIcc *icc, CdIccLoadFlags flags, GError **error) goto out; } out: - cmsSetLogErrorHandler (NULL); + _cd_context_lcms_pre26_stop (); return ret; } @@ -1222,7 +1165,8 @@ cd_icc_load_data (CdIcc *icc, } /* load icc into lcms */ - priv->lcms_profile = cmsOpenProfileFromMemTHR (icc, data, data_len); + priv->lcms_profile = cmsOpenProfileFromMemTHR (priv->context_lcms, + data, data_len); if (priv->lcms_profile == NULL) { ret = FALSE; g_set_error_literal (error, @@ -1388,7 +1332,7 @@ cd_util_write_tag_ascii (CdIcc *icc, } /* set value */ - mlu = cmsMLUalloc (icc, 1); + mlu = cmsMLUalloc (icc->priv->context_lcms, 1); ret = cmsMLUsetASCII (mlu, "en", "US", value); if (!ret) { g_set_error_literal (error, @@ -1482,7 +1426,7 @@ cd_util_write_tag_localized (CdIcc *icc, g_ptr_array_sort (array, cd_util_sort_mlu_array_cb); /* create MLU object to hold all the translations */ - mlu = cmsMLUalloc (icc, array->len); + mlu = cmsMLUalloc (icc->priv->context_lcms, array->len); for (i = 0; i < array->len; i++) { obj = g_ptr_array_index (array, i); if (obj->language_code == NULL && @@ -1562,7 +1506,11 @@ cd_icc_check_error_cb (cmsContext context_id, cmsUInt32Number code, const char *message) { +#ifdef HAVE_LCMS_CREATE_CONTEXT + gboolean *ret = (gboolean *) cmsGetContextUserData (context_id); +#else gboolean *ret = (gboolean *) context_id; +#endif *ret = FALSE; } @@ -1584,12 +1532,19 @@ cd_icc_check_lcms2_MemoryWrite (void) cmsUInt32Number size; gboolean ret = TRUE; gchar *data; + cmsContext ctx; - /* setup temporary log handler */ + /* create context */ +#ifdef HAVE_LCMS_CREATE_CONTEXT + ctx = cmsCreateContext (NULL, &ret); + cmsSetLogErrorHandlerTHR (ctx, cd_icc_check_error_cb); +#else cmsSetLogErrorHandler (cd_icc_check_error_cb); + ctx = (void *) &ret; +#endif /* create test data */ - p = cmsCreate_sRGBProfileTHR (&ret); + p = cmsCreate_sRGBProfileTHR (ctx); dict = cmsDictAlloc (NULL); cmsDictAddEntry (dict, L"1", L"2", NULL, NULL); cmsWriteTag (p, cmsSigMetaTag, dict); @@ -1600,12 +1555,16 @@ cd_icc_check_lcms2_MemoryWrite (void) cmsDictFree (dict); /* open file */ - p = cmsOpenProfileFromMemTHR (&ret, data, size); + p = cmsOpenProfileFromMemTHR (ctx, data, size); dict = cmsReadTag (p, cmsSigMetaTag); g_assert (dict != (gpointer) 0x01); /* appease GCC */ cmsCloseProfile (p); g_free (data); - cmsSetLogErrorHandler (NULL); +#ifdef HAVE_LCMS_CREATE_CONTEXT + cmsDeleteContext (ctx); +#else + _cd_context_lcms_pre26_stop (); +#endif return ret; } @@ -1747,8 +1706,7 @@ cd_icc_save_data (CdIcc *icc, g_return_val_if_fail (CD_IS_ICC (icc), FALSE); - /* setup error handler */ - cmsSetLogErrorHandler (cd_icc_lcms2_error_cb); + _cd_context_lcms_pre26_start (); /* convert profile kind */ for (i = 0; map_profile_kind[i].colord != CD_PROFILE_KIND_LAST; i++) { @@ -1774,7 +1732,7 @@ cd_icc_save_data (CdIcc *icc, /* save metadata */ if (g_hash_table_size (priv->metadata) != 0) { - dict = cmsDictAlloc (icc); + dict = cmsDictAlloc (priv->context_lcms); md_keys = g_hash_table_get_keys (priv->metadata); if (md_keys != NULL) { for (l = md_keys; l != NULL; l = l->next) { @@ -1896,7 +1854,7 @@ cd_icc_save_data (CdIcc *icc, data = cd_icc_serialize_profile_fallback (icc, error); } out: - cmsSetLogErrorHandler (NULL); + _cd_context_lcms_pre26_stop (); g_list_free (md_keys); if (dict != NULL) cmsDictFree (dict); @@ -2176,7 +2134,7 @@ cd_icc_load_fd (CdIcc *icc, } /* parse the ICC file */ - priv->lcms_profile = cmsOpenProfileFromStreamTHR (icc, stream, "r"); + priv->lcms_profile = cmsOpenProfileFromStreamTHR (priv->context_lcms, stream, "r"); if (priv->lcms_profile == NULL) { ret = FALSE; g_set_error_literal (error, @@ -2211,6 +2169,24 @@ cd_icc_get_handle (CdIcc *icc) } /** + * cd_icc_get_context: + * @icc: a #CdIcc instance. + * + * Return the cmsContext instance used locally. This may be required if you + * are using native LCMS calls and then cd_icc_load_handle(). + * + * Return value: (transfer none): Do not call cmsDeleteContext() on this value! + * + * Since: 1.1.7 + **/ +gpointer +cd_icc_get_context (CdIcc *icc) +{ + g_return_val_if_fail (CD_IS_ICC (icc), NULL); + return icc->priv->context_lcms; +} + +/** * cd_icc_load_handle: * @icc: a #CdIcc instance. * @handle: a cmsHPROFILE instance @@ -2226,8 +2202,8 @@ cd_icc_get_handle (CdIcc *icc) * by this module. * * To handle the internal error callback, you should use the thread-safe - * creation function, e.g. cmsCreateNULLProfileTHR(). The context_id should be - * set as the value as the @icc parameter. + * creation function, e.g. cmsCreateNULLProfileTHR(). The @context_id should be + * set as the value of cd_icc_get_context() for this object. * * Additionally, this function cannot be called more than once, and also can't * be called if cd_icc_load_file() has previously been used on the @icc object. @@ -2250,13 +2226,13 @@ cd_icc_load_handle (CdIcc *icc, /* check the THR version has been correctly set up */ context = cmsGetProfileContextID (handle); - if (!CD_IS_ICC (context)) { + if (context == NULL) { ret = FALSE; g_set_error_literal (error, CD_ICC_ERROR, CD_ICC_ERROR_FAILED_TO_CREATE, "lcms2 threadsafe version (THR) not used, " - "or CdIcc not set"); + "or context not set"); goto out; } @@ -2698,8 +2674,7 @@ cd_icc_get_mluc_data (CdIcc *icc, g_return_val_if_fail (CD_IS_ICC (icc), NULL); - /* setup error handler */ - cmsSetLogErrorHandler (cd_icc_lcms2_error_cb); + _cd_context_lcms_pre26_start (); /* does cache entry exist already? */ locale_key = cd_icc_get_locale_key (locale); @@ -2786,7 +2761,7 @@ cd_icc_get_mluc_data (CdIcc *icc, tmp); value = tmp; out: - cmsSetLogErrorHandler (NULL); + _cd_context_lcms_pre26_stop (); g_free (locale_key); g_free (text_buffer); g_free (wtext); @@ -3207,8 +3182,7 @@ cd_icc_create_default (CdIcc *icc, GError **error) CdIccPrivate *priv = icc->priv; gboolean ret = TRUE; - /* setup error handler */ - cmsSetLogErrorHandler (cd_icc_lcms2_error_cb); + _cd_context_lcms_pre26_start (); /* not loaded */ if (priv->lcms_profile != NULL) { @@ -3221,7 +3195,7 @@ cd_icc_create_default (CdIcc *icc, GError **error) } /* create our generated ICC */ - priv->lcms_profile = cmsCreate_sRGBProfileTHR (icc); + priv->lcms_profile = cmsCreate_sRGBProfileTHR (priv->context_lcms); if (priv->lcms_profile == NULL) { ret = FALSE; g_set_error (error, @@ -3239,7 +3213,7 @@ cd_icc_create_default (CdIcc *icc, GError **error) CD_PROFILE_METADATA_STANDARD_SPACE, cd_standard_space_to_string (CD_STANDARD_SPACE_SRGB)); out: - cmsSetLogErrorHandler (NULL); + _cd_context_lcms_pre26_stop (); return ret; } @@ -3338,8 +3312,7 @@ cd_icc_create_from_edid (CdIcc *icc, cmsToneCurve *transfer_curve[3] = { NULL, NULL, NULL }; gboolean ret = FALSE; - /* setup error handler */ - cmsSetLogErrorHandler (cd_icc_lcms2_error_cb); + _cd_context_lcms_pre26_start (); /* not loaded */ if (priv->lcms_profile != NULL) { @@ -3368,7 +3341,7 @@ cd_icc_create_from_edid (CdIcc *icc, transfer_curve[2] = transfer_curve[0]; /* create our generated ICC */ - priv->lcms_profile = cmsCreateRGBProfileTHR (icc, + priv->lcms_profile = cmsCreateRGBProfileTHR (priv->context_lcms, &white_point, &chroma, transfer_curve); @@ -3398,7 +3371,7 @@ cd_icc_create_from_edid (CdIcc *icc, /* success */ ret = TRUE; out: - cmsSetLogErrorHandler (NULL); + _cd_context_lcms_pre26_stop (); if (transfer_curve[0] != NULL) cmsFreeToneCurve (transfer_curve[0]); return ret; @@ -3428,8 +3401,7 @@ cd_icc_get_vcgt (CdIcc *icc, guint size, GError **error) g_return_val_if_fail (CD_IS_ICC (icc), NULL); g_return_val_if_fail (icc->priv->lcms_profile != NULL, NULL); - /* setup error handler */ - cmsSetLogErrorHandler (cd_icc_lcms2_error_cb); + _cd_context_lcms_pre26_start (); /* get tone curves from icc */ vcgt = cmsReadTag (icc->priv->lcms_profile, cmsSigVcgtType); @@ -3453,7 +3425,7 @@ cd_icc_get_vcgt (CdIcc *icc, guint size, GError **error) g_ptr_array_add (array, tmp); } out: - cmsSetLogErrorHandler (NULL); + _cd_context_lcms_pre26_stop (); return array; } @@ -3472,6 +3444,7 @@ out: GPtrArray * cd_icc_get_response (CdIcc *icc, guint size, GError **error) { + CdIccPrivate *priv = icc->priv; CdColorRGB *data; CdColorspace colorspace; cmsHPROFILE srgb_profile = NULL; @@ -3485,8 +3458,7 @@ cd_icc_get_response (CdIcc *icc, guint size, GError **error) GPtrArray *array = NULL; guint i; - /* setup error handler */ - cmsSetLogErrorHandler (cd_icc_lcms2_error_cb); + _cd_context_lcms_pre26_start (); /* run through the icc */ colorspace = cd_icc_get_colorspace (icc); @@ -3522,8 +3494,8 @@ cd_icc_get_response (CdIcc *icc, guint size, GError **error) /* create a transform from icc to sRGB */ values_out = g_new0 (gdouble, size * 3 * component_width); - srgb_profile = cmsCreate_sRGBProfileTHR (icc); - transform = cmsCreateTransformTHR (icc, + srgb_profile = cmsCreate_sRGBProfileTHR (priv->context_lcms); + transform = cmsCreateTransformTHR (priv->context_lcms, icc->priv->lcms_profile, TYPE_RGB_DBL, srgb_profile, TYPE_RGB_DBL, INTENT_PERCEPTUAL, 0); @@ -3555,7 +3527,7 @@ cd_icc_get_response (CdIcc *icc, guint size, GError **error) g_ptr_array_add (array, data); } out: - cmsSetLogErrorHandler (NULL); + _cd_context_lcms_pre26_stop (); g_free (values_in); g_free (values_out); if (transform != NULL) @@ -3591,8 +3563,7 @@ cd_icc_set_vcgt (CdIcc *icc, GPtrArray *vcgt, GError **error) g_return_val_if_fail (CD_IS_ICC (icc), FALSE); g_return_val_if_fail (icc->priv->lcms_profile != NULL, FALSE); - /* setup error handler */ - cmsSetLogErrorHandler (cd_icc_lcms2_error_cb); + _cd_context_lcms_pre26_start (); /* unwrap data */ red = g_new0 (guint16, vcgt->len); @@ -3624,7 +3595,7 @@ cd_icc_set_vcgt (CdIcc *icc, GPtrArray *vcgt, GError **error) goto out; } out: - cmsSetLogErrorHandler (NULL); + _cd_context_lcms_pre26_stop (); for (i = 0; i < 3; i++) cmsFreeToneCurve (curve[i]); g_free (red); @@ -3659,6 +3630,7 @@ out: static CdProfileWarning cd_icc_check_vcgt (CdIcc *icc) { + CdIccPrivate *priv = icc->priv; CdProfileWarning warning = CD_PROFILE_WARNING_NONE; cmsFloat32Number in; cmsFloat32Number now[3]; @@ -3668,7 +3640,7 @@ cd_icc_check_vcgt (CdIcc *icc) guint i; /* does profile have monotonic VCGT */ - vcgt = cmsReadTag (icc->priv->lcms_profile, cmsSigVcgtTag); + vcgt = cmsReadTag (priv->lcms_profile, cmsSigVcgtTag); if (vcgt == NULL) goto out; for (i = 0; i < size; i++) { @@ -3700,6 +3672,7 @@ out: static CdProfileWarning cd_profile_check_scum_dot (CdIcc *icc) { + CdIccPrivate *priv = icc->priv; CdProfileWarning warning = CD_PROFILE_WARNING_NONE; cmsCIELab white; cmsHPROFILE profile_lab; @@ -3707,10 +3680,10 @@ cd_profile_check_scum_dot (CdIcc *icc) guint8 rgb[3] = { 0, 0, 0 }; /* do Lab to RGB transform of 100,0,0 */ - profile_lab = cmsCreateLab2ProfileTHR (icc, cmsD50_xyY ()); - transform = cmsCreateTransformTHR (icc, + profile_lab = cmsCreateLab2ProfileTHR (priv->context_lcms, cmsD50_xyY ()); + transform = cmsCreateTransformTHR (priv->context_lcms, profile_lab, TYPE_Lab_DBL, - icc->priv->lcms_profile, TYPE_RGB_8, + priv->lcms_profile, TYPE_RGB_8, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE); if (transform == NULL) { @@ -3739,6 +3712,7 @@ out: static CdProfileWarning cd_icc_check_primaries (CdIcc *icc) { + CdIccPrivate *priv = icc->priv; CdProfileWarning warning = CD_PROFILE_WARNING_NONE; cmsCIEXYZ *tmp; @@ -3757,7 +3731,7 @@ cd_icc_check_primaries (CdIcc *icc) */ /* check red */ - tmp = cmsReadTag (icc->priv->lcms_profile, cmsSigRedColorantTag); + tmp = cmsReadTag (priv->lcms_profile, cmsSigRedColorantTag); if (tmp == NULL) goto out; if (tmp->X > 0.85f || tmp->Y < 0.15f || tmp->Z < -0.01) { @@ -3766,7 +3740,7 @@ cd_icc_check_primaries (CdIcc *icc) } /* check green */ - tmp = cmsReadTag (icc->priv->lcms_profile, cmsSigGreenColorantTag); + tmp = cmsReadTag (priv->lcms_profile, cmsSigGreenColorantTag); if (tmp == NULL) goto out; if (tmp->X < 0.10f || tmp->Y > 0.85f || tmp->Z < -0.01f) { @@ -3775,7 +3749,7 @@ cd_icc_check_primaries (CdIcc *icc) } /* check blue */ - tmp = cmsReadTag (icc->priv->lcms_profile, cmsSigBlueColorantTag); + tmp = cmsReadTag (priv->lcms_profile, cmsSigBlueColorantTag); if (tmp == NULL) goto out; if (tmp->X < 0.10f || tmp->Y < 0.01f || tmp->Z > 0.87f) { @@ -3792,6 +3766,7 @@ out: static CdProfileWarning cd_icc_check_gray_axis (CdIcc *icc) { + CdIccPrivate *priv = icc->priv; CdProfileWarning warning = CD_PROFILE_WARNING_NONE; cmsCIELab gray[16]; cmsHPROFILE profile_lab = NULL; @@ -3803,13 +3778,13 @@ cd_icc_check_gray_axis (CdIcc *icc) guint i; /* only do this for display profiles */ - if (cmsGetDeviceClass (icc->priv->lcms_profile) != cmsSigDisplayClass) + if (cmsGetDeviceClass (priv->lcms_profile) != cmsSigDisplayClass) goto out; /* do Lab to RGB transform of 100,0,0 */ - profile_lab = cmsCreateLab2ProfileTHR (icc, cmsD50_xyY ()); - transform = cmsCreateTransformTHR (icc, - icc->priv->lcms_profile, TYPE_RGB_8, + profile_lab = cmsCreateLab2ProfileTHR (priv->context_lcms, cmsD50_xyY ()); + transform = cmsCreateTransformTHR (priv->context_lcms, + priv->lcms_profile, TYPE_RGB_8, profile_lab, TYPE_Lab_DBL, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE); @@ -3858,6 +3833,7 @@ out: static CdProfileWarning cd_icc_check_d50_whitepoint (CdIcc *icc) { + CdIccPrivate *priv = icc->priv; CdProfileWarning warning = CD_PROFILE_WARNING_NONE; cmsCIExyY tmp; cmsCIEXYZ additive; @@ -3872,9 +3848,9 @@ cd_icc_check_d50_whitepoint (CdIcc *icc) guint i; /* do Lab to RGB transform to get primaries */ - profile_lab = cmsCreateXYZProfileTHR (icc); - transform = cmsCreateTransformTHR (icc, - icc->priv->lcms_profile, TYPE_RGB_8, + profile_lab = cmsCreateXYZProfileTHR (priv->context_lcms); + transform = cmsCreateTransformTHR (priv->context_lcms, + priv->lcms_profile, TYPE_RGB_8, profile_lab, TYPE_XYZ_DBL, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE); @@ -3920,7 +3896,7 @@ cd_icc_check_d50_whitepoint (CdIcc *icc) } /* only do the rest for display profiles */ - if (cmsGetDeviceClass (icc->priv->lcms_profile) != cmsSigDisplayClass) + if (cmsGetDeviceClass (priv->lcms_profile) != cmsSigDisplayClass) goto out; /* check white is D50 */ @@ -3968,28 +3944,28 @@ out: GArray * cd_icc_get_warnings (CdIcc *icc) { + CdIccPrivate *priv = icc->priv; GArray *flags; gboolean ret; gchar ascii_name[1024]; CdProfileWarning warning; g_return_val_if_fail (CD_IS_ICC (icc), NULL); - g_return_val_if_fail (icc->priv->lcms_profile != NULL, NULL); + g_return_val_if_fail (priv->lcms_profile != NULL, NULL); - /* setup error handler */ - cmsSetLogErrorHandler (cd_icc_lcms2_error_cb); + _cd_context_lcms_pre26_start (); flags = g_array_new (FALSE, FALSE, sizeof (CdProfileWarning)); /* check that the profile has a description and a copyright */ - ret = cmsGetProfileInfoASCII (icc->priv->lcms_profile, + ret = cmsGetProfileInfoASCII (priv->lcms_profile, cmsInfoDescription, "en", "US", ascii_name, 1024); if (!ret || ascii_name[0] == '\0') { warning = CD_PROFILE_WARNING_DESCRIPTION_MISSING; g_array_append_val (flags, warning); } - ret = cmsGetProfileInfoASCII (icc->priv->lcms_profile, + ret = cmsGetProfileInfoASCII (priv->lcms_profile, cmsInfoCopyright, "en", "US", ascii_name, 1024); if (!ret || ascii_name[0] == '\0') { @@ -3998,7 +3974,7 @@ cd_icc_get_warnings (CdIcc *icc) } /* not a RGB space */ - if (cmsGetColorSpace (icc->priv->lcms_profile) != cmsSigRgbData) + if (cmsGetColorSpace (priv->lcms_profile) != cmsSigRgbData) goto out; /* does profile have an unlikely whitepoint */ @@ -4032,7 +4008,7 @@ cd_icc_get_warnings (CdIcc *icc) if (warning != CD_PROFILE_WARNING_NONE) g_array_append_val (flags, warning); out: - cmsSetLogErrorHandler (NULL); + _cd_context_lcms_pre26_stop (); return flags; } @@ -4232,6 +4208,7 @@ cd_icc_init (CdIcc *icc) guint i; icc->priv = CD_ICC_GET_PRIVATE (icc); + icc->priv->context_lcms = cd_context_lcms_new (); icc->priv->kind = CD_PROFILE_KIND_UNKNOWN; icc->priv->colorspace = CD_COLORSPACE_UNKNOWN; icc->priv->named_colors = g_ptr_array_new_with_free_func ((GDestroyNotify) cd_color_swatch_free); @@ -4270,8 +4247,7 @@ cd_icc_finalize (GObject *object) g_hash_table_destroy (priv->mluc_data[i]); if (priv->lcms_profile != NULL) cmsCloseProfile (priv->lcms_profile); - if (priv->error_lcms != NULL) - g_error_free (priv->error_lcms); + cd_context_lcms_free (priv->context_lcms); G_OBJECT_CLASS (cd_icc_parent_class)->finalize (object); } diff --git a/lib/colord/cd-icc.h b/lib/colord/cd-icc.h index d74d3a2..599a933 100644 --- a/lib/colord/cd-icc.h +++ b/lib/colord/cd-icc.h @@ -182,6 +182,7 @@ gboolean cd_icc_save_default (CdIcc *icc, gchar *cd_icc_to_string (CdIcc *icc) G_GNUC_WARN_UNUSED_RESULT; gpointer cd_icc_get_handle (CdIcc *icc); +gpointer cd_icc_get_context (CdIcc *icc); guint32 cd_icc_get_size (CdIcc *icc); const gchar *cd_icc_get_filename (CdIcc *icc); void cd_icc_set_filename (CdIcc *icc, diff --git a/lib/colord/cd-it8.c b/lib/colord/cd-it8.c index 66dcd81..b1b74df 100644 --- a/lib/colord/cd-it8.c +++ b/lib/colord/cd-it8.c @@ -35,6 +35,7 @@ #include "cd-it8.h" #include "cd-color.h" +#include "cd-context-lcms.h" static void cd_it8_class_init (CdIt8Class *klass); static void cd_it8_init (CdIt8 *it8); @@ -50,6 +51,7 @@ static void cd_it8_finalize (GObject *object); struct _CdIt8Private { CdIt8Kind kind; + cmsContext context_lcms; CdMat3x3 matrix; gboolean normalized; gboolean spectral; @@ -217,17 +219,6 @@ cd_it8_get_kind (CdIt8 *it8) } /** - * cd_it8_lcms2_error_cb: - **/ -static void -cd_it8_lcms2_error_cb (cmsContext context_id, - cmsUInt32Number code, - const gchar *text) -{ - g_warning ("lcms2(it8): Failed with error: %s [%i]", text, code); -} - -/** * cd_it8_parse_luminance: **/ static gboolean @@ -571,6 +562,7 @@ cd_it8_load_from_data (CdIt8 *it8, gsize size, GError **error) { + GError *error_local = NULL; cmsHANDLE it8_lcms = NULL; const gchar *tmp; gboolean ret = TRUE; @@ -581,8 +573,7 @@ cd_it8_load_from_data (CdIt8 *it8, g_return_val_if_fail (data != NULL, FALSE); g_return_val_if_fail (size > 0, FALSE); - /* setup error handler */ - cmsSetLogErrorHandler (cd_it8_lcms2_error_cb); + _cd_context_lcms_pre26_start (); /* clear old data */ g_ptr_array_set_size (it8->priv->array_rgb, 0); @@ -591,11 +582,22 @@ cd_it8_load_from_data (CdIt8 *it8, cd_mat33_clear (&it8->priv->matrix); /* load the it8 data */ - it8_lcms = cmsIT8LoadFromMem (NULL, (void *) data, size); + it8_lcms = cmsIT8LoadFromMem (it8->priv->context_lcms, (void *) data, size); if (it8_lcms == NULL) { + ret = cd_context_lcms_error_check (it8->priv->context_lcms, &error_local); + if (!ret) { + g_set_error_literal (error, + CD_IT8_ERROR, + CD_IT8_ERROR_FAILED, + error_local->message); + g_error_free (error_local); + goto out; + } ret = FALSE; - g_set_error_literal (error, 1, 0, - "Cannot open CCMX file"); + g_set_error_literal (error, + CD_IT8_ERROR, + CD_IT8_ERROR_FAILED, + "Failed to load but no error set"); goto out; } @@ -643,6 +645,7 @@ cd_it8_load_from_data (CdIt8 *it8, cd_it8_set_originator (it8, cmsIT8GetProperty (it8_lcms, "ORIGINATOR")); cd_it8_set_reference (it8, cmsIT8GetProperty (it8_lcms, "REFERENCE")); out: + _cd_context_lcms_pre26_stop (); if (it8_lcms != NULL) cmsIT8Free (it8_lcms); return ret; @@ -933,11 +936,10 @@ cd_it8_save_to_data (CdIt8 *it8, g_return_val_if_fail (CD_IS_IT8 (it8), FALSE); - /* setup error handler */ - cmsSetLogErrorHandler (cd_it8_lcms2_error_cb); + _cd_context_lcms_pre26_start (); /* set common data */ - it8_lcms = cmsIT8Alloc (NULL); + it8_lcms = cmsIT8Alloc (it8->priv->context_lcms); if (it8->priv->title != NULL) { cmsIT8SetPropertyStr (it8_lcms, "DISPLAY", it8->priv->title); @@ -996,6 +998,7 @@ cd_it8_save_to_data (CdIt8 *it8, if (size != NULL) *size = size_tmp - 1; out: + _cd_context_lcms_pre26_stop (); if (it8_lcms != NULL) cmsIT8Free (it8_lcms); if (datetime != NULL) @@ -1451,6 +1454,7 @@ static void cd_it8_init (CdIt8 *it8) { it8->priv = CD_IT8_GET_PRIVATE (it8); + it8->priv->context_lcms = cd_context_lcms_new (); cd_mat33_clear (&it8->priv->matrix); it8->priv->array_rgb = g_ptr_array_new_with_free_func ((GDestroyNotify) cd_color_rgb_free); @@ -1472,6 +1476,7 @@ cd_it8_finalize (GObject *object) g_return_if_fail (CD_IS_IT8 (object)); + cd_context_lcms_free (it8->priv->context_lcms); g_ptr_array_unref (it8->priv->array_rgb); g_ptr_array_unref (it8->priv->array_xyz); g_ptr_array_unref (it8->priv->options); diff --git a/lib/colord/cd-transform.c b/lib/colord/cd-transform.c index 01b9b7a..07fa8fc 100644 --- a/lib/colord/cd-transform.c +++ b/lib/colord/cd-transform.c @@ -35,6 +35,7 @@ #include <glib.h> #include <lcms2.h> +#include "cd-context-lcms.h" #include "cd-transform.h" static void cd_transform_class_init (CdTransformClass *klass); @@ -56,6 +57,7 @@ struct _CdTransformPrivate CdPixelFormat input_pixel_format; CdPixelFormat output_pixel_format; CdRenderingIntent rendering_intent; + cmsContext context_lcms; cmsHPROFILE srgb; cmsHTRANSFORM lcms_transform; gboolean bpc; @@ -416,6 +418,7 @@ static gboolean cd_transform_setup (CdTransform *transform, GError **error) { CdTransformPrivate *priv = transform->priv; + GError *error_local = NULL; cmsHPROFILE profile_in; cmsHPROFILE profile_out; cmsUInt32Number lcms_flags = 0; @@ -473,7 +476,7 @@ cd_transform_setup (CdTransform *transform, GError **error) profiles[0] = profile_in; profiles[1] = cd_icc_get_handle (priv->abstract_icc); profiles[2] = profile_out; - priv->lcms_transform = cmsCreateMultiprofileTransformTHR (transform, + priv->lcms_transform = cmsCreateMultiprofileTransformTHR (priv->context_lcms, profiles, 3, priv->input_pixel_format, @@ -483,7 +486,7 @@ cd_transform_setup (CdTransform *transform, GError **error) } else { /* create basic transform */ - priv->lcms_transform = cmsCreateTransformTHR (transform, + priv->lcms_transform = cmsCreateTransformTHR (priv->context_lcms, profile_in, priv->input_pixel_format, profile_out, @@ -494,6 +497,15 @@ cd_transform_setup (CdTransform *transform, GError **error) /* failed? */ if (priv->lcms_transform == NULL) { + ret = cd_context_lcms_error_check (priv->context_lcms, &error_local); + if (!ret) { + g_set_error_literal (error, + CD_TRANSFORM_ERROR, + CD_TRANSFORM_ERROR_FAILED_TO_SETUP_TRANSFORM, + error_local->message); + g_error_free (error_local); + goto out; + } ret = FALSE; g_set_error_literal (error, CD_TRANSFORM_ERROR, @@ -570,17 +582,6 @@ out: } /** - * cd_transform_lcms2_error_cb: - **/ -static void -cd_transform_lcms2_error_cb (cmsContext context_id, - cmsUInt32Number code, - const gchar *text) -{ - g_warning ("lcms2(transform): Failed with error: %s [%i]", text, code); -} - -/** * cd_transform_process: * @transform: a #CdTransform instance. * @data_in: the data buffer to convert @@ -625,8 +626,7 @@ cd_transform_process (CdTransform *transform, g_return_val_if_fail (height != 0, FALSE); g_return_val_if_fail (rowstride != 0, FALSE); - /* setup error handler */ - cmsSetLogErrorHandler (cd_transform_lcms2_error_cb); + _cd_context_lcms_pre26_start (); /* check stuff that should have been set */ if (priv->rendering_intent == CD_RENDERING_INTENT_UNKNOWN) { @@ -707,7 +707,7 @@ cd_transform_process (CdTransform *transform, p_out += rowstride * rows_to_process; } out: - cmsSetLogErrorHandler (NULL); + _cd_context_lcms_pre26_stop (); if (pool != NULL) g_thread_pool_free (pool, FALSE, TRUE); return ret; @@ -864,10 +864,11 @@ static void cd_transform_init (CdTransform *transform) { transform->priv = CD_TRANSFORM_GET_PRIVATE (transform); + transform->priv->context_lcms = cd_context_lcms_new (); transform->priv->rendering_intent = CD_RENDERING_INTENT_UNKNOWN; transform->priv->input_pixel_format = CD_PIXEL_FORMAT_UNKNOWN; transform->priv->output_pixel_format = CD_PIXEL_FORMAT_UNKNOWN; - transform->priv->srgb = cmsCreate_sRGBProfileTHR (transform); + transform->priv->srgb = cmsCreate_sRGBProfileTHR (transform->priv->context_lcms); transform->priv->max_threads = 1; } @@ -889,6 +890,7 @@ cd_transform_finalize (GObject *object) g_object_unref (priv->abstract_icc); if (priv->lcms_transform != NULL) cmsDeleteTransform (priv->lcms_transform); + cd_context_lcms_free (priv->context_lcms); G_OBJECT_CLASS (cd_transform_parent_class)->finalize (object); } |