ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pcond.c
Revision: 3.32
Committed: Fri Oct 27 16:35:02 2023 UTC (6 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, HEAD
Changes since 3.31: +1 -2 lines
Log Message:
style: Removed repeated #include, spotted by Randolph Fritz

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: pcond.c,v 3.31 2021/04/07 21:13:52 greg Exp $";
3 #endif
4 /*
5 * Condition Radiance picture for display/output
6 * Added white-balance adjustment 10/01 (GW).
7 */
8
9 #include "platform.h"
10 #include "paths.h"
11 #include "pcond.h"
12
13
14 #define LDMAX 100 /* default max. display luminance */
15 #define LDDYN 100 /* default dynamic range */
16
17 int what2do = 0; /* desired adjustments */
18
19 double ldmax = LDMAX; /* maximum output luminance */
20 double lddyn = LDDYN; /* display dynamic range */
21 double Bldmin, Bldmax; /* Bl(ldmax/lddyn) and Bl(ldmax) */
22
23 char *progname; /* global argv[0] */
24
25 char *infn; /* input file name */
26 FILE *infp; /* input stream */
27 FILE *mapfp = NULL; /* tone-mapping function stream */
28 VIEW ourview = STDVIEW; /* picture view */
29 int gotview = 0; /* picture has view */
30 double pixaspect = 1.0; /* pixel aspect ratio */
31 double fixfrac = 0.; /* histogram share due to fixations */
32 RESOLU inpres; /* input picture resolution */
33
34 COLOR *fovimg; /* foveal (1 degree) averaged image */
35 int fvxr, fvyr; /* foveal image resolution */
36 float *crfimg; /* contrast reduction factors */
37 short (*fixlst)[2]; /* fixation history list */
38 int nfixations; /* number of fixation points */
39 double bwhist[HISTRES]; /* luminance histogram */
40 double histot; /* total count of histogram */
41 double bwmin, bwmax; /* histogram limits */
42 double bwavg; /* mean brightness */
43
44 double scalef = 0.; /* linear scaling factor */
45
46 static gethfunc headline;
47 static void getahead(void);
48 static void mapimage(void);
49 static void getfovimg(void);
50 static void check2do(void);
51
52
53
54 int
55 main(
56 int argc,
57 char *argv[]
58 )
59 {
60 static RGBPRIMS outprimS;
61 int i;
62 #define check_bool(flg) switch (argv[i][2]) { \
63 case '\0': what2do ^= flg; break; \
64 case 'y': case 'Y': case 't': case 'T': \
65 case '+': case '1': what2do |= flg; break; \
66 case 'n': case 'N': case 'f': case 'F': \
67 case '-': case '0': what2do &= ~(flg); break; \
68 default: goto userr; }
69
70 progname = argv[0];
71
72 for (i = 1; i < argc && argv[i][0] == '-'; i++)
73 switch (argv[i][1]) {
74 case 'h':
75 check_bool(DO_HUMAN);
76 break;
77 case 'a':
78 check_bool(DO_ACUITY);
79 break;
80 case 'v':
81 check_bool(DO_VEIL);
82 break;
83 case 's':
84 check_bool(DO_HSENS);
85 break;
86 case 'c':
87 check_bool(DO_COLOR);
88 break;
89 case 'w':
90 check_bool(DO_CWEIGHT);
91 break;
92 case 'i':
93 if (i+1 >= argc) goto userr;
94 fixfrac = atof(argv[++i]);
95 if (fixfrac > FTINY) what2do |= DO_FIXHIST;
96 else what2do &= ~DO_FIXHIST;
97 break;
98 case 'I':
99 check_bool(DO_PREHIST);
100 break;
101 case 'l':
102 check_bool(DO_LINEAR);
103 break;
104 case 'p':
105 if (i+8 >= argc) goto userr;
106 outprimS[RED][CIEX] = atof(argv[++i]);
107 outprimS[RED][CIEY] = atof(argv[++i]);
108 outprimS[GRN][CIEX] = atof(argv[++i]);
109 outprimS[GRN][CIEY] = atof(argv[++i]);
110 outprimS[BLU][CIEX] = atof(argv[++i]);
111 outprimS[BLU][CIEY] = atof(argv[++i]);
112 outprimS[WHT][CIEX] = atof(argv[++i]);
113 outprimS[WHT][CIEY] = atof(argv[++i]);
114 outprims = outprimS;
115 break;
116 case 'e':
117 if (i+1 >= argc) goto userr;
118 scalef = atof(argv[++i]);
119 if ((argv[i][0] == '+') | (argv[i][0] == '-'))
120 scalef = pow(2.0, scalef);
121 what2do |= DO_LINEAR;
122 break;
123 case 'f':
124 if (i+1 >= argc) goto userr;
125 mbcalfile = argv[++i];
126 break;
127 case 'm':
128 if (i+1 >= argc) goto userr;
129 cwarpfile = argv[++i];
130 break;
131 case 'u':
132 if (i+1 >= argc) goto userr;
133 ldmax = atof(argv[++i]);
134 if (ldmax <= FTINY)
135 goto userr;
136 break;
137 case 'd':
138 if (i+1 >= argc) goto userr;
139 lddyn = atof(argv[++i]);
140 break;
141 case 'x':
142 if (i+1 >= argc) goto userr;
143 if ((mapfp = fopen(argv[++i], "w")) == NULL) {
144 fprintf(stderr,
145 "%s: cannot open for writing\n",
146 argv[i]);
147 exit(1);
148 }
149 break;
150 default:
151 goto userr;
152 }
153 if ((what2do & (DO_FIXHIST|DO_PREHIST)) == (DO_FIXHIST|DO_PREHIST)) {
154 fprintf(stderr, "%s: only one of -i or -I option\n", progname);
155 exit(1);
156 }
157 if ((mbcalfile != NULL) + (cwarpfile != NULL) +
158 (outprims != stdprims) > 1) {
159 fprintf(stderr,
160 "%s: only one of -p, -m or -f option supported\n",
161 progname);
162 exit(1);
163 }
164 if ((outprims == stdprims) & (inprims != stdprims))
165 outprims = inprims;
166 Bldmin = Bl(ldmax/lddyn);
167 Bldmax = Bl(ldmax);
168 if (i >= argc || i+2 < argc)
169 goto userr;
170 /* open input file */
171 if ((infp = fopen(infn=argv[i], "r")) == NULL)
172 syserror(infn);
173 /* open output file */
174 if (i+2 == argc && freopen(argv[i+1], "w", stdout) == NULL)
175 syserror(argv[i+1]);
176 SET_FILE_BINARY(infp);
177 SET_FILE_BINARY(stdout);
178 getahead(); /* load input header */
179 printargs(argc, argv, stdout); /* add to output header */
180 if ((mbcalfile == NULL) & (outprims != stdprims))
181 fputprims(outprims, stdout);
182 if ((what2do & (DO_PREHIST|DO_VEIL|DO_ACUITY)) != DO_PREHIST)
183 getfovimg(); /* get foveal sample image? */
184 if (what2do&DO_PREHIST) /* get histogram? */
185 gethisto(stdin);
186 else if (what2do&DO_FIXHIST) /* get fixation history? */
187 getfixations(stdin);
188 mapimage(); /* map the picture */
189 if (mapfp != NULL) /* write out basic mapping */
190 putmapping(mapfp);
191 exit(0);
192 userr:
193 fprintf(stderr, "Usage: %s [-{h|a|v|s|c|l|w}[+-]][-I|-i ffrac][-e ev][-p xr yr xg yg xb yb xw yw|-f mbf.cal|-m rgb.cwp][-u Ldmax][-d Lddyn][-x mapfile] inpic [outpic]\n",
194 progname);
195 exit(1);
196 return 1; /* pro forma return */
197 #undef check_bool
198 }
199
200
201 void
202 syserror( /* report system error and exit */
203 char *s
204 )
205 {
206 fprintf(stderr, "%s: ", progname);
207 perror(s);
208 exit(2);
209 }
210
211
212 static int
213 headline( /* process header line */
214 char *s,
215 void *p
216 )
217 {
218 static RGBPRIMS inprimS;
219 char fmt[MAXFMTLEN];
220
221 if (formatval(fmt, s)) { /* check if format string */
222 if (!strcmp(fmt,COLRFMT)) lumf = rgblum;
223 else if (!strcmp(fmt,CIEFMT)) lumf = cielum;
224 else lumf = NULL;
225 return(0); /* don't echo */
226 }
227 /* get input primaries */
228 if (isprims(s) && primsval(inprimS, s)) {
229 inprims = inprimS;
230 return(0); /* don't echo */
231 }
232 if (isexpos(s)) { /* picture exposure */
233 inpexp *= exposval(s);
234 return(0); /* don't echo */
235 }
236 if (isaspect(s)) /* pixel aspect ratio */
237 pixaspect *= aspectval(s);
238 if (isview(s)) /* image view */
239 gotview += sscanview(&ourview, s);
240 return(fputs(s, stdout));
241 }
242
243
244 static void
245 getahead(void) /* load picture header */
246 {
247 char *err;
248
249 getheader(infp, headline, NULL);
250 if (lumf == NULL || !fgetsresolu(&inpres, infp)) {
251 fprintf(stderr, "%s: %s: not a Radiance picture\n",
252 progname, infn);
253 exit(1);
254 }
255 if (lumf == rgblum)
256 comprgb2xyzWBmat(inrgb2xyz, inprims);
257 else if (mbcalfile != NULL) {
258 fprintf(stderr, "%s: macbethcal only works with RGB pictures\n",
259 progname);
260 exit(1);
261 }
262 if (!gotview || ourview.type == VT_PAR ||
263 (ourview.horiz <= 5.) | (ourview.vert <= 5.)) {
264 ourview = stdview;
265 ourview.type = VT_PER;
266 if (pixaspect*inpres.yr < inpres.xr) {
267 ourview.horiz = 40.0;
268 ourview.vert = 2.*180./PI *
269 atan(.3639702*pixaspect*inpres.yr/inpres.xr);
270 } else {
271 ourview.vert = 40.0;
272 ourview.horiz = 2.*180./PI *
273 atan(.3639702*inpres.xr/pixaspect/inpres.yr);
274 }
275 }
276 if ((err = setview(&ourview)) != NULL) {
277 fprintf(stderr, "%s: view error in picture \"%s\": %s\n",
278 progname, infn, err);
279 exit(1);
280 }
281 }
282
283
284 static void
285 mapimage(void) /* map picture and send to stdout */
286 {
287 COLOR *scan;
288
289 comphist(); /* generate adaptation histogram */
290 check2do(); /* modify what2do flags */
291 if (what2do&DO_VEIL)
292 compveil(); /* compute veil image */
293 if (!(what2do&DO_LINEAR))
294 if (mkbrmap() < 0) /* make tone map */
295 what2do |= DO_LINEAR; /* failed! -- use linear */
296 #if ADJ_VEIL
297 else if (what2do&DO_VEIL)
298 adjveil(); /* else adjust veil image */
299 #endif
300 if (what2do&DO_LINEAR) {
301 if (scalef <= FTINY) {
302 if (what2do&DO_HSENS)
303 scalef = htcontrs(Lb(0.5*(Bldmax+Bldmin))) /
304 htcontrs(Lb(bwavg));
305 else
306 scalef = Lb(0.5*(Bldmax+Bldmin)) / Lb(bwavg);
307 scalef *= WHTEFFICACY/(inpexp*ldmax);
308 }
309 fputexpos(inpexp*scalef, stdout); /* record exposure */
310 if (lumf == cielum) scalef /= WHTEFFICACY;
311 }
312 fputformat(COLRFMT, stdout); /* complete header */
313 putchar('\n');
314 fputsresolu(&inpres, stdout); /* resolution doesn't change */
315 /* condition our image */
316 for (scan = firstscan(); scan != NULL; scan = nextscan())
317 if (fwritescan(scan, scanlen(&inpres), stdout) < 0) {
318 fprintf(stderr, "%s: scanline write error\n",
319 progname);
320 exit(1);
321 }
322 }
323
324
325 static void
326 getfovimg(void) /* load foveal sampled image */
327 {
328 char combuf[PATH_MAX];
329 FILE *fp;
330 int x, y;
331 /* compute image size */
332 fvxr = sqrt(ourview.hn2)/FOVDIA + 0.5;
333 if (fvxr < 2) fvxr = 2;
334 fvyr = sqrt(ourview.vn2)/FOVDIA + 0.5;
335 if (fvyr < 2) fvyr = 2;
336 if (!(inpres.rt & YMAJOR)) { /* picture is rotated? */
337 y = fvyr;
338 fvyr = fvxr;
339 fvxr = y;
340 }
341 if ((fovimg = (COLOR *)malloc(fvxr*fvyr*sizeof(COLOR))) == NULL)
342 syserror("malloc");
343 sprintf(combuf, "pfilt -1 -b -pa 0 -x %d -y %d \"%s\"", fvxr, fvyr, infn);
344 if ((fp = popen(combuf, "r")) == NULL)
345 syserror("popen");
346 SET_FILE_BINARY(fp);
347 getheader(fp, NULL, NULL); /* skip header */
348 if (fgetresolu(&x, &y, fp) < 0 || (x != fvxr) | (y != fvyr))
349 goto readerr;
350 for (y = 0; y < fvyr; y++)
351 if (freadscan(fovscan(y), fvxr, fp) < 0)
352 goto readerr;
353 pclose(fp);
354 return;
355 readerr:
356 fprintf(stderr, "%s: error reading from pfilt process in fovimage\n",
357 progname);
358 exit(1);
359 }
360
361
362 static void
363 check2do(void) /* check histogram to see what isn't worth doing */
364 {
365 double sum;
366 double b, l;
367 int i;
368
369 /* check for within display range */
370 if (bwmax - bwmin <= Bldmax - Bldmin)
371 what2do |= DO_LINEAR;
372 /* determine if veiling significant */
373 if (bwmax - bwmin < 4.5) /* heuristic */
374 what2do &= ~DO_VEIL;
375
376 if (!(what2do & (DO_ACUITY|DO_COLOR)))
377 return;
378 /* find 5th percentile */
379 sum = histot*0.05;
380 for (i = 0; i < HISTRES; i++)
381 if ((sum -= bwhist[i]) <= 0)
382 break;
383 b = (i+.5)*(bwmax-bwmin)/HISTRES + bwmin;
384 l = Lb(b);
385 /* determine if acuity adj. useful */
386 if (what2do&DO_ACUITY &&
387 hacuity(l) >= (inpres.xr/sqrt(ourview.hn2) +
388 inpres.yr/sqrt(ourview.vn2))/(2.*180./PI))
389 what2do &= ~DO_ACUITY;
390 /* color sensitivity loss? */
391 if (l >= TopMesopic)
392 what2do &= ~DO_COLOR;
393 }