summaryrefslogtreecommitdiff
path: root/xicc/xmono.c
diff options
context:
space:
mode:
Diffstat (limited to 'xicc/xmono.c')
-rw-r--r--xicc/xmono.c324
1 files changed, 324 insertions, 0 deletions
diff --git a/xicc/xmono.c b/xicc/xmono.c
new file mode 100644
index 0000000..f0ee04f
--- /dev/null
+++ b/xicc/xmono.c
@@ -0,0 +1,324 @@
+/*
+ * International Color Consortium color transform expanded support
+ *
+ * Author: Graeme W. Gill
+ * Date: 2/7/00
+ * Version: 1.00
+ *
+ * Copyright 2000 Graeme W. Gill
+ * All rights reserved.
+ * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
+ * see the License.txt file for licencing details.
+ *
+ * Based on the old iccXfm class.
+ */
+
+/*
+ * This module provides the expands icclib functionality
+ * for monochrome profiles.
+ * This file is #included in xicc.c, to keep its functions private.
+ */
+
+/*
+ * TTBD:
+ * Some of the error handling is crude. Shouldn't use
+ * error(), should return status.
+ *
+ */
+
+/* ============================================================= */
+/* Forward and Backward Monochrome type conversion */
+/* Return 0 on success, 1 if clipping occured, 2 on other error */
+
+/* - - - - - - - - - - - - - - - - - - - - - */
+/* Individual components of Fwd conversion: */
+static int
+icxLuMonoFwd_curve (
+icxLuMono *p, /* This */
+double *out, /* Vector of output values */
+double *in /* Vector of input values */
+) {
+ return ((icmLuMono *)p->plu)->fwd_curve((icmLuMono *)p->plu, out, in);
+}
+
+static int
+icxLuMonoFwd_map (
+icxLuMono *p, /* This */
+double *out, /* Vector of output values */
+double *in /* Vector of input values */
+) {
+ return ((icmLuMono *)p->plu)->fwd_map((icmLuMono *)p->plu, out, in);
+}
+
+static int
+icxLuMonoFwd_abs (
+icxLuMono *p, /* This */
+double *out, /* Vector of output values */
+double *in /* Vector of input values */
+) {
+ int rv = 0;
+ rv |= ((icmLuMono *)p->plu)->fwd_abs((icmLuMono *)p->plu, out, in);
+
+ if (p->pcs == icxSigJabData) {
+ p->cam->XYZ_to_cam(p->cam, out, out);
+ }
+ return rv;
+}
+
+
+/* Overall Fwd conversion routine */
+static int
+icxLuMonoFwd_lookup (
+icxLuBase *pp, /* This */
+double *out, /* Vector of output values */
+double *in /* Vector of input values */
+) {
+ int rv = 0;
+ icxLuMono *p = (icxLuMono *)pp;
+ rv |= icxLuMonoFwd_curve(p, out, in);
+ rv |= icxLuMonoFwd_map(p, out, out);
+ rv |= icxLuMonoFwd_abs(p, out, out);
+ return rv;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Given a relative XYZ or Lab PCS value, convert in the fwd direction into */
+/* the nominated output PCS (ie. Absolute, Jab etc.) */
+/* (This is used in generating gamut compression in B2A tables) */
+void icxLuMono_fwd_relpcs_outpcs(
+icxLuBase *pp,
+icColorSpaceSignature is, /* Input space, XYZ or Lab */
+double *out, double *in) {
+ icxLuMono *p = (icxLuMono *)pp;
+
+ icmLab2XYZ(&icmD50, out, in);
+ if (is == icSigLabData && p->natpcs == icSigXYZData) {
+ icxLuMonoFwd_abs(p, out, out);
+ } else if (is == icSigXYZData && p->natpcs == icSigLabData) {
+ icxLuMonoFwd_abs(p, out, out);
+ }
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - */
+/* Individual components of Bwd conversion: */
+
+static int
+icxLuMonoBwd_abs (
+icxLuMono *p, /* This */
+double *out, /* Vector of output values */
+double *in /* Vector of input values */
+) {
+ int rv = 0;
+
+ if (p->pcs == icxSigJabData) {
+ p->cam->cam_to_XYZ(p->cam, out, in);
+ rv |= ((icmLuMono *)p->plu)->bwd_abs((icmLuMono *)p->plu, out, out);
+ /* Hack to prevent CAM02 weirdness being amplified by */
+ /* any later per channel clipping. */
+ /* Limit -Y to non-stupid values by scaling */
+ if (out[1] < -0.1) {
+ out[0] *= -0.1/out[1];
+ out[2] *= -0.1/out[1];
+ out[1] = -0.1;
+ }
+ } else {
+ rv |= ((icmLuMono *)p->plu)->bwd_abs((icmLuMono *)p->plu, out, in);
+ }
+ return rv;
+}
+
+static int
+icxLuMonoBwd_map (
+icxLuMono *p, /* This */
+double *out, /* Vector of output values */
+double *in /* Vector of input values */
+) {
+ return ((icmLuMono *)p->plu)->bwd_map((icmLuMono *)p->plu, out, in);
+}
+
+static int
+icxLuMonoBwd_curve (
+icxLuMono *p, /* This */
+double *out, /* Vector of output values */
+double *in /* Vector of input values */
+) {
+ return ((icmLuMono *)p->plu)->bwd_curve((icmLuMono *)p->plu, out, in);
+}
+
+/* Overall Bwd conversion routine */
+static int
+icxLuMonoBwd_lookup (
+icxLuBase *pp, /* This */
+double *out, /* Vector of output values */
+double *in /* Vector of input values */
+) {
+ double temp[3];
+ int rv = 0;
+ icxLuMono *p = (icxLuMono *)pp;
+ rv |= icxLuMonoBwd_abs(p, temp, in);
+ rv |= icxLuMonoBwd_map(p, out, temp);
+ rv |= icxLuMonoBwd_curve(p, out, out);
+ return rv;
+}
+
+static void
+icxLuMono_free(
+icxLuBase *p
+) {
+ p->plu->del(p->plu);
+ if (p->cam != NULL)
+ p->cam->del(p->cam);
+ free(p);
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Given a nominated output PCS (ie. Absolute, Jab etc.), convert it in the bwd */
+/* direction into a relative XYZ or Lab PCS value */
+/* (This is used in generating gamut compression in B2A tables) */
+void icxLuMono_bwd_outpcs_relpcs(
+icxLuBase *pp,
+icColorSpaceSignature os, /* Output space, XYZ or Lab */
+double *out, double *in) {
+ icxLuMono *p = (icxLuMono *)pp;
+
+ if (os == icSigXYZData && p->natpcs == icSigLabData) {
+ icxLuMonoFwd_abs(p, out, in);
+ icmLab2XYZ(&icmD50, out, out);
+ } else if (os == icSigXYZData && p->natpcs == icSigLabData) {
+ icxLuMonoFwd_abs(p, out, in);
+ icmXYZ2Lab(&icmD50, out, out);
+ } else {
+ icxLuMonoFwd_abs(p, out, in);
+ }
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+static gamut *icxLuMonoGamut(icxLuBase *plu, double detail);
+
+static icxLuBase *
+new_icxLuMono(
+xicc *xicp,
+int flags, /* clip, merge flags */
+icmLuBase *plu, /* Pointer to Lu we are expanding */
+icmLookupFunc func, /* Functionality requested */
+icRenderingIntent intent, /* Rendering intent */
+icColorSpaceSignature pcsor, /* PCS override (0 = def) */
+icxViewCond *vc, /* Viewing Condition (NULL if pcsor is not CIECAM) */
+int dir /* 0 = fwd, 1 = bwd */
+) {
+ icxLuMono *p;
+
+ /* Do the basic icxLuMono creation and initialisation */
+
+ if ((p = (icxLuMono *) calloc(1,sizeof(icxLuMono))) == NULL)
+ return NULL;
+
+ p->pp = xicp;
+ p->plu = plu;
+ p->del = icxLuMono_free;
+ p->lutspaces = icxLutSpaces;
+ p->spaces = icxLuSpaces;
+ p->get_native_ranges = icxLu_get_native_ranges;
+ p->get_ranges = icxLu_get_ranges;
+ p->efv_wh_bk_points = icxLuEfv_wh_bk_points;
+ p->get_gamut = icxLuMonoGamut;
+ p->fwd_relpcs_outpcs = icxLuMono_fwd_relpcs_outpcs;
+ p->bwd_outpcs_relpcs = icxLuMono_bwd_outpcs_relpcs;
+ p->nearclip = 0; /* Set flag defaults */
+ p->mergeclut = 0;
+ p->noisluts = 0;
+ p->noipluts = 0;
+ p->nooluts = 0;
+ p->intsep = 0;
+
+ p->fwd_lookup = icxLuMonoFwd_lookup;
+ p->fwd_curve = icxLuMonoFwd_curve;
+ p->fwd_map = icxLuMonoFwd_map;
+ p->fwd_abs = icxLuMonoFwd_abs;
+ p->bwd_lookup = icxLuMonoBwd_lookup;
+ p->bwd_abs = icxLuMonoFwd_abs;
+ p->bwd_map = icxLuMonoFwd_map;
+ p->bwd_curve = icxLuMonoFwd_curve;
+ if (dir) {
+ p->lookup = icxLuMonoBwd_lookup;
+ p->inv_lookup = icxLuMonoFwd_lookup;
+ } else {
+ p->lookup = icxLuMonoFwd_lookup;
+ p->inv_lookup = icxLuMonoBwd_lookup;
+ }
+
+ /* There are no mono specific flags */
+ p->flags = flags;
+ p->func = func;
+
+ /* Get details of internal, native color space */
+ plu->lutspaces(p->plu, &p->natis, NULL, &p->natos, NULL, &p->natpcs);
+
+ /* Get other details of conversion */
+ p->plu->spaces(p->plu, NULL, &p->inputChan, NULL, &p->outputChan, NULL, NULL, NULL, NULL, NULL);
+
+ /* Init the CAM model */
+ if (pcsor == icxSigJabData) {
+ p->vc = *vc; /* Copy the structure */
+ p->cam = new_icxcam(cam_default);
+ p->cam->set_view(p->cam, vc->Ev, vc->Wxyz, vc->La, vc->Yb, vc->Lv, vc->Yf, vc->Fxyz,
+ XICC_USE_HK);
+ } else
+ p->cam = NULL;
+
+ /* Remember the effective intent */
+ p->intent = intent;
+
+ /* Get the effective spaces */
+ plu->spaces(plu, &p->ins, NULL, &p->outs, NULL, NULL, NULL, NULL, &p->pcs, NULL);
+
+ /* Override with pcsor */
+ if (pcsor == icxSigJabData) {
+ p->pcs = pcsor;
+ if (func == icmBwd || func == icmGamut || func == icmPreview)
+ p->ins = pcsor;
+ if (func == icmFwd || func == icmPreview)
+ p->outs = pcsor;
+ }
+
+ /* In general the native and effective ranges of the icx will be the same as the */
+ /* underlying icm lookup object. */
+ p->plu->get_lutranges(p->plu, p->ninmin, p->ninmax, p->noutmin, p->noutmax);
+ p->plu->get_ranges(p->plu, p->inmin, p->inmax, p->outmin, p->outmax);
+
+ /* If we have a Jab PCS override, reflect this in the effective icx range. */
+ /* Note that the ab ranges are nominal. They will exceed this range */
+ /* for colors representable in L*a*b* PCS */
+ if (p->ins == icxSigJabData) {
+ p->inmin[0] = 0.0; p->inmax[0] = 100.0;
+ p->inmin[1] = -128.0; p->inmax[1] = 128.0;
+ p->inmin[2] = -128.0; p->inmax[2] = 128.0;
+ } else if (p->outs == icxSigJabData) {
+ p->outmin[0] = 0.0; p->outmax[0] = 100.0;
+ p->outmin[1] = -128.0; p->outmax[1] = 128.0;
+ p->outmin[2] = -128.0; p->outmax[2] = 128.0;
+ }
+
+ return (icxLuBase *)p;
+}
+
+/* ============================================================= */
+
+/* Given an xicc lookup object, returm a gamut object. */
+/* Note that the PCS must be Lab or Jab */
+/* Return NULL on error, check errc+err for reason */
+static gamut *icxLuMonoGamut(
+icxLuBase *plu, /* this */
+double detail /* gamut detail level, 0.0 = def */
+) {
+ gamut *xgam;
+ xicc *p = plu->pp; /* parent xicc */
+
+ p->errc = 1;
+ sprintf(p->err,"Creating Mono gamut surface not supported yet.");
+ plu->del(plu);
+ xgam = NULL;
+
+ return xgam;
+}
+