From 22f703cab05b7cd368f4de9e03991b7664dc5022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Mon, 1 Sep 2014 13:56:46 +0200 Subject: Initial import of argyll version 1.5.1-8 --- xicc/xspect.h | 430 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 430 insertions(+) create mode 100644 xicc/xspect.h (limited to 'xicc/xspect.h') diff --git a/xicc/xspect.h b/xicc/xspect.h new file mode 100644 index 0000000..caca8b2 --- /dev/null +++ b/xicc/xspect.h @@ -0,0 +1,430 @@ + +#ifndef XSPECT_H +#define XSPECT_H + +/* + * Author: Graeme W. Gill + * Date: 21/6/01 + * Version: 1.00 + * + * Copyright 2000 - 2010 Graeme W. Gill + * All rights reserved. + * + * This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :- + * see the License2.txt file for licencing details. + */ + +/* + * This class supports converting spectral samples + * into CIE XYZ or D50 Lab tristimulous values. + */ + +/* + * TTBD: + * + */ + +#ifndef SALONEINSTLIB +#include "icc.h" /* icclib ICC definitions */ +#else /* SALONEINSTLIB */ +#include "conv.h" /* fake icclib ICC definitions */ +#endif /* SALONEINSTLIB */ + +#ifdef __cplusplus + extern "C" { +#endif + +/* ------------------------------------------------------------------------------ */ + +/* Structure for conveying spectral information */ + +/* NOTE :- should ditch norm, and replace it by */ +/* "units", ie. reflectance/transmittance 0..1, 0..100%, */ +/* W/nm/m^2 or mW/nm/m^2 */ +#define XSPECT_MAX_BANDS 601 /* Enought for 1nm from 300 to 900 */ + +typedef struct { + 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 */ + double spec[XSPECT_MAX_BANDS]; /* Spectral value, shortest to longest */ +} xspect; + +/* Some helpful macro's: */ + +/* Copy everything except the spectral values */ +#define XSPECT_COPY_INFO(PDST, PSRC) \ + (PDST)->spec_n = (PSRC)->spec_n, \ + (PDST)->spec_wl_short = (PSRC)->spec_wl_short, \ + (PDST)->spec_wl_long = (PSRC)->spec_wl_long, \ + (PDST)->norm = (PSRC)->norm + +/* Given an index and the sampling ranges, compute the sample wavelength */ +#define XSPECT_WL(SHORT, LONG, N, IX) \ +((SHORT) + (double)(IX) * ((LONG) - (SHORT))/((N)-1.0)) + +/* Given the address of an xspect and an index, compute the sample wavelegth */ +#define XSPECT_XWL(PXSP, IX) \ +(((PXSP)->spec_wl_short) + (double)(IX) * (((PXSP)->spec_wl_long) - ((PXSP)->spec_wl_short))/(((PXSP)->spec_n)-1.0)) + +/* Given a wavelength and the sampling ranges, compute the double index */ +#define XSPECT_DIX(SHORT, LONG, N, WL) \ +(((N)-1.0) * ((WL) - (SHORT))/((LONG) - (SHORT))) + +/* Given the wavelength and address of an xspect, compute the double index */ +#define XSPECT_XDIX(PXSP, WL) \ +(((PXSP)->spec_n-1.0) * ((WL) - ((PXSP)->spec_wl_short))/(((PXSP)->spec_wl_long) - ((PXSP)->spec_wl_short))) + +/* Given a wavelength and the sampling ranges, compute the nearest index */ +#define XSPECT_IX(SHORT, LONG, N, WL) \ +((int)floor(XSPECT_DIX(SHORT, LONG, N, WL) + 0.5)) + +/* Given a wavelength and address of an xspect, compute the nearest index */ +#define XSPECT_XIX(PXSP, WL) \ +((int)floor(XSPECT_DIX(PXSP, WL) + 0.5)) + +#ifndef SALONEINSTLIB + +/* Single spectrum utility functions. Return NZ if error */ +int write_xspect(char *fname, xspect *s); +int read_xspect(xspect *sp, char *fname); + +/* CMF utility functions. Return NZ if error */ +int write_cmf(char *fname, xspect cmf[3]); +int read_cmf(xspect cmf[3], char *fname); + +/* Save a set of nspec spectrum to a CGATS file. Return NZ if error */ +/* type 0 = SPECT, 1 = CMF */ +int write_nxspect(char *fname, xspect *sp, int nspec, int type); + +/* Restore a set of up to nspec spectrum from a CGATS file. Return NZ if error */ +/* type = any, 1 = SPECT, 2 = CMF, 3 = both */ +int read_nxspect(xspect *sp, char *fname, int *nret, int off, int nspec, int type); + +#endif /* !SALONEINSTLIB*/ + +/* Get interpolated value at wavelenth (not normalised) */ +double value_xspect(xspect *sp, double wl); + +/* De-normalize and set normalisation factor to 1.0 */ +void xspect_denorm(xspect *sp); + +#ifndef SALONEINSTLIB +/* Convert from one xspect type to another */ +void xspect2xspect(xspect *dst, xspect *targ, xspect *src); +#endif /* !SALONEINSTLIB*/ + +/* ------------------------------------------------------------------------------ */ +/* Class for converting between spectral and CIE */ + +/* We build in some useful spectra */ + +/* Type of illumination */ +typedef enum { + icxIT_default = 0, /* Default illuminant (usually D50) */ + icxIT_none = 1, /* No illuminant - self luminous spectrum */ + icxIT_custom = 2, /* Custom illuminant spectrum */ + icxIT_A = 3, /* Standard Illuminant A */ + icxIT_C = 4, /* Standard Illuminant C */ + icxIT_D50 = 5, /* Daylight 5000K */ + icxIT_D50M2 = 6, /* Daylight 5000K, UV filtered (M2) */ + icxIT_D65 = 7, /* Daylight 6500K */ + icxIT_E = 8, /* Equal Energy */ +#ifndef SALONEINSTLIB + icxIT_F5 = 9, /* Fluorescent, Standard, 6350K, CRI 72 */ + icxIT_F8 = 10, /* Fluorescent, Broad Band 5000K, CRI 95 */ + icxIT_F10 = 11, /* Fluorescent Narrow Band 5000K, CRI 81 */ + icxIT_Spectrocam = 12, /* Spectrocam Xenon Lamp */ + icxIT_Dtemp = 13, /* Daylight at specified temperature */ + icxIT_Ptemp = 14 /* Planckian at specified temperature */ +#endif /* !SALONEINSTLIB*/ +} icxIllumeType; + +/* Fill in an xpsect with a standard illuminant spectrum */ +/* return 0 on sucecss, nz if not matched */ +int standardIlluminant( +xspect *sp, /* Xspect to fill in */ +icxIllumeType ilType, /* Type of illuminant */ +double temp); /* Optional temperature in degrees kelvin, for Dtemp and Ptemp */ + +/* Given an emission spectrum, set the UV output to the given level. */ +/* The shape of the UV is taken from FWA1_stim, and the level is */ +/* with respect to the average of the input spectrum. */ +void xsp_setUV(xspect *out, xspect *in, double uvlevel); + + +/* Type of observer */ +typedef enum { + icxOT_default = 0, /* Default observer (usually CIE_1931_2) */ + icxOT_none = 1, /* No observer - (don't compute XYZ) */ + icxOT_custom = 2, /* Custom observer type weighting */ + icxOT_CIE_1931_2 = 3, /* Standard CIE 1931 2 degree */ + icxOT_CIE_1964_10 = 4, /* Standard CIE 1964 10 degree */ +#ifndef SALONEINSTLIB + icxOT_Stiles_Burch_2 = 5, /* Stiles & Burch 1955 2 degree */ + icxOT_Judd_Voss_2 = 6, /* Judd & Voss 1978 2 degree */ + icxOT_CIE_1964_10c = 7, /* Standard CIE 1964 10 degree, 2 degree compatible */ + icxOT_Shaw_Fairchild_2 = 8 /* Shaw & Fairchild 1997 2 degree */ +#endif /* !SALONEINSTLIB*/ +} icxObserverType; + +/* Return pointers to three xpsects with a standard observer weighting curves */ +/* return 0 on sucecss, nz if not matched */ +int standardObserver(xspect *sp[3], icxObserverType obType); + +/* Return a string describing the standard observer */ +char *standardObserverDescription(icxObserverType obType); + +/* Clamping state */ +typedef enum { + icxNoClamp = 0, /* Don't clamp XYZ/Lab to +ve */ + icxClamp = 1, /* Clamp XYZ/Lab to +ve */ +} icxClamping; + +/* The conversion object */ +struct _xsp2cie { + /* Private: */ + xspect illuminant; /* Lookup conversion/observer illuminant */ + int isemis; /* nz if we are doing an emission conversion */ + xspect observer[3]; + int doLab; /* Return D50 Lab result */ + icxClamping clamp; /* Clamp XYZ and Lab to be +ve */ + +#ifndef SALONEINSTLIB + /* FWA compensation */ + double bw; /* Integration bandwidth */ + xspect iillum; /* Y = 1 Normalised instrument illuminant spectrum */ + xspect imedia; /* Instrument measured media */ + xspect emits; /* Estimated FWA emmission spectrum */ + xspect media; /* Estimated base media (ie. minus FWA) */ + xspect tillum; /* Y = 1 Normalised target/simulated instrument illuminant spectrum */ + xspect oillum; /* Y = 1 Normalised observer illuminant spectrum */ + double Sm; /* FWA Stimulation level for emits contribution */ + double FWAc; /* FWA content (informational) */ + int insteqtarget; /* iillum == tillum, bypass FWA */ +#endif /* !SALONEINSTLIB*/ + + /* Public: */ + void (*del)(struct _xsp2cie *p); + + /* Convert (and possibly fwa correct) reflectance spectrum */ + /* Note that the input spectrum normalisation value is used. */ + /* Note that the returned XYZ is 0..1 range for reflectanc. */ + /* Emissive spectral values are assumed to be in mW/nm, and sampled */ + /* rather than integrated if they are not at 1nm spacing. */ + void (*convert) (struct _xsp2cie *p, /* this */ + double *out, /* Return XYZ or D50 Lab value */ + xspect *in /* Spectrum to be converted, normalised by norm */ + ); + + /* Convert and also return (possibly corrected) reflectance spectrum */ + /* Spectrum will be same wlength range and readings as input spectrum */ + /* Note that the returned XYZ is 0..1 range for reflectanc. */ + /* Emissive spectral values are assumed to be in mW/nm, and sampled */ + /* rather than integrated if they are not at 1nm spacing. */ + void (*sconvert) (struct _xsp2cie *p, /* this */ + xspect *sout, /* Return corrected refl. spectrum (may be NULL) */ + double *out, /* Return XYZ or D50 Lab value (may be NULL) */ + xspect *in /* Spectrum to be converted, normalised by norm */ + ); + +#ifndef SALONEINSTLIB + /* Set Media White. This enables extracting and applying the */ + /* colorant reflectance value from/to the meadia. */ + /* return NZ if error */ + int (*set_mw) (struct _xsp2cie *p, /* this */ + xspect *white /* Spectrum of plain media */ + ); + + /* Set Fluorescent Whitening Agent compensation */ + /* return NZ if error */ + int (*set_fwa) (struct _xsp2cie *p, /* this */ + xspect *iillum, /* Spectrum of instrument illuminant */ + xspect *tillum, /* Spectrum of target/simulated instrument illuminant, */ + /* NULL to use observer illuminant. */ + xspect *white /* Spectrum of plain media */ + ); + + /* Set FWA given updated conversion illuminant. */ + /* (We assume that xsp2cie_set_fwa has been called first) */ + /* return NZ if error */ + int (*update_fwa_custillum) (struct _xsp2cie *p, + xspect *tillum, /* Spectrum of target/simulated instrument illuminant, */ + /* NULL to use set_fwa() value. */ + xspect *custIllum /* Spectrum of observer illuminant */ + ); + + /* Get Fluorescent Whitening Agent compensation information */ + /* return NZ if error */ + void (*get_fwa_info) (struct _xsp2cie *p, /* this */ + double *FWAc /* FWA content as a ratio. */ + ); + + /* Extract the colorant reflectance value from the media. Takes FWA */ + /* into account if set. Media white or FWA must be set. */ + /* return NZ if error */ + int (*extract) (struct _xsp2cie *p, /* this */ + xspect *out, /* Extracted colorant refl. spectrum */ + xspect *in /* Spectrum to be converted, normalised by norm */ + ); + + + /* Apply the colorant reflectance value from the media. Takes FWA */ + /* into account if set. DOESN'T convert to FWA target illumination! */ + /* FWA must be set. */ + int (*apply) (struct _xsp2cie *p, /* this */ + xspect *out, /* Applied refl. spectrum */ + xspect *in /* Colorant reflectance to be applied */ + ); +#endif /* !SALONEINSTLIB*/ + +}; typedef struct _xsp2cie xsp2cie; + +xsp2cie *new_xsp2cie( + icxIllumeType ilType, /* Observer Illuminant to use */ + xspect *custIllum, + + icxObserverType obType, /* Observer */ + xspect custObserver[3], + icColorSpaceSignature rcs, /* Return color space, icSigXYZData or icSigLabData */ + /* ** Must be icSigXYZData if SALONEINSTLIB ** */ + icxClamping clamp /* NZ to clamp XYZ/Lab to be +ve */ +); + +#ifndef SALONEINSTLIB +/* --------------------------- */ +/* Spectrum locus */ + +/* Return the spectrum locus range for the given observer. */ +/* return 0 on sucecss, nz if observer not known */ +int icx_spectrum_locus_range(double *min_wl, double *max_wl, icxObserverType obType); + +/* Return an XYZ that is on the spectrum locus for the given observer. */ +/* wl is the input wavelength in the range icx_spectrum_locus_range(), */ +/* and return clipped result if outside this range. */ +/* Return nz if observer unknown. */ +int icx_spectrum_locus(double xyz[3], double in, icxObserverType obType); + +/* Determine whether the given XYZ is outside the spectrum locus */ +/* Return 0 if within locus */ +/* Return 1 if outside locus */ +/* Return 2 if unknown (bad observer) */ +int icx_outside_spec_locus(double xyz[3], icxObserverType obType); + +/* Return an aproximate RGB value for coloring within the spectrum locus */ +void icx_spec_locus_color(double rgb[3], double xyz[3], icxObserverType obType); + +/* --------------------------- */ +/* Density and other functions */ + +/* Given a reflectance or transmition spectral product, */ +/* return status T CMY + V density values */ +void xsp_Tdensity(double *out, /* Return CMYV density */ + xspect *in /* Spectral product to be converted */ + ); + +/* Given a reflectance or transmission XYZ value, */ +/* return approximate status T CMYV log10 density values */ +void icx_XYZ2Tdens( +double *out, /* Return aproximate CMYV log10 density */ +double *in /* Input XYZ values */ +); + +/* Given a reflectance or transmission XYZ value, */ +/* return log10 XYZ density values */ +void icx_XYZ2dens( +double *out, /* Return log10 XYZ density */ +double *in /* Input XYZ values */ +); + +/* Given an XYZ value, */ +/* return sRGB values */ +void icx_XYZ2sRGB( +double *out, /* Return sRGB value */ +double *wp, /* Input XYZ white point (may be NULL) */ +double *in /* Input XYZ values */ +); + + + +/* Given an illuminant definition and an observer model, return */ +/* the normalised XYZ value for that spectrum. */ +/* Return 0 on sucess, 1 on error */ +int icx_ill_sp2XYZ( +double xyz[3], /* Return XYZ value with Y == 1 */ +icxObserverType obType, /* Observer */ +xspect custObserver[3], /* Optional custom observer */ +icxIllumeType ilType, /* Type of illuminant */ +double ct, /* Input temperature in degrees K */ +xspect *custIllum); /* Optional custom illuminant */ + + +/* Given a choice of temperature dependent illuminant (icxIT_Dtemp or icxIT_Ptemp), */ +/* return the closest correlated color temperature to the given spectrum or XYZ. */ +/* An observer type can be chosen for interpretting the spectrum of the input and */ +/* the illuminant. */ +/* Note we're using CICDE94, rather than the traditional L*u*v* 2/3 space for CCT */ +/* Return -1 on erorr */ +double icx_XYZ2ill_ct( +double txyz[3], /* If not NULL, return the XYZ of the black body temperature */ +icxIllumeType ilType, /* Type of illuminant, icxIT_Dtemp or icxIT_Ptemp */ +icxObserverType obType, /* Observer */ +xspect custObserver[3], /* Optional custom observer */ +double xyz[3], /* Input XYZ value, NULL if spectrum intead */ +xspect *insp0, /* Input spectrum value, NULL if xyz[] instead */ +int viscct); /* nz to use visual CIEDE2000, 0 to use CCT CIE 1960 UCS. */ + +/* Compute the CIE1995 CRI: Ra */ +/* Return < 0.0 on error */ +/* If invalid is not NULL, set it to nz if CRI */ +/* is invalid because the sample is not white enough. */ +double icx_CIE1995_CRI( +int *invalid, /* if not NULL, set to nz if invalid */ +xspect *sample /* Illuminant sample to compute CRI of */ +); +#endif /* !SALONEINSTLIB*/ + +#ifdef __cplusplus + } +#endif + +#endif /* XSPECTFM_H */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3