summaryrefslogtreecommitdiff
path: root/xicc/xicc.h
blob: f521de244f83fa17a8e24240b0955bc91df23a41 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
#ifndef XICC_H
#define XICC_H
/* 
 * International Color Consortium color transform expanded support
 *
 * Author:  Graeme W. Gill
 * Date:    28/6/00
 * Version: 1.00
 *
 * Copyright 2000, 2011 Graeme W. Gill
 * All rights reserved.
 * This material is licenced under the GNU AFFERO GENERAL PUB LICENSE Version 3 :-
 * see the License.txt file for licencing details.
 *
 * Based on the old iccXfm class.
 */

/*
 * This library expands the icclib functionality,
 * particularly in creating and exercising color transforms.
 *
 * For the moment, this support is concentrated around the
 * Lut and Matrix subsets of the ICC profile tranforms.
 *
 * It is intended to allow color transformation, storage and retrieval
 * of ICC profiles, while permitting inititialization from scattered
 * data, reversing of the transform, and specific manipulations of
 * the internal processing elements.
 *
 * This class bases much of it's functionality on that of the
 * underlying icclib icmLuBase.
 */

#include "icc.h"		/* icclib ICC definitions */ 
#include "cgats.h"		/* CGAT format */	
#include "rspl.h"		/* rspllib thin plate spline definitions */
#include "gamut.h"		/* gamut definitions */
#include "xutils.h"		/* Utility functions */
#include "xcam.h"		/* CAM definitions */
#include "xspect.h"		/* Spectral conversion object */
#include "xcolorants.h"	/* Known colorants support */
#include "insttypes.h"	/* Instrument type support */
#include "mpp.h"		/* model printer profile support */
#include "moncurve.h"	/* monotonic curve support */
						/* (more at the end) */

#define XICC_USE_HK 1	/* [Set] Set to 1 to use Helmholtz-Kohlraush in all CAM conversions */
#define XICC_NEUTRAL_CMYK_BLACK		/* Use neutral axis black, else use K direction black. */
#define XICC_BLACK_POINT_TOLL 0.5			/* Tollerance of CMYK black point location */ 
#define XICC_BLACK_FIND_ABERR_WEIGHT 10.0	/* Weight of ab error against min L in BP */

/* ------------------------------------------------------------------------------ */

/* The "effective" PCS colorspace is the one specified by the PCS override, and */
/* visible in the overal profile conversion. The "native" PCS colorspace is the one */
/* that the underlying tags actually represent, and the PCS that the individual */
/* stages within each profile type handle (unless the ICX_MERGED flag is set, in which */
/* case the clut == native PCS appears to be the effective one). The conversion between */
/* the native and effective PCS is generally done in the to/from_abs() conversions. */

/* ------------------------------------------------------------------------------ */

/* Pseudo intents, valid as parameter to xicc get_luobj(): */

/* Default Color Appearance Space, based on absolute colorimetric */
#define icxAppearance ((icRenderingIntent)994)

/* Represents icAbsoluteColorimetric, converted to Color Appearance space */
#define icxAbsAppearance ((icRenderingIntent)995)	/* Fixed D50 white point */

/* Special Color Appearance Space, based on "absolute" perceptual */
#define icxPerceptualAppearance ((icRenderingIntent)996)

/* Default Color Appearance Space, based on "absolute" saturation */
#define icxSaturationAppearance ((icRenderingIntent)997)

/* These two are for completeness, they are unlikely to be useful: */
/* Special Color Appearance Space, based on "absolute" perceptual */
#define icxAbsPerceptualAppearance ((icRenderingIntent)998)

/* Default Color Appearance Space, based on "absolute" saturation */
#define icxAbsSaturationAppearance ((icRenderingIntent)999)


/* Pseudo PCS colospace returned as PCS for intent icxAppearanceJab */
#define icxSigJabData ((icColorSpaceSignature) icmMakeTag('J','a','b',' '))

/* Pseudo PCS colospace returned as PCS for intent icxAppearanceJCh */
#define icxSigJChData ((icColorSpaceSignature) icmMakeTag('J','C','h',' '))

/* Pseudo PCS colospace returned as PCS */
#define icxSigLChData ((icColorSpaceSignature) icmMakeTag('L','C','h',' '))

/* Return a string description of the given enumeration value */
const char *icx2str(icmEnumType etype, int enumval);


/* ------------------------------------------------------------------------------ */

/* A 3x3 matrix model */
struct _icxMatrixModel {
	void *imp;		/* Opaque implementation */

	icc *picc;		/* ICC profile used to set cone space matrix, NULL for Bradford. */
	int isLab;		/* Convert lookup to Lab */

	void (*force) (struct _icxMatrixModel *p, double *targ, double *in);
	void (*lookup) (struct _icxMatrixModel *p, double *out, double *in);
	void (*del) (struct _icxMatrixModel *p);

}; typedef struct _icxMatrixModel icxMatrixModel;

/* Create a matrix model of a set of points, and return an object to lookup */
/* points from the model. Return NULL on error. */
icxMatrixModel *new_MatrixModel(
icc *picc,			/* ICC profile used to set cone space matrix, NULL for Bradford. */
int verb,			/* NZ if verbose */
int nodp,			/* Number of points */
cow *ipoints,		/* Array of input points in XYZ space */
int isLab,			/* nz if data points are Lab */
int quality,		/* Quality metric, 0..3 (-1 == 2 orders only) */
int isLinear,		/* NZ if pure linear, gamma = 1.0 */
int isGamma,		/* NZ if gamma rather than shaper */
int isShTRC,		/* NZ if shared TRCs */
int shape0gam,		/* NZ if zero'th order shaper should be gamma function */
int clipbw,			/* Prevent white > 1 and -ve black */
int clipprims,		/* Prevent primaries going -ve */
double smooth,		/* Smoothing factor (nominal 1.0) */
double scale		/* Amount to scale device values */
);

