ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/depthcodec.c
Revision: 2.1
Committed: Thu Jul 18 18:51:56 2019 UTC (4 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Created rcode_depth utility to encode/decode 16-bit depth maps

File Contents

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