ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhcopy.c
Revision: 3.41
Committed: Thu Jun 5 19:10:31 2025 UTC (44 hours, 6 minutes ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 3.40: +2 -4 lines
Log Message:
refactor: Made progname declarations more consistent

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rhcopy.c,v 3.40 2025/02/05 23:43:41 greg Exp $";
3 #endif
4 /*
5 * Copy data into a holodeck file
6 */
7
8 #include "platform.h"
9 #include "rterror.h"
10 #include "holo.h"
11 #include "view.h"
12
13 #ifndef BKBSIZE
14 #define BKBSIZE 256 /* beam clump size (kilobytes) */
15 #endif
16 /* possible operations */
17 #define FROM_HOLO 1 /* copy between holodecks */
18 #define FROM_PICZ 2 /* copy from HDR + depth to holodeck */
19 #define FROM_STDIN 3 /* copy from stdin to holodeck */
20 #define TO_STDOUT 4 /* copy rays from holodeck to stdout */
21
22 int operation = 0; /* what we are doing */
23 char *rspec = ""; /* ray details for i/o */
24 int checkdepth = 1; /* check depth (!-d option)? */
25 int checkrepeats = 0; /* check for repeats (-u option)? */
26 int nholosects; /* number of original holodeck sections */
27 int iofmt = 'a'; /* input/output format for rays */
28
29 /* holodeck flags */
30 #define H_BADF 01 /* bad format */
31 #define H_OBST 02 /* OBSTRUCTIONS= True */
32 #define H_OBSF 04 /* OBSTRUCTIONS= False */
33 #define H_VDST 010 /* VDISTANCE= True */
34 #define H_SWAP 020 /* byte order is different */
35
36 struct phead {
37 VIEW vw;
38 double expos;
39 short gotview;
40 short badfmt;
41 short altprims;
42 };
43
44 typedef struct {
45 FVECT ro;
46 FVECT rd;
47 RREAL d;
48 COLR cv;
49 } RAYPAR;
50
51 static int openholo(char *fname, int append);
52 static int addray(RAYPAR *rp);
53 static int readval(RREAL *v, int n, FILE *fp);
54 static void readrays(FILE *fp);
55 static int writeval(RREAL *v, int n, FILE *fp);
56 static int write_ray(RAYPAR *rp, FILE *fp);
57 static void writerays(FILE *fp);
58 static gethfunc holheadline;
59 static int bpcmp(const void *b1p, const void *b2p);
60 static int addclump(HOLO *hp, int *bq, int nb);
61 static void addholo(char *hdf);
62 static gethfunc picheadline;
63 static void addpicz(char *pcf, char *zbf);
64
65
66 int
67 main(
68 int argc,
69 char *argv[]
70 )
71 {
72 int i;
73
74 fixargv0(argv[0]);
75 for (i = 2; i < argc && argv[i][0] == '-'; i++)
76 switch (argv[i][1]) {
77 case 'u':
78 checkrepeats = 1;
79 break;
80 case 'd':
81 checkdepth = 0;
82 break;
83 case 'f':
84 iofmt = argv[i][2];
85 if (!strchr("afd", iofmt))
86 error(USER, "-f? i/o format must be 'a', 'f', or 'd'");
87 break;
88 case 'h':
89 operation = FROM_HOLO;
90 break;
91 case 'p':
92 operation = FROM_PICZ;
93 break;
94 case 'i':
95 operation = FROM_STDIN;
96 rspec = argv[i]+2;
97 break;
98 case 'o':
99 operation = TO_STDOUT;
100 rspec = argv[i]+2;
101 break;
102 default:
103 goto userr;
104 }
105 if (!operation | (i > argc-((operation==FROM_HOLO)|(operation==FROM_PICZ))))
106 goto userr;
107 if (operation == FROM_PICZ && (argc-i)%2)
108 goto userr;
109 nholosects = openholo(argv[1], (operation != TO_STDOUT));
110 /* check requested i/o is compatible */
111 if (strchr(rspec, 'l') && !(*(int *)hdlist[0]->priv & H_VDST))
112 error(USER, "i/o parameter 'l' incompatible with VDISTANCE=False");
113 if (strchr(rspec, 'L') && *(int *)hdlist[0]->priv & H_VDST)
114 error(USER, "i/o parameter 'L' incompatible with VDISTANCE=True");
115
116 switch (operation) { /* perform requested operation */
117 case FROM_PICZ:
118 for ( ; i < argc; i += 2)
119 addpicz(argv[i], argv[i+1]);
120 break;
121 case FROM_HOLO:
122 if (BKBSIZE*1024*1.5 > hdcachesize)
123 hdcachesize = BKBSIZE*1024*1.5;
124 for ( ; i < argc; i++)
125 addholo(argv[i]);
126 break;
127 case FROM_STDIN:
128 readrays(stdin);
129 break;
130 case TO_STDOUT:
131 writerays(stdout);
132 break;
133 }
134 quit(0);
135 userr:
136 fprintf(stderr, "Usage: %s dest.hdk [-u][-d] -h inp1.hdk ..\n",
137 progname);
138 fprintf(stderr, " Or: %s dest.hdk [-u][-d] -p inp1.hdr inp1.zbf ..\n",
139 progname);
140 fprintf(stderr, " Or: %s dest.hdk [-f{a|f|d}][-u][-d] -i[odplLv]\n",
141 progname);
142 fprintf(stderr, " Or: %s src.hdk [-f{a|f|d}] -o[odplLv] ..\n",
143 progname);
144 exit(1);
145 }
146
147 static int
148 holheadline( /* check holodeck header line */
149 char *s,
150 void *vhf
151 )
152 {
153 int be;
154 char fmt[MAXFMTLEN];
155 int *hf = (int *)vhf;
156
157 if (formatval(fmt, s)) {
158 if (strcmp(fmt, HOLOFMT))
159 *hf |= H_BADF;
160 else
161 *hf &= ~H_BADF;
162 return(0);
163 }
164 if (!strncmp(s, "OBSTRUCTIONS=", 13)) {
165 s += 13;
166 while (*s == ' ') s++;
167 if ((*s == 't') | (*s == 'T'))
168 *hf |= H_OBST;
169 else if ((*s == 'f') | (*s == 'F'))
170 *hf |= H_OBSF;
171 else
172 error(WARNING, "bad OBSTRUCTIONS value in holodeck");
173 return(0);
174 }
175 if (!strncmp(s, "VDISTANCE=", 10)) {
176 s += 10;
177 while (*s == ' ') s++;
178 if ((*s == 't') | (*s == 'T'))
179 *hf |= H_VDST;
180 else if ((*s != 'f') % (*s != 'F'))
181 error(WARNING, "bad VDISTANCE value in holodeck");
182 return(0);
183 }
184 if ((be = isbigendian(s)) >= 0) {
185 if (be != nativebigendian())
186 *hf |= H_SWAP;
187 return(0);
188 }
189 return(0);
190 }
191
192 int
193 openholo( /* open existing holodeck file for i/o */
194 char *fname,
195 int append
196 )
197 {
198 FILE *fp;
199 int fd;
200 int hflags = 0;
201 int *hfstore;
202 off_t nextloc;
203 int n;
204 /* open holodeck file */
205 if ((fp = fopen(fname, append ? "rb+" : "rb")) == NULL) {
206 sprintf(errmsg, "cannot open \"%s\" for %s", fname,
207 append ? "appending" : "reading");
208 error(SYSTEM, errmsg);
209 }
210 /* check header and magic number */
211 if (getheader(fp, holheadline, &hflags) < 0 ||
212 hflags&(H_BADF|H_SWAP) || getw(fp) != HOLOMAGIC) {
213 sprintf(errmsg, "holodeck \"%s\" not in expected format", fname);
214 error(USER, errmsg);
215 }
216 fd = dup(fileno(fp)); /* dup file handle */
217 nextloc = ftell(fp); /* get stdio position */
218 fclose(fp); /* done with stdio */
219 hfstore = (int *)malloc(sizeof(int)); /* tiny memory leak but who cares? */
220 *hfstore = hflags;
221 for (n = 0; nextloc > 0L; n++) { /* initialize each section */
222 lseek(fd, nextloc, SEEK_SET);
223 read(fd, (char *)&nextloc, sizeof(nextloc));
224 hdinit(fd, NULL)->priv = hfstore;
225 }
226 return(n);
227 }
228
229 int
230 addray( /* add a ray to our output holodeck */
231 RAYPAR *rp
232 )
233 {
234 int sn, bi, n;
235 HOLO *hp;
236 GCOORD gc[2];
237 uby8 rr[2][2];
238 BEAM *bp;
239 double d0, d1;
240 unsigned dc;
241 RAYVAL *rv;
242 int nsects = 0;
243 /* check each output section */
244 for (sn = nholosects; sn--; ) {
245 hp = hdlist[sn];
246 d0 = hdinter(gc, rr, &d1, hp, rp->ro, rp->rd);
247 if (rp->d <= d0 || d1 < -0.001)
248 continue; /* missed section */
249 if (checkdepth) { /* check depth */
250 if (*(int *)hp->priv & H_OBST && d0 < -0.001)
251 continue; /* ray starts too late */
252 if (*(int *)hp->priv & H_OBSF && rp->d < 0.999*d1)
253 continue; /* ray ends too soon */
254 }
255 dc = hdcode(hp, rp->d-d0);
256 bi = hdbindex(hp, gc); /* check for duplicates */
257 if (checkrepeats && (bp = hdgetbeam(hp, bi)) != NULL) {
258 for (n = bp->nrm, rv = hdbray(bp); n--; rv++)
259 if ((rv->d == dc || *(int *)hp->priv & (H_OBST|H_OBSF)) &&
260 rv->r[0][0] == rr[0][0] &&
261 rv->r[0][1] == rr[0][1] &&
262 rv->r[1][0] == rr[1][0] &&
263 rv->r[1][1] == rr[1][1])
264 break;
265 if (n >= 0)
266 continue; /* found a matching ray */
267 }
268 rv = hdnewrays(hp, bi, 1);
269 rv->d = dc;
270 rv->r[0][0] = rr[0][0]; rv->r[0][1] = rr[0][1];
271 rv->r[1][0] = rr[1][0]; rv->r[1][1] = rr[1][1];
272 copycolr(rv->v, rp->cv);
273 ++nsects;
274 }
275 return nsects;
276 }
277
278 /* Read n-vector from file stream */
279 static int
280 readval(RREAL *v, int n, FILE *fp)
281 {
282 int i;
283 #ifdef SMLFLT
284 double vd[3];
285 switch (iofmt) {
286 case 'f':
287 return getbinary(v, sizeof(float), n, fp);
288 case 'd':
289 n = getbinary(vd, sizeof(double), n, fp);
290 for (i = n; i-- > 0; ) v[i] = vd[i];
291 return n;
292 case 'a':
293 for (i = 0; i < n; i++)
294 if (fscanf(fp, "%f ", &v[i]) != 1)
295 break;
296 return i;
297 }
298 #else
299 float vf[3];
300 switch (iofmt) {
301 case 'd':
302 return getbinary(v, sizeof(double), n, fp);
303 case 'f':
304 n = getbinary(vf, sizeof(float), n, fp);
305 for (i = n; i-- > 0; ) v[i] = vf[i];
306 return n;
307 case 'a':
308 for (i = 0; i < n; i++)
309 if (fscanf(fp, "%lf ", &v[i]) != 1)
310 break;
311 return i;
312 }
313 #endif
314 return -1;
315 }
316
317 #define GOT_ORG 0x01
318 #define GOT_DIR 0x02
319 #define GOT_LEN 0x04
320 #define GOT_VAL 0x10
321 #define ALSO_POS 0x20
322 #define BAD_DIR 0x40
323 #define BAD_LEN 0x80
324
325 /* Read rays from stream and add to holodeck */
326 static void
327 readrays(FILE *fp)
328 {
329 unsigned long nread=0, ngood=0;
330
331 if (iofmt != 'a')
332 SET_FILE_BINARY(fp);
333 #ifdef getc_unlocked
334 flockfile(fp);
335 #endif
336 while (!feof(fp)) { /* read entirety of input */
337 RAYPAR ryp;
338 FVECT pos;
339 FVECT col;
340 int flags = 0;
341 int i;
342 for (i = 0; rspec[i]; i++) {
343 switch (rspec[i]) {
344 case 'o': /* ray origin */
345 if (readval(ryp.ro, 3, fp) < 3)
346 break;
347 flags |= GOT_ORG;
348 continue;
349 case 'd': /* ray direction */
350 if (readval(ryp.rd, 3, fp) < 3)
351 break;
352 if (normalize(ryp.rd) == 0)
353 flags |= BAD_DIR;
354 else
355 flags |= GOT_DIR;
356 continue;
357 case 'p': /* ray intersection */
358 if (readval(pos, 3, fp) < 3)
359 break;
360 flags |= ALSO_POS;
361 continue;
362 case 'L': /* ray first length */
363 case 'l': /* ray virtual length */
364 if (readval(&ryp.d, 1, fp) < 1)
365 break;
366 if (ryp.d <= FTINY)
367 flags |= BAD_LEN;
368 else
369 flags |= GOT_LEN;
370 continue;
371 case 'v': /* ray value */
372 if (readval(col, 3, fp) < 3)
373 break;
374 setcolr(ryp.cv, col[0], col[1], col[2]);
375 flags |= GOT_VAL;
376 continue;
377 default:
378 sprintf(errmsg, "unsupported parameter '%c' in -i%s",
379 rspec[i], rspec);
380 error(USER, errmsg);
381 }
382 if (!flags) /* got nothing, so may be normal EOF */
383 return;
384 }
385 ++nread;
386 if (flags & (BAD_DIR|BAD_LEN))
387 continue; /* just a bad ray is all -- skip */
388 if (!(flags & GOT_VAL))
389 goto missingData;
390 if ((flags & (GOT_ORG|GOT_DIR|GOT_LEN)) != (GOT_ORG|GOT_DIR|GOT_LEN)) {
391 if (!(flags & ALSO_POS))
392 goto missingData;
393 if (flags & GOT_ORG) {
394 VSUB(ryp.rd, pos, ryp.ro);
395 ryp.d = normalize(ryp.rd);
396 if (ryp.d == 0)
397 continue;
398 } else if ((flags & (GOT_DIR|GOT_LEN)) == (GOT_DIR|GOT_LEN)) {
399 VSUM(ryp.ro, pos, ryp.rd, -ryp.d);
400 } else
401 goto missingData;
402 }
403 ngood += (addray(&ryp) > 0); /* add our ray to holodeck */
404 }
405 return;
406 missingData:
407 sprintf(errmsg, "insufficient data or read error with -i%s after %lu rays read (%lu used)",
408 rspec, nread, ngood);
409 error(USER, errmsg);
410 }
411
412 /* Write vector value to file stream */
413 static int
414 writeval(RREAL *v, int n, FILE *fp)
415 {
416 int i;
417
418 if (iofmt == 'a') {
419 for (i = 0; i < n; i++)
420 if (fprintf(fp, "\t%.4e", v[i]) < 0)
421 break;
422 return i;
423 }
424 #ifdef SMLFLT
425 if (iofmt == 'd') {
426 double vd[3];
427 for (i = n; i--; ) vd[i] = v[i];
428 return putbinary(vd, sizeof(double), n, fp);
429 }
430 #else
431 if (iofmt == 'f') {
432 float vf[3];
433 for (i = n; i--; ) vf[i] = v[i];
434 return putbinary(vf, sizeof(float), n, fp);
435 }
436 #endif
437 return putbinary(v, sizeof(*v), n, fp);
438 }
439
440 /* Write out an individual ray as requested */
441 static int
442 write_ray(RAYPAR *rp, FILE *fp)
443 {
444 COLOR cval;
445 FVECT v3;
446 char *typ = rspec;
447
448 for ( ; ; ) {
449 switch (*typ++) {
450 case 'o': /* ray origin */
451 if (writeval(rp->ro, 3, fp) < 3)
452 break;
453 continue;
454 case 'd': /* ray direction */
455 if (writeval(rp->rd, 3, fp) < 3)
456 break;
457 continue;
458 case 'p': /* ray intersection */
459 VSUM(v3, rp->ro, rp->rd, rp->d);
460 if (writeval(v3, 3, fp) < 3)
461 break;
462 continue;
463 case 'L': /* ray first length */
464 case 'l': /* ray virtual length */
465 if (writeval(&rp->d, 1, fp) < 1)
466 break;
467 continue;
468 case 'v': /* ray value */
469 colr_color(cval, rp->cv);
470 VCOPY(v3, cval);
471 if (writeval(v3, 3, fp) < 3)
472 break;
473 continue;
474 case '\0': /* end of spec -- success */
475 if (iofmt == 'a')
476 fputc('\n', fp);
477 return(1);
478 default:
479 sprintf(errmsg, "unsupported parameter '%c' in -o%s", typ[-1], rspec);
480 }
481 break; /* land here on error */
482 }
483 return 0; /* write error? */
484 }
485
486 static BEAMI *beamdir;
487
488 static int
489 bpcmp( /* compare beam positions on disk */
490 const void *b1p,
491 const void *b2p
492 )
493 {
494 off_t pdif = beamdir[*(int *)b1p].fo - beamdir[*(int *)b2p].fo;
495
496 if (pdif > 0L) return(1);
497 if (pdif < 0L) return(-1);
498 return(0);
499 }
500
501 /* Write all rays from holodeck to stream */
502 static void
503 writerays(FILE *fp)
504 {
505 int sn, bi, k;
506 GCOORD gc[2];
507 RAYVAL *rv;
508 RAYPAR ryp;
509
510 if (!*rspec) {
511 error(WARNING, "empty -o* output spec, quitting");
512 return;
513 }
514 if (iofmt != 'a')
515 SET_FILE_BINARY(fp);
516 #ifdef getc_unlocked
517 flockfile(fp);
518 #endif
519 for (sn = 0; sn < nholosects; sn++) { /* write each holodeck section */
520 HOLO *hp = hdlist[sn];
521 int nb = nbeams(hp); /* sort beams by file location */
522 int *bq = (int *)malloc(nb*sizeof(int));
523 if (!bq)
524 error(SYSTEM, "out of memory in writerays()");
525 for (bi = nb; bi--; ) bq[bi] = bi+1;
526 beamdir = hp->bi;
527 qsort(bq, nb, sizeof(*bq), bpcmp);
528 for (bi = 0; bi < nb; bi++) {
529 BEAM *bp = hdgetbeam(hp, bq[bi]);
530 if (!bp) /* empty beam? */
531 continue;
532 hdbcoord(gc, hp, bq[bi]);
533 rv = hdbray(bp);
534 for (k = bp->nrm; k--; rv++) {
535 RREAL hitd = hddepth(hp, rv->d);
536 ryp.d = hdray(ryp.ro, ryp.rd, hp, gc, rv->r);
537 if (*(int *)hp->priv & H_OBST) {
538 ryp.d = 0;
539 } else {
540 if (ryp.d > 0.97*hitd)
541 ryp.d = 0.97*hitd;
542 VSUM(ryp.ro, ryp.ro, ryp.rd, ryp.d);
543 }
544 ryp.d = hitd - ryp.d;
545 copycolr(ryp.cv, rv->v);
546 if (!write_ray(&ryp, fp)) {
547 free(bq);
548 goto writError;
549 }
550 }
551 hdfreebeam(hp, bq[bi]);
552 }
553 free(bq);
554 }
555 if (fflush(fp) != EOF)
556 return;
557 writError:
558 error(SYSTEM, "error writing holodeck rays");
559 }
560
561 static int
562 addclump( /* transfer the given clump and free */
563 HOLO *hp,
564 int *bq,
565 int nb
566 )
567 {
568 GCOORD gc[2];
569 RAYPAR ryp;
570 RAYVAL *rv;
571 int i;
572 int k;
573 BEAM *bp;
574 /* sort based on file position */
575 beamdir = hp->bi;
576 qsort(bq, nb, sizeof(*bq), bpcmp);
577 /* transfer each beam */
578 for (i = 0; i < nb; i++) {
579 bp = hdgetbeam(hp, bq[i]);
580 hdbcoord(gc, hp, bq[i]);
581 rv = hdbray(bp); /* add each ray to output */
582 for (k = bp->nrm; k--; rv++) {
583 ryp.d = hdray(ryp.ro, ryp.rd, hp, gc, rv->r);
584 if (*(int *)hp->priv & H_OBSF)
585 VSUM(ryp.ro, ryp.ro, ryp.rd, ryp.d);
586 else
587 ryp.d = 0.;
588 ryp.d = hddepth(hp, rv->d) - ryp.d;
589 copycolr(ryp.cv, rv->v);
590 addray(&ryp);
591 }
592 hdfreebeam(hp, bq[i]); /* free the beam */
593 }
594 return(0);
595 }
596
597
598 void
599 addholo( /* add a holodeck file */
600 char *hdf
601 )
602 {
603 int fd;
604 /* open the holodeck for reading */
605 openholo(hdf, 0);
606 fd = hdlist[nholosects]->fd; /* remember the file handle */
607 while (hdlist[nholosects] != NULL) { /* load each section */
608 /* clump the beams */
609 clumpbeams(hdlist[nholosects], 0, BKBSIZE*1024, addclump);
610 hddone(hdlist[nholosects]); /* free the section */
611 }
612 close(fd); /* close input file */
613 hdflush(NULL); /* flush output */
614 }
615
616
617
618 static int
619 picheadline( /* process picture header line */
620 char *s,
621 void *vph
622 )
623 {
624 char fmt[32];
625 struct phead *ph = (struct phead *)vph;
626
627 if (formatval(fmt, s)) {
628 ph->badfmt = strcmp(fmt, COLRFMT);
629 return(0);
630 }
631 if (isprims(s)) {
632 ph->altprims++; /* don't want to deal with this */
633 return(0);
634 }
635 if (isexpos(s)) {
636 ph->expos *= exposval(s);
637 return(0);
638 }
639 if (isview(s)) {
640 ph->gotview += sscanview(&ph->vw, s);
641 return(0);
642 }
643 return(0);
644 }
645
646
647 void
648 addpicz( /* add a picture + depth-buffer */
649 char *pcf,
650 char *zbf
651 )
652 {
653 FILE *pfp;
654 int zfd;
655 COLR *cscn;
656 float *zscn;
657 struct phead phd;
658 int eshft;
659 double emult;
660 RESOLU prs;
661 RREAL vl[2];
662 RAYPAR ryp;
663 double aftd;
664 int j, i;
665 /* open picture & get header */
666 if ((pfp = fopen(pcf, "rb")) == NULL) {
667 sprintf(errmsg, "cannot open picture file \"%s\"", pcf);
668 error(SYSTEM, pcf);
669 }
670 phd.vw = stdview;
671 phd.expos = 1.0;
672 phd.badfmt = phd.gotview = phd.altprims = 0;
673 if (getheader(pfp, picheadline, &phd) < 0 ||
674 phd.badfmt || !fgetsresolu(&prs, pfp)) {
675 sprintf(errmsg, "bad format for picture file \"%s\"", pcf);
676 error(USER, errmsg);
677 }
678 if (!phd.gotview || setview(&phd.vw) != NULL) {
679 sprintf(errmsg, "missing/illegal view in picture \"%s\"",
680 pcf);
681 error(USER, errmsg);
682 }
683 if (phd.altprims) {
684 sprintf(errmsg, "ignoring color primaries in picture \"%s\"",
685 pcf);
686 error(WARNING, errmsg);
687 }
688 /* open depth buffer */
689 if ((zfd = open_float_depth(zbf, prs.xr*prs.yr)) < 0)
690 quit(1);
691 /* figure out what to do about exposure */
692 if ((phd.expos < 0.99) | (phd.expos > 1.01)) {
693 emult = -log(phd.expos)/log(2.);
694 eshft = emult >= 0. ? emult+.5 : emult-.5;
695 emult -= (double)eshft;
696 if ((emult <= 0.01) & (emult >= -0.01))
697 emult = -1.;
698 else {
699 emult = 1./phd.expos;
700 eshft = 0;
701 }
702 } else {
703 emult = -1.;
704 eshft = 0;
705 }
706 /* allocate buffers */
707 cscn = (COLR *)malloc(scanlen(&prs)*sizeof(COLR));
708 zscn = (float *)malloc(scanlen(&prs)*sizeof(float));
709 if ((cscn == NULL) | (zscn == NULL))
710 error(SYSTEM, "out of memory in addpicz");
711 /* read and process each scanline */
712 for (j = 0; j < numscans(&prs); j++) {
713 i = scanlen(&prs); /* read colrs */
714 if (freadcolrs(cscn, i, pfp) < 0) {
715 sprintf(errmsg, "error reading picture \"%s\"", pcf);
716 error(USER, errmsg);
717 }
718 if (eshft) /* shift exposure */
719 shiftcolrs(cscn, i, eshft);
720 /* read depth */
721 if (read(zfd, zscn, i*sizeof(float)) != i*sizeof(float)) {
722 sprintf(errmsg, "error reading depth file \"%s\"", zbf);
723 error(USER, errmsg);
724 }
725 while (i--) { /* process each pixel */
726 if (zscn[i] <= 0.0)
727 continue; /* illegal depth */
728 pix2loc(vl, &prs, i, j);
729 aftd = viewray(ryp.ro, ryp.rd, &phd.vw, vl[0], vl[1]);
730 if (aftd < -FTINY)
731 continue; /* off view */
732 if (aftd > FTINY && zscn[i] > aftd)
733 continue; /* aft clipped */
734 ryp.d = (RREAL)zscn[i];
735 copycolr(ryp.cv, cscn[i]);
736 if (emult > 0.) { /* whatta pain */
737 COLOR ctmp;
738 colr_color(ctmp, ryp.cv);
739 scalecolor(ctmp, emult);
740 setcolr(ryp.cv, colval(ctmp,RED),
741 colval(ctmp,GRN), colval(ctmp,BLU));
742 }
743 addray(&ryp);
744 }
745 }
746 /* write output and free beams */
747 hdflush(NULL);
748 /* clean up */
749 free((void *)cscn);
750 free((void *)zscn);
751 fclose(pfp);
752 close(zfd);
753 }
754
755
756 void
757 eputs( /* put error message to stderr */
758 const char *s
759 )
760 {
761 static int midline = 0;
762
763 if (!*s)
764 return;
765 if (!midline++) { /* prepend line with program name */
766 fputs(progname, stderr);
767 fputs(": ", stderr);
768 }
769 fputs(s, stderr);
770 if (s[strlen(s)-1] == '\n') {
771 fflush(stderr);
772 midline = 0;
773 }
774 }
775
776
777 void
778 quit( /* exit the program gracefully */
779 int code
780 )
781 {
782 hdsync(NULL, 1); /* write out any buffered data */
783 exit(code);
784 }