/* ------------------------------------------------------------------------------ */
/* Basic class keeps extra state for an icc, and provides the */
/* expanded set of methods. */

/* Black generation rule */
/* The rule is all in terms of device K and L* values */
typedef enum {
    icxKvalue    = 0,	/* K is specified as output K target by PCS auxiliary */
    icxKlocus    = 1,	/* K is specified as proportion of K locus by PCS auxiliary */
    icxKluma5    = 2,	/* K is specified as locus by 5 parameters as a function of L */
    icxKluma5k   = 3,	/* K is specified as K value by 5 parameters as a function of L */
    icxKl5l      = 4,	/* K is specified as locus by 2x5 parameters as a function of L and K locus aux */
    icxKl5lk      = 5	/* K is specified as K value by 2x5 parameters as a function of L and K value aux */
} icxKrule;

/* Curve parameters */
typedef struct {
	double Ksmth;		/* K smoothing filter extent */
	double Kstle;		/* K start level at white end (0.0 - 1.0)*/
	double Kstpo;		/* K start point as prop. of L locus (0.0 - 1.0) */
	double Kenpo;		/* K end point as prop. of L locus (0.0 - 1.0) */
	double Kenle;		/* K end level at Black end (0.0 - 1.0) */
	double Kshap;		/* K transition shape, 0.0-1.0 concave, 1.0-2.0 convex */
	double Kskew;		/* K transition shape skew, 1.0 = even */
} icxInkCurve;

/* Default black generation smoothing value */
#define ICXINKDEFSMTH 0.09	/* Transition window of +/- ICXINKDEFSMTH */
#define ICXINKDEFSKEW 2.0	/* Curve shape skew (matches typical device behaviour) */

/* Structure to convey inking details */
typedef struct {
	double tlimit;		/* Total ink limit, > 0.0 to < inputChan, < 0.0 == off */
	double klimit;		/* Black limit, > 0.0 to < 1.0, < 0.0 == off */
	icxKrule k_rule;	/* type of K generation rule */
	int KonlyLmin;		/* Use K only black Locus Lmin */
	icxInkCurve c;		/* K curve, or locus minimum curve */
	icxInkCurve x;		/* locus maximum curve if icxKl5l */
} icxInk;

/* Structure to convey inverse lookup clip handling details */
struct _icxClip {
	int     nearclip;				/* Flag - use near clipping not vector */
	int     LabLike;				/* Flag Its an Lab like colorspace */
	int     fdi;					/* Dimentionality of clip vector */
	double  ocent[MXDO];			/* base of center of clut output gamut */
	double  ocentv[MXDO];			/* vector direction of clut output clip target line */
	double  ocentl;					/* clip target line length */
}; typedef struct _icxClip icxClip;

/* Structure to convey viewing conditions */
typedef struct {
	ViewingCondition Ev;/* Enumerated Viewing Condition */
	double Wxyz[3];		/* Reference/Adapted White XYZ (Y range 0.0 .. 1.0) */
	double La;			/* Adapting/Surround Luminance cd/m^2 */
	double Yb;			/* Relative Luminance of Background to reference white */
	double Lv;			/* Luminance of white in the Image/Scene/Viewing field (cd/m^2) */
						/* Ignored if Ev is set to other than vc_none */
	double Yf;			/* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
	double Yg;			/* Glare as a fraction of the adapting/surround (Y range 0.0 .. 1.0) */
	double Gxyz[3];		/* The Glare white coordinates (ie the Ambient color) */
						/* will be taken from Wxyz if Gxyz <= 0.0 */
	char *desc;			/* Possible description of this VC */
} icxViewCond;

/* Method of black point adaptation */
typedef enum {
	gmm_BPadpt    = 0,		/* Adapt source black point to destination */
	gmm_noBPadpt  = 1,		/* Don't adapt black point to destination */ 
	gmm_bendBP    = 2,		/* Don't adapt black point, bend it to dest. at end */  
	gmm_clipBP    = 3		/* Don't adapt black point, clip it to dest. at end */  
} icx_BPmap;

/* Structure to convey gamut mapping intent */
typedef struct {
	int    usecas;			/* 0x0 Use relative Lab space */
							/* 0x1 Use Absolute Lab Space */
							/* 0x2 Use Color Appearance Space */
							/* 0x3 Use Absolute Color Appearance Space */
							/* 0x102 Use Color Appearance Space with luminence scaling */
	int    usemap;			/* NZ if Gamut mapping should be used, else clip */
	double greymf;			/* Grey axis hue matching factor, 0.0 - 1.0 */
	double glumwcpf;		/* Grey axis luminance white compression factor, 0.0 - 1.0 */
	double glumwexf;		/* Grey axis luminance white expansion factor, 0.0 - 1.0 */
	double glumbcpf;		/* Grey axis luminance black compression factor, 0.0 - 1.0 */
	double glumbexf;		/* Grey axis luminance black expansion factor, 0.0 - 1.0 */
	double glumknf;			/* Grey axis luminance knee factor, 0.0 - 1.0 */
	icx_BPmap bph;			/* Method of black point adapation */
	double gamcpf;			/* Gamut compression factor, 0.0 - 1.0 */
	double gamexf;			/* Gamut expansion factor, 0.0 - 1.0 */
	double gamcknf;			/* Gamut compression knee factor, 0.0 - 1.0 */
	double gamxknf;			/* Gamut expansion knee factor, 0.0 - 1.0 */
	double gampwf;			/* Gamut Perceptual Map weighting factor, 0.0 - 1.0 */
	double gamswf;			/* Gamut Saturation Map weighting factor, 0.0 - 1.0 */
	double satenh;			/* Saturation enhancement value, 0.0 - Inf */
	char *as;				/* Alias string (option name) */
	char *desc;				/* Possible description of this VC */
	icRenderingIntent icci;	/* Closest ICC intent */
} icxGMappingIntent;

