ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcrop.c
Revision: 1.6
Committed: Tue Mar 15 15:01:22 2022 UTC (2 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.5: +6 -1 lines
Log Message:
fix(rcrop): Eliminated "broken pipe" error when reading from command

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 1.6 static const char RCSid[] = "$Id: rcrop.c,v 1.5 2022/03/15 04:41:45 greg Exp $";
3 greg 1.1 #endif
4     /*
5     * rcrop.c - crop a Radiance picture or matrix data
6     */
7    
8     #include <ctype.h>
9     #include "rtio.h"
10     #include "platform.h"
11     #include "color.h"
12     #include "fvect.h"
13     #include "view.h"
14    
15     #define MAXWORD 64 /* maximum word (number) length */
16    
17     char *progname; /* global argv[0] */
18    
19     VIEW vw = STDVIEW;
20     int gotvw = 0;
21     char fmt[MAXFMTLEN] = "Unknown";
22     int ncomp = 0;
23     RESOLU res;
24     int rmin, cmin, nrows, ncols;
25    
26     /* Process header line, copying to stdout when appropriate */
27     static int
28     headline(char *s, void *p)
29     {
30     if (formatval(fmt, s))
31     return(0);
32     if (!strncmp(s, "NCOMP=", 6)) {
33     ncomp = atoi(s+6);
34     return(-(ncomp <= 0));
35     }
36     if (!strncmp(s, "NROWS=", 6)) {
37     res.rt = PIXSTANDARD;
38     res.yr = atoi(s+6);
39     return(-(res.yr <= 0));
40     }
41     if (!strncmp(s, "NCOLS=", 6)) {
42     res.rt = PIXSTANDARD;
43     res.xr = atoi(s+6);
44     return(-(res.xr <= 0));
45     }
46     if (isview(s)) {
47     gotvw += sscanview(&vw, s);
48     return(0);
49     }
50     fputs(s, stdout); /* copy other header info. */
51     return(0);
52     }
53    
54     /* Copy routine for COLR data */
55     static int
56     colr_copyf(FILE *fp)
57     {
58     const int width = scanlen(&res);
59     COLR *scan = (COLR *)malloc(sizeof(COLR)*width);
60     int y;
61    
62     if (!scan) {
63     fputs(progname, stderr);
64     fputs(": out of memory!\n", stderr);
65     return(0);
66     }
67     for (y = 0; y < rmin; y++) /* initial skip */
68     if (freadcolrs(scan, width, fp) < 0)
69     goto readerr;
70     /* scanlines to copy */
71     for (y = 0; y < nrows; y++) {
72     if (freadcolrs(scan, width, fp) < 0)
73     goto readerr;
74     if (fwritecolrs(scan+cmin, ncols, stdout) < 0)
75     goto writerr;
76     }
77     free(scan);
78     if (fflush(stdout) == 0)
79     return(1);
80     writerr:
81     fputs(progname, stderr);
82 greg 1.4 fputs(": error writing picture\n", stderr);
83 greg 1.1 return(0);
84     readerr:
85     fputs(progname, stderr);
86 greg 1.4 fputs(": error reading picture\n", stderr);
87 greg 1.1 return(0);
88     }
89    
90     /* Copy routine for binary data (asize = sizeof(type)) */
91     static int
92     binary_copyf(FILE *fp, int asize)
93     {
94 greg 1.3 const int skip_thresh = 8192;
95 greg 1.1 const size_t elsiz = asize*ncomp;
96     const int width = scanlen(&res);
97 greg 1.2 const long skip_len = (width-ncols)*elsiz;
98     char *buf;
99 greg 1.1 int y;
100 greg 1.2 /* check if fseek() useful */
101     if (skip_len > skip_thresh &&
102     fseek(fp, (rmin*width + cmin)*elsiz, SEEK_CUR) == 0) {
103     buf = (char *)malloc(ncols*elsiz);
104     if (!buf)
105     goto memerr;
106     for (y = nrows; y-- > 0; ) {
107     if (getbinary(buf, elsiz, ncols, fp) != ncols)
108     goto readerr;
109     if (putbinary(buf, elsiz, ncols, stdout) != ncols)
110     goto writerr;
111     if (y && fseek(fp, skip_len, SEEK_CUR) < 0) {
112     fputs(progname, stderr);
113     fputs(": unexpected seek error on input\n", stderr);
114     return(0);
115     }
116     }
117     free(buf); /* success! */
118     return(1);
119     } /* else need to read it all... */
120     buf = (char *)malloc(width*elsiz);
121     if (!buf)
122     goto memerr;
123 greg 1.1 /* skip rows as requested */
124 greg 1.2 if (skip_len > skip_thresh ||
125     (rmin && fseek(fp, rmin*width*elsiz, SEEK_CUR) < 0))
126 greg 1.1 for (y = 0; y < rmin; y++)
127     if (getbinary(buf, elsiz, width, fp) != width)
128     goto readerr;
129     for (y = 0; y < nrows; y++) { /* copy portion */
130     if (getbinary(buf, elsiz, width, fp) != width)
131     goto readerr;
132     if (putbinary(buf+cmin*elsiz, elsiz, ncols, stdout) != ncols)
133     goto writerr;
134     }
135     free(buf); /* we're done */
136     if (fflush(stdout) == 0)
137     return(1);
138     writerr:
139     fputs(progname, stderr);
140     fputs(": error writing binary data\n", stderr);
141     return(0);
142     readerr:
143     fputs(progname, stderr);
144     fputs(": error reading binary data\n", stderr);
145     return(0);
146 greg 1.2 memerr:
147     fputs(progname, stderr);
148     fputs(": out of memory!\n", stderr);
149     return(0);
150 greg 1.1 }
151    
152     /* Read (and copy) specified number of white-space-separated words */
153     static int
154     readwords(FILE *finp, int nwords, FILE *fout)
155     {
156     while (nwords-- > 0) {
157     int c;
158     do {
159     c = getc(finp);
160     } while (isspace(c));
161     if (c == EOF)
162     return(-1);
163     if (fout && fputc(' ', fout) == EOF)
164     return(-1);
165     do {
166     if (fout)
167     putc(c, fout);
168     } while ((c = getc(finp)) != EOF && !isspace(c));
169     }
170     return(0);
171     }
172    
173     /* Copy routine for ascii data */
174     static int
175     ascii_copyf(FILE *fp)
176     {
177     const int width = scanlen(&res);
178     int x, y;
179    
180     SET_FILE_TEXT(fp); /* started as binary */
181     SET_FILE_TEXT(stdout);
182     /* skip rows as requested */
183     if (readwords(fp, rmin*width*ncomp, NULL) < 0)
184     goto io_err;
185     for (y = 0; y < nrows; y++) { /* copy part */
186     if (readwords(fp, cmin*ncomp, NULL) < 0)
187     goto io_err;
188     if (readwords(fp, ncols*ncomp, stdout) < 0)
189     goto io_err;
190     fputc('\n', stdout); /* newline per row */
191     if (readwords(fp, (width-ncols-cmin)*ncomp, NULL) < 0)
192     goto io_err;
193     }
194     if (fflush(stdout) == 0)
195     return(1);
196     io_err:
197     fputs(progname, stderr);
198     fputs(": error copying ascii data\n", stderr);
199     return(0);
200     }
201    
202     /* Main routine -- load header and call processor */
203     int
204     main(int argc, char *argv[])
205     {
206     FILE *fp = stdin;
207     int asiz = 0;
208     int gotdims;
209    
210     progname = argv[0];
211     /* get input and output */
212     if ((argc < 5) | (argc > 7))
213     goto usage;
214     if (!isint(argv[1]) | !isint(argv[2]) |
215     !isint(argv[3]) | !isint(argv[4]))
216     goto usage;
217     rmin = atoi(argv[1]);
218     cmin = atoi(argv[2]);
219     nrows = atoi(argv[3]);
220     ncols = atoi(argv[4]);
221     if ((rmin < 0) | (cmin < 0) | (nrows < 0) | (ncols < 0))
222     goto usage;
223     if (argc <= 5)
224     SET_FILE_BINARY(fp);
225     else if (!(fp = fopen(argv[5], "rb"))) {
226     fputs(argv[5], stderr);
227     fputs(": cannot open for reading\n", stderr);
228     return(1);
229     }
230     if (argc <= 6)
231     SET_FILE_BINARY(stdout);
232     else if (!freopen(argv[6], "wb", stdout)) {
233     fputs(argv[6], stderr);
234     fputs(": cannot open for writing\n", stderr);
235     return(1);
236     }
237     /* process information header */
238     if (getheader(fp, headline, NULL) < 0) {
239     fputs(progname, stderr);
240     fputs(": bad input header\n", stderr);
241     return(1);
242     }
243     gotdims = (res.rt == PIXSTANDARD) & (res.xr > 0) & (res.yr > 0);
244     if (!gotdims && !fgetsresolu(&res, fp)) {
245     fputs(progname, stderr);
246     fputs(": missing input dimensions\n", stderr);
247     return(1);
248     }
249     if (!nrows)
250     nrows = numscans(&res) - rmin;
251     if (!ncols)
252     ncols = scanlen(&res) - cmin;
253     if ((nrows <= 0) | (ncols <= 0) |
254     (rmin+nrows > numscans(&res)) |
255     (cmin+ncols > scanlen(&res))) {
256     fputs(progname, stderr);
257     fputs(": illegal crop\n", stderr);
258     return(1);
259     }
260     printargs(argc, argv, stdout);
261 greg 1.4 if (gotvw) { /* adjust view? */
262 greg 1.1 double p0[2], p1[2];
263     const char *err;
264     if (res.rt & YMAJOR) {
265     p0[0] = cmin/(double)res.xr;
266     p0[1] = rmin/(double)res.yr;
267     p1[0] = (cmin+ncols)/(double)res.xr;
268     p1[1] = (rmin+nrows)/(double)res.yr;
269     } else {
270     p0[1] = cmin/(double)res.xr;
271     p0[0] = rmin/(double)res.yr;
272     p1[1] = (cmin+ncols)/(double)res.xr;
273     p1[0] = (rmin+nrows)/(double)res.yr;
274     }
275     if (res.rt & XDECR) {
276     p0[0] = 1. - p0[0];
277     p1[0] = 1. - p1[0];
278     }
279     if (res.rt & YDECR) {
280     p0[1] = 1. - p0[1];
281     p1[1] = 1. - p1[1];
282     }
283     err = cropview(&vw, p0[0], p0[1], p1[0], p1[1]);
284     if (err) {
285     fputs(progname, stderr);
286     fputs(": view error - ", stderr);
287     fputs(err, stderr);
288     fputc('\n', stderr);
289     return(1);
290 greg 1.4 } else {
291     fputs(VIEWSTR, stdout);
292     fprintview(&vw, stdout);
293     fputc('\n', stdout);
294 greg 1.1 }
295     }
296     if (gotdims)
297     printf("NROWS=%d\nNCOLS=%d\n", nrows, ncols);
298     if (ncomp)
299     printf("NCOMP=%d\n", ncomp);
300     fputformat(fmt, stdout); /* will align bytes if it can */
301     fputc('\n', stdout); /* end of new header */
302     if (!gotdims) { /* add resolution string? */
303     RESOLU newres;
304     if (res.rt & YMAJOR) {
305     newres.xr = ncols;
306     newres.yr = nrows;
307     } else {
308     newres.xr = nrows;
309     newres.yr = ncols;
310     }
311     newres.rt = res.rt;
312     fputsresolu(&newres, stdout);
313     }
314     /* call appropriate processor */
315     if (!strcmp(fmt, "float")) {
316     asiz = sizeof(float);
317     } else if (!strcmp(fmt, "double")) {
318     asiz = sizeof(double);
319 greg 1.5 } else if (!strcmp(fmt, "32-bit_encoded_normal")) {
320     asiz = 4;
321     ncomp = 1;
322     } else if (!strcmp(fmt, "16-bit_encoded_depth")) {
323     asiz = 2;
324     ncomp = 1;
325 greg 1.1 } else if (globmatch(PICFMT, fmt)) {
326     asiz = -1;
327     if (!ncomp) ncomp = 3;
328 greg 1.4 else ncomp *= (ncomp == 3);
329 greg 1.1 } else if (strcasecmp(fmt, "ascii")) {
330     fputs(progname, stderr);
331     fputs(": unsupported format - ", stderr);
332     fputs(fmt, stderr);
333     fputc('\n', stderr);
334     return(1);
335     }
336     if (ncomp <= 0) {
337     fputs(progname, stderr);
338     fputs(": illegal number of components\n", stderr);
339     return(1);
340     }
341     if (!(asiz < 0 ? colr_copyf(fp) :
342     !asiz ? ascii_copyf(fp) : binary_copyf(fp, asiz)))
343     return(1);
344 greg 1.6 /* need to consume the rest? */
345     if (fp == stdin && rmin+nrows < numscans(&res) &&
346     fseek(fp, 0L, SEEK_END) < 0)
347     while (getc(fp) != EOF)
348     ;
349 greg 1.1 return(0);
350     usage:
351     fputs("Usage: ", stderr);
352     fputs(progname, stderr);
353     fputs(" row0 col0 nrows ncols [input [output]]\n", stderr);
354     return(1);
355     }