ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhcopy.c
Revision: 3.38
Committed: Tue Dec 19 20:49:05 2023 UTC (4 months, 1 week ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 3.37: +12 -5 lines
Log Message:
feat(rhcopy): Improved error reporting on read issues for -i*

File Contents

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