struct _xicc {
	/* Private: */
	icc *pp;			/* ICC profile we expand */

	struct _xcal *cal;	/* Optional device cal, NULL if none */
	int nodel_cal;		/* Flag, nz if cal was provided externally and shouldn't be deleted */

	/* Public: */
	void                 (*del)(struct _xicc *p);

	/* "use" flags */
#define ICX_CLIP_VECTOR  0x0000		/* If clipping is needed, clip in vector direction (default) */
#define ICX_CLIP_NEAREST 0x0010		/* If clipping is needed, clip to nearest */
#define ICX_MERGE_CLUT   0x0020		/* Merge the output() and out_abs() into the clut(), */
									/* for improved performance on reading, and */
									/* clipping in effective output space on inverse lookup. */
									/* Reduces accuracy noticably though. */
									/* Output output() and out_abs() become NOPs */
#define ICX_CAM_CLIP     0x0100		/* Use CAM space during invfwd clipping lookup, */
									/* irrespective of the native or effective PCS. */
									/* Ignored if MERGE_CLUT is set or vector clip is used. */
									/* May halve the inverse lookup performance! */ 
#define ICX_INT_SEPARATE 0x0400		/* Handle 4 dimensional devices with fixed inking rules */
									/* with an optimised internal separation pass, rather */
									/* than a point by point inverse locus lookup . */
									/* NOT IMPLEMENTED YET */
#define ICX_FAST_SETUP   0x0800		/* Improve initial setup speed at the cost of throughput */
#define ICX_VERBOSE      0x8000		/* Turn on verboseness during creation */

	                                /* Returm a lookup object from the icc */
	struct _icxLuBase *  (*get_luobj) (struct _xicc *p,
	                                   int flags,				/* clip, merge flags */
	                                   icmLookupFunc func,		/* Functionality */
	                                   icRenderingIntent intent,/* Intent */
	                                   icColorSpaceSignature pcsor,	/* PCS override (0 = def) */
	                                   icmLookupOrder order,	/* Search Order */
	                                   icxViewCond *vc,			/* Viewing Condition - only */
	                                                            /* used if pcsor == CIECAM. */
																/* or ICX_CAM_CLIP flag. */
	                                   icxInk *ink);			/* inking details (NULL = def) */


										/* Set a xluobj and icc table from scattered data */
										/* Return appropriate lookup object */
										/* NULL on error, check errc+err for reason */
	/* "create" flags */
#define ICX_SET_WHITE       0x00010000	/* find, set and make relative to the white point */
#define ICX_SET_WHITE_US    0x00030000	/* find, set and make relative to the white point hue, */
										/* but not scale to W L value, to avoid input clipping */
#define ICX_SET_WHITE_C     0x00050000	/* find, set and make relative to the white point hue, */
										/* and clip any cLUT values over D50 to D50 */
#define ICX_SET_BLACK       0x00080000	/* find and set the black point */
#define ICX_WRITE_WBL       0x00100000	/* Matrix: write White, Black & Luminance tags */
#define ICX_CLIP_WB         0x00200000	/* Clip white and black to be < 1 and > 0 respectively */
#define ICX_CLIP_PRIMS      0x00400000	/* Clip matrix primaries to be > 0 */
#define ICX_NO_IN_SHP_LUTS  0x00800000	/* Lut/Mtx: Don't create input (Device) shaper curves. */
#define ICX_NO_IN_POS_LUTS  0x01000000	/* LuLut: Don't create input (Device) postion curves. */
#define ICX_NO_OUT_LUTS     0x02000000	/* LuLut: Don't create output (PCS) curves. */
//#define ICX_2PASSSMTH     0x04000000	/* If LuLut: Use Gaussian smoothing */
//#define ICX_EXTRA_FIT     0x08000000	/* If LuLut: Counteract scat data point errors. */
/* And  ICX_VERBOSE         			   Turn on verboseness during creation */
	struct _icxLuBase * (*set_luobj) (struct _xicc *p,
	                                  icmLookupFunc func,		/* Functionality to set */
	                                  icRenderingIntent intent,	/* Intent to set */
	                                  icmLookupOrder order,		/* Search Order */
	                                  int flags,				/* white/black point flags */
	                                  int no,					/* Total Number of points */
	                                  int nobw,					/* Number of points to look */
																/* for white & black patches in */
	                                  cow *points,				/* Array of input points */
	                                  icxMatrixModel *skm, 		/* Optional skeleton model */
	                                  double dispLuminance,		/* > 0.0 if display luminance */
	                                                                    /* value and is known */
	                                  double wpscale,			/* > 0.0 if input white pt is */
	                                                                    /* is to be scaled */
//									  double *bpo, 				/* != NULL black point override */
	                                  double smooth,			/* RSPL smoothing factor, */
	                                                                        /* -ve if raw */
	                                  double avgdev,			/* Avge Dev. of points */
	                                  double demph,				/* cLut dark emphasis factor */
	                                  icxViewCond *vc,			/* Viewing Condition - only */
	                                                            /* used if pcsor == CIECAM. */
																/* or ICX_CAM_CLIP flag. */
	                                  icxInk *ink,				/* inking details */
	                                  struct _xcal *cal,		/* Optional cal Will override any */
																/* existing, not deltd with xicc. */
	                                  int quality);				/* Quality metric, 0..3 */


