--- ray/src/util/rmtxop.c 2023/12/03 02:28:33 2.28 +++ ray/src/util/rmtxop.c 2025/03/28 00:06:36 2.36 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: rmtxop.c,v 2.28 2023/12/03 02:28:33 greg Exp $"; +static const char RCSid[] = "$Id: rmtxop.c,v 2.36 2025/03/28 00:06:36 greg Exp $"; #endif /* * General component matrix operations. @@ -7,11 +7,12 @@ static const char RCSid[] = "$Id: rmtxop.c,v 2.28 2023 #include #include "rtio.h" -#include "resolu.h" #include "rmatrix.h" #include "platform.h" +#ifndef MAXCOMP #define MAXCOMP MAXCSAMP /* #components we support */ +#endif /* Unary matrix operation(s) */ typedef struct { @@ -35,7 +36,7 @@ typedef struct { int verbose = 0; /* verbose reporting? */ /* Load matrix */ -static int +int loadmatrix(ROPMAT *rop) { if (rop->mtx != NULL) /* already loaded? */ @@ -46,10 +47,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; @@ -69,7 +70,7 @@ checkreffile(ROPMAT *rop) fclose(fp); curRF = rop->preop.csym; } - if ((refm.ncomp == 3) & (refm.dtype != DTspec)) { + if (refm.ncomp == 3) { rop->preop.csym = (refm.dtype == DTxyze) ? "XYZ" : "RGB"; return(checksymbolic(rop)); } @@ -103,11 +104,12 @@ checkreffile(ROPMAT *rop) for (j = refm.ncomp; j-- > 0; ) rop->preop.cmat[j*nc + i] = scresp[j]; } + memcpy(rop->mtx->wlpart, refm.wlpart, sizeof(rop->mtx->wlpart)); return(0); } /* 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; @@ -124,7 +126,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; @@ -141,8 +143,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; @@ -156,11 +158,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) @@ -181,28 +184,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) { @@ -214,20 +226,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; @@ -238,20 +257,19 @@ 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); - } - if ((nc > 3) & (dt <= DTspec)) + } else if (dt == DTspec) return(DTfloat); /* probably not actual spectrum */ return(0); } /* Get matrix and perform unary operations */ -static RMATRIX * +RMATRIX * loadop(ROPMAT *rop) { int outtype = 0; @@ -351,7 +369,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 +446,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 +462,7 @@ op_left2right(ROPMAT *mop) } /* Perform matrix operations from right to left */ -static RMATRIX * +RMATRIX * op_right2left(ROPMAT *mop) { RMATRIX *mright; @@ -473,7 +491,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 +518,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 +528,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 +536,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) {