ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/depthcodec.c
Revision: 2.5
Committed: Thu Nov 7 23:20:28 2019 UTC (5 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.4: +18 -9 lines
Log Message:
Added ability for pinterp, pmblur2, and vwrays to read 16-bit encoded depth

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.5 static const char RCSid[] = "$Id: depthcodec.c,v 2.4 2019/08/14 21:00:14 greg Exp $";
3 greg 2.1 #endif
4     /*
5     * Routines to encode/decoded 16-bit depths
6     */
7    
8     #include "copyright.h"
9    
10     #include <stdlib.h>
11     #include <math.h>
12     #include <ctype.h>
13     #include "rtio.h"
14     #include "fvect.h"
15     #include "depthcodec.h"
16    
17    
18 greg 2.3 #ifndef depth2code
19 greg 2.1 /* Encode depth as 16-bit signed integer */
20     int
21     depth2code(double d, double dref)
22     {
23     if (d <= .0)
24     return -32768;
25    
26     if (d > dref)
27 greg 2.3 return (int)(32768.001 - 32768.*dref/d) - 1;
28 greg 2.1
29 greg 2.3 return (int)(32767.*d/dref - 32768.);
30 greg 2.1 }
31     #endif
32    
33    
34 greg 2.3 #ifndef code2depth
35 greg 2.1 /* Decode depth from 16-bit signed integer */
36     double
37     code2depth(int c, double dref)
38     {
39     if (c <= -32768)
40     return .0;
41    
42     if (c >= 32767)
43     return FHUGE;
44 greg 2.5
45     if (c >= 0)
46     return dref*32768./(32766.5 - c);
47    
48     return dref*(32767.5 + c)*(1./32767.);
49 greg 2.1 }
50 greg 2.3 #endif
51 greg 2.1
52    
53     /* Set codec defaults */
54     void
55     set_dc_defaults(DEPTHCODEC *dcp)
56     {
57     memset(dcp, 0, sizeof(DEPTHCODEC));
58     dcp->finp = stdin;
59     dcp->inpname = "<stdin>";
60     dcp->format = 'a';
61     dcp->refdepth = 1.;
62     dcp->depth_unit[0] = '1';
63     dcp->vw = stdview;
64     dcp->res.rt = PIXSTANDARD;
65     if (!progname) progname = "depth_codec";
66     }
67    
68    
69     /* process header line */
70     static int
71     headline(char *s, void *p)
72     {
73     DEPTHCODEC *dcp = (DEPTHCODEC *)p;
74 greg 2.4 int rv;
75 greg 2.1
76     if (formatval(dcp->inpfmt, s)) /* don't pass format */
77     return 0;
78 greg 2.4
79     if ((rv = isbigendian(s)) >= 0) {
80     dcp->swapped = (nativebigendian() != rv);
81     return 0;
82     }
83 greg 2.1 /* check for reference depth */
84     if (!strncmp(s, DEPTHSTR, LDEPTHSTR)) {
85     char *cp;
86     strlcpy(dcp->depth_unit, s+LDEPTHSTR, sizeof(dcp->depth_unit));
87     cp = dcp->depth_unit;
88     while (*cp) cp++;
89     while (cp > dcp->depth_unit && isspace(cp[-1])) cp--;
90     *cp = '\0';
91     dcp->refdepth = atof(dcp->depth_unit);
92     if (dcp->refdepth <= .0) {
93 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
94     fputs(dcp->inpname, stderr);
95     fputs(": bad reference depth in input header\n",
96     stderr);
97     }
98 greg 2.1 return -1;
99     }
100     } else if (isview(s)) /* get view params */
101     dcp->gotview += (sscanview(&dcp->vw, s) > 0);
102     if (dcp->hdrflags & HF_HEADOUT)
103     fputs(s, stdout); /* copy to standard output */
104     return 1;
105     }
106    
107    
108     /* Load/copy header */
109     int
110     process_dc_header(DEPTHCODEC *dcp, int ac, char *av[])
111     {
112     if (dcp->hdrflags & HF_HEADIN &&
113     getheader(dcp->finp, headline, dcp) < 0) {
114 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
115     fputs(dcp->inpname, stderr);
116     fputs(": bad header\n", stderr);
117     }
118     return 0;
119 greg 2.1 }
120     if (dcp->hdrflags & HF_HEADOUT) { /* finish header */
121     if (!(dcp->hdrflags & HF_HEADIN))
122     newheader("RADIANCE", stdout);
123     if (ac > 0)
124     printargs(ac, av, stdout);
125     if (dcp->hdrflags & HF_ENCODE) {
126     fputs(DEPTHSTR, stdout);
127     fputs(dcp->depth_unit, stdout);
128     fputc('\n', stdout);
129     fputformat(DEPTH16FMT, stdout);
130     } else
131     switch (dcp->format) {
132     case 'a':
133     fputformat("ascii", stdout);
134     break;
135     case 'f':
136 greg 2.4 fputendian(stdout);
137 greg 2.1 fputformat("float", stdout);
138     break;
139     case 'd':
140 greg 2.4 fputendian(stdout);
141 greg 2.1 fputformat("double", stdout);
142     break;
143     }
144     fputc('\n', stdout);
145     }
146     /* get/put resolution string */
147     if (dcp->hdrflags & HF_RESIN && !fgetsresolu(&dcp->res, dcp->finp)) {
148 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
149     fputs(dcp->inpname, stderr);
150     fputs(": bad resolution string\n", stderr);
151     }
152     return 0;
153 greg 2.1 }
154     if (dcp->hdrflags & HF_RESOUT)
155     fputsresolu(&dcp->res, stdout);
156    
157     dcp->dstart = dcp->curpos = ftell(dcp->finp);
158     return 1;
159     }
160    
161    
162     /* Check that we have what we need to decode depths */
163     int
164     check_decode_depths(DEPTHCODEC *dcp)
165     {
166     if (dcp->hdrflags & HF_ENCODE) {
167 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
168     fputs(progname, stderr);
169     fputs(": wrong header mode for decode\n", stderr);
170     }
171 greg 2.1 return 0;
172     }
173     if (dcp->inpfmt[0] && strcmp(dcp->inpfmt, DEPTH16FMT)) {
174 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
175     fputs(dcp->inpname, stderr);
176     fputs(": unexpected input format: ", stderr);
177     fputs(dcp->inpfmt, stderr);
178     fputc('\n', stderr);
179     }
180 greg 2.1 return 0;
181     }
182     return 1;
183     }
184    
185    
186     /* Check that we have what we need to decode world positions */
187     int
188     check_decode_worldpos(DEPTHCODEC *dcp)
189     {
190     char *err;
191    
192     if (!check_decode_depths(dcp))
193     return 0;
194     if ((dcp->res.xr <= 0) | (dcp->res.yr <= 0)) {
195 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
196     fputs(progname, stderr);
197     fputs(": missing map resolution\n", stderr);
198     }
199 greg 2.1 return 0;
200     }
201     if (!dcp->gotview) {
202 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
203     fputs(dcp->inpname, stderr);
204     fputs(": missing view\n", stderr);
205     }
206 greg 2.1 return 0;
207     }
208     if ((err = setview(&dcp->vw)) != NULL) {
209 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
210     fputs(dcp->inpname, stderr);
211     fputs(": input view error: ", stderr);
212     fputs(err, stderr);
213     fputc('\n', stderr);
214     }
215 greg 2.1 return 0;
216     }
217     return 1;
218     }
219    
220    
221     /* Decode next depth pixel */
222     double
223     decode_depth_next(DEPTHCODEC *dcp)
224     {
225 greg 2.5 int c;
226    
227     if (dcp->use_last) {
228     dcp->use_last = 0;
229     return code2depth(dcp->last_dc, dcp->refdepth);
230     }
231     c = getint(2, dcp->finp);
232 greg 2.1
233     if (c == EOF && feof(dcp->finp))
234     return -1.;
235    
236 greg 2.5 dcp->last_dc = c;
237 greg 2.1 dcp->curpos += 2;
238    
239     return code2depth(c, dcp->refdepth);
240     }
241    
242    
243     /* Compute world position from depth */
244     int
245     compute_worldpos(FVECT wpos, DEPTHCODEC *dcp, int x, int y, double d)
246     {
247     RREAL loc[2];
248     FVECT rdir;
249    
250     pix2loc(loc, &dcp->res, x, y);
251    
252     if (viewray(wpos, rdir, &dcp->vw, loc[0], loc[1]) < -FTINY) {
253     VCOPY(wpos, dcp->vw.vp);
254     return 0;
255     }
256     VSUM(wpos, wpos, rdir, d);
257     return 1;
258     }
259    
260    
261     /* Decode the next world position */
262     int
263     decode_worldpos_next(FVECT wpos, DEPTHCODEC *dcp)
264     {
265     const long n = (dcp->curpos - dcp->dstart)>>1;
266     int x, y;
267     double d;
268    
269     d = decode_depth_next(dcp);
270     if (d < -FTINY)
271     return -1;
272    
273     x = scanlen(&dcp->res);
274     y = n / x;
275     x = n - (long)y*x;
276    
277     return compute_worldpos(wpos, dcp, x, y, d);
278     }
279    
280    
281     /* Seek to the indicated pixel position */
282     int
283     seek_dc_pix(DEPTHCODEC *dcp, int x, int y)
284     {
285     long seekpos;
286    
287     if ((dcp->res.xr <= 0) | (dcp->res.yr <= 0)) {
288 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
289     fputs(progname, stderr);
290     fputs(": need map resolution to seek\n", stderr);
291     }
292 greg 2.1 return -1;
293     }
294     if ((x < 0) | (y < 0) ||
295     (x >= scanlen(&dcp->res)) | (y >= numscans(&dcp->res))) {
296 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
297     fputs(dcp->inpname, stderr);
298     fputs(": warning - pixel index off map\n", stderr);
299     }
300 greg 2.1 return 0;
301     }
302     seekpos = dcp->dstart + 2*((long)y*scanlen(&dcp->res) + x);
303    
304 greg 2.5 if (seekpos == dcp->curpos-2) {
305     dcp->use_last++; /* avoids seek/read */
306     return 1;
307     }
308 greg 2.1 if (seekpos != dcp->curpos &&
309     fseek(dcp->finp, seekpos, SEEK_SET) == EOF) {
310 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
311     fputs(dcp->inpname, stderr);
312     fputs(": seek error\n", stderr);
313     }
314 greg 2.1 return -1;
315     }
316     dcp->curpos = seekpos;
317     return 1;
318     }
319    
320    
321     /* Read and decode depth for the given pixel */
322     double
323     decode_depth_pix(DEPTHCODEC *dcp, int x, int y)
324     {
325     int rval = seek_dc_pix(dcp, x, y);
326    
327     if (rval < 0)
328     return -1.;
329     if (!rval)
330     return .0;
331    
332     return decode_depth_next(dcp);
333     }
334    
335    
336     /* Read and decode the world position at the given pixel */
337     int
338     get_worldpos_pix(FVECT wpos, DEPTHCODEC *dcp, int x, int y)
339     {
340     double d = decode_depth_pix(dcp, x, y);
341    
342     if (d < -FTINY)
343     return -1;
344    
345     return compute_worldpos(wpos, dcp, x, y, d);
346     }