								/* Return the devices viewing conditions. */
								/* Return value 0 if it is well defined */
								/* Return value 1 if it is a guess */
								/* Return value 2 if it is not possible/appropriate */
	int     (*get_viewcond)(struct _xicc *p, icxViewCond *vc);

	char             err[512];			/* Error message */
	int              errc;				/* Error code */
}; typedef struct _xicc xicc;

/* ~~~~~ */
/* Might be good to add a slow but very precise vector and closest "clip to gamut" */
/* function for use in setting white and black points. Use this in profile. */

xicc *new_xicc(icc *picc);

/* ------------------------------------------------------------------------------ */
/* Expanded lookup object support */
#define XLU_BASE_MEMBERS																\
	/* Private: */																		\
	int              trace;					/* Optional run time tracing flag */		\
	struct _xicc    *pp;					/* Pointer to XICC we're a part of */		\
	icmLuBase       *plu;					/* Pointer to icm Lu we are expanding */	\
	int              flags;					/* Flags passed to get_luobj */				\
	icmLookupFunc    func;					/* Function passed to get_luobj */			\
	icRenderingIntent intent;				/* Effective/External Intent */				\
											/* "in" and "out" are in reference to */	\
											/* the requested lookup direction. */		\
    icColorSpaceSignature ins;				/* Effective/External Clr space of input */	\
    icColorSpaceSignature outs;				/* Effective/External Clr space of output */\
	icColorSpaceSignature pcs;				/* Effective/External PCS */				\
    icColorSpaceSignature natis;			/* Native input Clr space */				\
    icColorSpaceSignature natos;			/* Native output Clr space */				\
    icColorSpaceSignature natpcs;			/* Native PCS Clr space */					\
    int	inputChan;      					/* Num of input channels */					\
    int	outputChan;     					/* Num of output channels */				\
	double ninmin[MXDI];					/* icc Native Input color space minimum */	\
	double ninmax[MXDI];					/* icc Native Input color space maximum */	\
	double noutmin[MXDO];					/* icc Native Output color space minimum */	\
	double noutmax[MXDO];					/* icc Native Output color space maximum */	\
	double inmin[MXDI];						/* icx Effective Input color space minimum */	\
	double inmax[MXDI];						/* icx Effective Input color space maximum */	\
	double outmin[MXDO];					/* icx Effective Output color space minimum */	\
	double outmax[MXDO];					/* icx Effective Output color space maximum */	\
	icxViewCond  vc;						/* Viewing Condition for CIECAM97s */		\
	icxcam      *cam;						/* CAM conversion */						\
																						\
	/* Attributes inhereted by ixcLu's */												\
	int noisluts;	/* Flag - If LuLut: Don't create input (Device) shaper curves. */			\
	int noipluts;	/* Flag - If LuLut: Don't create input (Device) position curves. */	\
	int nooluts;	/* Flag - If LuLut: Don't create output (PCS) curves. */			\
	int nearclip;	/* Flag - If clipping occurs, return the nearest solution, */		\
	int mergeclut;	/* Flag - If LuLut: Merge output() and out_abs() into clut(). */	\
	int camclip;	/* Flag - If LuLut: Use CIECAM for clut reverse lookup clipping */ \
	int intsep;		/* Flag - If LuLut: Do internal separation for 4d device */			\
	int fastsetup;	/* Flag - If LuLut: Do fast setup at cost of slower throughput */	\
																						\
	/* Public: */																		\
	void    (*del)(struct _icxLuBase *p);												\
																						\
								/* Return Internal native colorspaces */				\
	void    (*lutspaces) (struct _icxLuBase *p, icColorSpaceSignature *ins, int *inn,	\
	                                        icColorSpaceSignature *outs, int *outn,		\
	                                        icColorSpaceSignature *pcs);				\
																						\
								/* External effective colorspaces */       	    		\
	void    (*spaces) (struct _icxLuBase *p, icColorSpaceSignature *ins, int *inn,		\
	                                     icColorSpaceSignature *outs, int *outn,		\
	                                     icmLuAlgType *alg, icRenderingIntent *intt,	 \
	                                     icmLookupFunc *fnc, icColorSpaceSignature *pcs); \
																						\
	/* Get the Native input space and output space ranges */							\
	void (*get_native_ranges) (struct _icxLuBase *p,										\
		double *inmin, double *inmax,		/* Maximum range of inspace values */		\
		double *outmin, double *outmax);	/* Maximum range of outspace values */		\
																						\
																						\
	/* Get the Effective input space and output space ranges */							\
	void (*get_ranges) (struct _icxLuBase *p,											\
		double *inmin, double *inmax,		/* Maximum range of inspace values */		\
		double *outmin, double *outmax);	/* Maximum range of outspace values */		\
																						\
																						\
	/* Return the media white and black points */										\
	/* in the effective PCS colorspace. */												\
	/* (ie. these will be relative values for relative intent etc.) */					\
	void    (*efv_wh_bk_points)(struct _icxLuBase *p, double *wht, double *blk, double *kblk);	\
																						\
	/* Translate color values through profile */										\
	/* 0 = success */																	\
	/* 1 = warning: clipping occured */													\
	/* 2 = fatal: other error */														\
																						\
	/* (Note that clipping is not a reliable means of detecting out of gamut in the */	\
	/* lookup(bwd) call for clut based profiles, but is for inv_lookup() calls.) */		\
																						\
	int            (*lookup) (struct _icxLuBase *p, double *out, double *in);			\
											/* Requested conversion */					\
	int			   (*inv_lookup) (struct _icxLuBase *p, double *out, double *in);		\
											/* Inverse conversion */					\
																						\
	/* Given an xicc lookup object, returm a gamut object. */							\
	/* Note that the Effective PCS must be Lab or Jab */								\
	/* A icxLuLut type must be icmFwd or icmBwd, */										\
	/* and for icmFwd, the ink limit (if supplied) */									\
	/* will be applied. */																\
	/* Return NULL on error, check xicc errc+err for reason */							\
	gamut * (*get_gamut) (struct _icxLuBase *plu,	/* xicc lookup object */			\
	                      double detail);			/* gamut detail level, 0.0 = def */	\
																						\
	/* The following two functions expose the relative colorimetric native ICC PCS */	\
	/* <--> absolute/CAM space transform, so that CAM based gamut compression */		\
	/* can be applied in creating the ICC Lut tabls in profout.c. */					\
																						\
	/* Given a native ICC relative XYZ or Lab PCS value, convert in the fwd */			\
	/* direction into the nominated Effective output PCS (ie. Absolute, Jab etc.) */	\
	void (*fwd_relpcs_outpcs) (struct _icxLuBase *p, icColorSpaceSignature is,			\
	                                                   double *out, double *in);		\
																						\
	/* Given a nominated Effective output PCS (ie. Absolute, Jab etc.), convert it */	\
	/* in the bwd direction into a native ICC relative XYZ or Lab PCS value */			\
	void (*bwd_outpcs_relpcs) (struct _icxLuBase *p, icColorSpaceSignature os,			\
	                                                   double *out, double *in);		\
																						\


