--- ray/src/common/normcodec.c 2019/07/26 17:04:12 2.2 +++ ray/src/common/normcodec.c 2022/09/22 21:47:13 2.9 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: normcodec.c,v 2.2 2019/07/26 17:04:12 greg Exp $"; +static const char RCSid[] = "$Id: normcodec.c,v 2.9 2022/09/22 21:47:13 greg Exp $"; #endif /* * Routines to encode/decode 32-bit normals @@ -7,6 +7,7 @@ static const char RCSid[] = "$Id: normcodec.c,v 2.2 20 #include "copyright.h" +#include #include "rtio.h" #include "rtmath.h" #include "normcodec.h" @@ -30,10 +31,33 @@ static int headline(char *s, void *p) { NORMCODEC *ncp = (NORMCODEC *)p; + int rv; if (formatval(ncp->inpfmt, s)) /* don't pass format */ return 0; + if ((rv = isbigendian(s)) >= 0) { + ncp->swapped = (nativebigendian() != rv); + return 0; + } + if (!strncmp(s, "NCOMP=", 6)) { + if (atoi(s+6) != 3) { + if (ncp->hdrflags & HF_STDERR) { + fputs(ncp->inpname, stderr); + fputs(": NCOMP must equal 3\n", stderr); + } + return -1; + } + return 0; + } + if (!strncmp(s, "NROWS=", 6)) { + ncp->res.yr = atoi(s+6); + return 0; + } + if (!strncmp(s, "NCOLS=", 6)) { + ncp->res.xr = atoi(s+6); + return 0; + } if (ncp->hdrflags & HF_HEADOUT) fputs(s, stdout); /* copy to standard output */ return 1; @@ -52,6 +76,16 @@ process_nc_header(NORMCODEC *ncp, int ac, char *av[]) } return 0; } + /* get resolution string? */ + if (ncp->hdrflags & HF_RESIN && + (ncp->res.xr <= 0) | (ncp->res.yr <= 0) && + !fgetsresolu(&ncp->res, ncp->finp)) { + if (ncp->hdrflags & HF_STDERR) { + fputs(ncp->inpname, stderr); + fputs(": bad resolution string\n", stderr); + } + return 0; + } if (ncp->hdrflags & HF_HEADOUT) { /* finish header */ if (!(ncp->hdrflags & HF_HEADIN)) newheader("RADIANCE", stdout); @@ -59,32 +93,32 @@ process_nc_header(NORMCODEC *ncp, int ac, char *av[]) printargs(ac, av, stdout); if (ncp->hdrflags & HF_ENCODE) { fputformat(NORMAL32FMT, stdout); - } else + } else { + fputs("NCOMP=3\n", stdout); + if ((ncp->hdrflags & (HF_RESIN|HF_RESOUT)) == HF_RESIN) + printf("NCOLS=%d\nNROWS=%d\n", + scanlen(&ncp->res), + numscans(&ncp->res)); switch (ncp->format) { case 'a': fputformat("ascii", stdout); break; case 'f': + fputendian(stdout); fputformat("float", stdout); break; case 'd': + fputendian(stdout); fputformat("double", stdout); break; } + } fputc('\n', stdout); } - /* get/put resolution string */ - if (ncp->hdrflags & HF_RESIN && !fgetsresolu(&ncp->res, ncp->finp)) { - if (ncp->hdrflags & HF_STDERR) { - fputs(ncp->inpname, stderr); - fputs(": bad resolution string\n", stderr); - } - return 0; - } - if (ncp->hdrflags & HF_RESOUT) + if (ncp->hdrflags & HF_RESOUT) /* put resolution string? */ fputsresolu(&ncp->res, stdout); - ncp->dstart = ncp->curpos = ftell(ncp->finp); + ncp->dstart = ftell(ncp->finp); return 1; } @@ -117,15 +151,22 @@ check_decode_normals(NORMCODEC *ncp) int decode_normal_next(FVECT nrm, NORMCODEC *ncp) { - int32 c = getint(4, ncp->finp); + static int32 lastc; + static FVECT lastv; + int32 c = getint(4, ncp->finp); if (c == EOF && feof(ncp->finp)) return -1; - ncp->curpos += 4; - - decodedir(nrm, c); - + if (c == lastc) { /* optimization */ + VCOPY(nrm, lastv); + } else { + decodedir(nrm, c); + if (c) { + lastc = c; + VCOPY(lastv, nrm); + } + } return (c != 0); } @@ -134,8 +175,6 @@ decode_normal_next(FVECT nrm, NORMCODEC *ncp) int seek_nc_pix(NORMCODEC *ncp, int x, int y) { - long seekpos; - if ((ncp->res.xr <= 0) | (ncp->res.yr <= 0)) { if (ncp->hdrflags & HF_STDERR) { fputs(progname, stderr); @@ -151,17 +190,14 @@ seek_nc_pix(NORMCODEC *ncp, int x, int y) } return 0; } - seekpos = ncp->dstart + 4*((long)y*scanlen(&ncp->res) + x); - - if (seekpos != ncp->curpos && - fseek(ncp->finp, seekpos, SEEK_SET) == EOF) { + if (fseek(ncp->finp, ncp->dstart + 4*((long)y*scanlen(&ncp->res) + x), + SEEK_SET) == EOF) { if (ncp->hdrflags & HF_STDERR) { fputs(ncp->inpname, stderr); fputs(": seek error\n", stderr); } return -1; } - ncp->curpos = seekpos; return 1; }