ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/depthcodec.c
Revision: 2.12
Committed: Thu Mar 3 16:09:31 2022 UTC (3 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.11: +17 -11 lines
Log Message:
feat(rcode_depth,rcode_norm): Output NROWS & NCOLS with -Ho

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: depthcodec.c,v 2.11 2021/01/26 18:47:25 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.999);
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 >= -1)
46 return dref*32768./(32766.5 - c);
47
48 return dref*(32768.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 if (dcp->hdrflags & HF_ENCODE)
101 return 0; /* will add this later */
102 } else if (!strncmp(s, "SAMP360=", 8))
103 dcp->gotview--;
104 else if (isview(s)) /* get view params */
105 dcp->gotview += (sscanview(&dcp->vw, s) > 0);
106 if (dcp->hdrflags & HF_HEADOUT)
107 fputs(s, stdout); /* copy to standard output */
108 return 1;
109 }
110
111
112 /* Load/copy header */
113 int
114 process_dc_header(DEPTHCODEC *dcp, int ac, char *av[])
115 {
116 if (dcp->hdrflags & HF_HEADIN &&
117 getheader(dcp->finp, headline, dcp) < 0) {
118 if (dcp->hdrflags & HF_STDERR) {
119 fputs(dcp->inpname, stderr);
120 fputs(": bad header\n", stderr);
121 }
122 return 0;
123 }
124 dcp->gotview *= (dcp->gotview > 0);
125 /* get resolution string? */
126 if (dcp->hdrflags & HF_RESIN && !fgetsresolu(&dcp->res, dcp->finp)) {
127 if (dcp->hdrflags & HF_STDERR) {
128 fputs(dcp->inpname, stderr);
129 fputs(": bad resolution string\n", stderr);
130 }
131 return 0;
132 }
133 if (dcp->hdrflags & HF_HEADOUT) { /* finish header */
134 if (!(dcp->hdrflags & HF_HEADIN))
135 newheader("RADIANCE", stdout);
136 if (ac > 0)
137 printargs(ac, av, stdout);
138 if (dcp->hdrflags & HF_ENCODE) {
139 fputs(DEPTHSTR, stdout);
140 fputs(dcp->depth_unit, stdout);
141 fputc('\n', stdout);
142 fputformat(DEPTH16FMT, stdout);
143 } else {
144 fputs("NCOMP=1\n", stdout);
145 if ((dcp->hdrflags & (HF_RESIN|HF_RESOUT)) == HF_RESIN)
146 printf("NCOLS=%d\nNROWS=%d\n",
147 scanlen(&dcp->res),
148 numscans(&dcp->res));
149 switch (dcp->format) {
150 case 'a':
151 fputformat("ascii", stdout);
152 break;
153 case 'f':
154 fputendian(stdout);
155 fputformat("float", stdout);
156 break;
157 case 'd':
158 fputendian(stdout);
159 fputformat("double", stdout);
160 break;
161 }
162 }
163 fputc('\n', stdout);
164 }
165 if (dcp->hdrflags & HF_RESOUT) /* put resolution string? */
166 fputsresolu(&dcp->res, stdout);
167
168 dcp->dstart = dcp->curpos = ftell(dcp->finp);
169 return 1;
170 }
171
172
173 /* Check that we have what we need to decode depths */
174 int
175 check_decode_depths(DEPTHCODEC *dcp)
176 {
177 if (dcp->hdrflags & HF_ENCODE) {
178 if (dcp->hdrflags & HF_STDERR) {
179 fputs(progname, stderr);
180 fputs(": wrong header mode for decode\n", stderr);
181 }
182 return 0;
183 }
184 if (dcp->inpfmt[0] && strcmp(dcp->inpfmt, DEPTH16FMT)) {
185 if (dcp->hdrflags & HF_STDERR) {
186 fputs(dcp->inpname, stderr);
187 fputs(": unexpected input format: ", stderr);
188 fputs(dcp->inpfmt, stderr);
189 fputc('\n', stderr);
190 }
191 return 0;
192 }
193 return 1;
194 }
195
196
197 /* Check that we have what we need to decode world positions */
198 int
199 check_decode_worldpos(DEPTHCODEC *dcp)
200 {
201 char *err;
202
203 if (!check_decode_depths(dcp))
204 return 0;
205 if ((dcp->res.xr <= 0) | (dcp->res.yr <= 0)) {
206 if (dcp->hdrflags & HF_STDERR) {
207 fputs(progname, stderr);
208 fputs(": missing map resolution\n", stderr);
209 }
210 return 0;
211 }
212 if (!dcp->gotview) {
213 if (dcp->hdrflags & HF_STDERR) {
214 fputs(dcp->inpname, stderr);
215 fputs(": missing view\n", stderr);
216 }
217 return 0;
218 }
219 if ((err = setview(&dcp->vw)) != NULL) {
220 if (dcp->hdrflags & HF_STDERR) {
221 fputs(dcp->inpname, stderr);
222 fputs(": input view error: ", stderr);
223 fputs(err, stderr);
224 fputc('\n', stderr);
225 }
226 return 0;
227 }
228 return 1;
229 }
230
231
232 /* Decode next depth pixel */
233 double
234 decode_depth_next(DEPTHCODEC *dcp)
235 {
236 int c;
237
238 if (dcp->use_last) {
239 dcp->use_last = 0;
240 return code2depth(dcp->last_dc, dcp->refdepth);
241 }
242 c = getint(2, dcp->finp);
243
244 if (c == EOF && feof(dcp->finp))
245 return -1.;
246
247 dcp->last_dc = c;
248 dcp->curpos += 2;
249
250 return code2depth(c, dcp->refdepth);
251 }
252
253
254 /* Compute world position from depth */
255 int
256 compute_worldpos(FVECT wpos, DEPTHCODEC *dcp, int x, int y, double d)
257 {
258 RREAL loc[2];
259 FVECT rdir;
260
261 if (d >= FHUGE*.99)
262 goto badval;
263
264 pix2loc(loc, &dcp->res, x, y);
265
266 if (viewray(wpos, rdir, &dcp->vw, loc[0], loc[1]) >= -FTINY) {
267 VSUM(wpos, wpos, rdir, d);
268 return 1;
269 }
270 badval:
271 VCOPY(wpos, dcp->vw.vp);
272 return 0;
273 }
274
275
276 /* Decode the next world position */
277 int
278 decode_worldpos_next(FVECT wpos, DEPTHCODEC *dcp)
279 {
280 const long n = (dcp->curpos - dcp->dstart)>>1;
281 int x, y;
282 double d;
283
284 d = decode_depth_next(dcp);
285 if (d < -FTINY)
286 return -1;
287
288 x = scanlen(&dcp->res);
289 y = n / x;
290 x = n - (long)y*x;
291
292 return compute_worldpos(wpos, dcp, x, y, d);
293 }
294
295
296 /* Seek to the indicated pixel position */
297 int
298 seek_dc_pix(DEPTHCODEC *dcp, int x, int y)
299 {
300 long seekpos;
301
302 if ((dcp->res.xr <= 0) | (dcp->res.yr <= 0)) {
303 if (dcp->hdrflags & HF_STDERR) {
304 fputs(progname, stderr);
305 fputs(": need map resolution to seek\n", stderr);
306 }
307 return -1;
308 }
309 if ((x < 0) | (y < 0) ||
310 (x >= scanlen(&dcp->res)) | (y >= numscans(&dcp->res))) {
311 if (dcp->hdrflags & HF_STDERR) {
312 fputs(dcp->inpname, stderr);
313 fputs(": warning - pixel index off map\n", stderr);
314 }
315 return 0;
316 }
317 seekpos = dcp->dstart + 2*((long)y*scanlen(&dcp->res) + x);
318
319 if (seekpos == dcp->curpos-2) {
320 dcp->use_last++; /* avoids seek/read */
321 return 1;
322 }
323 if (seekpos != dcp->curpos &&
324 fseek(dcp->finp, seekpos, SEEK_SET) == EOF) {
325 if (dcp->hdrflags & HF_STDERR) {
326 fputs(dcp->inpname, stderr);
327 fputs(": seek error\n", stderr);
328 }
329 return -1;
330 }
331 dcp->curpos = seekpos;
332 dcp->use_last = 0;
333 return 1;
334 }
335
336
337 /* Read and decode depth for the given pixel */
338 double
339 decode_depth_pix(DEPTHCODEC *dcp, int x, int y)
340 {
341 int rval = seek_dc_pix(dcp, x, y);
342
343 if (rval < 0)
344 return -1.;
345 if (!rval)
346 return .0;
347
348 return decode_depth_next(dcp);
349 }
350
351
352 /* Read and decode the world position at the given pixel */
353 int
354 get_worldpos_pix(FVECT wpos, DEPTHCODEC *dcp, int x, int y)
355 {
356 double d = decode_depth_pix(dcp, x, y);
357
358 if (d < -FTINY)
359 return -1;
360
361 return compute_worldpos(wpos, dcp, x, y, d);
362 }