/* Base xlookup object */
struct _icxLuBase {
	XLU_BASE_MEMBERS
}; typedef struct _icxLuBase icxLuBase;

/* Monochrome  Fwd & Bwd type object */
struct _icxLuMono {
	XLU_BASE_MEMBERS

	/* Overall lookups */
	int (*fwd_lookup) (struct _icxLuBase *p, double *out, double *in);
	int (*bwd_lookup) (struct _icxLuBase *p, double *out, double *in);

	/* Components of Device to PCS lookup */
	int (*fwd_curve) (struct _icxLuMono *p, double *out, double *in);
	int (*fwd_map)   (struct _icxLuMono *p, double *out, double *in);
	int (*fwd_abs)   (struct _icxLuMono *p, double *out, double *in);

	/* Components of PCS to Device lookup */
	int (*bwd_abs)   (struct _icxLuMono *p, double *out, double *in);
	int (*bwd_map)   (struct _icxLuMono *p, double *out, double *in);
	int (*bwd_curve) (struct _icxLuMono *p, double *out, double *in);

}; typedef struct _icxLuMono icxLuMono;

/* 3D Matrix Fwd & Bwd type object */
struct _icxLuMatrix {
	XLU_BASE_MEMBERS

	/* Overall lookups */
	int (*fwd_lookup) (struct _icxLuBase *p, double *out, double *in);
	int (*bwd_lookup) (struct _icxLuBase *p, double *out, double *in);

	/* Components of Device to PCS lookup */
	int (*fwd_curve)  (struct _icxLuMatrix *p, double *out, double *in);
	int (*fwd_matrix) (struct _icxLuMatrix *p, double *out, double *in);
	int (*fwd_abs)    (struct _icxLuMatrix *p, double *out, double *in);

	/* Components of PCS to Device lookup */
	int (*bwd_abs)    (struct _icxLuMatrix *p, double *out, double *in);
	int (*bwd_matrix) (struct _icxLuMatrix *p, double *out, double *in);
	int (*bwd_curve)  (struct _icxLuMatrix *p, double *out, double *in);

}; typedef struct _icxLuMatrix icxLuMatrix;

/* Multi-D. Lut type object */
struct _icxLuLut {
	XLU_BASE_MEMBERS

	/* private: */
	icmLut *lut;							/* ICC Lut that is being used */
	rspl	        *inputTable[MXDI];		/* The input lookups */
	rspl	        *clutTable;				/* The multi dimention lookup */
	rspl	        *cclutTable;			/* Alternate multi dimention lookup in CAM space */
	rspl	        *outputTable[MXDO];		/* The output lookups */

	/* Inverted RSPLs used to speed ink limit calculation */
	/* input' -> input */
	rspl *revinputTable[MXDI];

	/* In/Out lookup flags used for rspl init. callback */
	int iol_out;	/* Non-zero if output lookup */
	int iol_ch;		/* Channel */

	/* In/Out inversion support */
	double inputClipc[MXDI];	/* The input lookups clip center */
	double outputClipc[MXDO];	/* The output lookups clip center */

	/* clut inversion support */
	double      icent[MXDI];		/* center of input gamut */
	double      licent[MXDI];		/* last icent value used */

	icxClip clip;					/* Clip setup information */

