Files
argyllcms/gamut/gamut.h
T
2026-08-20 20:28:40 +01:00

421 lines
17 KiB
C

#ifndef GAMUT_H
#define GAMUT_H
/*
* gamut
*
* Gamut support routines.
*
* Author: Graeme W. Gill
* Date: 9/3/2000
* Version: 1.00
*
* Copyright 2000-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.
*/
/*
Note that the input and output are expected to be Lab style
color coordinates, and that L->Z, a->X, b->Y.
*/
#include "../h/llist.h"
#define BSPDEPTH 100 /* Maximum BSP tree depth */
#define PFARNDIST 0.1 /* Positive (inwards) far "near" distance */
#define NFARNDIST -200.0 /* Negative (outwards) far "near" distance */
#define MFARNDIST PFARNDIST /* Minimum (absolute) of the two */
#define MAXGAMN 10 /* Maximum gamut point neighbors returned */
#define NSLOTS 6 /* Number of maximum direction slots */
struct _vrml; /* Declared in vrml.h, which may be #included after this */
/* ------------------------------------ */
#define NODE_STRUCT \
int tag; /* Type of node, 1 = vertex, 2 = quad */ \
double w, h; /* longitude width, latitude height of this box */ \
double hc, vc; /* longitude center, latitude center of this box */ \
struct _gnode {
NODE_STRUCT
}; typedef struct _gnode gnode;
/* ------------------------------------ */
/* Vertex node */
struct _gvert {
NODE_STRUCT
int rc; /* reference count */
struct _gvert *ul; /* Unused list */
int n; /* Index number of vertex */
int sn; /* Set Index number of vertex */
int tn; /* Triangulated Index number of vertex */
int f; /* Flag value */
#define GVERT_NONE 0x0000 /* No flags */
#define GVERT_SET 0x0001 /* Value has been set */
#define GVERT_TRI 0x0002 /* Vertex has been added to triangulation (Exclsv with _INSIDE) */
#define GVERT_INSIDE 0x0004 /* Vertex is inside the log hull (Exclusive with _TRI) */
#define GVERT_ISOS 0x0008 /* Intersecting gamuts "outside other gamut" flag */
#define GVERT_ESTP 0x0010 /* Non-fake establishment point */
#define GVERT_FAKE 0x0020 /* Fake establishment point */
int k0; /* k0 direction reference count */
double p[3]; /* Point in xyz rectangular coordinates, absolute */
double r[3]; /* Radial coordinates */
double lr0; /* log scaled r[0] */
double sp[3]; /* Point mapped to surface of unit sphere, relative to center */
double ch[3]; /* Point mapped for convex hull testing, relative to center */
int as; /* Assert checking flag, expdstbysrcmdst flag */
}; typedef struct _gvert gvert;
/* ------------------------------------ */
/* Quadtree node */
struct _gquad {
NODE_STRUCT
gnode *qt[4][NSLOTS];
/* Child nodes, NULL if none, */
/* Nodes are ordered: */
/* --------- */
/* | 2 | 3 | */
/* --------- */
/* | 0 | 1 | */
/* --------- */
/* and each node contains NSLOTS slots. */
/* If the quadtree recurses, the first slot containts another */
/* quadtree, otherwise the slots contain pointers to the */
/* four best vertices in the various directions. */
}; typedef struct _gquad gquad;
/* ------------------------------------ */
/* Common base class of BSP nodes */
#define BSP_STRUCT \
int tag; /* Type of node, 1 = bsp node, 2 = triangle, 3 = list */ \
double rs0, rs1; /* min/max radius squared from origin of all contained triangles */
struct _gbsp {
BSP_STRUCT
}; typedef struct _gbsp gbsp;
/* ------------------------------------ */
/* A BSP tree decision node */
struct _gbspn {
BSP_STRUCT
int n; /* Serial number */
double pe[4]; /* Plane equation values (center relative) */
struct _gbsp *po; /* Positive branch */
struct _gbsp *ne; /* Negative branch */
}; typedef struct _gbspn gbspn;
/* ------------------------------------ */
/* A BSP tree triangle list node */
struct _gbspl {
BSP_STRUCT
int n; /* Serial number */
int nt; /* Number of triangles in the list */
struct _gtri *t[]; /* List of triangles - allocated with struct */
}; typedef struct _gbspl gbspl;
/* ------------------------------------ */
/* A triangle in the surface mesh */
struct _gtri {
BSP_STRUCT
int n; /* Serial number */
struct _gvert *v[3]; /* Vertices in cw order */
struct _gedge *e[3]; /* Edges v[n] - v[n+1] */
int ei[3]; /* Index within edge structure of this triangle [0..1] */
double pe[4]; /* Vertex plane equation (absolute) */
/* (The first three elements is the unit normal vector to the plane, */
/* which points inwards) */
double che[4]; /* convex hull testing triangle plane equation (relative) */
double spe[4]; /* sphere mapped triangle plane equation (relative) */
double ee[3][4]; /* sphere sp[] Edge triangle plane equations for opposite edge (relative) */
int sort; /* lookup: Plane sorting result for each try */
int bsort; /* lookup: Current best tries sort */
unsigned int touch; /* nn: Per value touch count */
double mix[2][3]; /* nn: Bounding box min and max */
double area; /* Area - computed by nssverts() */
int ssverts; /* Number of stratified sampling verts needed - computed by nssverts() */
LINKSTRUCT(struct _gtri); /* Linked list structure */
}; typedef struct _gtri gtri;
/* ------------------------------------ */
/* An edge shared by two triangle in the mesh */
struct _gedge {
int n; /* Serial number */
struct _gvert *v[2]; /* Vertices of edge */
struct _gtri *t[2]; /* Triangles edge is part of */
int ti[2]; /* record of indexes of edge within the triangles [0..2]*/
double re[4]; /* Radial edge plane equation (relative) */
int as; /* Assert checking flag */
LINKSTRUCT(struct _gedge); /* Linked list structure */
}; typedef struct _gedge gedge;
/* ------------------------------------ */
/* The gamut nearest neighbor search structure */
struct _gnn {
struct _gamut *s; /* Base gamut object */
int n; /* Number of points stored */
gtri **sax[3 * 2]; /* Sorted axis pointers, one for each direction */
unsigned int tbase; /* Touch base value for this pass */
unsigned int ttarget; /* Touch target value for this pass */
}; typedef struct _gnn gnn;
/* ------------------------------------ */
/* A vector intersction point */
struct _gispnt {
double ip[3]; /* Intersecion Point */
double pv; /* Parameter value at intersection */
int dir; /* Direction: 1 = into gamut, 0 = out of gamut */
int edge; /* Edge: 2 = no isect, 1 = on edge, 0 = not on edge */
gtri *tri; /* Pointer to intersection triangle */
}; typedef struct _gispnt gispnt;
/* Gamut object */
struct _gamut {
/* Private: */
double sres; /* Surface triangle resolution */
int isJab; /* nz if Jab CIECAM02 type space rather than L*a*b* */
int isRast; /* nz if raster file point cloud, else colorspace */
/* (This affects convex hull filtering) */
double cent[3]; /* Gamut center for radial conversion. Default 50.0,0,0 */
/* Must be same to compare radial values. */
int nv; /* Number of vertices used out of allocation */
gvert *ul; /* Linked list of unused vertices */
int na; /* Number of vertices allocated */
int nsv; /* Number of vertices that have been set */
int ntv; /* Number of vertices used in triangulation */
gvert **verts; /* Pointers to allocated vertices */
int read_inited; /* Flag set if gamut was initialised from a read */
int lu_inited; /* Flag set if radial surface lookup is inited */
int ne_inited; /* Flag set if nearest lookup is inited */
int cu_inited; /* Flag set if cusp values inited and trustworthy */
int nofilter; /* Flag, skip segmented maxima filtering */
int no2pass; /* Flag, do only one pass of convex hull */
int doingfake; /* Internal transient state */
int pass; /* Pass number for multi-pass */
double logpow; /* Convex hull compression power (default 0.25) */
gquad *tl, *tr; /* Top left and quadtree elements */
gtri *tris; /* Surface triangles linked list */
gedge *edges; /* Edges between the triangles linked list */
gbsp *lutree; /* Lookup function BSP tree root */
gnn *nns; /* nearest neighbor acceleration structure */
int cswbset; /* Flag to indicate that the cs white & black points are set */
double cs_wp[3]; /* Color spaces white point */
double cs_bp[3]; /* Color spaces black point */
double cs_kp[3]; /* Color spaces K only black point */
int gawbset; /* Flag to indicate that the gamut white & black points are set */
double ga_wp[3]; /* Gamut white point */
double ga_bp[3]; /* Gamut black point */
double ga_kp[3]; /* Gamut K only black point */
int dcuspixs; /* Cusp we're up to */
double dcusps[6][3];/* Entered cusp values to setcusps(, 3, ) */
double cusps[6][3]; /* Cusp values for red, yellow, green, cyan, blue & magenta */
/* if cu_inited nz */
double mx[3], mn[3]; /* Range covered by input points */
double xvra; /* Extra vertex ratio - set/used by nssverts() */
int ssnverts; /* total ss vertices - set/used by nssverts() */
int ssvertn; /* Number of verts created for current triangle */
sobol *ss; /* Sobol ss generator currently being used */
gtri *nexttri; /* Context for getnexttri() */
/* Public: */
/* Methods */
void (*del)(struct _gamut *s); /* Free ourselves */
gvert *(*expand)(struct _gamut *s, double in[3]); /* Expand the gamut surface */
void (*set_cs_bp_kp_ovrd)(struct _gamut *s, double *bk, double *kp); /* Override cs black points */
int (*getisjab)(struct _gamut *s); /* Return the isJab flag value */
int (*getisrast)(struct _gamut *s); /* Return the isRast flag value */
void (*setnofilt)(struct _gamut *s); /* Disable segmented maxima filtering */
void (*getcent)(struct _gamut *s, double *cent); /* Return the gamut center location */
void (*getrange)(struct _gamut *s, double *min, double *max); /* Return the gamut range */
double (*getsres)(struct _gamut *s); /* Return the surface resolution */
int (*compatible)(struct _gamut *s, struct _gamut *t); /* Return the nz if compatible gamuts */
int (*nrawverts)(struct _gamut *s); /* Return the number of raw vertices */
int (*getrawvert)(struct _gamut *s, double pos[3], int ix);
/* Return the raw vertices location */
int (*nraw0verts)(struct _gamut *s); /* Return the number of raw vertices in */
/* the radial maxima direction*/
int (*getraw0vert)(struct _gamut *s, double pos[3], int ix);
/* Return the raw 0 direction vertices location */
int (*nverts)(struct _gamut *s); /* Return the number of surface vertices */
int (*getvert)(struct _gamut *s, double *rad, double pos[3], int ix);
/* Return the surface triangle vertices location and radius */
/* start at 0, and returns value is next index or -1 if last */
/* rad and/or pos may be NULL */
int (*nssverts)(struct _gamut *s, double vpua);
/* Return the number of stratified sampling surface vertices, */
/* for the given vertices per unit area parameter. */
int (*getssvert)(struct _gamut *s, double *rad, double pos[3], double norn[3], int ix);
/* Return the stratified sampling surface vertices */
/* location and radius. nssverts() sets vpua */
/* norm will contain the normal of the triangle */
/* the point originates from. */
void (*startnexttri)(struct _gamut *s); /* Reset indexing through triangles for getnexttri() */
int (*getnexttri)(struct _gamut *s, int v[3]);
/* Return the next surface triange, nz on no more */
/* Index v[] corresponds to order of getvert() */
double (*volume)(struct _gamut *s);
/* Return the total volume enclosed by the gamut */
int (*intersect)(struct _gamut *s, struct _gamut *s1, struct _gamut *s2);
/* Initialise this gamut with the intersection of the */
/* the two given gamuts. */
int (*exp_cyl)(struct _gamut *s, struct _gamut *s1, double ratio);
/* Initialise this gamut with the source gamut */
/* expanded cylindrically around the nautral axis by */
/* the given ratio. */
int (*nexpintersect)(struct _gamut *s, struct _gamut *s1, struct _gamut *s2);
/* Initialise this gamut with neutral axis points from sa, */
/* and then intersected with sb. */
int (*expdstbysrcmdst)(struct _gamut *s,
struct _gamut *dst, struct _gamut *sc, struct _gamut *dc,
void (*cvect)(void *cntx, double *p2, double *p1), void *cntx);
/* Expand dst by ((dc - sc) > 0) */
/* Initialise this gamut with the image/destination gamut sc */
/* expanded by the amount that dest (dc) colorspace is outside */
/* the source colorspace gamut. */
double (*radial)(struct _gamut *s, double out[3], double in[3]);
/* return point on surface in same radial direction. */
/* Return the radial radius to the surface point in */
/* colorspace units. out[] may be NULL */
double (*nradial)(struct _gamut *s, double out[3], double in[3]);
/* return point on surface in same radial direction, */
/* and normalised radial radius. This will be <= 1.0 if within */
/* gamut, and > 1.0 if out of gamut. out[] may be NULL */
void (*nearest)(struct _gamut *s, double out[3], double in[3]);
/* return point on surface closest to input */
void (*nearest_tri)(struct _gamut *s, double out[3], double in[3], gtri **ctri);
/* return point on surface closest to input & triangle */
int (*vector_isect)(struct _gamut *s, double *p1, double *p2, double *min, double *max,
double *mint, double *maxt,
gtri **mntri, gtri **mxtri);
/* Compute the intersection of the (extended to infinity) vector */
/* p1->p2 with the gamut surface. */
/* min is the intersection in the p1 direction, */
/* max is intersection in the p2 direction. mint and maxt are */
/* the parameter values at the two intersection points, a value of 0 */
/* being at p1 and 1 being at p2. mintri and maxtri return the */
/* intersection triangles. min, max, mint, maxt, */
/* mintri & maxtri may be NULL */
/* Return 0 if there is no intersection with the gamut. */
int (*vector_isectns)(struct _gamut *s, double *p1, double *p2, gispnt *lp, int ll);
/* Compute all the intersection pairs of the vector p1->p2 with */
/* the gamut surface. lp points to an array of ll gispnt to be */
/* filled in. If the list is too small, intersections will be */
/* arbitrarily ignored. */
/* Return the number of intersections set in list. Will be even. */
/* These will all be in then out pairs in direction p1->p2. */
void (*setwb)(struct _gamut *s, double *wp, double *bp, double *kp);
/* Define the colorspaces white, black and K only black points. */
/* May be NULL if unknown, and will be set to a default. */
/* Same colorspace as gamut */
int (*getwb)(struct _gamut *s, double *cswp, double *csbp, double *cskp,
double *gawp, double *gabp, double *gakp);
/* Get the colorspace and gamut white, black and K only black points. */
/* Return non-zero if not possible. Same colorspace as gamut */
void (*setcusps)(struct _gamut *s, int flag, double in[3]); /* Set potential cusp values. */
/* flag == 0 = reset, */
/* flag == 1 = add general point, */
/* flag == 3 = add definite point, */
/* flag == 2 = finish */
int (*getcusps)(struct _gamut *s, double cusps[6][3]); /* Get the cusp values for */
/* red, yellow, green, cyan, */
/* blue & magenta. Return */
/* nz if no cusps available. */
/* Following return nz on error: */
int (*write_to_vrml)(struct _gamut *s, struct _vrml *wrl, double trans, int docusps);
/* Append gamut surface to vrml. See also vrml->make_gamut_surface() etc. */
int (*write_vrml)(struct _gamut *s, char *filename,
int doaxes, int docusps); /* Write to a VRML .wrl/.x3d file */
int (*write_gam)(struct _gamut *s, char *filename); /* Write to a CGATS .gam file */
int (*read_gam)(struct _gamut *s, char *filename); /* Read from a CGATS .gam file */
int (*read_gam_fp)(struct _gamut *s, cgatsFile *fp, char *filename); /* Read using fp */
int (*write_trans_vrml)(struct _gamut *s, char *filename, /* Write transformed VRML/X3D .wrl */
int doaxes, int docusps, void (*transform)(void *cntx, double out[3], double in[3]), /* with xform */
void *cntx);
}; typedef struct _gamut gamut;
/* Creator */
gamut *new_gamut(double sres, int isJab, int isRast); /* Surface resolution, 0.0 = default */
/* Utility */
void gamut_rect2radial(gamut *s, double out[3], double in[3]);
void gamut_radial2rect(gamut *s, double out[3], double in[3]);
void gamut_Lab2RGB(double *in, double *out);
extern double gam_hues[2][7]; /* Generic Lab & Jab color hues in degrees */
#endif /* GAMUT_H */