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

# Content
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 }