ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/depthcodec.c
Revision: 2.2
Committed: Thu Jul 18 22:33:34 2019 UTC (4 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.1: +15 -10 lines
Log Message:
Improved accuracy + made depth2code() a macro so module not needed for encoding

File Contents

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