| 24 |  | if ((nr <= 0) | (nc <= 0) | (n <= 0)) | 
| 25 |  | return(NULL); | 
| 26 |  | dnew = (RMATRIX *)malloc(sizeof(RMATRIX)-sizeof(dnew->mtx) + | 
| 27 | < | sizeof(dnew->mtx[0])*(n*nr*nc)); | 
| 27 | > | sizeof(dnew->mtx[0])*n*nr*nc); | 
| 28 |  | if (!dnew) | 
| 29 |  | return(NULL); | 
| 30 |  | dnew->nrows = nr; dnew->ncols = nc; dnew->ncomp = n; | 
| 203 |  |  | 
| 204 |  | /* Load matrix from supported file type */ | 
| 205 |  | RMATRIX * | 
| 206 | < | rmx_load(const char *inspec) | 
| 206 | > | rmx_load(const char *inspec, RMPref rmp) | 
| 207 |  | { | 
| 208 | < | FILE            *fp = stdin; | 
| 208 | > | FILE            *fp; | 
| 209 |  | RMATRIX         dinfo; | 
| 210 |  | RMATRIX         *dnew; | 
| 211 |  |  | 
| 212 | < | if (!inspec) {                          /* reading from stdin? */ | 
| 213 | < | inspec = "<stdin>"; | 
| 214 | < | SET_FILE_BINARY(stdin); | 
| 212 | > | if (!inspec) | 
| 213 | > | inspec = stdin_name; | 
| 214 | > | else if (!*inspec) | 
| 215 | > | return(NULL); | 
| 216 | > | if (inspec == stdin_name) {             /* reading from stdin? */ | 
| 217 | > | fp = stdin; | 
| 218 |  | } else if (inspec[0] == '!') { | 
| 219 |  | if (!(fp = popen(inspec+1, "r"))) | 
| 220 |  | return(NULL); | 
| 218 | – | SET_FILE_BINARY(fp); | 
| 221 |  | } else { | 
| 222 |  | const char      *sp = inspec;   /* check suffix */ | 
| 223 |  | while (*sp) | 
| 225 |  | while (sp > inspec && sp[-1] != '.') | 
| 226 |  | --sp; | 
| 227 |  | if (!strcasecmp(sp, "XML")) {   /* assume it's a BSDF */ | 
| 228 | < | CMATRIX *cm = cm_loadBTDF((char *)inspec); | 
| 228 | > | CMATRIX *cm = rmp==RMPtrans ? cm_loadBTDF(inspec) : | 
| 229 | > | cm_loadBRDF(inspec, rmp==RMPreflB) ; | 
| 230 |  | if (!cm) | 
| 231 |  | return(NULL); | 
| 232 |  | dnew = rmx_from_cmatrix(cm); | 
| 235 |  | return(dnew); | 
| 236 |  | } | 
| 237 |  | /* else open it ourselves */ | 
| 238 | < | if (!(fp = fopen(inspec, "rb"))) | 
| 238 | > | if (!(fp = fopen(inspec, "r"))) | 
| 239 |  | return(NULL); | 
| 240 |  | } | 
| 241 | + | SET_FILE_BINARY(fp); | 
| 242 |  | #ifdef getc_unlocked | 
| 243 |  | flockfile(fp); | 
| 244 |  | #endif | 
| 398 |  | return(1); | 
| 399 |  | } | 
| 400 |  |  | 
| 401 | + | /* Check if CIE XYZ primaries were specified */ | 
| 402 | + | static int | 
| 403 | + | findCIEprims(const char *info) | 
| 404 | + | { | 
| 405 | + | RGBPRIMS        prims; | 
| 406 | + |  | 
| 407 | + | if (!info) | 
| 408 | + | return(0); | 
| 409 | + | info = strstr(info, PRIMARYSTR); | 
| 410 | + | if (!info || !primsval(prims, info)) | 
| 411 | + | return(0); | 
| 412 | + |  | 
| 413 | + | return((prims[RED][CIEX] > .99) & (prims[RED][CIEY] < .01) && | 
| 414 | + | (prims[GRN][CIEX] < .01) & (prims[GRN][CIEY] > .99) && | 
| 415 | + | (prims[BLU][CIEX] < .01) & (prims[BLU][CIEY] < .01)); | 
| 416 | + | } | 
| 417 | + |  | 
| 418 |  | /* Write matrix to file type indicated by dtype */ | 
| 419 |  | int | 
| 420 |  | rmx_write(const RMATRIX *rm, int dtype, FILE *fp) | 
| 432 |  | fputs(rm->info, fp); | 
| 433 |  | if (dtype == DTfromHeader) | 
| 434 |  | dtype = rm->dtype; | 
| 435 | < | else if ((dtype == DTrgbe) & (rm->dtype == DTxyze)) | 
| 435 | > | else if (dtype == DTrgbe && (rm->dtype == DTxyze || | 
| 436 | > | findCIEprims(rm->info))) | 
| 437 |  | dtype = DTxyze; | 
| 438 |  | else if ((dtype == DTxyze) & (rm->dtype == DTrgbe)) | 
| 439 |  | dtype = DTrgbe; | 
| 453 |  | } | 
| 454 |  | if ((dtype == DTfloat) | (dtype == DTdouble)) | 
| 455 |  | fputendian(fp);                 /* important to record */ | 
| 456 | < | fputformat((char *)cm_fmt_id[dtype], fp); | 
| 456 | > | fputformat(cm_fmt_id[dtype], fp); | 
| 457 |  | fputc('\n', fp); | 
| 458 |  | switch (dtype) {                        /* write data */ | 
| 459 |  | case DTascii: |