--- ray/src/util/rmtxop.c 2023/12/08 00:12:31 2.30 +++ ray/src/util/rmtxop.c 2024/11/08 17:52:26 2.35 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: rmtxop.c,v 2.30 2023/12/08 00:12:31 greg Exp $"; +static const char RCSid[] = "$Id: rmtxop.c,v 2.35 2024/11/08 17:52:26 greg Exp $"; #endif /* * General component matrix operations. @@ -7,7 +7,6 @@ static const char RCSid[] = "$Id: rmtxop.c,v 2.30 2023 #include #include "rtio.h" -#include "resolu.h" #include "rmatrix.h" #include "platform.h" @@ -35,7 +34,7 @@ typedef struct { int verbose = 0; /* verbose reporting? */ /* Load matrix */ -static int +int loadmatrix(ROPMAT *rop) { if (rop->mtx != NULL) /* already loaded? */ @@ -46,10 +45,10 @@ loadmatrix(ROPMAT *rop) return(!rop->mtx ? -1 : 1); } -static int checksymbolic(ROPMAT *rop); +extern int checksymbolic(ROPMAT *rop); /* Check/set transform based on a reference input file */ -static int +int checkreffile(ROPMAT *rop) { static const char *curRF = NULL; @@ -108,7 +107,7 @@ checkreffile(ROPMAT *rop) } /* Compute conversion row from spectrum to one channel of RGB */ -static void +void rgbrow(ROPMAT *rop, int r, int p) { const int nc = rop->mtx->ncomp; @@ -125,7 +124,7 @@ rgbrow(ROPMAT *rop, int r, int p) } /* Compute conversion row from spectrum to one channel of XYZ */ -static void +void xyzrow(ROPMAT *rop, int r, int p) { const int nc = rop->mtx->ncomp; @@ -142,8 +141,8 @@ xyzrow(ROPMAT *rop, int r, int p) } /* Use the spectral sensitivity function to compute matrix coefficients */ -static void -sensrow(ROPMAT *rop, int r, double (*sf)(SCOLOR sc, int ncs, const float wlpt[4])) +void +sensrow(ROPMAT *rop, int r, double (*sf)(const SCOLOR sc, int ncs, const float wlpt[4])) { const int nc = rop->mtx->ncomp; int i; @@ -157,11 +156,12 @@ sensrow(ROPMAT *rop, int r, double (*sf)(SCOLOR sc, in } /* Check/set symbolic transform */ -static int +int checksymbolic(ROPMAT *rop) { const int nc = rop->mtx->ncomp; const int dt = rop->mtx->dtype; + double cf = 1; int i, j; /* check suffix => reference file */ if (strchr(rop->preop.csym, '.') > rop->preop.csym) @@ -182,28 +182,37 @@ checksymbolic(ROPMAT *rop) int comp = 0; switch (rop->preop.csym[j]) { case 'B': + case 'b': ++comp; /* fall through */ case 'G': + case 'g': ++comp; /* fall through */ case 'R': + case 'r': + if (rop->preop.csym[j] <= 'Z') + cf = 1./WHTEFFICACY; if (dt == DTxyze) { for (i = 3; i--; ) - rop->preop.cmat[j*nc+i] = 1./WHTEFFICACY * - xyz2rgbmat[comp][i]; + rop->preop.cmat[j*nc+i] = cf*xyz2rgbmat[comp][i]; } else if (nc == 3) rop->preop.cmat[j*nc+comp] = 1.; else rgbrow(rop, j, comp); break; case 'Z': + case 'z': ++comp; /* fall through */ case 'Y': + case 'y': ++comp; /* fall through */ case 'X': + case 'x': + if ((rop->preop.csym[j] <= 'Z') & (dt != DTxyze)) + cf = WHTEFFICACY; if (dt == DTxyze) { rop->preop.cmat[j*nc+comp] = 1.; } else if (nc == 3) { @@ -215,20 +224,27 @@ checksymbolic(ROPMAT *rop) else xyzrow(rop, j, comp); - for (i = nc*(dt != DTxyze); i--; ) - rop->preop.cmat[j*nc+i] *= WHTEFFICACY; + for (i = nc*(cf != 1); i--; ) + rop->preop.cmat[j*nc+i] *= cf; break; case 'S': /* scotopic (il)luminance */ + cf = WHTSCOTOPIC; + /* fall through */ + case 's': sensrow(rop, j, scolor2scotopic); - for (i = nc; i--; ) - rop->preop.cmat[j*nc+i] *= WHTSCOTOPIC; + for (i = nc*(cf != 1); i--; ) + rop->preop.cmat[j*nc+i] *= cf; break; case 'M': /* melanopic (il)luminance */ + cf = WHTMELANOPIC; + /* fall through */ + case 'm': sensrow(rop, j, scolor2melanopic); - for (i = nc; i--; ) - rop->preop.cmat[j*nc+i] *= WHTMELANOPIC; + for (i = nc*(cf != 1); i--; ) + rop->preop.cmat[j*nc+i] *= cf; break; case 'A': /* average component */ + case 'a': for (i = nc; i--; ) rop->preop.cmat[j*nc+i] = 1./(double)nc; break; @@ -239,10 +255,10 @@ checksymbolic(ROPMAT *rop) } } /* return recommended output type */ - if (!strcmp(rop->preop.csym, "XYZ")) { + if (!strcasecmp(rop->preop.csym, "XYZ")) { if (dt <= DTspec) return(DTxyze); - } else if (!strcmp(rop->preop.csym, "RGB")) { + } else if (!strcasecmp(rop->preop.csym, "RGB")) { if (dt <= DTspec) return(DTrgbe); } else if (dt == DTspec) @@ -251,7 +267,7 @@ checksymbolic(ROPMAT *rop) } /* Get matrix and perform unary operations */ -static RMATRIX * +RMATRIX * loadop(ROPMAT *rop) { int outtype = 0; @@ -351,7 +367,7 @@ failure: } /* Execute binary operation, free matrix arguments and return new result */ -static RMATRIX * +RMATRIX * binaryop(const char *inspec, RMATRIX *mleft, int op, RMATRIX *mright) { RMATRIX *mres = NULL; @@ -428,7 +444,7 @@ binaryop(const char *inspec, RMATRIX *mleft, int op, R } /* Perform matrix operations from left to right */ -static RMATRIX * +RMATRIX * op_left2right(ROPMAT *mop) { RMATRIX *mleft = loadop(mop); @@ -444,7 +460,7 @@ op_left2right(ROPMAT *mop) } /* Perform matrix operations from right to left */ -static RMATRIX * +RMATRIX * op_right2left(ROPMAT *mop) { RMATRIX *mright; @@ -473,7 +489,7 @@ op_right2left(ROPMAT *mop) : (mop)->mtx->ncols) /* Should we prefer concatenating from rightmost matrix towards left? */ -static int +int prefer_right2left(ROPMAT *mop) { int mri = 0; @@ -500,7 +516,7 @@ prefer_right2left(ROPMAT *mop) return(t_ncols(mop+mri) < t_nrows(mop)); } -static int +int get_factors(double da[], int n, char *av[]) { int ac; @@ -510,7 +526,7 @@ get_factors(double da[], int n, char *av[]) return(ac); } -static ROPMAT * +ROPMAT * resize_moparr(ROPMAT *mop, int n2alloc) { int nmats = 0; @@ -518,7 +534,7 @@ resize_moparr(ROPMAT *mop, int n2alloc) while (mop[nmats++].binop) ; - for (i = nmats; i > n2alloc; i--) + for (i = nmats; i >= n2alloc; i--) rmx_free(mop[i].mtx); mop = (ROPMAT *)realloc(mop, n2alloc*sizeof(ROPMAT)); if (mop == NULL) {