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 (4 years, 6 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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: depthcodec.c,v 2.4 2019/08/14 21:00:14 greg Exp $";
3 #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 #ifndef depth2code
19 /* 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 return (int)(32768.001 - 32768.*dref/d) - 1;
28
29 return (int)(32767.*d/dref - 32768.);
30 }
31 #endif
32
33
34 #ifndef code2depth
35 /* 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
45 if (c >= 0)
46 return dref*32768./(32766.5 - c);
47
48 return dref*(32767.5 + c)*(1./32767.);
49 }
50 #endif
51
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 int rv;
75
76 if (formatval(dcp->inpfmt, s)) /* don't pass format */
77 return 0;
78
79 if ((rv = isbigendian(s)) >= 0) {
80 dcp->swapped = (nativebigendian() != rv);
81 return 0;
82 }
83 /* 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 if (dcp->hdrflags & HF_STDERR) {
94 fputs(dcp->inpname, stderr);
95 fputs(": bad reference depth in input header\n",
96 stderr);
97 }
98 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 if (dcp->hdrflags & HF_STDERR) {
115 fputs(dcp->inpname, stderr);
116 fputs(": bad header\n", stderr);
117 }
118 return 0;
119 }
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 fputendian(stdout);
137 fputformat("float", stdout);
138 break;
139 case 'd':
140 fputendian(stdout);
141 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 if (dcp->hdrflags & HF_STDERR) {
149 fputs(dcp->inpname, stderr);
150 fputs(": bad resolution string\n", stderr);
151 }
152 return 0;
153 }
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 if (dcp->hdrflags & HF_STDERR) {
168 fputs(progname, stderr);
169 fputs(": wrong header mode for decode\n", stderr);
170 }
171 return 0;
172 }
173 if (dcp->inpfmt[0] && strcmp(dcp->inpfmt, DEPTH16FMT)) {
174 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 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 if (dcp->hdrflags & HF_STDERR) {
196 fputs(progname, stderr);
197 fputs(": missing map resolution\n", stderr);
198 }
199 return 0;
200 }
201 if (!dcp->gotview) {
202 if (dcp->hdrflags & HF_STDERR) {
203 fputs(dcp->inpname, stderr);
204 fputs(": missing view\n", stderr);
205 }
206 return 0;
207 }
208 if ((err = setview(&dcp->vw)) != NULL) {
209 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 return 0;
216 }
217 return 1;
218 }
219
220
221 /* Decode next depth pixel */
222 double
223 decode_depth_next(DEPTHCODEC *dcp)
224 {
225 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
233 if (c == EOF && feof(dcp->finp))
234 return -1.;
235
236 dcp->last_dc = c;
237 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 if (dcp->hdrflags & HF_STDERR) {
289 fputs(progname, stderr);
290 fputs(": need map resolution to seek\n", stderr);
291 }
292 return -1;
293 }
294 if ((x < 0) | (y < 0) ||
295 (x >= scanlen(&dcp->res)) | (y >= numscans(&dcp->res))) {
296 if (dcp->hdrflags & HF_STDERR) {
297 fputs(dcp->inpname, stderr);
298 fputs(": warning - pixel index off map\n", stderr);
299 }
300 return 0;
301 }
302 seekpos = dcp->dstart + 2*((long)y*scanlen(&dcp->res) + x);
303
304 if (seekpos == dcp->curpos-2) {
305 dcp->use_last++; /* avoids seek/read */
306 return 1;
307 }
308 if (seekpos != dcp->curpos &&
309 fseek(dcp->finp, seekpos, SEEK_SET) == EOF) {
310 if (dcp->hdrflags & HF_STDERR) {
311 fputs(dcp->inpname, stderr);
312 fputs(": seek error\n", stderr);
313 }
314 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 }