/** * cd_util_get_profile_coverage: **/ static gdouble cd_util_get_profile_coverage (CdUtilPrivate *priv, CdStandardSpace standard_space, GError **error) { gchar *filename = NULL; gdouble coverage = -1.0f; cmsHPROFILE profile; /* get the correct standard space */ filename = cd_util_get_standard_space_filename (priv, standard_space, error); if (filename == NULL) goto out; /* work out the coverage */ profile = cd_icc_get_handle (priv->icc); coverage = cd_util_get_coverage (profile, filename, error); if (coverage < 0.0f) goto out; out: g_free (filename); return coverage; }
/** * cd_util_extract_vcgt: **/ static gboolean cd_util_extract_vcgt (CdUtilPrivate *priv, gchar **values, GError **error) { cmsFloat32Number in; cmsHPROFILE lcms_profile; const cmsToneCurve **vcgt; guint i; guint size; /* check arguments */ if (g_strv_length (values) != 2) { g_set_error_literal (error, 1, 0, "invalid input, expect 'filename' size'"); return FALSE; } /* invalid size */ size = atoi (values[1]); if (size <= 1 || size > 1024) { g_set_error_literal (error, 1, 0, "invalid size,expected 2-1024"); return FALSE; } /* does profile have VCGT */ lcms_profile = cd_icc_get_handle (priv->icc); vcgt = cmsReadTag (lcms_profile, cmsSigVcgtTag); if (vcgt == NULL || vcgt[0] == NULL) { g_set_error_literal (error, 1, 0, "profile does not have any VCGT data"); return FALSE; } /* output data */ g_print ("idx,red,green,blue\n"); for (i = 0; i < size; i++) { in = (gdouble) i / (gdouble) (size - 1); g_print ("%u,", i); g_print ("%f,", cmsEvalToneCurveFloat(vcgt[0], in)); g_print ("%f,", cmsEvalToneCurveFloat(vcgt[1], in)); g_print ("%f\n", cmsEvalToneCurveFloat(vcgt[2], in)); } /* success */ priv->rewrite_file = FALSE; return TRUE; }
/** * cd_icc_utils_get_coverage_calc: **/ static gboolean cd_icc_utils_get_coverage_calc (CdIcc *icc, CdIcc *icc_reference, gdouble *coverage, GError **error) { const guint cube_size = 33; cmsHPROFILE profile_null = NULL; cmsHTRANSFORM transform = 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; g_autofree cmsFloat32Number *data = NULL; g_autofree cmsUInt16Number *alarm_codes = NULL; /* create a proofing transform with gamut check */ 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, 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: cmsCloseProfile (profile_null); if (transform != NULL) cmsDeleteTransform (transform); return ret; }