ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcrop.c
Revision: 1.18
Committed: Tue Jun 3 21:31:51 2025 UTC (2 days, 22 hours ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.17: +3 -5 lines
Log Message:
refactor: More consistent use of global char * progname and fixargv0()

File Contents

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