summaryrefslogtreecommitdiff
path: root/xicc/mpp.h
blob: 26fa3a841628e8104e32d55238a028ecceb260e3 (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
#ifndef MPP_H
#define MPP_H

/* 
 * Argyll Color Correction System
 * Model Printer Profile object.
 *
 * Author: Graeme W. Gill
 * Date:   24/2/2002
 *
 * Copyright 2002 Graeme W. Gill
 * All rights reserved.
 * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
 * see the License.txt file for licencing details.
 *
 */

/* This version (based on mpp_x1) has n * 2^(n-1) shape params, */
/* used for linear interpolation of the shaping correction. */

/*
 * This object provides a model based printer forward profile
 * functionality, to support forward profiling and optimised
 * separation of printing devices with more than 4 inks.
 */

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

#define MPP_MXINKS 8		/* Would like to be ICX_MXINKS but need more dynamic allocation */
#define MPP_MXTCORD 20		/* Maximum shaper harmonic orders to use */
#define MPP_MXCCOMB (1 << MPP_MXINKS)	/* Maximum number of primary combinations */
#define MPP_MXPARMS (MPP_MXINKS * MPP_MXTCORD + (MPP_MXINKS * MPP_MXCCOMB/2) + MPP_MXCCOMB)
							/* Maximum total parameters for a band */
#define MPP_MXBANDS 61		/* Maximum number of spectral bands (enought for 10nm) */

/* A test patch value */
typedef struct {
  /* public: */
	double *nv;			/* [MPP_MXINKS] Device values */
	double *band;		/* [3+MPP_MXBANDS];	Target XYZ & Spectral reflectance values */

  /* private: */
	double w;			/* Weight for this pass */
	double *lband;		/* [3+MPP_MXBANDS];	L* scale Target XYZ & Spectral reflectance values */
	double Lab[3];		/* Target Lab value */
	double tpcnv, tpcnv1;	/* Intermediate values for band oba without channel och */
	double *tcnv;		/* [MPP_MXINKS] Transfer curve corrected device values */
	double *scnv;		/* [MPP_MXINKS] Ideal shape correction values for device input */
	double *pcnv;		/* [MPP_MXCCOMB] Primary combination values (pre or post shape) */
	double *fcnv;		/* [MPP_MXINKS * MPP_MXCCOMB/2] shape interpolation weights for och */
	double cXYZ[3];		/* Current model XYZ value */
	double err;			/* Delta E squared */
} mppcol;

struct _mpp {

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


	/* Create the mpp from scattered data points */
	/* Returns nz on error */
	int (*create) (struct _mpp *p,
	               int verb,				/* Vebosity level, 0 = none */
	               int quality,				/* Profile quality, 0..3 */
	               int display,				/* non-zero if display device */
	               double limit,			/* Total ink limit (not %) (if not display) */
	               inkmask imask,			/* Inkmask describing device colorspace */
	               int    spec_n,			/* Number of spectral bands, 0 if not valid */
	               double spec_wl_short,	/* First reading wavelength in nm (shortest) */
	               double spec_wl_long,		/* Last reading wavelength in nm (longest) */
	               double norm,				/* Normalising scale value */
	               instType itype,			/* Spectral instrument type (if not display) */
	               int no,					/* Number of points */
	               mppcol *points);			/* Array of input points */

	int (*write_mpp)(struct _mpp *p, char *filename, int lab);	/* write to a CGATS .mpp file */
	int (*read_mpp)(struct _mpp *p, char *filename);	/* read from a CGATS .mpp file */

	/* Get various types of information about the mpp */
	void (*get_info) (struct _mpp *p,
	                  inkmask *imask,		/* Inkmask, describing device colorspace */
	                  int *nodchan,			/* Number of device channels */
	                  double *limit,		/* Total ink limit (0.0 .. devchan) */
	                  int *spec_n,			/* Number of spectral bands, 0 if none */
	                  double *spec_wl_short,/* First reading wavelength in nm (shortest) */
	                  double *spec_wl_long, /* Last reading wavelength in nm (longest) */
	                  instType *itype,		/* Instrument type */
					  int *display);		/* NZ if display type */

	/* Set an illuminant and observer to use spectral model */
	/* for CIE lookup with optional FWA. Set both to default for XYZ mpp model. */
	/* Return 0 on OK, 1 on spectral not supported */
	/* If the model is for a display, the illuminant will be ignored. */
	int (*set_ilob) (struct _mpp *p,
		icxIllumeType ilType,			/* Illuminant type (icxIT_default for none) */
		xspect        *custIllum,		/* Custom illuminant (NULL for none) */
		icxObserverType obType,			/* Observer type (icxOT_default for none) */	
		xspect        custObserver[3],	/* Custom observer (NULL for none)  */
		icColorSpaceSignature  rcs,		/* Return color space, icSigXYZData or icSigLabData */
		int           use_fwa			/* NZ to involke FWA. */
	);

	/* Get the white and black points for this profile (default XYZ) */
	void (*get_wb) (struct _mpp *p,
	                  double *white,
	                  double *black,
	                  double *kblack);


	/* Lookup an XYZ or Lab color (default XYZ) */
	/* [will use spectral and FWA if configured] */
	void (*lookup) (struct _mpp *p,
	               double *out,					/* Returned XYZ or Lab */
	               double *in);					/* Input device values */

	/* Lookup an XYZ or Lab color with its partial derivative. */
	/* [will ignore spectral and FWA even if configured] */
	void (*dlookup)(struct _mpp *p,
	               double *out,					/* Return the XYZ or Lab */
	               double **dout,				/* Return the partial derivative dout[3][n] */
	               double *dev);

	/* Lookup an XYZ value. (never FWA corrected) */
	void (*lookup_xyz) (struct _mpp *p,
	               double *out,					/* Returned XYZ value */
	               double *in);					/* Input device values */

	/* Lookup a spectral value. (never FWA corrected) */
	void (*lookup_spec) (struct _mpp *p,
	               xspect *out,					/* Returned spectral value */
	               double *in);					/* Input device values */

	/* Return a gamut object, return NULL on error */
	gamut *(*get_gamut)(struct _mpp *p, double detail);	/* detail level 0.0 = default */

  /* Private: */
	int verb;				/* Verbose */

	/* General model information */
	int    display;			/* Non-zero if display profile rather than output */
	inkmask imask;			/* Inkmask describing device space */
	double limit;			/* Total ink limit (If output device) */
	int    spec_n;			/* Number of spectral bands, 0 if not valid */
	double spec_wl_short;	/* First reading wavelength in nm (shortest) */
	double spec_wl_long;	/* Last reading wavelength in nm (longest) */
	double norm;			/* Normalising scale value (will be 1.0) */
	instType itype;			/* Spectral instrument type (If output device) */
	mppcol white, black;	/* White and black points */
	mppcol kblack;			/* K only black point */

	/* Foward model parameters */
	int n;					/* Number of chanels */
	int nn;					/* Number of primary combinations = 1 << n  */
	int nnn2;				/* Total shape combinations = n * nn/2 */

	int cord;				/* Device transfer curve order (must be 1 <= cord <= MPP_MXTCORD) */
	double tc[MPP_MXINKS][3+MPP_MXBANDS][MPP_MXTCORD];	/* Device transfer curve parameters */
	int useshape;			/* Flag, NZ if shape parameters are being used */
	double ***shape;		/* [MPP_MXINKS][MPP_MXCCOMB][3+MPP_MXBANDS] Extra shaping parameters */
	double pc[MPP_MXCCOMB][3+MPP_MXBANDS];	/* Primary overlay combinations color values */

	/* Model housekeeping */
	/* Translate sparse shape color combo to compacted parameters and back */
	int f2c[MPP_MXINKS][MPP_MXCCOMB];		/* Full to Compact */
	struct { int ink; int comb; } c2f[MPP_MXINKS * MPP_MXCCOMB/2];	/* Compact to Full */

	/* Optimisation state */
	mppcol *otp;			/* Optimisation test point */
	int oit, ott;			/* Optimisation itteration and total itterations */
	int och;				/* Optimisation device channel 0..n-1 */
	int oba;				/* Optimisation band, 0..2 are XYZ, 3..spec_n+3 are spectral */
	double lpca[MPP_MXCCOMB][MPP_MXBANDS];	/* Primary combinations anchor L* band values */
	int nodp;				/* Number of device data points */
	mppcol *cols;			/* List of test points */
	double spmax;			/* Maximum spectral value of any sample and band */

	/* Lookup */
	icColorSpaceSignature pcs;	/* PCS to return, XYZ, Lab */
	xsp2cie *spc;			/* Spectral to CIE converter (NULL if using XYZ model) */

	/* Houskeeping */
	int errc;				/* Error code */
	char err[200];			/* Error message */
}; typedef struct _mpp mpp;

/* Create a new, uninitialised mpp */
mpp *new_mpp(void);


/* - - - - - - - - - - - - - */
/* mppcol utility functions */
/* Allocate the data portion of an mppcol */
/* Return NZ if malloc error */
int new_mppcol(
mppcol *p,			/* mppcol to allocate */
int n,				/* Number of inks */
int nb				/* Number of spectral bands */
);

/* Free the data allocation of an mppcol */
void del_mppcol(
mppcol *p,			/* mppcol to free */
int n,				/* Number of inks */
int nb				/* Number of spectral bands */
);

/* Copy the contents of one mppcol to another */
void copy_mppcol(
	mppcol *d,			/* Destination */
	mppcol *s,			/* Source */
	int n,				/* Number of inks */
	int nb				/* Number of spectral bands */
);

/* Allocate an array of mppcol, */
/* Return NULL if malloc error */
mppcol *new_mppcols(
	int no,				/* Number in array */
	int n,				/* Number of inks */
	int nb				/* Number of spectral bands */
);

/* Free an array of mppcol */
void del_mppcols(
	mppcol *p,			/* mppcol array to be free'd */
	int no,				/* Number in array */
	int n,				/* Number of inks */
	int nb				/* Number of spectral bands */
);

#endif /* MPP_H */