Files
2026-08-20 20:28:40 +01:00

293 lines
9.9 KiB
C

#ifndef MPP_H
#define MPP_H
/*
* Argyll Color Management 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: */
int version; /* 1 */
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 (= no of pairs?) = 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 */
icmErr e; /* Error code & 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 */
);
/* ================================ */
#ifdef COMMPLUS /* Commercial+ */
/* A channel change */
typedef struct {
inkmask im; /* Identity of ink */
int add; /* nz to add, z to delete */
xspect sp; /* If not NULL, spectra of colorant to add */
double Lab[3]; /* or if L > 0.0, L*a*b* of colorant to add */
double mix[MPP_MXINKS]; /* or mix of input profile colorants (can be < 0.0 and > 1.0) */
} mppchch;
/* Create a modified mpp */
mpp *mpp_modify(
mppchch *chl, /* List of changes */
int nil, /* Number in list */
mpp *p /* mpp2 to use as base */
);
#endif /* COMMPLUS Commercial+ */
#endif /* MPP_H */