From 4c1188a4d1bc74970c9fa6583d5503d9f935e7de Mon Sep 17 00:00:00 2001 From: "Gregory J. Ward" Date: Tue, 19 Jan 2021 23:32:00 +0000 Subject: [PATCH] feat: Added -rf and -rb options to rmtxop to load XML reflectance matrices --- doc/man/man1/rmtxop.1 | 15 +++++++++---- doc/notes/ReleaseNotes | 6 ++++- src/util/cmatrix.c | 12 ++++++---- src/util/cmatrix.h | 8 +++++-- src/util/cmbsdf.c | 50 ++++++++++++++++++++++++++++++++++++------ src/util/rmatrix.c | 20 +++++++++-------- src/util/rmatrix.h | 8 +++++-- src/util/rmtxop.c | 18 ++++++++++----- 8 files changed, 102 insertions(+), 35 deletions(-) diff --git a/doc/man/man1/rmtxop.1 b/doc/man/man1/rmtxop.1 index cf2af0709..b38ca9c86 100644 --- a/doc/man/man1/rmtxop.1 +++ b/doc/man/man1/rmtxop.1 @@ -1,4 +1,4 @@ -.\" RCSid "$Id: rmtxop.1,v 1.19 2020/08/31 22:17:56 greg Exp $" +.\" RCSid "$Id: rmtxop.1,v 1.20 2021/01/19 23:32:00 greg Exp $" .TH RMTXOP 1 7/8/97 RADIANCE .SH NAME rmtxop - concatenate, add, multiply, divide, transpose, scale, and convert matrices @@ -14,6 +14,8 @@ rmtxop - concatenate, add, multiply, divide, transpose, scale, and convert matri .B "\-s sf .." ][ .B "\-c ce .." +][ +.B -r[fb] ] .B m1 [ @@ -47,9 +49,14 @@ instead of a file by using quotes and a beginning exclamation point ('!'). .PP Two special cases are handled for component matrices that are either -XML files containing BTDF data, or Radiance picture files. -In the first case, a BSDF library is used to load and interpret the -transmission matrix. +XML files containing BSDF data, or Radiance picture files. +In the first case, the BSDF library loads and interprets the +transmission matrix by default. +Alternatively, the front (normal-side) reflectance is selected if the +.I \-rf +option precedes the file name, or the backside reflectance if +.I \-rb +is specified. (XML files cannot be read from the standard input or from a command.)\0 In the second case, the RGBE or XYZE values are loaded in a 3-component matrix where the number of columns match the X-dimension of the picture, and diff --git a/doc/notes/ReleaseNotes b/doc/notes/ReleaseNotes index 801a5fa7a..e09e5b519 100644 --- a/doc/notes/ReleaseNotes +++ b/doc/notes/ReleaseNotes @@ -2395,4 +2395,8 @@ Added "test" target to makeall to run unit tests. Modified bsdf2ttree to allow different parameters per input SIR file. -Fixed issues with very large matrix files (> 2GB) in dctimestep, rmtxop, and rcollate. +Fixed issues with very large matrix files (> 2GB) in dctimestep, rmtxop, +and rcollate. + +Added -rf and -rb options to rmtxop to load front or back reflectance +matrix data from XML file rather than transmission. (Lars Grobe suggested.) diff --git a/src/util/cmatrix.c b/src/util/cmatrix.c index 30f71ed00..397a2ef88 100644 --- a/src/util/cmatrix.c +++ b/src/util/cmatrix.c @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: cmatrix.c,v 2.31 2021/01/15 18:31:38 greg Exp $"; +static const char RCSid[] = "$Id: cmatrix.c,v 2.32 2021/01/19 23:32:00 greg Exp $"; #endif /* * Color matrix routines. @@ -15,6 +15,8 @@ static const char RCSid[] = "$Id: cmatrix.c,v 2.31 2021/01/15 18:31:38 greg Exp #include "paths.h" #include "resolu.h" +const char stdin_name[] = ""; + const char *cm_fmt_id[] = { "unknown", COLRFMT, CIEFMT, "float", "ascii", "double" @@ -212,13 +214,15 @@ CMATRIX * cm_load(const char *inspec, int nrows, int ncols, int dtype) { const int ROWINC = 2048; - FILE *fp = stdin; int swap = 0; + FILE *fp; COLOR scale; CMATRIX *cm; - if (!inspec) - inspec = ""; + if (!inspec || !*inspec) + return(NULL); + if (inspec == stdin_name) + fp = stdin; else if (inspec[0] == '!') { fp = popen(inspec+1, "r"); if (!fp) { diff --git a/src/util/cmatrix.h b/src/util/cmatrix.h index 4d509ab33..6942d123e 100644 --- a/src/util/cmatrix.h +++ b/src/util/cmatrix.h @@ -1,4 +1,4 @@ -/* RCSid $Id: cmatrix.h,v 2.12 2020/03/25 01:51:09 greg Exp $ */ +/* RCSid $Id: cmatrix.h,v 2.13 2021/01/19 23:32:00 greg Exp $ */ /* * Color matrix routine declarations. * @@ -18,6 +18,7 @@ extern "C" { /* Data types for file loading */ enum {DTfromHeader=0, DTrgbe, DTxyze, DTfloat, DTascii, DTdouble, DTend}; +extern const char stdin_name[]; extern const char *cm_fmt_id[]; extern const int cm_elem_size[]; @@ -58,7 +59,10 @@ extern CMATRIX *cm_multiply(const CMATRIX *cm1, const CMATRIX *cm2); extern int cm_write(const CMATRIX *cm, int dtype, FILE *fp); /* Load and convert a matrix BTDF from the given XML file */ -extern CMATRIX *cm_loadBTDF(char *fname); +extern CMATRIX *cm_loadBTDF(const char *fname); + +/* Load and convert a matrix BRDF from the given XML file */ +extern CMATRIX *cm_loadBRDF(const char *fname, int backside); #ifdef __cplusplus } diff --git a/src/util/cmbsdf.c b/src/util/cmbsdf.c index 6a58d9b06..82658bc5c 100644 --- a/src/util/cmbsdf.c +++ b/src/util/cmbsdf.c @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: cmbsdf.c,v 2.8 2020/03/17 23:24:05 greg Exp $"; +static const char RCSid[] = "$Id: cmbsdf.c,v 2.9 2021/01/19 23:32:00 greg Exp $"; #endif /* * Load and convert BSDF into color coefficient matrix representation. @@ -144,34 +144,70 @@ cm_bsdf_Lamb(const COLOR diffBSDF) /* Load and convert a matrix BTDF from the given XML file */ CMATRIX * -cm_loadBTDF(char *fname) +cm_loadBTDF(const char *fname) { CMATRIX *Tmat; int recip; SDError ec; SDData myBSDF; SDSpectralDF *tdf; - COLOR diffBSDF; + COLOR diffBTDF; SDclearBSDF(&myBSDF, fname); /* load XML and check type */ ec = SDloadFile(&myBSDF, fname); if (ec) error(USER, transSDError(ec)); - ccy2rgb(&myBSDF.tLamb.spec, myBSDF.tLamb.cieY/PI, diffBSDF); + ccy2rgb(&myBSDF.tLamb.spec, myBSDF.tLamb.cieY/PI, diffBTDF); recip = (myBSDF.tb == NULL); tdf = recip ? myBSDF.tf : myBSDF.tb; if (tdf == NULL) { /* no non-Lambertian transmission? */ SDfreeBSDF(&myBSDF); - return(cm_bsdf_Lamb(diffBSDF)); + return(cm_bsdf_Lamb(diffBTDF)); } if (tdf->ncomp != 1 || tdf->comp[0].func != &SDhandleMtx) { sprintf(errmsg, "unsupported BSDF '%s'", fname); error(USER, errmsg); } /* convert BTDF to matrix */ - Tmat = recip ? cm_bsdf_recip(diffBSDF, (SDMat *)tdf->comp[0].dist) - : cm_bsdf(diffBSDF, (SDMat *)tdf->comp[0].dist); + Tmat = recip ? cm_bsdf_recip(diffBTDF, (SDMat *)tdf->comp[0].dist) + : cm_bsdf(diffBTDF, (SDMat *)tdf->comp[0].dist); /* free BSDF and return */ SDfreeBSDF(&myBSDF); return(Tmat); } + +/* Load and convert a matrix BRDF from the given XML file */ +CMATRIX * +cm_loadBRDF(const char *fname, int backside) +{ + CMATRIX *Rmat; + SDError ec; + SDData myBSDF; + SDSpectralDF *rdf; + COLOR diffBRDF; + + SDclearBSDF(&myBSDF, fname); /* load XML and check type */ + ec = SDloadFile(&myBSDF, fname); + if (ec) + error(USER, transSDError(ec)); + if (backside) { + ccy2rgb(&myBSDF.rLambBack.spec, myBSDF.rLambBack.cieY/PI, diffBRDF); + rdf = myBSDF.rb; + } else { + ccy2rgb(&myBSDF.rLambFront.spec, myBSDF.rLambFront.cieY/PI, diffBRDF); + rdf = myBSDF.rf; + } + if (rdf == NULL) { /* no non-Lambertian reflection? */ + SDfreeBSDF(&myBSDF); + return(cm_bsdf_Lamb(diffBRDF)); + } + if (rdf->ncomp != 1 || rdf->comp[0].func != &SDhandleMtx) { + sprintf(errmsg, "unsupported BSDF '%s'", fname); + error(USER, errmsg); + } + /* convert BRDF to matrix */ + Rmat = cm_bsdf(diffBRDF, (SDMat *)rdf->comp[0].dist); + /* free BSDF and return */ + SDfreeBSDF(&myBSDF); + return(Rmat); +} diff --git a/src/util/rmatrix.c b/src/util/rmatrix.c index 0d76fe8ee..e8e56d66c 100644 --- a/src/util/rmatrix.c +++ b/src/util/rmatrix.c @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: rmatrix.c,v 2.45 2021/01/15 02:46:28 greg Exp $"; +static const char RCSid[] = "$Id: rmatrix.c,v 2.46 2021/01/19 23:32:00 greg Exp $"; #endif /* * General matrix operations. @@ -203,19 +203,19 @@ rmx_load_rgbe(RMATRIX *rm, FILE *fp) /* Load matrix from supported file type */ RMATRIX * -rmx_load(const char *inspec) +rmx_load(const char *inspec, RMPref rmp) { - FILE *fp = stdin; + FILE *fp; RMATRIX dinfo; RMATRIX *dnew; - if (!inspec) { /* reading from stdin? */ - inspec = ""; - SET_FILE_BINARY(stdin); + if (!inspec || !*inspec) + return(NULL); + if (inspec == stdin_name) { /* reading from stdin? */ + fp = stdin; } else if (inspec[0] == '!') { if (!(fp = popen(inspec+1, "r"))) return(NULL); - SET_FILE_BINARY(fp); } else { const char *sp = inspec; /* check suffix */ while (*sp) @@ -223,7 +223,8 @@ rmx_load(const char *inspec) while (sp > inspec && sp[-1] != '.') --sp; if (!strcasecmp(sp, "XML")) { /* assume it's a BSDF */ - CMATRIX *cm = cm_loadBTDF((char *)inspec); + CMATRIX *cm = rmp==RMPtrans ? cm_loadBTDF(inspec) : + cm_loadBRDF(inspec, rmp==RMPreflB) ; if (!cm) return(NULL); dnew = rmx_from_cmatrix(cm); @@ -232,9 +233,10 @@ rmx_load(const char *inspec) return(dnew); } /* else open it ourselves */ - if (!(fp = fopen(inspec, "rb"))) + if (!(fp = fopen(inspec, "r"))) return(NULL); } + SET_FILE_BINARY(fp); #ifdef getc_unlocked flockfile(fp); #endif diff --git a/src/util/rmatrix.h b/src/util/rmatrix.h index 99153eb3f..f00345b6c 100644 --- a/src/util/rmatrix.h +++ b/src/util/rmatrix.h @@ -1,4 +1,4 @@ -/* RCSid $Id: rmatrix.h,v 2.12 2020/03/25 01:51:09 greg Exp $ */ +/* RCSid $Id: rmatrix.h,v 2.13 2021/01/19 23:32:00 greg Exp $ */ /* * Header file for general matrix routines. */ @@ -12,6 +12,10 @@ extern "C" { #endif +/* Preferred BSDF component: + transmission, reflection front (normal side), reflection back */ +typedef enum {RMPtrans=0, RMPreflF, RMPreflB} RMPref; + /* General plane-ordered component matrix */ typedef struct { int nrows, ncols; @@ -34,7 +38,7 @@ extern void rmx_free(RMATRIX *rm); extern int rmx_newtype(int dtyp1, int dtyp2); /* Load matrix from supported file type (NULL for stdin, '!' with command) */ -extern RMATRIX *rmx_load(const char *inspec); +extern RMATRIX *rmx_load(const char *inspec, RMPref rmp); /* Append header information associated with matrix data */ extern int rmx_addinfo(RMATRIX *rm, const char *info); diff --git a/src/util/rmtxop.c b/src/util/rmtxop.c index dddaca053..59c30fafc 100644 --- a/src/util/rmtxop.c +++ b/src/util/rmtxop.c @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: rmtxop.c,v 2.17 2019/12/28 18:05:14 greg Exp $"; +static const char RCSid[] = "$Id: rmtxop.c,v 2.18 2021/01/19 23:32:00 greg Exp $"; #endif /* * General component matrix operations. @@ -14,8 +14,6 @@ static const char RCSid[] = "$Id: rmtxop.c,v 2.17 2019/12/28 18:05:14 greg Exp $ #define MAXCOMP 16 /* #components we support */ -static const char stdin_name[] = ""; - /* unary matrix operation(s) */ typedef struct { double sca[MAXCOMP]; /* scalar coefficients */ @@ -28,6 +26,7 @@ typedef struct { /* matrix input source and requested operation(s) */ typedef struct { const char *inspec; /* input specification */ + RMPref rmp; /* matrix preference */ RUNARYOP preop; /* unary operation(s) */ RMATRIX *mtx; /* original matrix if loaded */ int binop; /* binary op with next (or 0) */ @@ -42,8 +41,7 @@ loadmatrix(ROPMAT *rop) if (rop->mtx != NULL) return(0); - rop->mtx = rmx_load(rop->inspec == stdin_name ? - (const char *)NULL : rop->inspec); + rop->mtx = rmx_load(rop->inspec, rop->rmp); if (rop->mtx == NULL) { fputs(rop->inspec, stderr); fputs(": cannot load matrix\n", stderr); @@ -382,6 +380,14 @@ main(int argc, char *argv[]) get_factors(mop[nmats].preop.cmat, n, argv+i+1); break; + case 'r': + if (argv[i][2] == 'f') + mop[nmats].rmp = RMPreflF; + else if (argv[i][2] == 'b') + mop[nmats].rmp = RMPreflB; + else + goto userr; + break; default: fprintf(stderr, "%s: unknown operation '%s'\n", argv[0], argv[i]); @@ -424,7 +430,7 @@ main(int argc, char *argv[]) return(0); userr: fprintf(stderr, - "Usage: %s [-v][-f[adfc][-t][-s sf .. | -c ce ..] m1 [.+*/] .. > mres\n", + "Usage: %s [-v][-f[adfc][-t][-s sf .. | -c ce ..][-r[fb]] m1 [.+*/] .. > mres\n", argv[0]); return(1); }