ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/srcskipload.c
Revision: 2.3
Committed: Sat Jan 18 03:49:00 2025 UTC (3 months, 2 weeks ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.2: +1 -1 lines
State: FILE REMOVED
Log Message:
refactor: Removed experimental SRCSKIPOPT code

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.3 static const char RCSid[] = "$Id: srcskipload.c,v 2.2 2024/12/13 00:48:19 greg Exp $";
3 greg 2.1 #endif
4     /*
5     * Load source exclusion maps (BMP and MTX)
6     *
7     * External symbols declared in source.h
8     */
9    
10     #ifdef SSKIPOPT /* currently an optional compile */
11    
12     #include "copyright.h"
13    
14     #include "platform.h"
15     #include "paths.h"
16     #include "ray.h"
17     #include "source.h"
18     #include "bmpfile.h"
19     #include "resolu.h"
20    
21     int sskip_dim[2] = {0,0}; /* source skip image size */
22    
23     /* correction file types */
24     enum {CFnone=0, CFfloatY, CFbmpY8};
25    
26     /* struct for bitmap file loading */
27     typedef struct skipbmp {
28     struct skipbmp *next; /* next in skip list */
29     BMPReader *bmp; /* BMP file reader */
30     uby8 *sfl; /* corresponding sources */
31     char bname[1]; /* BMP file name */
32     } SKIPBMP;
33    
34     /* holder for source exclusion images */
35     struct {
36     SKIPBMP *sbmplist; /* list of BMP inputs */
37     int cftype; /* correction file type */
38     union {
39     struct {
40     int fd;
41     int dstart;
42     } Y; /* float Y input */
43     BMPReader *bmp; /* BMP input pointer */
44     } cf; /* correction file input */
45     int *ndxmap; /* allocated index map */
46     float *corrmap; /* allocated correction map */
47     char cfname[MAXSTR]; /* correction file name */
48     } skipin; /* just need the one */
49    
50     /* call-back for matrix header line */
51     static int
52     check_mtx(char *hl, void *p)
53     {
54     int *dim = (int *)p;
55     char fmt[MAXFMTLEN];
56     int rv;
57    
58     if ((rv = isbigendian(hl)) >= 0) {
59     if (rv != nativebigendian()) {
60     eputs("cannot handle byte-swapped data\n");
61     return(-1);
62     }
63     return(1);
64     }
65     if (!strncmp(hl, "NCOLS=", 6)) {
66     dim[0] = atoi(hl+6);
67     if (dim[0] <= 0)
68     return(-1);
69     return(1);
70     }
71     if (!strncmp(hl, "NROWS=", 6)) {
72     dim[1] = atoi(hl+6);
73     if (dim[1] <= 0)
74     return(-1);
75     return(1);
76     }
77     if (isncomp(hl)) {
78     if (ncompval(hl) != 1) {
79     eputs("require single component\n");
80     return(-1);
81     }
82     return(1);
83     }
84     if (formatval(fmt, hl)) {
85     if (strcmp(fmt, "float")) {
86     eputs("require binary float format\n");
87     return(-1);
88     }
89     return(1);
90     }
91     return(0);
92     }
93    
94     /* private call to open floating-point matrix and check dimensions */
95     static void
96     open_float_mtx()
97     {
98     int mydim[2];
99     FILE *fp;
100    
101     skipin.cf.Y.fd = open(skipin.cfname, O_RDONLY);
102     if (skipin.cf.Y.fd < 0) {
103     sprintf(errmsg, "cannot open matrix '%s'", skipin.cfname);
104     error(SYSTEM, errmsg);
105     }
106     SET_FD_BINARY(skipin.cf.Y.fd); /* get temporary FILE pointer */
107     fp = fdopen(dup(skipin.cf.Y.fd), "rb");
108     if (fp == NULL)
109     error(SYSTEM, "out of memory in open_float_mtx()");
110     mydim[0] = mydim[1] = 0; /* check header format, etc. */
111     if (getheader(fp, check_mtx, mydim) < 0)
112     goto badheader;
113     if (!mydim[0] | !mydim[1] &&
114     !fscnresolu(&mydim[0], &mydim[1], fp))
115     goto badheader;
116     if ((mydim[0] == sskip_dim[0]) & (mydim[1] == sskip_dim[1])) {
117     skipin.cf.Y.dstart = ftell(fp);
118     fclose(fp);
119     return; /* lookin' good! */
120     }
121     badheader:
122     sprintf(errmsg, "incompatible header for matrix '%s'", skipin.cfname);
123     error(USER, errmsg);
124     fclose(fp);
125     }
126    
127     /* Open a set of bitmaps corresponding to loaded sources w/ corrections */
128     int
129     srcskip_open(char *bmpspec, char *scorrimg)
130     {
131     int bmcnt = 0;
132     char fname[MAXSTR];
133     char *sfx;
134     int sn;
135    
136     srcskip_free_maps(); /* clear previous */
137     srcskip_close();
138     sskip_dim[0] = sskip_dim[1] = 0;
139     if (!nsources) {
140     sskip_rsi(NULL);
141     return(0);
142     }
143     if (bmpspec == NULL)
144     return(0);
145     if (strstr(bmpspec, "%s") == NULL)
146     error(USER, "missing '%s' in source skip BMP file spec");
147     if (ssf_select == NULL) /* starting fresh? */
148     ssf_select = sskip_new();
149     if (scorrimg == NULL) /* no correction map? */
150     skipin.cfname[0] = '\0';
151     else
152     strcpy(skipin.cfname, scorrimg);
153     skipin.cftype = CFnone; /* open input BMPs */
154     for (sn = 0; sn < nsources; sn++) {
155     OBJECT mod;
156     const char *modname;
157     SKIPBMP *sbmp;
158     int sn1;
159     if (source[sn].sflags & (SSKIP|SVIRTUAL) ||
160     sskip_chk(ssf_select, sn))
161     continue;
162     mod = source[sn].so->omod;
163     modname = objptr(mod)->oname;
164     sprintf(fname, bmpspec, modname);
165     if (access(fname, R_OK) < 0)
166     continue; /* none such input */
167     /* else check it out */
168     sbmp = (SKIPBMP *)emalloc(sizeof(SKIPBMP)+strlen(fname));
169     strcpy(sbmp->bname, fname);
170     sbmp->bmp = BMPopenInputFile(fname);
171     if (sbmp->bmp == NULL) {
172     sprintf(errmsg, "cannot open bitmap '%s'", fname);
173     error(SYSTEM, errmsg);
174     }
175     if (sbmp->bmp->hdr->nColors > 2) {
176     sprintf(errmsg, "expected bilevel bitmap in '%s'", fname);
177     error(USER, errmsg);
178     }
179     if (!sbmp->bmp->hdr->yIsDown) {
180     sprintf(errmsg, "bad orientation for '%s'", fname);
181     error(INTERNAL, errmsg);
182     }
183     if (skipin.sbmplist == NULL) {
184     sskip_dim[0] = sbmp->bmp->hdr->width;
185     sskip_dim[1] = sbmp->bmp->hdr->height;
186     } else if ((sbmp->bmp->hdr->width != sskip_dim[0]) |
187     (sbmp->bmp->hdr->height != sskip_dim[1])) {
188     sprintf(errmsg, "dimensions do not match for '%s'",
189     fname);
190     error(USER, errmsg);
191     }
192     /* flag this light source */
193     sbmp->sfl = sskip_new();
194     sskip_set(sbmp->sfl, sn);
195     /* flag others w/ same modifier */
196     for (sn1 = sn; ++sn1 < nsources; ) {
197     OBJECT mod1;
198     if (source[sn1].sflags & (SSKIP|SVIRTUAL) ||
199     sskip_chk(ssf_select, sn1))
200     continue;
201     mod1 = source[sn1].so->omod;
202     if (mod1 == mod || !strcmp(objptr(mod1)->oname, modname))
203     sskip_set(sbmp->sfl, sn1);
204     }
205     sskip_addflags(ssf_select, sbmp->sfl);
206     sbmp->next = skipin.sbmplist;
207     skipin.sbmplist = sbmp;
208     bmcnt++;
209     }
210     if (!bmcnt) {
211     sprintf(errmsg, "no matching BMP input files for '%s'", bmpspec);
212     error(WARNING, errmsg);
213     return(0);
214     }
215     if (!skipin.cfname[0]) /* no correction image? */
216     return(bmcnt);
217     /* else open correction image */
218     sfx = skipin.cfname; /* find file type */
219     while (*sfx) sfx++;
220     while (--sfx > skipin.cfname && !ISDIRSEP(*sfx))
221     if (*sfx == '.') {
222     if (!strcasecmp(sfx, ".mtx"))
223     skipin.cftype = CFfloatY;
224     else if (!strcasecmp(sfx, ".bmp"))
225     skipin.cftype = CFbmpY8;
226     break;
227     }
228     switch (skipin.cftype) {
229     case CFfloatY:
230     open_float_mtx();
231     break;
232     case CFbmpY8:
233     skipin.cf.bmp = BMPopenInputFile(skipin.cfname);
234     if (skipin.cf.bmp == NULL) {
235     sprintf(errmsg, "cannot open image '%s'", skipin.cfname);
236     error(SYSTEM, errmsg);
237     }
238     if (!skipin.cf.bmp->hdr->yIsDown |
239     (skipin.cf.bmp->hdr->bpp != 8) |
240     (skipin.cf.bmp->hdr->width != sskip_dim[0]) |
241     (skipin.cf.bmp->hdr->height != sskip_dim[1])) {
242     sprintf(errmsg, "bad type/size/orientation for '%s'",
243     skipin.cfname);
244     error(USER, errmsg);
245     }
246     break;
247     case CFnone:
248     sprintf(errmsg, "unsupported image type for '%s'", skipin.cfname);
249     error(USER, errmsg);
250     }
251     return(bmcnt); /* ready to roll */
252     }
253    
254     /* private function to convert 8-bit to float correction multiplier */
255     static void
256     srcskip_cvtY8(float *scorr, const uby8 *y8, int n)
257     {
258     static float gamtab[256];
259    
260     if (gamtab[0] < 0.5f) { /* initialize lookup */
261     int i = 256;
262     while (i--)
263     gamtab[i] = 1./(1. - pow((i+.5)*(1./255.), 2.2));
264     }
265     while (n-- > 0)
266     *scorr++ = gamtab[*y8++];
267     }
268    
269     /* Read and convert the specified source skip scanline */
270     int
271     srcskip_getrow(int row, int *sndx, float *scorr)
272     {
273     int err;
274    
275     if ((0 > row) | (row >= sskip_dim[1]))
276     goto badargum;
277     if (sndx != NULL) { /* read bitmap flags & convert? */
278     uby8 *scanflags;
279     SKIPBMP *sbmp;
280     int x;
281     if (skipin.sbmplist == NULL)
282     goto inpclosed;
283     errno = 0;
284     for (sbmp = skipin.sbmplist; sbmp != NULL; sbmp = sbmp->next)
285     if ((err = BMPseekScanline(row, sbmp->bmp)) != BIR_OK) {
286     sprintf(errmsg, "%s '%s'",
287     BMPerrorMessage(err), sbmp->bname);
288     error(SYSTEM, errmsg);
289     }
290     /* per-column source skip flags */
291     scanflags = (uby8 *)ecalloc(sskip_dim[0], SSKIPFLSIZ);
292     for (sbmp = skipin.sbmplist; sbmp != NULL; sbmp = sbmp->next) {
293     const uby8 *bscn = sbmp->bmp->scanline;
294     for (x = 0; x < sskip_dim[0]; bscn += !(++x & 7))
295     if (!(*bscn & 0x80>>(x&7)))
296     sskip_addflags(scanflags + x*SSKIPFLSIZ,
297     sbmp->sfl);
298     }
299     /* convert to lookup indices */
300     for (x = sskip_dim[0]; x-- > 0; )
301     sndx[x] = sskip_rsi(scanflags + x*SSKIPFLSIZ);
302     efree(scanflags);
303     }
304     if (scorr == NULL) /* all done? */
305     return(row);
306     switch (skipin.cftype) { /* else read correction row */
307     case CFfloatY:
308     if (skipin.cf.Y.fd < 0)
309     goto inpclosed;
310     if (pread(skipin.cf.Y.fd, scorr, sizeof(float)*sskip_dim[0],
311     skipin.cf.Y.dstart + sizeof(float)*sskip_dim[0]*row)
312     != sizeof(float)*sskip_dim[0]) {
313     sprintf(errmsg, "read error from '%s'", skipin.cfname);
314     error(SYSTEM, errmsg);
315     }
316     return(row);
317     case CFbmpY8:
318     if (skipin.cf.bmp == NULL)
319     goto inpclosed;
320     err = BMPseekScanline(row, skipin.cf.bmp);
321     if (err != BIR_OK) {
322     sprintf(errmsg, "%s '%s'",
323     BMPerrorMessage(err), skipin.cfname);
324     error(SYSTEM, errmsg);
325     }
326     srcskip_cvtY8(scorr, skipin.cf.bmp->scanline, sskip_dim[0]);
327     return(row);
328     case CFnone: /* caller asking for missing input */
329     break;
330     }
331     inpclosed:
332     error(CONSISTENCY, "call to srcskip_getrow() on closed input");
333 greg 2.2 return(EOF);
334 greg 2.1 badargum:
335     error(CONSISTENCY, "bad argument in srcskip_readrow()");
336     return(EOF); /* pro forma */
337     }
338    
339     /* Close input images and free memory (leaving any maps) */
340     void
341     srcskip_close()
342     {
343     while (skipin.sbmplist != NULL) {
344     SKIPBMP *sbmp = skipin.sbmplist;
345     skipin.sbmplist = sbmp->next;
346     BMPcloseInput(sbmp->bmp);
347     sskip_free(sbmp->sfl);
348     efree(sbmp);
349     }
350     switch (skipin.cftype) {
351     case CFfloatY:
352     if (skipin.cf.Y.fd >= 0) {
353     close(skipin.cf.Y.fd);
354     skipin.cf.Y.fd = -1;
355     }
356     break;
357     case CFbmpY8:
358     if (skipin.cf.bmp != NULL) {
359     BMPcloseInput(skipin.cf.bmp);
360     skipin.cf.bmp = NULL;
361     }
362     break;
363     }
364     skipin.cfname[0] = '\0';
365     if (ssf_select == NULL) { /* freed lookup table already? */
366     srcskip_free_maps();
367     skipin.cftype = CFnone;
368     sskip_dim[0] = sskip_dim[1] = 0;
369     }
370     }
371    
372     #if defined(_WIN32) || defined(_WIN64)
373    
374     /* Allocate and load entire source skip index array */
375     int *
376     srcskip_ndxmap()
377     {
378     int y;
379    
380     if (ssf_select == NULL) { /* rug pulled from under us? */
381     srcskip_free_maps();
382     return(NULL);
383     }
384     if (skipin.ndxmap != NULL)
385     return(skipin.ndxmap);
386    
387     skipin.ndxmap = (int *)emalloc(sizeof(int) *
388     sskip_dim[0]*sskip_dim[1]);
389    
390     for (y = 0; y < sskip_dim[1]; y++)
391     srcskip_getrow(y, skipin.ndxmap + sskip_dim[0]*y, NULL);
392    
393     return(skipin.ndxmap);
394     }
395    
396     /* Allocate and load entire source correction array */
397     float *
398     srcskip_corrmap()
399     {
400     int y;
401     ssize_t nbytes;
402    
403     if (ssf_select == NULL) { /* rug pulled from under us? */
404     srcskip_free_maps();
405     return(NULL);
406     }
407     if (skipin.corrmap != NULL)
408     return(skipin.corrmap);
409    
410     if (skipin.cftype == CFnone)
411     return(NULL);
412    
413     nbytes = sizeof(float)*sskip_dim[0]*sskip_dim[1];
414    
415     skipin.corrmap = (float *)emalloc(nbytes);
416    
417     switch (skipin.cftype) {
418     case CFfloatY:
419     if (pread(skipin.cf.Y.fd, skipin.corrmap, nbytes,
420     skipin.cf.Y.dstart) != nbytes) {
421     sprintf(errmsg, "read error from '%s'", skipin.cfname);
422     error(SYSTEM, errmsg);
423     }
424     break;
425     case CFbmpY8:
426     for (y = 0; y < sskip_dim[1]; y++)
427     srcskip_getrow(y, NULL, skipin.corrmap + sskip_dim[0]*y);
428     break;
429     }
430     skipin.cref = 1;
431     return(skipin.corrmap);
432     }
433    
434     /* Free allocated memory for source skip index and correction maps */
435     void
436     srcskip_free_maps()
437     {
438     efree(skipin.ndxmap); skipin.ndxmap = NULL;
439     efree(skipin.corrmap); skipin.corrmap = NULL;
440     }
441    
442     #else /* ! Windows */
443    
444     #include <sys/mman.h> /* mmap() support */
445    
446     /* Create memory map with entire source skip index array */
447     int *
448     srcskip_ndxmap()
449     {
450     int y;
451    
452     if (ssf_select == NULL) { /* rug pulled from under us? */
453     srcskip_free_maps();
454     return(NULL);
455     }
456     if (skipin.ndxmap != NULL)
457     return(skipin.ndxmap);
458    
459     skipin.ndxmap = (int *)mmap(NULL, sizeof(int)*sskip_dim[0]*sskip_dim[1],
460     PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
461    
462     if ((void *)skipin.ndxmap == MAP_FAILED)
463     error(SYSTEM, "out of memory in srcskip_ndxmap()");
464    
465     for (y = 0; y < sskip_dim[1]; y++)
466     srcskip_getrow(y, skipin.ndxmap + sskip_dim[0]*y, NULL);
467    
468     return(skipin.ndxmap);
469     }
470    
471     /* Create memory map with entire source skip correction array */
472     float *
473     srcskip_corrmap()
474     {
475     int y;
476     ssize_t nbytes;
477    
478     if (ssf_select == NULL) { /* rug pulled from under us? */
479     srcskip_free_maps();
480     return(NULL);
481     }
482     if (skipin.corrmap != NULL)
483     return(skipin.corrmap);
484    
485     if (skipin.cftype == CFnone)
486     return(NULL);
487    
488     nbytes = sizeof(float)*sskip_dim[0]*sskip_dim[1];
489    
490     if (skipin.cftype != CFfloatY || skipin.cf.Y.dstart % sizeof(float)) {
491     skipin.corrmap = (float *)mmap(NULL, nbytes,
492     PROT_READ|PROT_WRITE,
493     MAP_ANON|MAP_PRIVATE, -1, 0);
494     if ((void *)skipin.corrmap == MAP_FAILED)
495     error(SYSTEM, "out of memory in srcskip_corrmap()");
496     }
497     switch (skipin.cftype) {
498     case CFfloatY:
499     if (skipin.corrmap != NULL) {
500     if (pread(skipin.cf.Y.fd, skipin.corrmap, nbytes,
501     skipin.cf.Y.dstart) != nbytes) {
502     sprintf(errmsg, "read error from '%s'",
503     skipin.cfname);
504     error(SYSTEM, errmsg);
505     }
506     break; /* best we could do */
507     } /* else map directly to file data */
508     skipin.corrmap = (float *)mmap(NULL, skipin.cf.Y.dstart + nbytes,
509     PROT_READ|PROT_WRITE,
510     MAP_FILE|MAP_PRIVATE, skipin.cf.Y.fd, 0);
511     if ((void *)skipin.corrmap == MAP_FAILED)
512     error(SYSTEM, "cannot map file in srcskip_corrmap()");
513     skipin.corrmap += skipin.cf.Y.dstart/sizeof(float);
514     break;
515     case CFbmpY8:
516     for (y = 0; y < sskip_dim[1]; y++)
517     srcskip_getrow(y, NULL, skipin.corrmap + sskip_dim[0]*y);
518     break;
519     }
520     return(skipin.corrmap);
521     }
522    
523     /* Unmap memory allocated for source skip index and correction arrays */
524     void
525     srcskip_free_maps()
526     {
527     if (skipin.ndxmap != NULL) {
528     munmap(skipin.ndxmap, sizeof(int)*sskip_dim[0]*sskip_dim[1]);
529     skipin.ndxmap = NULL;
530     }
531     if (skipin.corrmap != NULL) {
532     off_t headlen = 0;
533     if (skipin.cftype == CFfloatY &&
534     !(skipin.cf.Y.dstart % sizeof(float)))
535     headlen = skipin.cf.Y.dstart;
536    
537     munmap((char *)skipin.corrmap - headlen,
538     headlen + sizeof(float)*sskip_dim[0]*sskip_dim[1]);
539     skipin.corrmap = NULL;
540     }
541     }
542    
543     #endif /* ! Windows */
544     #endif /* SSKIPOPT */