	int kch;						/* Black ink channel if discovered */
									/* -1 if not known or applicable */
									/* (Only set by icxLu_comp_bk_point()) */
	icxInk      ink;				/* inking details */
	double Lmin, Lmax;				/* L min/max for inking rule */

	/* Auxiliary parameter flags, non-zero for inputs that will be */
	/* used as auxiliary parameters the rspl input */
	/* dimensionality exceeds the output dimension (i.e. CMYK->Lab) */
	int auxm[MXDI];	

	/* Auxiliar linearization function - NULL if none */
 	/* Only the used auxiliary chanels need be calculated. */
	/* ~~ not implimented yet ~~~ */
//	void (*auxlinf)(void *auxlinf_ctx, double inout[MXDI]);

	/* Opaque context for auxlin */
//	void *auxlinf_ctx;

	/* Temporary icm fwd abs XYZ LuLut used for setting up icx clut */
	icmLuBase *absxyzlu;

	/* Optional function to compute the input chanel */
 	/* sum from the raw rspl input values. NULL if not used. */
	/* Use this to take account of any transformation beyond */
	/* the input space, or 6 color masquerading as 4 etc. */
	double (*limitf)(void *limitf_ctx, float in[MXDI]);		/* ~~ not implimented yet */

	/* Opaque context for limitf */
	void *limitf_ctx;

	/* Input space sum limit. Points with a limitf() over */
	/* this number will not be considered in gamut. Valid if gt 0 */
	double slimit;

	/* public: */

	/* Note that black inking rules are always defined and provided */
	/* in dev[] and pcs[] space, even for component functions */
	/* (ie. the implementation of the inking rule deals with */
	/*  the dev<->dev' and pcs<->pcs' conversions) */
	
	/* Requested direction component lookup */
	int (*in_abs)  (struct _icxLuLut *p, double *out, double *in);
	int (*matrix)  (struct _icxLuLut *p, double *out, double *in);
	int (*input)   (struct _icxLuLut *p, double *out, double *in);
	int (*clut)    (struct _icxLuLut *p, double *out, double *in);
	int (*clut_aux)(struct _icxLuLut *p, double *out, double *olimit,
	                                     double *auxv, double *in);
	int (*output)  (struct _icxLuLut *p, double *out, double *in);
	int (*out_abs) (struct _icxLuLut *p, double *out, double *in);

	/* Inverse direction component lookup (in reverse order) */
	int (*inv_out_abs) (struct _icxLuLut *p, double *out, double *in);
	int (*inv_output)  (struct _icxLuLut *p, double *out, double *in);
	int (*inv_clut)    (struct _icxLuLut *p, double *out, double *in);
	int (*inv_clut_aux)(struct _icxLuLut *p, double *out, double *auxv,
                 double *auxr, double *auxt, double *clipd, double *in);
	int (*inv_input)   (struct _icxLuLut *p, double *out, double *in);
	int (*inv_matrix)  (struct _icxLuLut *p, double *out, double *in);
	int (*inv_in_abs)  (struct _icxLuLut *p, double *out, double *in);

	/* Get locus information for a clut (see xlut.c for details) */
	int (*clut_locus)  (struct _icxLuLut *p, double *locus, double *out, double *in);

	/* Get various types of information about the LuLut */
	void (*get_info) (struct _icxLuLut *p, icmLut **lutp,
	                 icmXYZNumber *pcswhtp, icmXYZNumber *whitep,
	                 icmXYZNumber *blackp);

	/* Get the matrix contents */
	void (*get_matrix) (struct _icxLuLut *p, double m[3][3]);

}; typedef struct _icxLuLut icxLuLut;

/* ------------------------------------------------------------------------------ */
/* Utility declarations and functions */

/* Profile Creation Suplimental Information structure */
struct _profxinf {
    icmSig manufacturer;	/* Device manufacturer ICC Sig, 0 for default */
	char *deviceMfgDesc;	/* Manufacturer text description, NULL for none */

    icmSig model;			/* Device model ICC Sig, 0 for default */
	char *modelDesc;		/* Model text description, NULL for none */

    icmSig creator;			/* Profile creator ICC Sig, 0 for default */

	char *profDesc;			/* Text profile description, NULL for default */

	char *copyright;		/* Copyrigh text, NULL for default */

	/* Attribute flags */
	int transparency;		/* NZ for Trasparency, else Reflective */
	int matte;				/* NZ for Matte, else Glossy */
	int negative;			/* NZ for Negative, else Positive */
	int blackandwhite;		/* NZ for BlackAndWhite, else Color */

	/* Default intent */
	icRenderingIntent  default_ri;	/* Default rendering intent */

	/* Other stuff ICC ?? */

}; typedef struct _profxinf profxinf;

