--- ray/src/util/rcrop.c 2022/03/15 00:25:50 1.1 +++ ray/src/util/rcrop.c 2022/04/07 16:58:30 1.13 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: rcrop.c,v 1.1 2022/03/15 00:25:50 greg Exp $"; +static const char RCSid[] = "$Id: rcrop.c,v 1.13 2022/04/07 16:58:30 greg Exp $"; #endif /* * rcrop.c - crop a Radiance picture or matrix data @@ -12,13 +12,11 @@ static const char RCSid[] = "$Id: rcrop.c,v 1.1 2022/0 #include "fvect.h" #include "view.h" -#define MAXWORD 64 /* maximum word (number) length */ - char *progname; /* global argv[0] */ VIEW vw = STDVIEW; int gotvw = 0; -char fmt[MAXFMTLEN] = "Unknown"; +char fmt[MAXFMTLEN] = "ascii"; /* assumed when unspecified */ int ncomp = 0; RESOLU res; int rmin, cmin, nrows, ncols; @@ -79,11 +77,11 @@ colr_copyf(FILE *fp) return(1); writerr: fputs(progname, stderr); - fputs(": error writing scanline\n", stderr); + fputs(": error writing picture\n", stderr); return(0); readerr: fputs(progname, stderr); - fputs(": error reading scanline\n", stderr); + fputs(": error reading picture\n", stderr); return(0); } @@ -91,22 +89,55 @@ readerr: static int binary_copyf(FILE *fp, int asize) { + const int skip_thresh = 8192; const size_t elsiz = asize*ncomp; const int width = scanlen(&res); - char *buf = (char *)malloc(elsiz*width); + const long skip_len = (width-ncols)*elsiz; + char *buf; int y; - - if (!buf) { - fputs(progname, stderr); - fputs(": out of memory!\n", stderr); - return(0); - } + /* check if fseek() useful */ + if (skip_len > skip_thresh && + fseek(fp, (rmin*width + cmin)*elsiz, SEEK_CUR) == 0) { + off_t curpos; + buf = (char *)malloc(ncols*elsiz); + if (!buf) + goto memerr; +#ifdef NON_POSIX + for (y = nrows; y-- > 0; ) { + if (getbinary(buf, elsiz, ncols, fp) != ncols) + goto readerr; + if (putbinary(buf, elsiz, ncols, stdout) != ncols) + goto writerr; + if (y && fseek(fp, skip_len, SEEK_CUR) < 0) { + fputs(progname, stderr); + fputs(": unexpected seek error on input\n", stderr); + return(0); + } + } +#else + curpos = ftello(fp); + for (y = nrows; y-- > 0; curpos += width*elsiz) { + if (pread(fileno(fp), buf, ncols*elsiz, + curpos) != ncols*elsiz) + goto readerr; + if (putbinary(buf, elsiz, ncols, stdout) != ncols) + goto writerr; + } +#endif + free(buf); + if (fflush(stdout) == EOF) + goto writerr; + return(1); /* success! */ + } /* else need to read it all... */ + buf = (char *)malloc(width*elsiz); + if (!buf) + goto memerr; /* skip rows as requested */ - if (rmin && fseek(fp, rmin*width*elsiz, SEEK_CUR) < 0) { + if (skip_len > skip_thresh || + (rmin && fseek(fp, rmin*width*elsiz, SEEK_CUR) < 0)) for (y = 0; y < rmin; y++) if (getbinary(buf, elsiz, width, fp) != width) goto readerr; - } for (y = 0; y < nrows; y++) { /* copy portion */ if (getbinary(buf, elsiz, width, fp) != width) goto readerr; @@ -124,6 +155,10 @@ readerr: fputs(progname, stderr); fputs(": error reading binary data\n", stderr); return(0); +memerr: + fputs(progname, stderr); + fputs(": out of memory!\n", stderr); + return(0); } /* Read (and copy) specified number of white-space-separated words */ @@ -176,6 +211,45 @@ io_err: return(0); } +/* Adjust (crop) our view */ +static int +adjust_view(void) +{ + double p0[2], p1[2]; + const char *err; + + if (res.rt & YMAJOR) { + p0[0] = cmin/(double)res.xr; + p0[1] = rmin/(double)res.yr; + p1[0] = (cmin+ncols)/(double)res.xr; + p1[1] = (rmin+nrows)/(double)res.yr; + } else { + p0[0] = rmin/(double)res.xr; + p0[1] = cmin/(double)res.yr; + p1[0] = (rmin+nrows)/(double)res.xr; + p1[1] = (cmin+ncols)/(double)res.yr; + } + if (res.rt & XDECR) { + p0[0] = 1. - p0[0]; + p1[0] = 1. - p1[0]; + } + if (res.rt & YDECR) { + p0[1] = 1. - p0[1]; + p1[1] = 1. - p1[1]; + } + err = cropview(&vw, p0[0], p0[1], p1[0], p1[1]); + + if (!err) + return(1); /* success! */ + + fputs(progname, stderr); + fputs(": view error - ", stderr); + fputs(err, stderr); + fputc('\n', stderr); + return(0); /* something went wrong */ +} + + /* Main routine -- load header and call processor */ int main(int argc, char *argv[]) @@ -211,6 +285,10 @@ main(int argc, char *argv[]) fputs(": cannot open for writing\n", stderr); return(1); } +#ifdef getc_unlocked /* avoid stupid semaphores */ + flockfile(fp); + flockfile(stdout); +#endif /* process information header */ if (getheader(fp, headline, NULL) < 0) { fputs(progname, stderr); @@ -234,42 +312,13 @@ main(int argc, char *argv[]) fputs(": illegal crop\n", stderr); return(1); } - printargs(argc, argv, stdout); - if (gotvw) { - double p0[2], p1[2]; - const char *err; - if (res.rt & YMAJOR) { - p0[0] = cmin/(double)res.xr; - p0[1] = rmin/(double)res.yr; - p1[0] = (cmin+ncols)/(double)res.xr; - p1[1] = (rmin+nrows)/(double)res.yr; - } else { - p0[1] = cmin/(double)res.xr; - p0[0] = rmin/(double)res.yr; - p1[1] = (cmin+ncols)/(double)res.xr; - p1[0] = (rmin+nrows)/(double)res.yr; - } - if (res.rt & XDECR) { - p0[0] = 1. - p0[0]; - p1[0] = 1. - p1[0]; - } - if (res.rt & YDECR) { - p0[1] = 1. - p0[1]; - p1[1] = 1. - p1[1]; - } - err = cropview(&vw, p0[0], p0[1], p1[0], p1[1]); - if (err) { - fputs(progname, stderr); - fputs(": view error - ", stderr); - fputs(err, stderr); - fputc('\n', stderr); - return(1); - } - fputs(VIEWSTR, stdout); + printargs(5, argv, stdout); /* add to header */ + if (gotvw && adjust_view()) { + fputs(VIEWSTR, stdout); /* write adjusted view */ fprintview(&vw, stdout); fputc('\n', stdout); } - if (gotdims) + if (gotdims) /* dimensions + format */ printf("NROWS=%d\nNCOLS=%d\n", nrows, ncols); if (ncomp) printf("NCOMP=%d\n", ncomp); @@ -292,9 +341,16 @@ main(int argc, char *argv[]) asiz = sizeof(float); } else if (!strcmp(fmt, "double")) { asiz = sizeof(double); + } else if (!strcmp(fmt, "32-bit_encoded_normal")) { + asiz = 4; + ncomp = 1; + } else if (!strcmp(fmt, "16-bit_encoded_depth")) { + asiz = 2; + ncomp = 1; } else if (globmatch(PICFMT, fmt)) { asiz = -1; if (!ncomp) ncomp = 3; + else ncomp *= (ncomp == 3); } else if (strcasecmp(fmt, "ascii")) { fputs(progname, stderr); fputs(": unsupported format - ", stderr); @@ -308,8 +364,13 @@ main(int argc, char *argv[]) return(1); } if (!(asiz < 0 ? colr_copyf(fp) : - !asiz ? ascii_copyf(fp) : binary_copyf(fp, asiz))) + asiz ? binary_copyf(fp, asiz) : ascii_copyf(fp))) return(1); + /* need to consume the rest? */ + if (fp == stdin && rmin+nrows < numscans(&res) && + fseek(fp, 0L, SEEK_END) < 0) + while (getc(fp) != EOF) + ; return(0); usage: fputs("Usage: ", stderr);