ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/depthcodec.c
Revision: 2.3
Committed: Fri Jul 26 18:52:32 2019 UTC (4 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.2: +6 -4 lines
Log Message:
Made macro for code2depth() and made both it and depth2code() macros optional

File Contents

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