1 #ifndef XICC_H
2 #define XICC_H
3 /*
4  * International Color Consortium color transform expanded support
5  *
6  * Author:  Graeme W. Gill
7  * Date:    28/6/00
8  * Version: 1.00
9  *
10  * Copyright 2000, 2011 Graeme W. Gill
11  * All rights reserved.
12  * This material is licenced under the GNU AFFERO GENERAL PUB LICENSE Version 3 :-
13  * see the License.txt file for licencing details.
14  *
15  * Based on the old iccXfm class.
16  */
17 
18 /*
19  * This library expands the icclib functionality,
20  * particularly in creating and exercising color transforms.
21  *
22  * For the moment, this support is concentrated around the
23  * Lut and Matrix subsets of the ICC profile tranforms.
24  *
25  * It is intended to allow color transformation, storage and retrieval
26  * of ICC profiles, while permitting inititialization from scattered
27  * data, reversing of the transform, and specific manipulations of
28  * the internal processing elements.
29  *
30  * This class bases much of it's functionality on that of the
31  * underlying icclib icmLuBase.
32  */
33 
34 #include "icc.h"		/* icclib ICC definitions */
35 #include "cgats.h"		/* CGAT format */
36 #include "rspl.h"		/* rspllib thin plate spline definitions */
37 #include "gamut.h"		/* gamut definitions */
38 #include "xutils.h"		/* Utility functions */
39 #include "xcam.h"		/* CAM definitions */
40 #include "xspect.h"		/* Spectral conversion object */
41 #include "xcolorants.h"	/* Known colorants support */
42 #include "insttypes.h"	/* Instrument type support */
43 #include "mpp.h"		/* model printer profile support */
44 #include "moncurve.h"	/* monotonic curve support */
45 						/* (more at the end) */
46 
47 #define XICC_USE_HK 1	/* [Set] Set to 1 to use Helmholtz-Kohlraush in all CAM conversions */
48 #define XICC_NEUTRAL_CMYK_BLACK		/* Use neutral axis black, else use K direction black. */
49 #define XICC_BLACK_POINT_TOLL 0.5			/* Tollerance of CMYK black point location */
50 #define XICC_BLACK_FIND_ABERR_WEIGHT 10.0	/* Weight of ab error against min L in BP */
51 
52 /* ------------------------------------------------------------------------------ */
53 
54 /* The "effective" PCS colorspace is the one specified by the PCS override, and */
55 /* visible in the overal profile conversion. The "native" PCS colorspace is the one */
56 /* that the underlying tags actually represent, and the PCS that the individual */
57 /* stages within each profile type handle (unless the ICX_MERGED flag is set, in which */
58 /* case the clut == native PCS appears to be the effective one). The conversion between */
59 /* the native and effective PCS is generally done in the to/from_abs() conversions. */
60 
61 /* ------------------------------------------------------------------------------ */
62 
63 /* Pseudo intents, valid as parameter to xicc get_luobj(): */
64 
65 /* Default Color Appearance Space, based on absolute colorimetric */
66 #define icxAppearance ((icRenderingIntent)994)
67 
68 /* Represents icAbsoluteColorimetric, converted to Color Appearance space */
69 #define icxAbsAppearance ((icRenderingIntent)995)	/* Fixed D50 white point */
70 
71 /* Special Color Appearance Space, based on "absolute" perceptual */
72 #define icxPerceptualAppearance ((icRenderingIntent)996)
73 
74 /* Default Color Appearance Space, based on "absolute" saturation */
75 #define icxSaturationAppearance ((icRenderingIntent)997)
76 
77 /* These two are for completeness, they are unlikely to be useful: */
78 /* Special Color Appearance Space, based on "absolute" perceptual */
79 #define icxAbsPerceptualAppearance ((icRenderingIntent)998)
80 
81 /* Default Color Appearance Space, based on "absolute" saturation */
82 #define icxAbsSaturationAppearance ((icRenderingIntent)999)
83 
84 
85 /* Pseudo PCS colospace returned as PCS for intent icxAppearanceJab */
86 #define icxSigJabData ((icColorSpaceSignature) icmMakeTag('J','a','b',' '))
87 
88 /* Pseudo PCS colospace returned as PCS for intent icxAppearanceJCh */
89 #define icxSigJChData ((icColorSpaceSignature) icmMakeTag('J','C','h',' '))
90 
91 /* Pseudo PCS colospace returned as PCS */
92 #define icxSigLChData ((icColorSpaceSignature) icmMakeTag('L','C','h',' '))
93 
94 /* Return a string description of the given enumeration value */
95 const char *icx2str(icmEnumType etype, int enumval);
96 
97 
98 /* ------------------------------------------------------------------------------ */
99 
100 /* A 3x3 matrix model */
101 struct _icxMatrixModel {
102 	void *imp;		/* Opaque implementation */
103 
104 	icc *picc;		/* ICC profile used to set cone space matrix, NULL for Bradford. */
105 	int isLab;		/* Convert lookup to Lab */
106 
107 	void (*force) (struct _icxMatrixModel *p, double *targ, double *in);
108 	void (*lookup) (struct _icxMatrixModel *p, double *out, double *in);
109 	void (*del) (struct _icxMatrixModel *p);
110 
111 }; typedef struct _icxMatrixModel icxMatrixModel;
112 
113 /* Create a matrix model of a set of points, and return an object to lookup */
114 /* points from the model. Return NULL on error. */
115 icxMatrixModel *new_MatrixModel(
116 icc *picc,			/* ICC profile used to set cone space matrix, NULL for Bradford. */
117 int verb,			/* NZ if verbose */
118 int nodp,			/* Number of points */
119 cow *ipoints,		/* Array of input points in XYZ space */
120 int isLab,			/* nz if data points are Lab */
121 int quality,		/* Quality metric, 0..3 (-1 == 2 orders only) */
122 int isLinear,		/* NZ if pure linear, gamma = 1.0 */
123 int isGamma,		/* NZ if gamma rather than shaper */
124 int isShTRC,		/* NZ if shared TRCs */
125 int shape0gam,		/* NZ if zero'th order shaper should be gamma function */
126 int clipbw,			/* Prevent white > 1 and -ve black */
127 int clipprims,		/* Prevent primaries going -ve */
128 double smooth,		/* Smoothing factor (nominal 1.0) */
129 double scale		/* Amount to scale device values */
130 );
131 
132 /* ------------------------------------------------------------------------------ */
133 /* Basic class keeps extra state for an icc, and provides the */
134 /* expanded set of methods. */
135 
136 /* Black generation rule */
137 /* The rule is all in terms of device K and L* values */
138 typedef enum {
139     icxKvalue    = 0,	/* K is specified as output K target by PCS auxiliary */
140     icxKlocus    = 1,	/* K is specified as proportion of K locus by PCS auxiliary */
141     icxKluma5    = 2,	/* K is specified as locus by 5 parameters as a function of L */
142     icxKluma5k   = 3,	/* K is specified as K value by 5 parameters as a function of L */
143     icxKl5l      = 4,	/* K is specified as locus by 2x5 parameters as a function of L and K locus aux */
144     icxKl5lk      = 5	/* K is specified as K value by 2x5 parameters as a function of L and K value aux */
145 } icxKrule;
146 
147 /* Curve parameters */
148 typedef struct {
149 	double Ksmth;		/* K smoothing filter extent */
150 	double Kstle;		/* K start level at white end (0.0 - 1.0)*/
151 	double Kstpo;		/* K start point as prop. of L locus (0.0 - 1.0) */
152 	double Kenpo;		/* K end point as prop. of L locus (0.0 - 1.0) */
153 	double Kenle;		/* K end level at Black end (0.0 - 1.0) */
154 	double Kshap;		/* K transition shape, 0.0-1.0 concave, 1.0-2.0 convex */
155 	double Kskew;		/* K transition shape skew, 1.0 = even */
156 } icxInkCurve;
157 
158 /* Default black generation smoothing value */
159 #define ICXINKDEFSMTH 0.09	/* Transition window of +/- ICXINKDEFSMTH */
160 #define ICXINKDEFSKEW 2.0	/* Curve shape skew (matches typical device behaviour) */
161 
162 /* Structure to convey inking details */
163 typedef struct {
164 	double tlimit;		/* Total ink limit, > 0.0 to < inputChan, < 0.0 == off */
165 	double klimit;		/* Black limit, > 0.0 to < 1.0, < 0.0 == off */
166 	icxKrule k_rule;	/* type of K generation rule */
167 	int KonlyLmin;		/* Use K only black Locus Lmin */
168 	icxInkCurve c;		/* K curve, or locus minimum curve */
169 	icxInkCurve x;		/* locus maximum curve if icxKl5l */
170 } icxInk;
171 
172 /* Structure to convey inverse lookup clip handling details */
173 struct _icxClip {
174 	int     nearclip;				/* Flag - use near clipping not vector */
175 	int     LabLike;				/* Flag It's an Lab like colorspace */
176 	int     fdi;					/* Dimentionality of clip vector */
177 	struct  _icxCuspMap *cm;		/* Cusp map for computing vector (if !NULL) */
178 	double  ocent[MXDO];			/* Default center of clut output gamut used if cm == NULL */
179 }; typedef struct _icxClip icxClip;
180 
181 /* Structure to convey viewing conditions */
182 typedef struct {
183 	ViewingCondition Ev;/* Enumerated Viewing Condition */
184 	double Wxyz[3];		/* Reference/Adapted White XYZ (Y range 0.0 .. 1.0) */
185 	double La;			/* Adapting/Surround Luminance cd/m^2 */
186 	double Yb;			/* Relative Luminance of Background to reference white */
187 	double Lv;			/* Luminance of white in the Image/Scene/Viewing field (cd/m^2) */
188 						/* Ignored if Ev is set to other than vc_none */
189 	double Yf;			/* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
190 	double Yg;			/* Glare as a fraction of the adapting/surround (Y range 0.0 .. 1.0) */
191 	double Gxyz[3];		/* The Glare white coordinates (ie the Ambient color) */
192 						/* will be taken from Wxyz if Gxyz <= 0.0 */
193 	double hkscale;		/* [1.0] HK scaling factor */
194 	char *desc;			/* Possible description of this VC */
195 } icxViewCond;
196 
197 #define XICC_DEFAULT_GLARE 5	/* Default glare in % */
198 
199 /* Method of black point adaptation */
200 typedef enum {
201 	gmm_BPadpt    = 0,		/* Adapt source black point to destination */
202 	gmm_noBPadpt  = 1,		/* Don't adapt black point to destination */
203 	gmm_bendBP    = 2,		/* Don't adapt black point, bend it to dest. at end */
204 	gmm_clipBP    = 3		/* Don't adapt black point, clip it to dest. at end */
205 } icx_BPmap;
206 
207 /* Structure to convey gamut mapping intent */
208 typedef struct {
209 	int    usecas;			/* 0x0 Use relative Lab space */
210 							/* 0x1 Use Absolute Lab Space */
211 							/* 0x2 Use Color Appearance Space */
212 							/* 0x3 Use Absolute Color Appearance Space */
213 							/* 0x102 Use Color Appearance Space with luminence scaling */
214 	int    usemap;			/* NZ if Gamut mapping should be used, else clip */
215 	double greymf;			/* Grey axis hue matching factor, 0.0 - 1.0 */
216 	double glumwcpf;		/* Grey axis luminance white compression factor, 0.0 - 1.0 */
217 	double glumwexf;		/* Grey axis luminance white expansion factor, 0.0 - 1.0 */
218 	double glumbcpf;		/* Grey axis luminance black compression factor, 0.0 - 1.0 */
219 	double glumbexf;		/* Grey axis luminance black expansion factor, 0.0 - 1.0 */
220 	double glumknf;			/* Grey axis luminance knee factor, 0.0 - 1.0 */
221 	icx_BPmap bph;			/* Method of black point adapation */
222 	double gamcpf;			/* Gamut compression factor, 0.0 - 1.0 */
223 	double gamexf;			/* Gamut expansion factor, 0.0 - 1.0 */
224 	double gamcknf;			/* Gamut compression knee factor, 0.0 - 1.0 */
225 	double gamxknf;			/* Gamut expansion knee factor, 0.0 - 1.0 */
226 	double gampwf;			/* Gamut Perceptual Map weighting factor, 0.0 - 1.0 */
227 	double gamlpwf;			/* Gamut Lightness preserving perceptual Map whtg. factor, 0.0 - 1.0 */
228 	double gamswf;			/* Gamut Saturation Map weighting factor, 0.0 - 1.0 */
229 	double satenh;			/* Saturation enhancement value, 0.0 - Inf */
230 	double hkscale;			/* [1.0] Optional HK scaling factor */
231 	char *as;				/* Alias string (option name) */
232 	char *desc;				/* Possible description of this VC */
233 	icRenderingIntent icci;	/* Closest ICC intent */
234 } icxGMappingIntent;
235 
236 struct _xicc {
237 	/* Private: */
238 	icc *pp;			/* ICC profile we expand */
239 
240 	struct _xcal *cal;	/* Optional device cal, NULL if none */
241 	int nodel_cal;		/* Flag, nz if cal was provided externally and shouldn't be deleted */
242 
243 	/* Public: */
244 	void                 (*del)(struct _xicc *p);
245 
246 	/* "use" flags */
247 #define ICX_CLIP_VECTOR  0x0000		/* If clipping is needed, clip in vector direction (default) */
248 #define ICX_CLIP_NEAREST 0x0010		/* If clipping is needed, clip to nearest */
249 #define ICX_MERGE_CLUT   0x0020		/* Merge the output() and out_abs() into the clut(), */
250 									/* for improved performance on reading, and */
251 									/* clipping in effective output space on inverse lookup. */
252 									/* Reduces accuracy noticably though. */
253 									/* Output output() and out_abs() become NOPs */
254 #define ICX_CAM_CLIP     0x0100		/* Use CAM space during invfwd clipping lookup, */
255 									/* irrespective of the native or effective PCS. */
256 									/* Ignored if MERGE_CLUT is set or vector clip is used. */
257 									/* May halve the inverse lookup performance! */
258 #define ICX_INT_SEPARATE 0x0400		/* Handle 4 dimensional devices with fixed inking rules */
259 									/* with an optimised internal separation pass, rather */
260 									/* than a point by point inverse locus lookup . */
261 									/* NOT IMPLEMENTED YET */
262 #define ICX_FAST_SETUP   0x0800		/* Improve initial setup speed at the cost of throughput */
263 #define ICX_VERBOSE      0x8000		/* Turn on verboseness during creation */
264 
265 	                                /* Returm a lookup object from the icc */
266 	struct _icxLuBase *  (*get_luobj) (struct _xicc *p,
267 	                                   int flags,				/* clip, merge flags */
268 	                                   icmLookupFunc func,		/* Functionality */
269 	                                   icRenderingIntent intent,/* Intent */
270 	                                   icColorSpaceSignature pcsor,	/* PCS override (0 = def) */
271 	                                   icmLookupOrder order,	/* Search Order */
272 	                                   icxViewCond *vc,			/* Viewing Condition - only */
273 	                                                            /* used if pcsor == CIECAM. */
274 																/* or ICX_CAM_CLIP flag. */
275 	                                   icxInk *ink);			/* inking details (NULL = def) */
276 
277 
278 										/* Set a xluobj and icc table from scattered data */
279 										/* Return appropriate lookup object */
280 										/* NULL on error, check errc+err for reason */
281 	/* "create" flags */
282 #define ICX_SET_WHITE       0x00010000	/* find, set and make relative to the white point */
283 #define ICX_SET_WHITE_US    0x00030000	/* find, set and make relative to the white point hue, */
284 										/* but not scale to W L value, to avoid input clipping */
285 #define ICX_SET_WHITE_C     0x00050000	/* find, set and make relative to the white point hue, */
286 										/* and clip any cLUT values over D50 to D50 */
287 #define ICX_SET_BLACK       0x00080000	/* find and set the black point */
288 #define ICX_WRITE_WBL       0x00100000	/* Matrix: write White, Black & Luminance tags */
289 #define ICX_CLIP_WB         0x00200000	/* Clip white and black to be < 1 and > 0 respectively */
290 #define ICX_CLIP_PRIMS      0x00400000	/* Clip matrix primaries to be > 0 */
291 #define ICX_NO_IN_SHP_LUTS  0x00800000	/* Lut/Mtx: Don't create input (Device) shaper curves. */
292 #define ICX_NO_IN_POS_LUTS  0x01000000	/* LuLut: Don't create input (Device) postion curves. */
293 #define ICX_NO_OUT_LUTS     0x02000000	/* LuLut: Don't create output (PCS) curves. */
294 //#define ICX_2PASSSMTH     0x04000000	/* If LuLut: Use Gaussian smoothing */
295 //#define ICX_EXTRA_FIT     0x08000000	/* If LuLut: Counteract scat data point errors. */
296 /* And  ICX_VERBOSE         			   Turn on verboseness during creation */
297 	struct _icxLuBase * (*set_luobj) (struct _xicc *p,
298 	                                  icmLookupFunc func,		/* Functionality to set */
299 	                                  icRenderingIntent intent,	/* Intent to set */
300 	                                  icmLookupOrder order,		/* Search Order */
301 	                                  int flags,				/* white/black point flags */
302 	                                  int no,					/* Total Number of points */
303 	                                  int nobw,					/* Number of points to look */
304 																/* for white & black patches in */
305 	                                  cow *points,				/* Array of input points */
306 	                                  icxMatrixModel *skm, 		/* Optional skeleton model */
307 	                                  double dispLuminance,		/* > 0.0 if display luminance */
308 	                                                                    /* value and is known */
309 	                                  double wpscale,			/* > 0.0 if input white pt is */
310 	                                                                    /* is to be scaled */
311 //									  double *bpo, 				/* != NULL black point override */
312 	                                  double smooth,			/* RSPL smoothing factor, */
313 	                                                                        /* -ve if raw */
314 	                                  double avgdev,			/* Avge Dev. of points */
315 	                                  double demph,				/* cLut dark emphasis factor */
316 	                                  icxViewCond *vc,			/* Viewing Condition - only */
317 	                                                            /* used if pcsor == CIECAM. */
318 																/* or ICX_CAM_CLIP flag. */
319 	                                  icxInk *ink,				/* inking details */
320 	                                  struct _xcal *cal,		/* Optional cal Will override any */
321 																/* existing, not deltd with xicc. */
322 	                                  int quality);				/* Quality metric, 0..3 */
323 
324 
325 								/* Return the devices viewing conditions. */
326 								/* Return value 0 if it is well defined */
327 								/* Return value 1 if it is a guess */
328 								/* Return value 2 if it is not possible/appropriate */
329 	int     (*get_viewcond)(struct _xicc *p, icxViewCond *vc);
330 
331 	char             err[512];			/* Error message */
332 	int              errc;				/* Error code */
333 }; typedef struct _xicc xicc;
334 
335 /* ~~~~~ */
336 /* Might be good to add a slow but very precise vector and closest "clip to gamut" */
337 /* function for use in setting white and black points. Use this in profile. */
338 
339 xicc *new_xicc(icc *picc);
340 
341 /* ------------------------------------------------------------------------------ */
342 /* Expanded lookup object support */
343 #define XLU_BASE_MEMBERS																\
344 	/* Private: */																		\
345 	int              trace;					/* Optional run time tracing flag */		\
346 	struct _xicc    *pp;					/* Pointer to XICC we're a part of */		\
347 	icmLuBase       *plu;					/* Pointer to icm Lu we are expanding */	\
348 	int              flags;					/* Flags passed to get_luobj */				\
349 	icmLookupFunc    func;					/* Function passed to get_luobj */			\
350 	icRenderingIntent intent;				/* Effective/External Intent */				\
351 											/* "in" and "out" are in reference to */	\
352 											/* the requested lookup direction. */		\
353     icColorSpaceSignature ins;				/* Effective/External Clr space of input */	\
354     icColorSpaceSignature outs;				/* Effective/External Clr space of output */\
355 	icColorSpaceSignature pcs;				/* Effective/External PCS */				\
356     icColorSpaceSignature natis;			/* Native input Clr space */				\
357     icColorSpaceSignature natos;			/* Native output Clr space */				\
358     icColorSpaceSignature natpcs;			/* Native PCS Clr space */					\
359     int	inputChan;      					/* Num of input channels */					\
360     int	outputChan;     					/* Num of output channels */				\
361 	double ninmin[MXDI];					/* icc Native Input color space minimum */	\
362 	double ninmax[MXDI];					/* icc Native Input color space maximum */	\
363 	double noutmin[MXDO];					/* icc Native Output color space minimum */	\
364 	double noutmax[MXDO];					/* icc Native Output color space maximum */	\
365 	double inmin[MXDI];						/* icx Effective Input color space minimum */	\
366 	double inmax[MXDI];						/* icx Effective Input color space maximum */	\
367 	double outmin[MXDO];					/* icx Effective Output color space minimum */	\
368 	double outmax[MXDO];					/* icx Effective Output color space maximum */	\
369 	icxViewCond  vc;						/* Viewing Condition for CIECAM97s */		\
370 	icxcam      *cam;						/* CAM conversion */						\
371 																						\
372 	/* Attributes inhereted by ixcLu's */												\
373 	int noisluts;	/* Flag - If LuLut: Don't create input (Device) shaper curves. */			\
374 	int noipluts;	/* Flag - If LuLut: Don't create input (Device) position curves. */	\
375 	int nooluts;	/* Flag - If LuLut: Don't create output (PCS) curves. */			\
376 	int nearclip;	/* Flag - If clipping occurs, return the nearest solution, */		\
377 	int mergeclut;	/* Flag - If LuLut: Merge output() and out_abs() into clut(). */	\
378 	int camclip;	/* Flag - If LuLut: Use CIECAM for clut reverse lookup clipping */ \
379 	int intsep;		/* Flag - If LuLut: Do internal separation for 4d device */			\
380 	int fastsetup;	/* Flag - If LuLut: Do fast setup at cost of slower throughput */	\
381 																						\
382 	/* Public: */																		\
383 	void    (*del)(struct _icxLuBase *p);												\
384 																						\
385 								/* Return Internal native colorspaces */				\
386 	void    (*lutspaces) (struct _icxLuBase *p, icColorSpaceSignature *ins, int *inn,	\
387 	                                        icColorSpaceSignature *outs, int *outn,		\
388 	                                        icColorSpaceSignature *pcs);				\
389 																						\
390 								/* External effective colorspaces */       	    		\
391 	void    (*spaces) (struct _icxLuBase *p, icColorSpaceSignature *ins, int *inn,		\
392 	                                     icColorSpaceSignature *outs, int *outn,		\
393 	                                     icmLuAlgType *alg, icRenderingIntent *intt,	 \
394 	                                     icmLookupFunc *fnc, icColorSpaceSignature *pcs); \
395 																						\
396 	/* Get the Native input space and output space ranges */							\
397 	void (*get_native_ranges) (struct _icxLuBase *p,										\
398 		double *inmin, double *inmax,		/* Maximum range of inspace values */		\
399 		double *outmin, double *outmax);	/* Maximum range of outspace values */		\
400 																						\
401 																						\
402 	/* Get the Effective input space and output space ranges */							\
403 	void (*get_ranges) (struct _icxLuBase *p,											\
404 		double *inmin, double *inmax,		/* Maximum range of inspace values */		\
405 		double *outmin, double *outmax);	/* Maximum range of outspace values */		\
406 																						\
407 																						\
408 	/* Return the media white and black points */										\
409 	/* in the effective PCS colorspace. */												\
410 	/* (ie. these will be relative values for relative intent etc.) */					\
411 	void    (*efv_wh_bk_points)(struct _icxLuBase *p, double *wht, double *blk, double *kblk);	\
412 																						\
413 	/* Translate color values through profile */										\
414 	/* 0 = success */																	\
415 	/* 1 = warning: clipping occured */													\
416 	/* 2 = fatal: other error */														\
417 																						\
418 	/* (Note that clipping is not a reliable means of detecting out of gamut in the */	\
419 	/* lookup(bwd) call for clut based profiles, but is for inv_lookup() calls.) */		\
420 																						\
421 	int            (*lookup) (struct _icxLuBase *p, double *out, double *in);			\
422 											/* Requested conversion */					\
423 	int			   (*inv_lookup) (struct _icxLuBase *p, double *out, double *in);		\
424 											/* Inverse conversion */					\
425 																						\
426 	/* Given an xicc lookup object, returm a gamut object. */							\
427 	/* Note that the Effective PCS must be Lab or Jab */								\
428 	/* A icxLuLut type must be icmFwd or icmBwd, */										\
429 	/* and for icmFwd, the ink limit (if supplied) */									\
430 	/* will be applied. */																\
431 	/* Return NULL on error, check xicc errc+err for reason */							\
432 	gamut * (*get_gamut) (struct _icxLuBase *plu,	/* xicc lookup object */			\
433 	                      double detail);			/* gamut detail level, 0.0 = def */	\
434 																						\
435 	/* Given an xicc lookup object, return an icxCuspMap object. */						\
436 	/* Note that the PCS must be Lab or Jab. */											\
437 	/* An icxLuLut type must be icmFwd, and the ink limit (if supplied) */				\
438 	/* will be applied. */																\
439 	/* Return NULL on error, check errc+err for reason */								\
440 	struct _icxCuspMap *(*get_cuspmap)(struct _icxLuBase *p, int res);					\
441 																						\
442 	/* The following two functions expose the relative colorimetric native ICC PCS */	\
443 	/* <--> absolute/CAM space transform, so that CAM based gamut compression */		\
444 	/* can be applied in creating the ICC Lut tabls in profout.c. */					\
445 																						\
446 	/* Given a native ICC relative XYZ or Lab PCS value, convert in the fwd */			\
447 	/* direction into the nominated Effective output PCS (ie. Absolute, Jab etc.) */	\
448 	void (*fwd_relpcs_outpcs) (struct _icxLuBase *p, icColorSpaceSignature is,			\
449 	                                                   double *out, double *in);		\
450 																						\
451 	/* Given a nominated Effective output PCS (ie. Absolute, Jab etc.), convert it */	\
452 	/* in the bwd direction into a native ICC relative XYZ or Lab PCS value */			\
453 	void (*bwd_outpcs_relpcs) (struct _icxLuBase *p, icColorSpaceSignature os,			\
454 	                                                   double *out, double *in);		\
455 																						\
456 
457 
458 /* Base xlookup object */
459 struct _icxLuBase {
460 	XLU_BASE_MEMBERS
461 }; typedef struct _icxLuBase icxLuBase;
462 
463 /* Monochrome  Fwd & Bwd type object */
464 struct _icxLuMono {
465 	XLU_BASE_MEMBERS
466 
467 	/* Overall lookups */
468 	int (*fwd_lookup) (struct _icxLuBase *p, double *out, double *in);
469 	int (*bwd_lookup) (struct _icxLuBase *p, double *out, double *in);
470 
471 	/* Components of Device to PCS lookup */
472 	int (*fwd_curve) (struct _icxLuMono *p, double *out, double *in);
473 	int (*fwd_map)   (struct _icxLuMono *p, double *out, double *in);
474 	int (*fwd_abs)   (struct _icxLuMono *p, double *out, double *in);
475 
476 	/* Components of PCS to Device lookup */
477 	int (*bwd_abs)   (struct _icxLuMono *p, double *out, double *in);
478 	int (*bwd_map)   (struct _icxLuMono *p, double *out, double *in);
479 	int (*bwd_curve) (struct _icxLuMono *p, double *out, double *in);
480 
481 }; typedef struct _icxLuMono icxLuMono;
482 
483 /* 3D Matrix Fwd & Bwd type object */
484 struct _icxLuMatrix {
485 	XLU_BASE_MEMBERS
486 
487 	/* Overall lookups */
488 	int (*fwd_lookup) (struct _icxLuBase *p, double *out, double *in);
489 	int (*bwd_lookup) (struct _icxLuBase *p, double *out, double *in);
490 
491 	/* Components of Device to PCS lookup */
492 	int (*fwd_curve)  (struct _icxLuMatrix *p, double *out, double *in);
493 	int (*fwd_matrix) (struct _icxLuMatrix *p, double *out, double *in);
494 	int (*fwd_abs)    (struct _icxLuMatrix *p, double *out, double *in);
495 
496 	/* Components of PCS to Device lookup */
497 	int (*bwd_abs)    (struct _icxLuMatrix *p, double *out, double *in);
498 	int (*bwd_matrix) (struct _icxLuMatrix *p, double *out, double *in);
499 	int (*bwd_curve)  (struct _icxLuMatrix *p, double *out, double *in);
500 
501 }; typedef struct _icxLuMatrix icxLuMatrix;
502 
503 /* Multi-D. Lut type object */
504 struct _icxLuLut {
505 	XLU_BASE_MEMBERS
506 
507 	/* private: */
508 	icmLut *lut;							/* ICC Lut that is being used */
509 	rspl	        *inputTable[MXDI];		/* The input lookups */
510 	rspl	        *clutTable;				/* The multi dimention lookup */
511 	rspl	        *cclutTable;			/* Alternate multi dimention lookup in CAM space */
512 	rspl	        *outputTable[MXDO];		/* The output lookups */
513 
514 	/* Inverted RSPLs used to speed ink limit calculation */
515 	/* input' -> input */
516 	rspl *revinputTable[MXDI];
517 
518 	/* In/Out lookup flags used for rspl init. callback */
519 	int iol_out;	/* Non-zero if output lookup */
520 	int iol_ch;		/* Channel */
521 
522 	/* In/Out inversion support */
523 	double inputClipc[MXDI];	/* The input lookups clip center */
524 	double outputClipc[MXDO];	/* The output lookups clip center */
525 
526 	/* clut inversion support */
527 	double      icent[MXDI];		/* center of input gamut */
528 	double      licent[MXDI];		/* last icent value used */
529 
530 	icxClip clip;					/* Clip setup information */
531 
532 	int kch;						/* Black ink channel if discovered */
533 									/* -1 if not known or applicable */
534 									/* (Only set by icxLu_comp_bk_point()) */
535 	icxInk      ink;				/* inking details */
536 	double Lmin, Lmax;				/* L min/max for inking rule */
537 
538 	/* Auxiliary parameter flags, non-zero for inputs that will be */
539 	/* used as auxiliary parameters the rspl input */
540 	/* dimensionality exceeds the output dimension (i.e. CMYK->Lab) */
541 	int auxm[MXDI];
542 
543 	/* Auxiliar linearization function - NULL if none */
544  	/* Only the used auxiliary chanels need be calculated. */
545 	/* ~~ not implimented yet ~~~ */
546 //	void (*auxlinf)(void *auxlinf_ctx, double inout[MXDI]);
547 
548 	/* Opaque context for auxlin */
549 //	void *auxlinf_ctx;
550 
551 	/* Temporary icm fwd abs XYZ LuLut used for setting up icx clut */
552 	icmLuBase *absxyzlu;
553 
554 	/* Optional function to compute the input chanel */
555  	/* sum from the raw rspl input values. NULL if not used. */
556 	/* Use this to take account of any transformation beyond */
557 	/* the input space, or 6 color masquerading as 4 etc. */
558 	double (*limitf)(void *limitf_ctx, float in[MXDI]);		/* ~~ not implimented yet */
559 
560 	/* Opaque context for limitf */
561 	void *limitf_ctx;
562 
563 	/* Input space sum limit. Points with a limitf() over */
564 	/* this number will not be considered in gamut. Valid if gt 0 */
565 	double slimit;
566 
567 	/* public: */
568 
569 	/* Note that black inking rules are always defined and provided */
570 	/* in dev[] and pcs[] space, even for component functions */
571 	/* (ie. the implementation of the inking rule deals with */
572 	/*  the dev<->dev' and pcs<->pcs' conversions) */
573 
574 	/* Requested direction component lookup */
575 	int (*in_abs)  (struct _icxLuLut *p, double *out, double *in);
576 	int (*matrix)  (struct _icxLuLut *p, double *out, double *in);
577 	int (*input)   (struct _icxLuLut *p, double *out, double *in);
578 	int (*clut)    (struct _icxLuLut *p, double *out, double *in);
579 	int (*clut_aux)(struct _icxLuLut *p, double *out, double *olimit,
580 	                                     double *auxv, double *in);
581 	int (*output)  (struct _icxLuLut *p, double *out, double *in);
582 	int (*out_abs) (struct _icxLuLut *p, double *out, double *in);
583 
584 	/* Inverse direction component lookup (in reverse order) */
585 	int (*inv_out_abs) (struct _icxLuLut *p, double *out, double *in);
586 	int (*inv_output)  (struct _icxLuLut *p, double *out, double *in);
587 	int (*inv_clut)    (struct _icxLuLut *p, double *out, double *in);
588 	int (*inv_clut_aux)(struct _icxLuLut *p, double *out, double *auxv,
589                  double *auxr, double *auxt, double *clipd, double *in);
590 	int (*inv_input)   (struct _icxLuLut *p, double *out, double *in);
591 	int (*inv_matrix)  (struct _icxLuLut *p, double *out, double *in);
592 	int (*inv_in_abs)  (struct _icxLuLut *p, double *out, double *in);
593 
594 	/* Get locus information for a clut (see xlut.c for details) */
595 	int (*clut_locus)  (struct _icxLuLut *p, double *locus, double *out, double *in);
596 
597 	/* Get various types of information about the LuLut */
598 	void (*get_info) (struct _icxLuLut *p, icmLut **lutp,
599 	                 icmXYZNumber *pcswhtp, icmXYZNumber *whitep,
600 	                 icmXYZNumber *blackp);
601 
602 	/* Get the matrix contents */
603 	void (*get_matrix) (struct _icxLuLut *p, double m[3][3]);
604 
605 }; typedef struct _icxLuLut icxLuLut;
606 
607 /* ------------------------------------------------------------------------------ */
608 /* Utility declarations and functions */
609 
610 /* Utility that mirrors get_luobj intent handling: */
611 /* return nz if the intent implies Jab space */
612 int xiccIsIntentJab(icRenderingIntent intent);
613 
614 /* Profile Creation Suplimental Information structure */
615 struct _profxinf {
616     icmSig manufacturer;	/* Device manufacturer ICC Sig, 0 for default */
617 	char *deviceMfgDesc;	/* Manufacturer text description, NULL for none */
618 
619     icmSig model;			/* Device model ICC Sig, 0 for default */
620 	char *modelDesc;		/* Model text description, NULL for none */
621 
622     icmSig creator;			/* Profile creator ICC Sig, 0 for default */
623 
624 	char *profDesc;			/* Text profile description, NULL for default */
625 
626 	char *copyright;		/* Copyrigh text, NULL for default */
627 
628 	/* Attribute flags */
629 	int transparency;		/* NZ for Trasparency, else Reflective */
630 	int matte;				/* NZ for Matte, else Glossy */
631 	int negative;			/* NZ for Negative, else Positive */
632 	int blackandwhite;		/* NZ for BlackAndWhite, else Color */
633 
634 	/* Default intent */
635 	icRenderingIntent  default_ri;	/* Default rendering intent */
636 
637 	/* Other stuff ICC ?? */
638 
639 }; typedef struct _profxinf profxinf;
640 
641 /* Set an icc's Lut tables, and take care of auxiliary continuity problems. */
642 /* Only useful if there are auxiliary device output chanels to be set. */
643 int icxLut_set_tables_auxfix(
644 icmLut *p,						/* Pointer to icmLut object */
645 void   *cbctx,							/* Opaque callback context pointer value */
646 icColorSpaceSignature insig, 			/* Input color space */
647 icColorSpaceSignature outsig, 			/* Output color space */
648 void (*infunc)(void *cbctx, double *out, double *in),
649 						/* Input transfer function, inspace->inspace' (NULL = default) */
650 double *inmin, double *inmax,			/* Maximum range of inspace' values */
651 										/* (NULL = default) */
652 void (*clutfunc)(void *cbntx, double *out, double *aux, double *auxr, double *pcs, double *in),
653 						/* inspace' -> outspace' transfer function, also */
654 						/* return the internal target PCS and the  (packed) auxiliary locus */
655 						/* range as [min0, max0, min1, max1...], and the actual auxiliary */
656 						/* target used. */
657 void (*clutpcsfunc)(void *cbntx, double *out, double *aux, double *pcs),
658 						/* Internal PCS + actual aux_target -> outspace' transfer function */
659 void (*clutipcsfunc)(void *cbntx, double *pcs, double *olimit, double *auxv, double *in),
660 						/* outspace' -> Internal PCS + auxv check function */
661 double *clutmin, double *clutmax,		/* Maximum range of outspace' values */
662 										/* (NULL = default) */
663 void (*outfunc)(void *cbntx, double *out, double *in)
664 						/* Output transfer function, outspace'->outspace (NULL = deflt) */
665 );
666 
667 
668 /* Return an enumerated viewing condition */
669 /* Return enumeration if OK, -999 if there is no such enumeration. */
670 /* xicc may be NULL if just the description is wanted, */
671 /* or an explicit white point is provided. */
672 int xicc_enum_viewcond(
673 xicc *p,			/* Expanded profile to get white point (May be NULL if desc NZ) */
674 icxViewCond *vc,	/* Viewing parameters to return, May be NULL if desc is nz */
675 int no,				/* Enumeration to return, -1 for default, -2 for none */
676 char *as,			/* String alias to number, NULL if none */
677 int desc,			/* NZ - Just return a description of this enumeration in vc */
678 double *wp			/* Provide XYZ white point if xicc is NULL */
679 );
680 
681 /* Debug: dump a Viewing Condition to standard out */
682 void xicc_dump_viewcond(icxViewCond *vc);
683 
684 /* Debug: dump an Inking setup to standard out */
685 void xicc_dump_inking(icxInk *ik);
686 
687 /* Return enumerated gamut mapping intents */
688 /* Return 0 if OK, 1 if there is no such enumeration. */
689 /* Note the following fixed numbers meanings: */
690 #define icxNoGMIntent -1
691 #define icxDefaultGMIntent -2
692 #define icxAbsoluteGMIntent -3
693 #define icxRelativeGMIntent -4
694 #define icxPerceptualGMIntent -5
695 #define icxSaturationGMIntent -6
696 #define icxIllegalGMIntent -999
697 int xicc_enum_gmapintent(icxGMappingIntent *gmi, int no, char *as);
698 void xicc_dump_gmi(icxGMappingIntent *gmi);
699 
700 /* - - - - - - - - - - */
701 /* Utility functions: */
702 
703 /* Given an open icc profile, */
704 /* guess which channel is the black. */
705 /* Return -1 if there is no black channel or it can't be guessed */
706 int icxGuessBlackChan(icc *p);
707 
708 /* Given an icc profile, try and create an xcal */
709 /* Return NULL on error or no cal */
710 struct _xcal *xiccReadCalTag(icc *p);
711 
712 /* A callback that uses an xcal, that can be used with icc get_tac */
713 void xiccCalCallback(void *cntx, double *out, double *in);
714 
715 /* Given an xicc icc profile, estmate the total ink limit and black ink limit. */
716 void icxGetLimits(xicc *p, double *tlimit, double *klimit);
717 
718 /* Using the above function, set default total and black ink values */
719 void icxDefaultLimits(xicc *p, double *tlout, double tlin, double *klout, double klin);
720 
721 /* Given a calibrated total ink limit and an xcal, return the */
722 /* equivalent underlying (pre-calibration) total ink limit. */
723 /* This is the maximum equivalent, that makes sure that */
724 /* the calibrated limit is met or exceeded. */
725 double icxMaxUnderlyingLimit(struct _xcal *cal, double ilimit);
726 
727 /* - - - - - - - - - - */
728 
729 /* Utility function - compute the clip vector direction. */
730 /* return NULL if vector clip isn't used. */
731 double *icxClipVector(
732 icxClip *p,			/* Clipping setup information */
733 double *in,			/* Target point */
734 double *cdirv,		/* Returned clip vector */
735 int safe			/* Flag - return safe vector */
736 );
737 
738 /* - - - - - - - - - - */
739 
740 /* CIE XYZ to perceptual Lab with partial derivatives. */
741 void icxdXYZ2Lab(icmXYZNumber *w, double *out, double dout[3][3], double *in);
742 
743 /* Return the normal Delta E squared, given two Lab values, */
744 /* including partial derivatives. */
745 double icxdLabDEsq(double dout[2][3], double *Lab0, double *Lab1);
746 
747 /* Return the CIE94 Delta E color difference measure, squared */
748 /* including partial derivatives. */
749 double icxdCIE94sq(double dout[2][3], double Lab0[3], double Lab1[3]);
750 
751 /* Return the normal Delta E given two Lab values, */
752 /* including partial derivatives. */
753 double icxdLabDE(double dout[2][3], double *Lab0, double *Lab1);
754 
755 /* Return the CIE94 Delta E color difference measure */
756 /* including partial derivatives. */
757 double icxdCIE94(double dout[2][3], double Lab0[3], double Lab1[3]);
758 
759 /* - - - - - - - - - - */
760 /* Power like function, based on Graphics Gems adjustment curve. */
761 /* Avoids "toe" problem of pure power. */
762 /* Adjusted so that "power" 2 and 0.5 agree with real power at 0.5 */
763 double icx_powlike(double vv, double pp);
764 
765 /* Compute the necessary aproximate power, to transform */
766 /* the given value from src to dst. They are assumed to be */
767 /* in the range 0.0 .. 1.0 */
768 double icx_powlike_needed(double src, double dst);
769 
770 /* - - - - - - - - - - */
771 
772 /* Transfer function */
773 double icxTransFunc(
774 double *v,			/* Pointer to first parameter */
775 int    luord,		/* Number of parameters */
776 double vv			/* Source of value */
777 );
778 
779 /* Inverse Transfer function */
780 double icxInvTransFunc(
781 double *v,			/* Pointer to first parameter */
782 int    luord,		/* Number of parameters */
783 double vv			/* Source of value */
784 );
785 
786 /* Transfer function with scaling */
787 double icxSTransFunc(
788 double *v,			/* Pointer to first parameter */
789 int    luord,		/* Number of parameters */
790 double vv,			/* Source of value */
791 double min,			/* Scale values */
792 double max
793 );
794 
795 /* Inverse Transfer function with scaling */
796 double icxInvSTransFunc(
797 double *v,			/* Pointer to first parameter */
798 int    luord,		/* Number of parameters */
799 double vv,			/* Source of value */
800 double min,			/* Scale values */
801 double max
802 );
803 
804 /* Transfer function with partial derivative */
805 /* with respect to the parameters. */
806 double icxdpTransFunc(
807 double *v,			/* Pointer to first parameter */
808 double *dv,			/* Return derivative wrt each parameter [luord] */
809 int    luord,		/* Number of parameters */
810 double vv			/* Source of value */
811 );
812 
813 /* Transfer function with scaling and */
814 /* partial derivative with respect to the parameters. */
815 double icxdpSTransFunc(
816 double *v,			/* Pointer to first parameter */
817 double *dv,			/* Return derivative wrt each parameter [luord] */
818 int    luord,		/* Number of parameters */
819 double vv,			/* Source of value */
820 double min,			/* Scale values */
821 double max
822 );
823 
824 /* Transfer function with partial derivative */
825 /* with respect to the input value. */
826 double icxdiTransFunc(
827 double *v,			/* Pointer to first parameter */
828 double *pdv,		/* Return derivative wrt source value [1] */
829 int    luord,		/* Number of parameters */
830 double vv			/* Source of value */
831 );
832 
833 /* Transfer function with scaling and */
834 /* partial derivative with respect to the input value. */
835 double icxdiSTransFunc(
836 double *v,			/* Pointer to first parameter */
837 double *pdv,		/* Return derivative wrt source value [1] */
838 int    luord,		/* Number of parameters */
839 double vv,			/* Source of value */
840 double min,			/* Scale values */
841 double max
842 );
843 
844 /* Transfer function with partial derivative */
845 /* with respect to the parameters and the input value. */
846 double icxdpdiTransFunc(
847 double *v,			/* Pointer to first parameter */
848 double *dv,			/* Return derivative wrt each parameter [luord] */
849 double *pdin,		/* Return derivative wrt source value [1] */
850 int    luord,		/* Number of parameters */
851 double vv			/* Source of value */
852 );
853 
854 /* Transfer function with scaling and */
855 /* partial derivative with respect to the */
856 /* parameters and the input value. */
857 double icxdpdiSTransFunc(
858 double *v,			/* Pointer to first parameter */
859 double *dv,			/* Return derivative wrt each parameter [luord] */
860 double *pdin,		/* Return derivative wrt source value [1] */
861 int    luord,		/* Number of parameters */
862 double vv,			/* Source of value */
863 double min,			/* Scale values */
864 double max
865 );
866 
867 /* Should add/move the spectro/moncurve stuff in here, */
868 /* since it has offset and scaling. */
869 
870 /* - - - - - - - - - - */
871 /* Multi-plane interpolation - uses base + di slope values.  */
872 /* Parameters are assumed to be fdi groups of di + 1 parameters. */
873 void icxPlaneInterp(
874 double *v,			/* Pointer to first parameter [fdi * (di + 1)] */
875 int    fdi,			/* Number of output channels */
876 int    di,			/* Number of input channels */
877 double *out,		/* Resulting fdi values */
878 double *in			/* Input di values */
879 );
880 
881 /* Matrix cube interpolation. with partial derivative */
882 /* with respect to the input and parameters. */
883 void icxdpdiPlaneInterp(
884 double *v,			/* Pointer to first parameter value [fdi * (di + 1)] */
885 double *dv,			/* Return [1 + di] deriv. wrt each parameter v */
886 double *din,		/* Return [fdi * di] deriv. wrt each input value */
887 int    fdi,			/* Number of output channels */
888 int    di,			/* Number of input channels */
889 double *out,		/* Resulting fdi values */
890 double *in			/* Input di values */
891 );
892 
893 /* - - - - - - - - - - */
894 
895 /* Matrix cube interpolation - interpolate between 2^di output corner values. */
896 /* Parameters are assumed to be fdi groups of 2^di parameters. */
897 void icxCubeInterp(
898 double *v,			/* Pointer to first parameter */
899 int    fdi,			/* Number of output channels */
900 int    di,			/* Number of input channels */
901 double *out,		/* Resulting fdi values */
902 double *in			/* Input di values */
903 );
904 
905 /* Matrix cube interpolation. with partial derivative */
906 /* with respect to the input and parameters. */
907 void icxdpdiCubeInterp(
908 double *v,			/* Pointer to first parameter value */
909 double *dv,			/* Return [fdi * 2^di] deriv wrt each parameter v */
910 double *din,		/* Return [fdi * di] deriv wrt each input value */
911 int    fdi,			/* Number of output channels */
912 int    di,			/* Number of input channels */
913 double *out,		/* Resulting fdi values */
914 double *in			/* Input di values */
915 );
916 
917 /* - - - - - - - - - - */
918 
919 /* 3x3 matrix in 1D array multiplication */
920 void icxMulBy3x3Parm(
921 	double out[3],			/* Return input multiplied by matrix */
922 	double mat[9],			/* Matrix organised in [slow][fast] order */
923 	double in[3]			/* Input values */
924 );
925 
926 /* 3x3 matrix in 1D array multiplication, with partial derivatives */
927 /* with respect to just the input. */
928 void icxdpdiiMulBy3x3Parm(
929 	double out[3],			/* Return input multiplied by matrix */
930 	double din[3][3],		/* Return deriv for each [output] with respect to [input] */
931 	double mat[9],			/* Matrix organised in [slow][fast] order */
932 	double in[3]			/* Input values */
933 );
934 
935 /* 3x3 matrix in 1D array multiplication, with partial derivatives */
936 /* with respect to the input and parameters. */
937 void icxdpdiMulBy3x3Parm(
938 	double out[3],			/* Return input multiplied by matrix */
939 	double dv[3][9],		/* Return deriv for each [output] with respect to [param] */
940 	double din[3][3],		/* Return deriv for each [output] with respect to [input] */
941 	double mat[9],			/* Matrix organised in [slow][fast] order */
942 	double in[3]			/* Input values */
943 );
944 
945 /* - - - - - - - - - - */
946 
947 /* Cusp map - used for vector clipping in Lab like spaces */
948 struct _icxCuspMap {
949 	double Lmax[3];	/* Maximum L* value found */
950 	double Lmin[3];	/* Minimum L* value found */
951 	int res;		/* Resolution of hue map */
952 	double *L;		/* L* value of cusp at hue angle */
953 	double *C;		/* C* value of cusp at hue angle */
954 
955 	/* Expand cusp map with given point */
956 	void (*expand)(struct _icxCuspMap *p, double lab[3]);
957 
958 	/* Return the corresponding cusp location, given the source point */
959 	void (*getCusp)(struct _icxCuspMap *p,double cuspLCh[3], double srcLab[3]);
960 
961 	/* We're done with CuspMap */
962 	void (*del)(struct _icxCuspMap *p);
963 
964 }; typedef struct _icxCuspMap icxCuspMap;
965 
966 
967 /* - - - - - - - - - - */
968 
969 #include "xcal.h"
970 
971 #endif /* XICC_H */
972 
973 
974 
975 
976 
977 
978 
979 
980 
981 
982 
983 
984 
985 
986 
987 
988 
989 
990 
991 
992 
993 
994 
995 
996 
997 
998 
999 
1000 
1001 
1002 
1003 
1004 
1005 
1006 
1007