ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rpiece.c
Revision: 2.13
Committed: Thu Nov 12 10:13:35 1992 UTC (31 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.12: +2 -2 lines
Log Message:
minor bug fix for compilers that don't handle variable arguments

File Contents

# Content
1 /* Copyright (c) 1992 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ LBL";
5 #endif
6
7 /*
8 * Generate sections of a picture.
9 */
10
11 #include "standard.h"
12 #include <fcntl.h>
13 #include <signal.h>
14 #include "color.h"
15 #include "view.h"
16 #include "resolu.h"
17
18 #ifndef NFS
19 #define NFS 1
20 #endif
21 /* set the following to 0 to forgo forking */
22 #ifndef MAXFORK
23 #if NFS
24 #define MAXFORK 3 /* allotment of duped processes */
25 #else
26 #define MAXFORK 0
27 #endif
28 #endif
29
30 /* rpict command */
31 char *rpargv[128] = {"rpict", "-S", "1", "-x", "512", "-y", "512", "-pa", "1"};
32 int rpargc = 9;
33 int rpd[3];
34 FILE *torp, *fromrp;
35 COLR *pbuf;
36 /* our view parameters */
37 VIEW ourview = STDVIEW;
38 double pixaspect = 1.0;
39 int hres = 512, vres = 512, hmult = 2, vmult = 2;
40 /* output file */
41 char *outfile = NULL;
42 int outfd;
43 long scanorig;
44 int syncfd = -1; /* lock file descriptor */
45 int nforked = 0;
46
47 char *progname;
48 int verbose = 0;
49
50 extern long lseek(), ftell();
51
52 int gotalrm = 0;
53 int onalrm() { gotalrm++; }
54
55
56 main(argc, argv)
57 int argc;
58 char *argv[];
59 {
60 register int i, rval;
61
62 progname = argv[0];
63 for (i = 1; i < argc; i++) {
64 if (argv[i][0] == '-')
65 switch (argv[i][1]) {
66 case 'v':
67 switch (argv[i][2]) {
68 case '\0': /* verbose option */
69 verbose = !verbose;
70 continue;
71 case 'f': /* view file */
72 if (viewfile(argv[++i], &ourview, NULL) <= 0) {
73 fprintf(stderr,
74 "%s: not a view file\n", argv[i]);
75 exit(1);
76 }
77 continue;
78 default: /* view option? */
79 rval = getviewopt(&ourview, argc-i, argv+i);
80 if (rval >= 0) {
81 i += rval;
82 continue;
83 }
84 break;
85 }
86 break;
87 case 'p': /* pixel aspect ratio? */
88 if (argv[i][2] == 'a' && !argv[i][3])
89 pixaspect = atof(argv[i+1]);
90 break;
91 case 'x': /* piece x resolution */
92 if (!argv[i][2])
93 hres = atoi(argv[i+1]);
94 break;
95 case 'y': /* piece y resolution */
96 if (!argv[i][2])
97 vres = atoi(argv[i+1]);
98 break;
99 case 'X': /* horizontal multiplier */
100 if (argv[i][2])
101 break;
102 hmult = atoi(argv[++i]);
103 continue;
104 case 'Y': /* vertical multiplier */
105 if (argv[i][2])
106 break;
107 vmult = atoi(argv[++i]);
108 continue;
109 case 'F': /* syncronization file */
110 if (argv[i][2])
111 break;
112 if ((syncfd = open(argv[++i], O_RDWR)) < 0) {
113 fprintf(stderr, "%s: cannot open\n",
114 argv[i]);
115 exit(1);
116 }
117 continue;
118 case 'o': /* output file */
119 if (argv[i][2])
120 break;
121 outfile = argv[++i];
122 continue;
123 }
124 rpargv[rpargc++] = argv[i];
125 }
126 rpargv[rpargc] = NULL;
127 if (outfile == NULL) {
128 fprintf(stderr, "%s: missing output file\n", argv[0]);
129 exit(1);
130 }
131 init(argc, argv);
132 rpiece();
133 rval = cleanup(0);
134 exit(rval);
135 }
136
137
138 init(ac, av) /* set up output file and start rpict */
139 int ac;
140 char **av;
141 {
142 extern char VersionID[];
143 char *err;
144 FILE *fp;
145 int hr, vr;
146 /* set up view */
147 if ((err = setview(&ourview)) != NULL) {
148 fprintf(stderr, "%s: %s\n", progname, err);
149 exit(1);
150 }
151 if (syncfd != -1) {
152 char buf[32];
153 buf[read(syncfd, buf, sizeof(buf)-1)] = '\0';
154 sscanf(buf, "%d %d", &hmult, &vmult);
155 }
156 normaspect(viewaspect(&ourview)*hmult/vmult, &pixaspect, &hres, &vres);
157 /* open output file */
158 if ((outfd = open(outfile, O_WRONLY|O_CREAT|O_EXCL, 0666)) >= 0) {
159 if ((fp = fdopen(dup(outfd), "w")) == NULL)
160 goto filerr;
161 printargs(ac, av, fp); /* write header */
162 fprintf(fp, "SOFTWARE= %s\n", VersionID);
163 fputs(VIEWSTR, fp);
164 fprintview(&ourview, fp);
165 putc('\n', fp);
166 if (pixaspect < .99 || pixaspect > 1.01)
167 fputaspect(pixaspect, fp);
168 fputformat(COLRFMT, fp);
169 putc('\n', fp);
170 fprtresolu(hres*hmult, vres*vmult, fp);
171 } else if ((outfd = open(outfile, O_RDWR)) >= 0) {
172 if ((fp = fdopen(dup(outfd), "r+")) == NULL)
173 goto filerr;
174 getheader(fp, NULL, NULL); /* skip header */
175 if (fscnresolu(&hr, &vr, fp) < 0 || /* check resolution */
176 hr != hres*hmult || vr != vres*vmult) {
177 fprintf(stderr, "%s: resolution mismatch on file \"%s\"\n",
178 progname, outfile);
179 exit(1);
180 }
181 } else {
182 fprintf(stderr, "%s: cannot open file \"%s\"\n",
183 progname, outfile);
184 exit(1);
185 }
186 scanorig = ftell(fp); /* record position of first scanline */
187 if (fclose(fp) == -1) /* done with stream i/o */
188 goto filerr;
189 #if NFS
190 sync(); /* flush NFS buffers */
191 #endif
192 /* start rpict process */
193 if (open_process(rpd, rpargv) <= 0) {
194 fprintf(stderr, "%s: cannot start %s\n", progname, rpargv[0]);
195 exit(1);
196 }
197 if ((fromrp = fdopen(rpd[0], "r")) == NULL ||
198 (torp = fdopen(rpd[1], "w")) == NULL) {
199 fprintf(stderr, "%s: cannot open stream to %s\n",
200 progname, rpargv[0]);
201 exit(1);
202 }
203 if ((pbuf = (COLR *)malloc(hres*vres*sizeof(COLR))) == NULL) {
204 fprintf(stderr, "%s: out of memory\n", progname);
205 exit(1);
206 }
207 signal(SIGALRM, onalrm);
208 return;
209 filerr:
210 fprintf(stderr, "%s: i/o error on file \"%s\"\n", progname, outfile);
211 exit(1);
212 }
213
214
215 int
216 nextpiece(xp, yp) /* get next piece assignment */
217 int *xp, *yp;
218 {
219 extern char *fgets();
220 struct flock fls;
221 char buf[64];
222
223 if (gotalrm) /* someone wants us to quit */
224 return(0);
225 if (syncfd != -1) { /* use sync file */
226 fls.l_type = F_WRLCK; /* gain exclusive access */
227 fls.l_whence = 0;
228 fls.l_start = 0L;
229 fls.l_len = 0L;
230 fcntl(syncfd, F_SETLKW, &fls);
231 lseek(syncfd, 0L, 0);
232 buf[read(syncfd, buf, sizeof(buf)-1)] = '\0';
233 if (sscanf(buf, "%*d %*d %d %d", xp, yp) < 2) {
234 *xp = hmult-1;
235 *yp = vmult;
236 }
237 if (--(*yp) < 0) { /* decrement position */
238 *yp = vmult-1;
239 if (--(*xp) < 0) { /* all done! */
240 close(syncfd);
241 return(0);
242 }
243 }
244 sprintf(buf, "%d %d\n%d %d\n", hmult, vmult, *xp, *yp);
245 lseek(syncfd, 0L, 0); /* write new position */
246 write(syncfd, buf, strlen(buf));
247 fls.l_type = F_UNLCK; /* release sync file */
248 fcntl(syncfd, F_SETLKW, &fls);
249 return(1);
250 }
251 if (fgets(buf, sizeof(buf), stdin) == NULL) /* use stdin */
252 return(0);
253 if (sscanf(buf, "%d %d", xp, yp) == 2)
254 return(1);
255 fprintf(stderr, "%s: input format error\n", progname);
256 exit(cleanup(1));
257 }
258
259
260 int
261 cleanup(rstat) /* close rpict process and clean up */
262 int rstat;
263 {
264 int status;
265
266 free((char *)pbuf);
267 fclose(torp);
268 fclose(fromrp);
269 while (wait(&status) != -1)
270 if (rstat == 0)
271 rstat = status>>8 & 0xff;
272 return(rstat);
273 }
274
275
276 rpiece() /* render picture piece by piece */
277 {
278 VIEW pview;
279 int xorg, yorg;
280 /* compute view parameters */
281 copystruct(&pview, &ourview);
282 switch (ourview.type) {
283 case VT_PER:
284 pview.horiz = 2.*180./PI*atan(
285 tan(PI/180./2.*ourview.horiz)/hmult );
286 pview.vert = 2.*180./PI*atan(
287 tan(PI/180./2.*ourview.vert)/vmult );
288 break;
289 case VT_PAR:
290 case VT_ANG:
291 pview.horiz = ourview.horiz / hmult;
292 pview.vert = ourview.vert / vmult;
293 break;
294 case VT_HEM:
295 pview.horiz = 2.*180./PI*asin(
296 sin(PI/180./2.*ourview.horiz)/hmult );
297 pview.vert = 2.*180./PI*asin(
298 sin(PI/180./2.*ourview.vert)/vmult );
299 break;
300 default:
301 fprintf(stderr, "%s: unknown view type '-vt%c'\n",
302 progname, ourview.type);
303 exit(cleanup(1));
304 }
305 /* render each piece */
306 while (nextpiece(&xorg, &yorg)) {
307 pview.hoff = ourview.hoff + xorg - 0.5*(hmult-1);
308 pview.voff = ourview.voff + yorg - 0.5*(vmult-1);
309 fputs(VIEWSTR, torp);
310 fprintview(&pview, torp);
311 putc('\n', torp);
312 fflush(torp); /* assigns piece to rpict */
313 putpiece(xorg, yorg); /* place piece in output */
314 if (verbose) { /* notify caller */
315 printf("%d %d done\n", xorg, yorg);
316 fflush(stdout);
317 }
318 }
319 }
320
321
322 int
323 putpiece(xpos, ypos) /* get next piece from rpict */
324 int xpos, ypos;
325 {
326 struct flock fls;
327 int pid, status;
328 int hr, vr;
329 register int y;
330 /* check bounds */
331 if (xpos < 0 | ypos < 0 | xpos >= hmult | ypos >= vmult) {
332 fprintf(stderr, "%s: requested piece (%d,%d) out of range\n",
333 progname, xpos, ypos);
334 exit(cleanup(1));
335 }
336 /* check header from rpict */
337 getheader(fromrp, NULL, NULL);
338 if (fscnresolu(&hr, &vr, fromrp) < 0 || hr != hres | vr != vres) {
339 fprintf(stderr, "%s: resolution mismatch from %s\n",
340 progname, rpargv[0]);
341 exit(cleanup(1));
342 }
343 /* load new piece into buffer */
344 for (y = 0; y < vr; y++)
345 if (freadcolrs(pbuf+y*hr, hr, fromrp) < 0) {
346 fprintf(stderr, "%s: read error from %s\n",
347 progname, rpargv[0]);
348 exit(cleanup(1));
349 }
350 #if MAXFORK
351 /* fork so we don't slow rpict down */
352 if ((pid = fork()) > 0) {
353 if (++nforked >= MAXFORK) {
354 wait(&status); /* reap a child */
355 if (status)
356 exit(cleanup(status>>8 & 0xff));
357 nforked--;
358 }
359 return(pid);
360 }
361 #else
362 pid = -1; /* no forking */
363 #endif
364 #if NFS
365 /* lock file section so NFS doesn't mess up */
366 fls.l_whence = 0;
367 fls.l_len = (long)vres*hmult*hres*sizeof(COLR);
368 fls.l_start = scanorig + (vmult-1-ypos)*fls.l_len;
369 fls.l_type = F_WRLCK;
370 fcntl(outfd, F_SETLKW, &fls);
371 #endif
372 /* write new piece to file */
373 if (lseek(outfd, fls.l_start+(long)xpos*hres*sizeof(COLR), 0) == -1)
374 goto seekerr;
375 if (hmult == 1) {
376 if (writebuf(outfd, (char *)pbuf,
377 vr*hr*sizeof(COLR)) != vr*hr*sizeof(COLR))
378 goto writerr;
379 } else
380 for (y = 0; y < vr; y++) {
381 if (writebuf(outfd, (char *)(pbuf+y*hr),
382 hr*sizeof(COLR)) != hr*sizeof(COLR))
383 goto writerr;
384 if (y < vr-1 && lseek(outfd,
385 (long)(hmult-1)*hr*sizeof(COLR),
386 1) == -1)
387 goto seekerr;
388 }
389 if (pid == -1) { /* fork failed */
390 #if NFS
391 fls.l_type = F_UNLCK; /* release lock */
392 fcntl(outfd, F_SETLKW, &fls);
393 #endif
394 return(0);
395 }
396 _exit(0); /* else exit child process (releasing lock) */
397 seekerr:
398 fprintf(stderr, "%s: seek error on file \"%s\"\n", progname, outfile);
399 _exit(1);
400 writerr:
401 fprintf(stderr, "%s: write error on file \"%s\"\n", progname, outfile);
402 _exit(1);
403 }