ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rv2.c
Revision: 1.10
Committed: Thu Jul 27 22:58:26 1989 UTC (34 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.9: +6 -6 lines
Log Message:
Changed getpath() to check access modes

File Contents

# User Rev Content
1 greg 1.1 /* Copyright (c) 1987 Regents of the University of California */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #endif
6    
7     /*
8     * rv2.c - command routines used in tracing a view.
9     *
10     * 3/24/87
11     */
12    
13     #include "ray.h"
14    
15     #include "octree.h"
16    
17     #include "otypes.h"
18    
19     #include "rpaint.h"
20    
21     #include <ctype.h>
22    
23     #define CTRL(c) ('c'-'@')
24    
25     extern char *progname;
26    
27    
28     getframe(s) /* get a new frame */
29     char *s;
30     {
31     int x0, y0, x1, y1;
32    
33     if (!strcmp("all", s)) {
34     pframe.l = pframe.d = 0;
35     pframe.r = ourview.hresolu;
36     pframe.u = ourview.vresolu;
37     pdepth = 0;
38     return;
39     }
40     if (sscanf(s, "%d %d %d %d", &x0, &y0, &x1, &y1) != 4) {
41     if (dev->getcur == NULL)
42     return;
43     (*dev->comout)("Pick first corner\n");
44     if ((*dev->getcur)(&x0, &y0) == ABORT)
45     return;
46     (*dev->comout)("Pick second corner\n");
47     if ((*dev->getcur)(&x1, &y1) == ABORT)
48     return;
49     }
50     if (x0 < x1) {
51     pframe.l = x0;
52     pframe.r = x1;
53     } else {
54     pframe.l = x1;
55     pframe.r = x0;
56     }
57     if (y0 < y1) {
58     pframe.d = y0;
59     pframe.u = y1;
60     } else {
61     pframe.d = y1;
62     pframe.u = y0;
63     }
64     if (pframe.l < 0) pframe.l = 0;
65     if (pframe.d < 0) pframe.d = 0;
66     if (pframe.r > ourview.hresolu) pframe.r = ourview.hresolu;
67     if (pframe.u > ourview.vresolu) pframe.u = ourview.vresolu;
68 greg 1.9 if (pframe.l > pframe.r) pframe.l = pframe.r;
69     if (pframe.d > pframe.u) pframe.d = pframe.u;
70 greg 1.1 pdepth = 0;
71     }
72    
73    
74     getview(s) /* get/show view parameters */
75     char *s;
76     {
77     FILE *fp;
78     char buf[128];
79 greg 1.10 char *fname;
80 greg 1.3 int change = 0;
81 greg 1.1 VIEW nv;
82    
83     if (sscanf(s, "%s", buf) == 1) { /* write parameters to a file */
84 greg 1.10 if ((fname = getpath(buf, NULL, 0)) == NULL ||
85 greg 1.1 (fp = fopen(fname, "a")) == NULL) {
86     sprintf(errmsg, "cannot open \"%s\"", buf);
87     error(COMMAND, errmsg);
88     return;
89     }
90 greg 1.2 fputs(progname, fp);
91 greg 1.1 fprintview(&ourview, fp);
92     fputs("\n", fp);
93     fclose(fp);
94     return;
95     }
96     sprintf(buf, "view type (%c): ", ourview.type);
97     (*dev->comout)(buf);
98     (*dev->comin)(buf);
99     if (buf[0] == CTRL(C)) return;
100 greg 1.3 if (buf[0] && buf[0] != ourview.type) {
101 greg 1.1 nv.type = buf[0];
102 greg 1.3 change++;
103     } else
104 greg 1.1 nv.type = ourview.type;
105     sprintf(buf, "view point (%.6g %.6g %.6g): ",
106     ourview.vp[0], ourview.vp[1], ourview.vp[2]);
107     (*dev->comout)(buf);
108     (*dev->comin)(buf);
109     if (buf[0] == CTRL(C)) return;
110 greg 1.3 if (sscanf(buf, "%lf %lf %lf", &nv.vp[0], &nv.vp[1], &nv.vp[2]) == 3)
111     change++;
112     else
113 greg 1.1 VCOPY(nv.vp, ourview.vp);
114     sprintf(buf, "view direction (%.6g %.6g %.6g): ",
115     ourview.vdir[0], ourview.vdir[1], ourview.vdir[2]);
116     (*dev->comout)(buf);
117     (*dev->comin)(buf);
118     if (buf[0] == CTRL(C)) return;
119 greg 1.3 if (sscanf(buf,"%lf %lf %lf",&nv.vdir[0],&nv.vdir[1],&nv.vdir[2]) == 3)
120     change++;
121     else
122 greg 1.1 VCOPY(nv.vdir, ourview.vdir);
123     sprintf(buf, "view up (%.6g %.6g %.6g): ",
124     ourview.vup[0], ourview.vup[1], ourview.vup[2]);
125     (*dev->comout)(buf);
126     (*dev->comin)(buf);
127     if (buf[0] == CTRL(C)) return;
128 greg 1.3 if (sscanf(buf,"%lf %lf %lf",&nv.vup[0],&nv.vup[1],&nv.vup[2]) == 3)
129     change++;
130     else
131 greg 1.1 VCOPY(nv.vup, ourview.vup);
132     sprintf(buf, "view horiz and vert size (%.6g %.6g): ",
133     ourview.horiz, ourview.vert);
134     (*dev->comout)(buf);
135     (*dev->comin)(buf);
136     if (buf[0] == CTRL(C)) return;
137 greg 1.3 if (sscanf(buf, "%lf %lf", &nv.horiz, &nv.vert) == 2)
138     change++;
139     else {
140 greg 1.1 nv.horiz = ourview.horiz; nv.vert = ourview.vert;
141     }
142     sprintf(buf, "x and y resolution (%d %d): ",
143     ourview.hresolu, ourview.vresolu);
144     (*dev->comout)(buf);
145     (*dev->comin)(buf);
146     if (buf[0] == CTRL(C)) return;
147 greg 1.3 if (sscanf(buf, "%d %d", &nv.hresolu, &nv.vresolu) == 2)
148     change++;
149     else {
150 greg 1.1 nv.hresolu = ourview.hresolu; nv.vresolu = ourview.vresolu;
151     }
152 greg 1.3 if (change)
153     newview(&nv);
154 greg 1.1 }
155    
156    
157     lastview(s) /* return to a previous view */
158     char *s;
159     {
160     char buf[128];
161 greg 1.10 char *fname;
162 greg 1.1 int success;
163     VIEW nv;
164    
165     if (sscanf(s, "%s", buf) == 1) { /* get parameters from a file */
166     bcopy(&stdview, &nv, sizeof(VIEW));
167 greg 1.10 if ((fname = getpath(buf, NULL, 0)) == NULL ||
168 greg 1.1 (success = viewfile(fname, &nv)) == -1) {
169     sprintf(errmsg, "cannot open \"%s\"", buf);
170     error(COMMAND, errmsg);
171     return;
172     }
173     if (!success)
174     error(COMMAND, "wrong file format");
175     else
176     newview(&nv);
177     return;
178     }
179     if (oldview.hresolu == 0) { /* no old view! */
180     error(COMMAND, "no previous view");
181     return;
182     }
183     bcopy(&ourview, &nv, sizeof(VIEW));
184     bcopy(&oldview, &ourview, sizeof(VIEW));
185     bcopy(&nv, &oldview, sizeof(VIEW));
186     newimage();
187     }
188    
189    
190     getinterest(s, direc, vec, mp) /* get area of interest */
191     char *s;
192     int direc;
193     FVECT vec;
194     double *mp;
195     {
196     int x, y;
197     RAY thisray;
198     register int i;
199    
200     if (sscanf(s, "%lf", mp) != 1)
201     *mp = 1.0;
202     else if (*mp < -FTINY) /* negative zoom is reduction */
203     *mp = -1.0 / *mp;
204     else if (*mp <= FTINY) { /* too small */
205     error(COMMAND, "illegal magnification");
206     return(-1);
207     }
208     if (sscanf(s, "%*lf %lf %lf %lf", &vec[0], &vec[1], &vec[2]) != 3) {
209     if (dev->getcur == NULL)
210     return(-1);
211     (*dev->comout)("Pick view center\n");
212     if ((*dev->getcur)(&x, &y) == ABORT)
213     return(-1);
214     rayview(thisray.rorg, thisray.rdir, &ourview, x+.5, y+.5);
215     if (!direc || ourview.type == VT_PAR) {
216     rayorigin(&thisray, NULL, PRIMARY, 1.0);
217     if (!localhit(&thisray, &thescene)) {
218     error(COMMAND, "not a local object");
219     return(-1);
220     }
221     }
222     if (direc)
223     if (ourview.type == VT_PAR)
224     for (i = 0; i < 3; i++)
225     vec[i] = thisray.rop[i] - ourview.vp[i];
226     else
227     VCOPY(vec, thisray.rdir);
228     else
229     VCOPY(vec, thisray.rop);
230     } else if (direc)
231     for (i = 0; i < 3; i++)
232     vec[i] -= ourview.vp[i];
233     return(0);
234     }
235    
236    
237     getaim(s) /* aim camera */
238     char *s;
239     {
240     extern double tan(), atan();
241     double zfact;
242     VIEW nv;
243    
244     if (getinterest(s, 1, nv.vdir, &zfact) < 0)
245     return;
246     VCOPY(nv.vp, ourview.vp);
247     VCOPY(nv.vup, ourview.vup);
248     nv.hresolu = ourview.hresolu; nv.vresolu = ourview.vresolu;
249     if ((nv.type = ourview.type) == VT_PAR) {
250     nv.horiz = ourview.horiz / zfact;
251     nv.vert = ourview.vert / zfact;
252     } else {
253     nv.horiz = atan(tan(ourview.horiz*(PI/180./2.))/zfact) /
254     (PI/180./2.);
255     nv.vert = atan(tan(ourview.vert*(PI/180./2.))/zfact) /
256     (PI/180./2.);
257     }
258     newview(&nv);
259     }
260    
261    
262     getmove(s) /* move camera */
263     char *s;
264     {
265     FVECT vc;
266     double mag;
267    
268     if (getinterest(s, 0, vc, &mag) < 0)
269     return;
270 greg 1.4 moveview(0.0, 0.0, mag, vc);
271 greg 1.1 }
272    
273    
274     getrotate(s) /* rotate camera */
275     char *s;
276     {
277 greg 1.4 extern double normalize(), tan(), atan();
278 greg 1.1 VIEW nv;
279     FVECT v1;
280 greg 1.4 double angle, elev, zfact;
281 greg 1.1
282 greg 1.4 elev = 0.0; zfact = 1.0;
283     if (sscanf(s, "%lf %lf %lf", &angle, &elev, &zfact) < 1) {
284 greg 1.1 error(COMMAND, "missing angle");
285     return;
286     }
287     VCOPY(nv.vp, ourview.vp);
288     VCOPY(nv.vup, ourview.vup);
289     nv.hresolu = ourview.hresolu; nv.vresolu = ourview.vresolu;
290     spinvector(nv.vdir, ourview.vdir, ourview.vup, angle*(PI/180.));
291     if (elev != 0.0) {
292     fcross(v1, nv.vdir, ourview.vup);
293     normalize(v1);
294     spinvector(nv.vdir, nv.vdir, v1, elev*(PI/180.));
295     }
296 greg 1.4 if ((nv.type = ourview.type) == VT_PAR) {
297     nv.horiz = ourview.horiz / zfact;
298     nv.vert = ourview.vert / zfact;
299     } else {
300     nv.horiz = atan(tan(ourview.horiz*(PI/180./2.))/zfact) /
301     (PI/180./2.);
302     nv.vert = atan(tan(ourview.vert*(PI/180./2.))/zfact) /
303     (PI/180./2.);
304     }
305 greg 1.1 newview(&nv);
306     }
307    
308    
309     getpivot(s) /* pivot viewpoint */
310     register char *s;
311     {
312     FVECT vc;
313 greg 1.4 double angle, elev, mag;
314 greg 1.1
315 greg 1.4 elev = 0.0;
316     if (sscanf(s, "%lf %lf", &angle, &elev) < 1) {
317 greg 1.1 error(COMMAND, "missing angle");
318     return;
319     }
320 greg 1.4 if (getinterest(sskip(sskip(s)), 0, vc, &mag) < 0)
321 greg 1.1 return;
322 greg 1.4 moveview(angle, elev, mag, vc);
323 greg 1.1 }
324    
325    
326     getexposure(s) /* get new exposure */
327     char *s;
328     {
329     double atof(), pow(), fabs();
330     char buf[128];
331     register char *cp;
332     register PNODE *p;
333     RECT r;
334     int x, y;
335     double e;
336    
337     for (cp = s; isspace(*cp); cp++)
338     ;
339     if (*cp == '\0') { /* normalize to point */
340     if (dev->getcur == NULL)
341     return;
342     (*dev->comout)("Pick point for exposure\n");
343     if ((*dev->getcur)(&x, &y) == ABORT)
344     return;
345     r.l = r.d = 0;
346     r.r = ourview.hresolu; r.u = ourview.vresolu;
347     p = findrect(x, y, &ptrunk, &r, -1);
348     e = 1.0;
349     } else {
350     if (*cp == '=') { /* absolute setting */
351     p = NULL;
352     e = 1.0/exposure;
353     for (cp++; isspace(*cp); cp++)
354     ;
355     if (*cp == '\0') { /* interactive */
356     sprintf(buf, "exposure (%lf): ", exposure);
357     (*dev->comout)(buf);
358     (*dev->comin)(buf);
359     for (cp = buf; isspace(*cp); cp++)
360     ;
361     if (*cp == '\0')
362     return;
363     }
364     } else { /* normalize to average */
365     p = &ptrunk;
366     e = 1.0;
367     }
368     if (*cp == '+' || *cp == '-') /* f-stops */
369     e *= pow(2.0, atof(cp));
370     else /* multiplier */
371     e *= atof(cp);
372     }
373     if (p != NULL) { /* relative setting */
374 greg 1.6 if (bright(p->v) <= FTINY) {
375 greg 1.1 error(COMMAND, "cannot normalize to zero");
376     return;
377     }
378 greg 1.6 e *= 0.5 / bright(p->v);
379 greg 1.1 }
380     if (e <= FTINY || fabs(1.0 - e) <= FTINY)
381     return;
382     scalepict(&ptrunk, e);
383     exposure *= e;
384     redraw();
385     }
386    
387    
388     setparam(s) /* get/set program parameter */
389     register char *s;
390     {
391     extern int psample;
392     extern double maxdiff;
393     extern double minweight;
394     extern int maxdepth;
395     extern double dstrsrc;
396 greg 1.5 extern double shadthresh;
397 greg 1.9 extern double shadcert;
398 greg 1.1 extern COLOR ambval;
399     extern double ambacc;
400     extern double minarad;
401     extern int ambres;
402     extern int ambdiv;
403     extern int ambssamp;
404     extern int ambounce;
405     int i0;
406     double d0, d1, d2;
407     char buf[128];
408    
409     if (s[0] == '\0') {
410 greg 1.9 (*dev->comout)("aa ab ad ar as av dc dj dt lr lw sp st: ");
411 greg 1.1 (*dev->comin)(buf);
412     s = buf;
413     }
414     switch (s[0]) {
415     case 'l': /* limit */
416     switch (s[1]) {
417     case 'w': /* weight */
418     if (sscanf(s+2, "%lf", &d0) != 1) {
419     sprintf(buf, "limit weight (%.6g): ",
420     minweight);
421     (*dev->comout)(buf);
422     (*dev->comin)(buf);
423     if (sscanf(buf, "%lf", &d0) != 1)
424     break;
425     }
426     minweight = d0;
427     break;
428     case 'r': /* reflection */
429     if (sscanf(s+2, "%d", &i0) != 1) {
430     sprintf(buf, "limit reflection (%d): ",
431     maxdepth);
432     (*dev->comout)(buf);
433     (*dev->comin)(buf);
434     if (sscanf(buf, "%d", &i0) != 1)
435     break;
436     }
437     maxdepth = i0;
438     break;
439     default:
440     goto badparam;
441     }
442     break;
443 greg 1.5 case 'd': /* direct */
444     switch (s[1]) {
445     case 'j': /* jitter */
446     if (sscanf(s+2, "%lf", &d0) != 1) {
447     sprintf(buf, "direct jitter (%.6g): ",
448     dstrsrc);
449     (*dev->comout)(buf);
450     (*dev->comin)(buf);
451     if (sscanf(buf, "%lf", &d0) != 1)
452     break;
453     }
454     dstrsrc = d0;
455 greg 1.9 break;
456     case 'c': /* certainty */
457     if (sscanf(s+2, "%lf", &d0) != 1) {
458     sprintf(buf, "direct certainty (%.6g): ",
459     shadcert);
460     (*dev->comout)(buf);
461     (*dev->comin)(buf);
462     if (sscanf(buf, "%lf", &d0) != 1)
463     break;
464     }
465     shadcert = d0;
466 greg 1.5 break;
467 greg 1.8 case 't': /* threshold */
468 greg 1.5 if (sscanf(s+2, "%lf", &d0) != 1) {
469 greg 1.8 sprintf(buf, "direct threshold (%.6g): ",
470 greg 1.5 shadthresh);
471     (*dev->comout)(buf);
472     (*dev->comin)(buf);
473     if (sscanf(buf, "%lf", &d0) != 1)
474     break;
475     }
476     shadthresh = d0;
477     break;
478     default:
479 greg 1.1 goto badparam;
480     }
481     break;
482     case 'a': /* ambient */
483     switch (s[1]) {
484     case 'v': /* value */
485     if (sscanf(s+2, "%lf %lf %lf", &d0, &d1, &d2) != 3) {
486     sprintf(buf,
487     "ambient value (%.6g %.6g %.6g): ",
488     colval(ambval,RED),
489     colval(ambval,GRN),
490     colval(ambval,BLU));
491     (*dev->comout)(buf);
492     (*dev->comin)(buf);
493     if (sscanf(buf, "%lf %lf %lf",
494     &d0, &d1, &d2) != 3)
495     break;
496     }
497     setcolor(ambval, d0, d1, d2);
498     break;
499     case 'a': /* accuracy */
500     if (sscanf(s+2, "%lf", &d0) != 1) {
501     sprintf(buf, "ambient accuracy (%.6g): ",
502     ambacc);
503     (*dev->comout)(buf);
504     (*dev->comin)(buf);
505     if (sscanf(buf, "%lf", &d0) != 1)
506     break;
507     }
508     ambacc = d0;
509     break;
510     case 'd': /* divisions */
511     if (sscanf(s+2, "%d", &i0) != 1) {
512     sprintf(buf, "ambient divisions (%d): ",
513     ambdiv);
514     (*dev->comout)(buf);
515     (*dev->comin)(buf);
516     if (sscanf(buf, "%d", &i0) != 1)
517     break;
518     }
519     ambdiv = i0;
520     break;
521     case 's': /* samples */
522     if (sscanf(s+2, "%d", &i0) != 1) {
523     sprintf(buf, "ambient super-samples (%d): ",
524     ambssamp);
525     (*dev->comout)(buf);
526     (*dev->comin)(buf);
527     if (sscanf(buf, "%d", &i0) != 1)
528     break;
529     }
530     ambssamp = i0;
531     break;
532     case 'b': /* bounces */
533     if (sscanf(s+2, "%d", &i0) != 1) {
534     sprintf(buf, "ambient bounces (%d): ",
535     ambounce);
536     (*dev->comout)(buf);
537     (*dev->comin)(buf);
538     if (sscanf(buf, "%d", &i0) != 1)
539     break;
540     }
541     ambounce = i0;
542     break;
543     case 'r':
544     if (sscanf(s+2, "%d", &i0) != 1) {
545     sprintf(buf, "ambient resolution (%d): ",
546     ambres);
547     (*dev->comout)(buf);
548     (*dev->comin)(buf);
549     if (sscanf(buf, "%d", &i0) != 1)
550     break;
551     }
552     ambres = i0;
553     minarad = ambres > 0 ? thescene.cusize/ambres : 0.0;
554     break;
555     default:
556     goto badparam;
557     }
558     break;
559     case 's': /* sample */
560     switch (s[1]) {
561     case 'p': /* pixel */
562     if (sscanf(s+2, "%d", &i0) != 1) {
563     sprintf(buf, "sample pixel (%d): ", psample);
564     (*dev->comout)(buf);
565     (*dev->comin)(buf);
566     if (sscanf(buf, "%d", &i0) != 1)
567     break;
568     }
569     psample = i0;
570     pdepth = 0;
571     break;
572 greg 1.8 case 't': /* threshold */
573 greg 1.1 if (sscanf(s+2, "%lf", &d0) != 1) {
574 greg 1.8 sprintf(buf, "sample threshold (%.6g): ",
575 greg 1.1 maxdiff);
576     (*dev->comout)(buf);
577     (*dev->comin)(buf);
578     if (sscanf(buf, "%lf", &d0) != 1)
579     break;
580     }
581     maxdiff = d0;
582     pdepth = 0;
583     break;
584     default:
585     goto badparam;
586     }
587     break;
588     case '\0': /* nothing */
589     break;
590     default:;
591     badparam:
592     sprintf(errmsg, "%s: unknown variable", s);
593     error(COMMAND, errmsg);
594     break;
595     }
596     }
597    
598    
599     traceray(s) /* trace a single ray */
600     char *s;
601     {
602     char buf[128];
603     int x, y;
604     RAY thisray;
605    
606     if (sscanf(s, "%lf %lf %lf %lf %lf %lf",
607     &thisray.rorg[0], &thisray.rorg[1], &thisray.rorg[2],
608     &thisray.rdir[0], &thisray.rdir[1], &thisray.rdir[2]) != 6) {
609    
610     if (dev->getcur == NULL)
611     return;
612     (*dev->comout)("Pick ray\n");
613     if ((*dev->getcur)(&x, &y) == ABORT)
614     return;
615    
616     rayview(thisray.rorg, thisray.rdir, &ourview, x+.5, y+.5);
617    
618     } else if (normalize(thisray.rdir) == 0.0) {
619     error(COMMAND, "zero ray direction");
620     return;
621     }
622    
623     rayorigin(&thisray, NULL, PRIMARY, 1.0);
624    
625     rayvalue(&thisray);
626    
627     if (thisray.ro == NULL)
628     (*dev->comout)("ray hit nothing");
629     else {
630     sprintf(buf, "ray hit %s %s \"%s\"",
631     objptr(thisray.ro->omod)->oname,
632     ofun[thisray.ro->otype].funame,
633     thisray.ro->oname);
634     (*dev->comout)(buf);
635     (*dev->comin)(buf);
636     if (thisray.rot >= FHUGE)
637     (*dev->comout)("at infinity");
638     else {
639     sprintf(buf, "at (%.6g %.6g %.6g)", thisray.rop[0],
640     thisray.rop[1], thisray.rop[2]);
641     (*dev->comout)(buf);
642     }
643     (*dev->comin)(buf);
644     sprintf(buf, "with value (%.6g %.6g %.6g)",
645     colval(thisray.rcol,RED),
646     colval(thisray.rcol,GRN),
647     colval(thisray.rcol,BLU));
648     (*dev->comout)(buf);
649     }
650     (*dev->comin)(buf);
651     }
652    
653    
654     writepict(s) /* write the picture to a file */
655     char *s;
656     {
657     static char buf[128];
658 greg 1.10 char *fname;
659 greg 1.1 FILE *fp;
660     COLR *scanline;
661     int y;
662    
663     if (sscanf(s, "%s", buf) != 1 && buf[0] == '\0') {
664     error(COMMAND, "no file");
665     return;
666     }
667 greg 1.10 if ((fname = getpath(buf, NULL, 0)) == NULL ||
668 greg 1.1 (fp = fopen(fname, "w")) == NULL) {
669     sprintf(errmsg, "cannot open \"%s\"", buf);
670     error(COMMAND, errmsg);
671     return;
672     }
673     (*dev->comout)("writing \"");
674     (*dev->comout)(fname);
675     (*dev->comout)("\"...\n");
676     /* write header */
677     fputs(progname, fp);
678     fprintview(&ourview, fp);
679     fputs("\n", fp);
680     if (exposure != 1.0)
681     fprintf(fp, "EXPOSURE=%e\n", exposure);
682     fprintf(fp, "\n-Y %d +X %d\n", ourview.vresolu, ourview.hresolu);
683    
684     scanline = (COLR *)malloc(ourview.hresolu*sizeof(COLR));
685     if (scanline == NULL)
686     error(SYSTEM, "out of memory in writepict");
687     for (y = ourview.vresolu-1; y >= 0; y--) {
688     getpictcolrs(y, scanline, &ptrunk,
689     ourview.hresolu, ourview.vresolu);
690     if (fwritecolrs(scanline, ourview.hresolu, fp) < 0)
691     break;
692     }
693     if (fclose(fp) < 0)
694     error(COMMAND, "write error");
695     free((char *)scanline);
696     }