ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/depthcodec.c
Revision: 2.13
Committed: Thu Sep 22 21:45:28 2022 UTC (19 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, HEAD
Changes since 2.12: +23 -3 lines
Log Message:
feat(rcode_depth,rcode_norm): Allow NROWS,NCOLS in header rather than res string

File Contents

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