ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcrop.c
Revision: 1.1
Committed: Tue Mar 15 00:25:50 2022 UTC (2 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
feat(rcrop): Created simple cropping utility for matrices and pictures

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2     static const char RCSid[] = "$Id$";
3     #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     fputs(": error writing scanline\n", stderr);
83     return(0);
84     readerr:
85     fputs(progname, stderr);
86     fputs(": error reading scanline\n", stderr);
87     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     const size_t elsiz = asize*ncomp;
95     const int width = scanlen(&res);
96     char *buf = (char *)malloc(elsiz*width);
97     int y;
98    
99     if (!buf) {
100     fputs(progname, stderr);
101     fputs(": out of memory!\n", stderr);
102     return(0);
103     }
104     /* skip rows as requested */
105     if (rmin && fseek(fp, rmin*width*elsiz, SEEK_CUR) < 0) {
106     for (y = 0; y < rmin; y++)
107     if (getbinary(buf, elsiz, width, fp) != width)
108     goto readerr;
109     }
110     for (y = 0; y < nrows; y++) { /* copy portion */
111     if (getbinary(buf, elsiz, width, fp) != width)
112     goto readerr;
113     if (putbinary(buf+cmin*elsiz, elsiz, ncols, stdout) != ncols)
114     goto writerr;
115     }
116     free(buf); /* we're done */
117     if (fflush(stdout) == 0)
118     return(1);
119     writerr:
120     fputs(progname, stderr);
121     fputs(": error writing binary data\n", stderr);
122     return(0);
123     readerr:
124     fputs(progname, stderr);
125     fputs(": error reading binary data\n", stderr);
126     return(0);
127     }
128    
129     /* Read (and copy) specified number of white-space-separated words */
130     static int
131     readwords(FILE *finp, int nwords, FILE *fout)
132     {
133     while (nwords-- > 0) {
134     int c;
135     do {
136     c = getc(finp);
137     } while (isspace(c));
138     if (c == EOF)
139     return(-1);
140     if (fout && fputc(' ', fout) == EOF)
141     return(-1);
142     do {
143     if (fout)
144     putc(c, fout);
145     } while ((c = getc(finp)) != EOF && !isspace(c));
146     }
147     return(0);
148     }
149    
150     /* Copy routine for ascii data */
151     static int
152     ascii_copyf(FILE *fp)
153     {
154     const int width = scanlen(&res);
155     int x, y;
156    
157     SET_FILE_TEXT(fp); /* started as binary */
158     SET_FILE_TEXT(stdout);
159     /* skip rows as requested */
160     if (readwords(fp, rmin*width*ncomp, NULL) < 0)
161     goto io_err;
162     for (y = 0; y < nrows; y++) { /* copy part */
163     if (readwords(fp, cmin*ncomp, NULL) < 0)
164     goto io_err;
165     if (readwords(fp, ncols*ncomp, stdout) < 0)
166     goto io_err;
167     fputc('\n', stdout); /* newline per row */
168     if (readwords(fp, (width-ncols-cmin)*ncomp, NULL) < 0)
169     goto io_err;
170     }
171     if (fflush(stdout) == 0)
172     return(1);
173     io_err:
174     fputs(progname, stderr);
175     fputs(": error copying ascii data\n", stderr);
176     return(0);
177     }
178    
179     /* Main routine -- load header and call processor */
180     int
181     main(int argc, char *argv[])
182     {
183     FILE *fp = stdin;
184     int asiz = 0;
185     int gotdims;
186    
187     progname = argv[0];
188     /* get input and output */
189     if ((argc < 5) | (argc > 7))
190     goto usage;
191     if (!isint(argv[1]) | !isint(argv[2]) |
192     !isint(argv[3]) | !isint(argv[4]))
193     goto usage;
194     rmin = atoi(argv[1]);
195     cmin = atoi(argv[2]);
196     nrows = atoi(argv[3]);
197     ncols = atoi(argv[4]);
198     if ((rmin < 0) | (cmin < 0) | (nrows < 0) | (ncols < 0))
199     goto usage;
200     if (argc <= 5)
201     SET_FILE_BINARY(fp);
202     else if (!(fp = fopen(argv[5], "rb"))) {
203     fputs(argv[5], stderr);
204     fputs(": cannot open for reading\n", stderr);
205     return(1);
206     }
207     if (argc <= 6)
208     SET_FILE_BINARY(stdout);
209     else if (!freopen(argv[6], "wb", stdout)) {
210     fputs(argv[6], stderr);
211     fputs(": cannot open for writing\n", stderr);
212     return(1);
213     }
214     /* process information header */
215     if (getheader(fp, headline, NULL) < 0) {
216     fputs(progname, stderr);
217     fputs(": bad input header\n", stderr);
218     return(1);
219     }
220     gotdims = (res.rt == PIXSTANDARD) & (res.xr > 0) & (res.yr > 0);
221     if (!gotdims && !fgetsresolu(&res, fp)) {
222     fputs(progname, stderr);
223     fputs(": missing input dimensions\n", stderr);
224     return(1);
225     }
226     if (!nrows)
227     nrows = numscans(&res) - rmin;
228     if (!ncols)
229     ncols = scanlen(&res) - cmin;
230     if ((nrows <= 0) | (ncols <= 0) |
231     (rmin+nrows > numscans(&res)) |
232     (cmin+ncols > scanlen(&res))) {
233     fputs(progname, stderr);
234     fputs(": illegal crop\n", stderr);
235     return(1);
236     }
237     printargs(argc, argv, stdout);
238     if (gotvw) {
239     double p0[2], p1[2];
240     const char *err;
241     if (res.rt & YMAJOR) {
242     p0[0] = cmin/(double)res.xr;
243     p0[1] = rmin/(double)res.yr;
244     p1[0] = (cmin+ncols)/(double)res.xr;
245     p1[1] = (rmin+nrows)/(double)res.yr;
246     } else {
247     p0[1] = cmin/(double)res.xr;
248     p0[0] = rmin/(double)res.yr;
249     p1[1] = (cmin+ncols)/(double)res.xr;
250     p1[0] = (rmin+nrows)/(double)res.yr;
251     }
252     if (res.rt & XDECR) {
253     p0[0] = 1. - p0[0];
254     p1[0] = 1. - p1[0];
255     }
256     if (res.rt & YDECR) {
257     p0[1] = 1. - p0[1];
258     p1[1] = 1. - p1[1];
259     }
260     err = cropview(&vw, p0[0], p0[1], p1[0], p1[1]);
261     if (err) {
262     fputs(progname, stderr);
263     fputs(": view error - ", stderr);
264     fputs(err, stderr);
265     fputc('\n', stderr);
266     return(1);
267     }
268     fputs(VIEWSTR, stdout);
269     fprintview(&vw, stdout);
270     fputc('\n', stdout);
271     }
272     if (gotdims)
273     printf("NROWS=%d\nNCOLS=%d\n", nrows, ncols);
274     if (ncomp)
275     printf("NCOMP=%d\n", ncomp);
276     fputformat(fmt, stdout); /* will align bytes if it can */
277     fputc('\n', stdout); /* end of new header */
278     if (!gotdims) { /* add resolution string? */
279     RESOLU newres;
280     if (res.rt & YMAJOR) {
281     newres.xr = ncols;
282     newres.yr = nrows;
283     } else {
284     newres.xr = nrows;
285     newres.yr = ncols;
286     }
287     newres.rt = res.rt;
288     fputsresolu(&newres, stdout);
289     }
290     /* call appropriate processor */
291     if (!strcmp(fmt, "float")) {
292     asiz = sizeof(float);
293     } else if (!strcmp(fmt, "double")) {
294     asiz = sizeof(double);
295     } else if (globmatch(PICFMT, fmt)) {
296     asiz = -1;
297     if (!ncomp) ncomp = 3;
298     } else if (strcasecmp(fmt, "ascii")) {
299     fputs(progname, stderr);
300     fputs(": unsupported format - ", stderr);
301     fputs(fmt, stderr);
302     fputc('\n', stderr);
303     return(1);
304     }
305     if (ncomp <= 0) {
306     fputs(progname, stderr);
307     fputs(": illegal number of components\n", stderr);
308     return(1);
309     }
310     if (!(asiz < 0 ? colr_copyf(fp) :
311     !asiz ? ascii_copyf(fp) : binary_copyf(fp, asiz)))
312     return(1);
313     return(0);
314     usage:
315     fputs("Usage: ", stderr);
316     fputs(progname, stderr);
317     fputs(" row0 col0 nrows ncols [input [output]]\n", stderr);
318     return(1);
319     }