/* Set an icc's Lut tables, and take care of auxiliary continuity problems. */
/* Only useful if there are auxiliary device output chanels to be set. */
int icxLut_set_tables_auxfix(
icmLut *p,						/* Pointer to icmLut object */
void   *cbctx,							/* Opaque callback context pointer value */
icColorSpaceSignature insig, 			/* Input color space */
icColorSpaceSignature outsig, 			/* Output color space */
void (*infunc)(void *cbctx, double *out, double *in),
						/* Input transfer function, inspace->inspace' (NULL = default) */
double *inmin, double *inmax,			/* Maximum range of inspace' values */
										/* (NULL = default) */
void (*clutfunc)(void *cbntx, double *out, double *aux, double *auxr, double *pcs, double *in),
						/* inspace' -> outspace' transfer function, also */
						/* return the internal target PCS and the  (packed) auxiliary locus */
						/* range as [min0, max0, min1, max1...], and the actual auxiliary */
						/* target used. */
void (*clutpcsfunc)(void *cbntx, double *out, double *aux, double *pcs),
						/* Internal PCS + actual aux_target -> outspace' transfer function */
void (*clutipcsfunc)(void *cbntx, double *pcs, double *olimit, double *auxv, double *in),
						/* outspace' -> Internal PCS + auxv check function */
double *clutmin, double *clutmax,		/* Maximum range of outspace' values */
										/* (NULL = default) */
void (*outfunc)(void *cbntx, double *out, double *in)
						/* Output transfer function, outspace'->outspace (NULL = deflt) */
);

		
/* Return an enumerated viewing condition */
/* Return enumeration if OK, -999 if there is no such enumeration. */
/* xicc may be NULL if just the description is wanted, */
/* or an explicit white point is provided. */
int xicc_enum_viewcond(
xicc *p,			/* Expanded profile to get white point (May be NULL if desc NZ) */
icxViewCond *vc,	/* Viewing parameters to return, May be NULL if desc is nz */
int no,				/* Enumeration to return, -1 for default, -2 for none */
char *as,			/* String alias to number, NULL if none */
int desc,			/* NZ - Just return a description of this enumeration in vc */
double *wp			/* Provide white point if xicc is NULL */
);

/* Debug: dump a Viewing Condition to standard out */
void xicc_dump_viewcond(icxViewCond *vc);

/* Debug: dump an Inking setup to standard out */
void xicc_dump_inking(icxInk *ik);

/* Return enumerated gamut mapping intents */
/* Return 0 if OK, 1 if there is no such enumeration. */
/* Note the following fixed numbers meanings: */
#define icxNoGMIntent -1
#define icxDefaultGMIntent -2
#define icxAbsoluteGMIntent -3
#define icxRelativeGMIntent -4
#define icxPerceptualGMIntent -5
#define icxSaturationGMIntent -6
#define icxIllegalGMIntent -999
int xicc_enum_gmapintent(icxGMappingIntent *gmi, int no, char *as);
void xicc_dump_gmi(icxGMappingIntent *gmi);

/* - - - - - - - - - - */
/* Utility functions: */

/* Given an open icc profile, */
/* guess which channel is the black. */
/* Return -1 if there is no black channel or it can't be guessed */
int icxGuessBlackChan(icc *p);

/* Given an icc profile, try and create an xcal */
/* Return NULL on error or no cal */
struct _xcal *xiccReadCalTag(icc *p);

/* A callback that uses an xcal, that can be used with icc get_tac */
void xiccCalCallback(void *cntx, double *out, double *in);

/* Given an xicc icc profile, estmate the total ink limit and black ink limit. */
void icxGetLimits(xicc *p, double *tlimit, double *klimit);

/* Using the above function, set default total and black ink values */
void icxDefaultLimits(xicc *p, double *tlout, double tlin, double *klout, double klin);

/* Given a calibrated total ink limit and an xcal, return the */
/* equivalent underlying (pre-calibration) total ink limit. */
/* This is the maximum equivalent, that makes sure that */
/* the calibrated limit is met or exceeded. */
double icxMaxUnderlyingLimit(struct _xcal *cal, double ilimit);

/* - - - - - - - - - - */

/* Utility function - compute the clip vector direction. */
/* return NULL if vector clip isn't used. */
double *icxClipVector(
icxClip *p,			/* Clipping setup information */
double *in,			/* Target point */
double *cdirv		/* Space for returned clip vector */
);

/* - - - - - - - - - - */

/* CIE XYZ to perceptual Lab with partial derivatives. */
void icxdXYZ2Lab(icmXYZNumber *w, double *out, double dout[3][3], double *in);

/* Return the normal Delta E squared, given two Lab values, */
/* including partial derivatives. */
double icxdLabDEsq(double dout[2][3], double *Lab0, double *Lab1);

/* Return the CIE94 Delta E color difference measure, squared */
/* including partial derivatives. */
double icxdCIE94sq(double dout[2][3], double Lab0[3], double Lab1[3]);

/* Return the normal Delta E given two Lab values, */
/* including partial derivatives. */
double icxdLabDE(double dout[2][3], double *Lab0, double *Lab1);

/* Return the CIE94 Delta E color difference measure */
/* including partial derivatives. */
double icxdCIE94(double dout[2][3], double Lab0[3], double Lab1[3]);

/* - - - - - - - - - - */
/* Power like function, based on Graphics Gems adjustment curve. */
/* Avoids "toe" problem of pure power. */
/* Adjusted so that "power" 2 and 0.5 agree with real power at 0.5 */
double icx_powlike(double vv, double pp);

/* Compute the necessary aproximate power, to transform */
/* the given value from src to dst. They are assumed to be */
/* in the range 0.0 .. 1.0 */
double icx_powlike_needed(double src, double dst);

/* - - - - - - - - - - */

/* Transfer function */
double icxTransFunc(
double *v,			/* Pointer to first parameter */
int    luord,		/* Number of parameters */
double vv			/* Source of value */
);

/* Inverse Transfer function */
double icxInvTransFunc(
double *v,			/* Pointer to first parameter */
int    luord,		/* Number of parameters */
double vv			/* Source of value */
);

/* Transfer function with scaling */
double icxSTransFunc(
double *v,			/* Pointer to first parameter */
int    luord,		/* Number of parameters */
double vv,			/* Source of value */
double min,			/* Scale values */
double max
);

