302 lines
10 KiB
C
302 lines
10 KiB
C
#ifndef NEARSMTH_H
|
|
#define NEARSMTH_H
|
|
|
|
/*
|
|
* nearsmth
|
|
*
|
|
* Gamut mapping support routine that creates a list of
|
|
* guide vectors from the source to destination
|
|
* gamut, smoothed to retain reasonably even spacing.
|
|
*
|
|
* Author: Graeme W. Gill
|
|
* Date: 17/1/2002
|
|
* Version: 1.00
|
|
*
|
|
* Copyright 2002 - 2006 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.
|
|
*/
|
|
|
|
|
|
/* Settings for nearsmth & gammap */
|
|
|
|
#define GAMMAP_RSPLFLAGS (0) /* Default rspl flags */
|
|
#define GAMMAP_RSPLAVGDEV 0.005 /* Default average deviation */
|
|
|
|
/* Structures to hold weightings */
|
|
|
|
/* Color x light & dark = 14 combinations */
|
|
typedef enum {
|
|
/* Combinations in prioroty order */
|
|
gmm_light_red = 0x101,
|
|
gmm_light_yellow = 0x102,
|
|
gmm_light_green = 0x104,
|
|
gmm_light_cyan = 0x108,
|
|
gmm_light_blue = 0x110,
|
|
gmm_light_magenta = 0x120,
|
|
gmm_light_neutral = 0x140,
|
|
|
|
gmm_dark_red = 0x201,
|
|
gmm_dark_yellow = 0x202,
|
|
gmm_dark_green = 0x204,
|
|
gmm_dark_cyan = 0x208,
|
|
gmm_dark_blue = 0x210,
|
|
gmm_dark_magenta = 0x220,
|
|
gmm_dark_neutral = 0x240,
|
|
|
|
gmm_l_d_red = 0x301,
|
|
gmm_l_d_yellow = 0x302,
|
|
gmm_l_d_green = 0x304,
|
|
gmm_l_d_cyan = 0x308,
|
|
gmm_l_d_blue = 0x310,
|
|
gmm_l_d_magenta = 0x320,
|
|
gmm_l_d_neutral = 0x340,
|
|
|
|
gmm_light_colors = 0x17f, /* All light colors */
|
|
gmm_dark_colors = 0x27f, /* All dark colors */
|
|
|
|
gmm_default = 0x37f, /* All light and dark colors */
|
|
|
|
gmm_end = 0x0000, /* Mark the end of the list */
|
|
gmm_ignore = 0x1001, /* Ignore this entry */
|
|
|
|
/* Components */
|
|
gmc_light = 0x100,
|
|
gmc_dark = 0x200,
|
|
gmc_l_d = 0x300, /* Both Light and dark */
|
|
gmc_red = 0x001,
|
|
gmc_yellow = 0x002,
|
|
gmc_green = 0x004,
|
|
gmc_cyan = 0x008,
|
|
gmc_blue = 0x010,
|
|
gmc_magenta = 0x020,
|
|
gmc_neutral = 0x040,
|
|
gmc_colors = 0x07f /* All colors */
|
|
|
|
} gmm_chex;
|
|
|
|
/* Single weight */
|
|
typedef struct {
|
|
double l,c,h;
|
|
} iweight;
|
|
|
|
/* Group of complete weights */
|
|
/* (Remeber to alter near_wcopy() and near_wblend() !!) */
|
|
typedef struct {
|
|
|
|
gmm_chex ch; /* Color hextant this applies to */
|
|
|
|
/* Cusp alignment control */
|
|
struct {
|
|
iweight w; /* Component alignment weights, 0 - 1 */
|
|
double tw; /* Alignment twist power, 0 = linear, 1 = curve, 2+ late curve */
|
|
/* Use > 0 to make cusp alignment only affect surface colors. */
|
|
double cx; /* Chroma expansion, 1 = none, > 1 = more */
|
|
} c;
|
|
|
|
/* Radial weighting (This seems to be not working at the moment ?) */
|
|
/* Weight to give to minimizing delta E to source mapped radially */
|
|
struct {
|
|
double o; /* Overall Radial weight */
|
|
double h; /* Hue dominance vs l+c, 0 - 1 */
|
|
double l; /* l dominance vs, c, 0 - 1 */
|
|
} l;
|
|
|
|
/* Absolute error weighting. */
|
|
/* Weight given to minimizing delta E to destination closest point */
|
|
struct {
|
|
double o; /* Overall Absolute weight */
|
|
|
|
double h; /* Hue dominance vs l+c, 0 - 1 */
|
|
|
|
double wl; /* White l dominance vs, c, 0 - 1 */
|
|
double gl; /* Grey l dominance vs, c, 0 - 1 */
|
|
double bl; /* Black l dominance vs, c, 0 - 1 */
|
|
|
|
double wlth; /* White l blend start radius, 0 - 1, at white = 0 */
|
|
double blpow; /* Black l blend power, linear = 1.0, enhance < 1.0 */
|
|
|
|
double lxpow; /* L error extra power, none = 1.0 */
|
|
double lxthr; /* L error xover threshold in DE */
|
|
} a;
|
|
|
|
/* Relative vector smoothing. */
|
|
struct {
|
|
double rdl; /* Direction smoothing radius L* dir. (delta E radius at src point)*/
|
|
double rdh; /* Direction smoothing radius H* (delta E radius at src point)*/
|
|
|
|
double dsm; /* Degree of smoothing (non-linear response) */
|
|
} r;
|
|
|
|
/* Depth room weighting. */
|
|
/* Weighing to give to minimizing depth ratio by mapping to/from adequate dest/src depth. */
|
|
/* The idea is to compromize luminance and/or hue to allow room for */
|
|
/* preserving saturation distinction under heavy compression. */
|
|
struct {
|
|
double co; /* Overall compression weighting */
|
|
double xo; /* Overall expansion weighting */
|
|
} d;
|
|
|
|
/* Fine tuning destination gamut mapping */
|
|
struct {
|
|
double x; /* Final expansion weight, 0 - 1 */
|
|
} f; /* Weights fine tuning to expand rather than just compress */
|
|
|
|
/* Internal use */
|
|
iweight rl; /* Resolved radial weight */
|
|
iweight ra; /* Resolved absolute weight */
|
|
|
|
int set; /* Whether this has been set */
|
|
} gammapweights;
|
|
|
|
|
|
/* Blend a two groups of weights into one, given two weightings */
|
|
void near_wblend(gammapweights *dst,
|
|
gammapweights *src1, double wgt1, gammapweights *src2, double wgt2);
|
|
|
|
|
|
/* A neighbour and it's weight for relative error */
|
|
typedef struct {
|
|
struct _nearsmth *n; /* Pointer to neigbor */
|
|
double rw; /* Raw neighbor interpolation weight (1.0 at point) */
|
|
double w; /* Neighbor interpolation weight (sums to 1.0) */
|
|
} neighb;
|
|
|
|
/* Returned point values. */
|
|
/* Note that source == input point, destination == output point */
|
|
/* (All the source values are in rotated L mapped partial gamut mapped space) */
|
|
struct _nearsmth {
|
|
|
|
/* Public: */
|
|
int uflag; /* Use flag, 0 = normal, 1 = grid surface point */
|
|
int gflag; /* Gamut direction flag. 0 = not determinable, 1 = comp., 2 = exp. */
|
|
int vflag; /* Vector direction flag. 0 = not determinable, 1 = comp., 2 = exp. */
|
|
/* sv2, dv2, sd3 etc. are valid if vflag != 0 */
|
|
|
|
/* Gamut surface mapping guide point */
|
|
double sv[3]; /* Source value (input, cusp aligned during fwd optimization) */
|
|
double sr; /* Corresponding source radius from center */
|
|
double drv[3]; /* Destination radial value (starting point & reference) */
|
|
double drr; /* Destination radial value radius from center */
|
|
double dv[3]; /* Output destination value */
|
|
double dr; /* Output destination value radius from center */
|
|
double div[3]; /* gam[cx]pf moderated dv[] value */
|
|
double w1; /* guide point weight */
|
|
|
|
/* Gamut sub-surface mapping guide point (knee shape controlled by gamcknf & gamxknf) */
|
|
double sv2[3]; /* Sub-surface source value */
|
|
double dv2[3]; /* Sub-surface knee'd adjusted destination value */
|
|
double div2[3]; /* gam[cx]pf moderated dv2[] value */
|
|
double w2; /* Sub-surface weight (set in nearsmth) */
|
|
|
|
double sd3[3]; /* Deep sub-surface source & destination value */
|
|
double w3; /* Deep sub-surface weight */
|
|
|
|
/* Diagnostic points */
|
|
double csv[3]; /* Non-cusp mapped source value */
|
|
|
|
/* Private to nearsmth: */
|
|
gammapweights wt; /* Weight for this point determined from original source location */
|
|
int swap; /* Swapped during nearest finding */
|
|
double mL, fmL; /* Mid point L value, filtered mid point L value */
|
|
double m2d[3][4]; /* Tangent alignment rotation for sv[] 3D -> 2D */
|
|
double m3d[3][4]; /* Tangent alignment rotation for 2D -> sv[] 3D */
|
|
double _sv[3]; /* Original (non cusp aligned) source value (input) */
|
|
double _sr; /* Original source radius */
|
|
double naxbf; /* Blend factor that goes to 0.0 at white & black points. */
|
|
double aodv[3]; /* Absolute error optimized destination value */
|
|
double nrdv[3]; /* No relative smoothed destination value */
|
|
double anv[3]; /* Average neighborhood target point (relative target) */
|
|
|
|
double tdst[3]; /* Target destination on gamut */
|
|
int nott; /* NZ if not a point that needs to land on gamut */
|
|
double evect[3]; /* Accumulated extension vector direction */
|
|
double clen; /* Current correction length needed */
|
|
double coff[3]; /* Correction offset */
|
|
double rext;
|
|
|
|
double temp[3]; /* General temporary */
|
|
gamut *sgam; /* Source gamut src_gam = intersection of src and img gamut gamut */
|
|
gamut *dgam; /* Intersected destination gamut dst_gam */
|
|
gamut *dcgam; /* Destination Colorspace gamut dc_gam */
|
|
|
|
int nnd, _nnd; /* No & size of direction neighbour list */
|
|
neighb *nd; /* Allocated list of neighbours */
|
|
double nscale[3]; /* Neighborhood scale change from sv to dv */
|
|
|
|
double dcratio; /* Depth compression ratio */
|
|
double dxratio; /* Depth expansion ratio */
|
|
|
|
int debug;
|
|
double dbgv[3]; /* Error components va, vr, vd on last itteration */
|
|
|
|
}; typedef struct _nearsmth nearsmth;
|
|
|
|
|
|
/* Return the upper bound on the number of points that will be generated */
|
|
int near_smooth_np(
|
|
gamut **pp_gam, /* Return gamut that was used for points */
|
|
gamut *sc_gam, /* Source colorspace gamut */
|
|
gamut *s_gam, /* Source image gamut (== sc_gam if none) */
|
|
gamut *d_gam, /* Destination colorspace gamut */
|
|
double xvra, /* Extra vertex ratio */
|
|
int gmult, /* Guide point multiplier, typically 4 */
|
|
int surfgres /* surface grid point resolution, 0 for none */
|
|
);
|
|
|
|
/* Return a list of points. Call free_nearsmth() after use */
|
|
/* Return NULL on error */
|
|
nearsmth *near_smooth(
|
|
int verb, /* Verbose flag */
|
|
int *npp, /* Return the number of points returned */
|
|
gamut *sc_gam, /* Source colorspace gamut */
|
|
gamut *s_gam, /* Source image gamut (== sc_gam if none) */
|
|
gamut *d_gam, /* Destination colorspace gamut */
|
|
int src_kbp, /* Use K only black point as src gamut black point */
|
|
int dst_kbp, /* Use K only black point as dst gamut black point */
|
|
double d_bp[3], /* Destination target black point - may be NULL */
|
|
gammapweights *wh, /* Structure holding weights */
|
|
double gamcknf, /* Gamut compression knee factor, 0.0 - 1.0 */
|
|
double gamxknf, /* Gamut expansion knee factor, 0.0 - 1.0 */
|
|
int usecomp, /* Flag indicating whether smoothed compressed value will be used */
|
|
int useexp, /* Flag indicating whether smoothed expanded value will be used */
|
|
double xvra, /* Extra vertex ratio */
|
|
int mapres, /* Target grid res for 3D RSPL, (allowing for gexp) */
|
|
double mapsmooth, /* Target smoothing for 3D RSPL */
|
|
double gexp, /* Total grid expansion ratio, none = 1.0 */
|
|
int surfgres, /* Surface grid point resolution, 0 for none */
|
|
datai map_il, /* Return input range */
|
|
datai map_ih,
|
|
datao map_ol, /* Return output range */
|
|
datao map_oh
|
|
);
|
|
|
|
/* Free the list of points that was returned */
|
|
void free_nearsmth(nearsmth *smp, int npp);
|
|
|
|
/* Expand the compact form of weights into the explicit form. */
|
|
int expand_weights(gammapweights out[14], gammapweights *in);
|
|
|
|
/* Blend two expanded groups of individual weights into one */
|
|
void near_xwblend(
|
|
gammapweights *dst,
|
|
gammapweights *src1, double wgt1,
|
|
gammapweights *src2, double wgt2
|
|
);
|
|
|
|
/* Blend three expanded groups of individual weights into one */
|
|
void near_xwblend3(
|
|
gammapweights *dst,
|
|
gammapweights *src1, double wgt1,
|
|
gammapweights *src2, double wgt2,
|
|
gammapweights *src3, double wgt3
|
|
);
|
|
|
|
/* Tweak weights according to extra cmy cusp flags or rel override */
|
|
void tweak_weights(gammapweights out[14], int dst_cmymap, int rel_oride);
|
|
|
|
#endif /* NEARSMTH_H */
|
|
|