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 (2 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

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.12 static const char RCSid[] = "$Id: depthcodec.c,v 2.11 2021/01/26 18:47:25 greg Exp $";
3 greg 2.1 #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 greg 2.3 #ifndef depth2code
19 greg 2.1 /* 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 greg 2.3 return (int)(32768.001 - 32768.*dref/d) - 1;
28 greg 2.1
29 greg 2.8 return (int)(32767.*d/dref - 32768.999);
30 greg 2.1 }
31     #endif
32    
33    
34 greg 2.3 #ifndef code2depth
35 greg 2.1 /* 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 greg 2.5
45 greg 2.7 if (c >= -1)
46 greg 2.5 return dref*32768./(32766.5 - c);
47    
48 greg 2.7 return dref*(32768.5 + c)*(1./32767.);
49 greg 2.1 }
50 greg 2.3 #endif
51 greg 2.1
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 greg 2.4 int rv;
75 greg 2.1
76     if (formatval(dcp->inpfmt, s)) /* don't pass format */
77     return 0;
78 greg 2.4
79     if ((rv = isbigendian(s)) >= 0) {
80     dcp->swapped = (nativebigendian() != rv);
81     return 0;
82     }
83 greg 2.1 /* 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 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
94     fputs(dcp->inpname, stderr);
95     fputs(": bad reference depth in input header\n",
96     stderr);
97     }
98 greg 2.1 return -1;
99     }
100 greg 2.9 if (dcp->hdrflags & HF_ENCODE)
101     return 0; /* will add this later */
102 greg 2.6 } else if (!strncmp(s, "SAMP360=", 8))
103     dcp->gotview--;
104     else if (isview(s)) /* get view params */
105 greg 2.1 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 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
119     fputs(dcp->inpname, stderr);
120     fputs(": bad header\n", stderr);
121     }
122     return 0;
123 greg 2.1 }
124 greg 2.6 dcp->gotview *= (dcp->gotview > 0);
125 greg 2.12 /* 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 greg 2.1 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 greg 2.12 } 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 greg 2.1 switch (dcp->format) {
150     case 'a':
151     fputformat("ascii", stdout);
152     break;
153     case 'f':
154 greg 2.4 fputendian(stdout);
155 greg 2.1 fputformat("float", stdout);
156     break;
157     case 'd':
158 greg 2.4 fputendian(stdout);
159 greg 2.1 fputformat("double", stdout);
160     break;
161     }
162 greg 2.12 }
163 greg 2.1 fputc('\n', stdout);
164     }
165 greg 2.12 if (dcp->hdrflags & HF_RESOUT) /* put resolution string? */
166 greg 2.1 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 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
179     fputs(progname, stderr);
180     fputs(": wrong header mode for decode\n", stderr);
181     }
182 greg 2.1 return 0;
183     }
184     if (dcp->inpfmt[0] && strcmp(dcp->inpfmt, DEPTH16FMT)) {
185 greg 2.2 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 greg 2.1 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 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
207     fputs(progname, stderr);
208     fputs(": missing map resolution\n", stderr);
209     }
210 greg 2.1 return 0;
211     }
212     if (!dcp->gotview) {
213 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
214     fputs(dcp->inpname, stderr);
215     fputs(": missing view\n", stderr);
216     }
217 greg 2.1 return 0;
218     }
219     if ((err = setview(&dcp->vw)) != NULL) {
220 greg 2.2 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 greg 2.1 return 0;
227     }
228     return 1;
229     }
230    
231    
232     /* Decode next depth pixel */
233     double
234     decode_depth_next(DEPTHCODEC *dcp)
235     {
236 greg 2.5 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 greg 2.1
244     if (c == EOF && feof(dcp->finp))
245     return -1.;
246    
247 greg 2.5 dcp->last_dc = c;
248 greg 2.1 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 greg 2.11 if (d >= FHUGE*.99)
262     goto badval;
263    
264 greg 2.1 pix2loc(loc, &dcp->res, x, y);
265    
266 greg 2.11 if (viewray(wpos, rdir, &dcp->vw, loc[0], loc[1]) >= -FTINY) {
267     VSUM(wpos, wpos, rdir, d);
268     return 1;
269 greg 2.1 }
270 greg 2.11 badval:
271     VCOPY(wpos, dcp->vw.vp);
272     return 0;
273 greg 2.1 }
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 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
304     fputs(progname, stderr);
305     fputs(": need map resolution to seek\n", stderr);
306     }
307 greg 2.1 return -1;
308     }
309     if ((x < 0) | (y < 0) ||
310     (x >= scanlen(&dcp->res)) | (y >= numscans(&dcp->res))) {
311 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
312     fputs(dcp->inpname, stderr);
313     fputs(": warning - pixel index off map\n", stderr);
314     }
315 greg 2.1 return 0;
316     }
317     seekpos = dcp->dstart + 2*((long)y*scanlen(&dcp->res) + x);
318    
319 greg 2.5 if (seekpos == dcp->curpos-2) {
320     dcp->use_last++; /* avoids seek/read */
321     return 1;
322     }
323 greg 2.1 if (seekpos != dcp->curpos &&
324     fseek(dcp->finp, seekpos, SEEK_SET) == EOF) {
325 greg 2.2 if (dcp->hdrflags & HF_STDERR) {
326     fputs(dcp->inpname, stderr);
327     fputs(": seek error\n", stderr);
328     }
329 greg 2.1 return -1;
330     }
331     dcp->curpos = seekpos;
332 greg 2.10 dcp->use_last = 0;
333 greg 2.1 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     }