/* Inverse Transfer function with scaling */
double icxInvSTransFunc(
double *v,			/* Pointer to first parameter */
int    luord,		/* Number of parameters */
double vv,			/* Source of value */
double min,			/* Scale values */
double max
);

/* Transfer function with partial derivative */
/* with respect to the parameters. */
double icxdpTransFunc(
double *v,			/* Pointer to first parameter */
double *dv,			/* Return derivative wrt each parameter [luord] */
int    luord,		/* Number of parameters */
double vv			/* Source of value */
);

/* Transfer function with scaling and */
/* partial derivative with respect to the parameters. */
double icxdpSTransFunc(
double *v,			/* Pointer to first parameter */
double *dv,			/* Return derivative wrt each parameter [luord] */
int    luord,		/* Number of parameters */
double vv,			/* Source of value */
double min,			/* Scale values */
double max
);

/* Transfer function with partial derivative */
/* with respect to the input value. */
double icxdiTransFunc(
double *v,			/* Pointer to first parameter */
double *pdv,		/* Return derivative wrt source value [1] */
int    luord,		/* Number of parameters */
double vv			/* Source of value */
);

/* Transfer function with scaling and */
/* partial derivative with respect to the input value. */
double icxdiSTransFunc(
double *v,			/* Pointer to first parameter */
double *pdv,		/* Return derivative wrt source value [1] */
int    luord,		/* Number of parameters */
double vv,			/* Source of value */
double min,			/* Scale values */
double max
);

/* Transfer function with partial derivative */
/* with respect to the parameters and the input value. */
double icxdpdiTransFunc(
double *v,			/* Pointer to first parameter */
double *dv,			/* Return derivative wrt each parameter [luord] */
double *pdin,		/* Return derivative wrt source value [1] */
int    luord,		/* Number of parameters */
double vv			/* Source of value */
);

/* Transfer function with scaling and */
/* partial derivative with respect to the */
/* parameters and the input value. */
double icxdpdiSTransFunc(
double *v,			/* Pointer to first parameter */
double *dv,			/* Return derivative wrt each parameter [luord] */
double *pdin,		/* Return derivative wrt source value [1] */
int    luord,		/* Number of parameters */
double vv,			/* Source of value */
double min,			/* Scale values */
double max
);

/* Should add/move the spectro/moncurve stuff in here, */
/* since it has offset and scaling. */

/* - - - - - - - - - - */
/* Multi-plane interpolation - uses base + di slope values.  */
/* Parameters are assumed to be fdi groups of di + 1 parameters. */
void icxPlaneInterp(
double *v,			/* Pointer to first parameter [fdi * (di + 1)] */
int    fdi,			/* Number of output channels */
int    di,			/* Number of input channels */
double *out,		/* Resulting fdi values */
double *in			/* Input di values */
);

/* Matrix cube interpolation. with partial derivative */
/* with respect to the input and parameters. */
void icxdpdiPlaneInterp(
double *v,			/* Pointer to first parameter value [fdi * (di + 1)] */
double *dv,			/* Return [1 + di] deriv. wrt each parameter v */
double *din,		/* Return [fdi * di] deriv. wrt each input value */
int    fdi,			/* Number of output channels */
int    di,			/* Number of input channels */
double *out,		/* Resulting fdi values */
double *in			/* Input di values */
);

/* - - - - - - - - - - */

/* Matrix cube interpolation - interpolate between 2^di output corner values. */
/* Parameters are assumed to be fdi groups of 2^di parameters. */
void icxCubeInterp(
double *v,			/* Pointer to first parameter */
int    fdi,			/* Number of output channels */
int    di,			/* Number of input channels */
double *out,		/* Resulting fdi values */
double *in			/* Input di values */
);

/* Matrix cube interpolation. with partial derivative */
/* with respect to the input and parameters. */
void icxdpdiCubeInterp(
double *v,			/* Pointer to first parameter value */
double *dv,			/* Return [fdi * 2^di] deriv wrt each parameter v */
double *din,		/* Return [fdi * di] deriv wrt each input value */
int    fdi,			/* Number of output channels */
int    di,			/* Number of input channels */
double *out,		/* Resulting fdi values */
double *in			/* Input di values */
);

/* - - - - - - - - - - */

/* 3x3 matrix in 1D array multiplication */
void icxMulBy3x3Parm(
	double out[3],			/* Return input multiplied by matrix */
	double mat[9],			/* Matrix organised in [slow][fast] order */
	double in[3]			/* Input values */
);

/* 3x3 matrix in 1D array multiplication, with partial derivatives */
/* with respect to just the input. */
void icxdpdiiMulBy3x3Parm(
	double out[3],			/* Return input multiplied by matrix */
	double din[3][3],		/* Return deriv for each [output] with respect to [input] */
	double mat[9],			/* Matrix organised in [slow][fast] order */
	double in[3]			/* Input values */
);

/* 3x3 matrix in 1D array multiplication, with partial derivatives */
/* with respect to the input and parameters. */
void icxdpdiMulBy3x3Parm(
	double out[3],			/* Return input multiplied by matrix */
	double dv[3][9],		/* Return deriv for each [output] with respect to [param] */
	double din[3][3],		/* Return deriv for each [output] with respect to [input] */
	double mat[9],			/* Matrix organised in [slow][fast] order */
	double in[3]			/* Input values */
);

/* - - - - - - - - - - */

#include "xcal.h"

#endif /* XICC_H */