ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pfilt.c
Revision: 2.26
Committed: Sun Jul 27 22:12:03 2003 UTC (20 years, 8 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.25: +3 -3 lines
Log Message:
Added grouping parens to reduce ambiguity warnings.

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 schorsch 2.26 static const char RCSid[] = "$Id: pfilt.c,v 2.25 2003/06/30 14:59:12 schorsch Exp $";
3 greg 1.1 #endif
4     /*
5     * pfilt.c - program to post-process picture file.
6     *
7     * 9/26/85
8 greg 2.9 * 6/23/93 Added additional buffers for value spreading
9 greg 1.1 */
10    
11 schorsch 2.25 #include "copyright.h"
12    
13 greg 1.1 #include <signal.h>
14 schorsch 2.25 #include <string.h>
15 greg 1.1
16 schorsch 2.23 #include "standard.h"
17 schorsch 2.24 #include "platform.h"
18 greg 1.1 #include "color.h"
19 greg 2.17 #include "view.h"
20 greg 2.3 #include "paths.h"
21    
22 greg 1.13 extern float *matchlamp();
23 greg 1.1
24 greg 2.4 #define FEQ(a,b) ((a) >= .98*(b) && (a) <= 1.02*(b))
25 greg 1.15
26 greg 2.22 double CHECKRAD = 2.0; /* radius to check for filtering */
27 greg 1.1
28 greg 2.9 #define THRESHRAD 5.0 /* maximum sample spread in output */
29    
30 greg 1.1 COLOR exposure = WHTCOLOR; /* exposure for the frame */
31    
32 greg 2.4 double rad = 0.0; /* output pixel radius for filtering */
33 greg 1.1
34 greg 2.9 double thresh = 0.0; /* maximum contribution for subpixel */
35    
36 greg 1.1 int nrows = 0; /* number of rows for output */
37     int ncols = 0; /* number of columns for output */
38    
39 greg 2.4 double x_c = 1.0; /* ratio of output x size to input */
40     double y_r = 1.0; /* ratio of output y size to input */
41 greg 1.2
42 greg 1.1 int singlepass = 0; /* true means skip first pass */
43    
44     int avghot = 0; /* true means average in bright spots */
45    
46 greg 2.8 double hotlvl = 100.0; /* level considered "hot" */
47 greg 1.1
48     int npts = 0; /* (half) number of points for stars */
49    
50 greg 2.4 double spread = 1e-4; /* spread for star points */
51 greg 1.1
52     char *tfname = NULL;
53    
54 greg 2.11 char template[] = TEMPLATE;
55    
56 greg 1.13 char *lampdat = "lamp.tab"; /* lamp data file */
57    
58 greg 1.19 int order; /* scanline ordering of input */
59 greg 1.1 int xres, yres; /* resolution of input */
60 greg 2.4 double inpaspect = 1.0; /* pixel aspect ratio of input */
61 greg 1.12 int correctaspect = 0; /* aspect ratio correction? */
62 greg 1.1
63 greg 1.16 int wrongformat = 0;
64    
65 greg 2.17 VIEW ourview = STDVIEW;
66     int gotview = 0;
67     int wrapfilt = 0; /* wrap filter horizontally? */
68    
69 greg 2.18 int estatus = 0; /* exit status (for non-fatal errors) */
70    
71 greg 2.9 int xrad; /* x search radius */
72     int yrad; /* y search radius */
73     int xbrad; /* x box size */
74     int ybrad; /* y box size */
75 greg 1.1
76     int barsize; /* size of input scan bar */
77     COLOR **scanin; /* input scan bar */
78     COLOR *scanout; /* output scan line */
79 greg 2.9 COLOR **scoutbar; /* output scan bar (if thresh > 0) */
80     float **greybar; /* grey-averaged input values */
81     int obarsize = 0; /* size of output scan bar */
82     int orad = 0; /* output window radius */
83 greg 1.1
84     char *progname;
85    
86    
87     main(argc, argv)
88     int argc;
89     char **argv;
90     {
91 greg 2.21 extern int headline();
92 greg 1.1 FILE *fin;
93 greg 1.13 float *lampcolor;
94     char *lamptype = NULL;
95 greg 1.1 long fpos;
96 greg 2.4 double outaspect = 0.0;
97     double d;
98 greg 2.13 int i, j;
99 schorsch 2.23 SET_DEFAULT_BINARY();
100     SET_FILE_BINARY(stdin);
101     SET_FILE_BINARY(stdout);
102 greg 1.1 if (signal(SIGINT, quit) == SIG_IGN)
103     signal(SIGINT, SIG_IGN);
104 schorsch 2.24 #ifdef SIGHUP
105 greg 1.1 if (signal(SIGHUP, quit) == SIG_IGN)
106 greg 2.11 signal(SIGHUP, SIG_IGN);
107 schorsch 2.24 #endif
108 greg 1.1 signal(SIGTERM, quit);
109 schorsch 2.24 #ifdef SIGPIPE
110 greg 1.1 signal(SIGPIPE, quit);
111 schorsch 2.24 #endif
112 greg 2.4 #ifdef SIGXCPU
113 greg 1.1 signal(SIGXCPU, quit);
114     signal(SIGXFSZ, quit);
115     #endif
116    
117 greg 2.6 progname = argv[0] = fixargv0(argv[0]);
118 greg 1.1
119     for (i = 1; i < argc; i++)
120     if (argv[i][0] == '-')
121     switch (argv[i][1]) {
122     case 'x':
123 greg 1.3 i++;
124 greg 1.5 if (argv[i][0] == '/') {
125 greg 1.4 x_c = 1.0/atof(argv[i]+1);
126 greg 1.5 ncols = 0;
127     } else
128 greg 1.3 ncols = atoi(argv[i]);
129 greg 1.1 break;
130     case 'y':
131 greg 1.3 i++;
132 greg 1.5 if (argv[i][0] == '/') {
133 greg 1.4 y_r = 1.0/atof(argv[i]+1);
134 greg 1.5 nrows = 0;
135     } else
136 greg 1.3 nrows = atoi(argv[i]);
137 greg 1.1 break;
138 greg 1.12 case 'c':
139     correctaspect = !correctaspect;
140     break;
141 greg 1.9 case 'p':
142     i++;
143     outaspect = atof(argv[i]);
144     break;
145 greg 1.1 case 'e':
146     if (argv[i+1][0] == '+' || argv[i+1][0] == '-')
147     d = pow(2.0, atof(argv[i+1]));
148     else
149     d = atof(argv[i+1]);
150 greg 1.15 if (d < 1e-20 || d > 1e20) {
151     fprintf(stderr,
152     "%s: exposure out of range\n",
153     argv[0]);
154 greg 2.18 quit(1);
155 greg 1.15 }
156 greg 1.1 switch (argv[i][2]) {
157     case '\0':
158     scalecolor(exposure, d);
159     break;
160     case 'r':
161     colval(exposure,RED) *= d;
162     break;
163     case 'g':
164     colval(exposure,GRN) *= d;
165     break;
166     case 'b':
167     colval(exposure,BLU) *= d;
168     break;
169     default:
170     goto badopt;
171     }
172     i++;
173     break;
174 greg 1.13 case 'f':
175     lampdat = argv[++i];
176     break;
177     case 't':
178     lamptype = argv[++i];
179     break;
180 greg 1.1 case '1':
181     singlepass = 1;
182     break;
183 greg 1.6 case '2':
184     singlepass = 0;
185     break;
186 greg 1.9 case 'n':
187 greg 1.1 npts = atoi(argv[++i]) / 2;
188     break;
189     case 's':
190     spread = atof(argv[++i]);
191     break;
192     case 'a':
193     avghot = !avghot;
194     break;
195     case 'h':
196     hotlvl = atof(argv[++i]);
197     break;
198     case 'r':
199     rad = atof(argv[++i]);
200     break;
201 greg 2.9 case 'm':
202     thresh = atof(argv[++i]);
203     if (rad <= FTINY)
204 greg 2.21 rad = 0.6;
205 greg 2.9 break;
206 greg 1.1 case 'b':
207 greg 2.9 rad = thresh = 0.0;
208 greg 1.1 break;
209     default:;
210     badopt:
211     fprintf(stderr, "%s: unknown option: %s\n",
212     progname, argv[i]);
213     quit(1);
214     break;
215     }
216     else
217     break;
218 greg 1.14 /* get lamp data (if necessary) */
219     if (lamptype != NULL) {
220     if (loadlamps(lampdat) < 0)
221     quit(1);
222     if ((lampcolor = matchlamp(lamptype)) == NULL) {
223     fprintf(stderr, "%s: unknown lamp type\n", lamptype);
224     quit(1);
225     }
226 greg 2.13 for (j = 0; j < 3; j++)
227     if (lampcolor[j] > 1e-4)
228     colval(exposure,j) /= lampcolor[j];
229 greg 1.14 freelamps();
230     }
231     /* open input file */
232 greg 1.1 if (i == argc) {
233     if (singlepass)
234     fin = stdin;
235     else {
236 greg 2.11 tfname = mktemp(template);
237 greg 1.1 if ((fin = fopen(tfname, "w+")) == NULL) {
238     fprintf(stderr, "%s: can't create ", progname);
239     fprintf(stderr, "temp file \"%s\"\n", tfname);
240     quit(1);
241     }
242     copyfile(stdin, fin);
243     if (fseek(fin, 0L, 0) == -1) {
244     fprintf(stderr, "%s: seek fail\n", progname);
245     quit(1);
246     }
247     }
248     } else if (i == argc-1) {
249     if ((fin = fopen(argv[i], "r")) == NULL) {
250     fprintf(stderr, "%s: can't open file \"%s\"\n",
251     progname, argv[i]);
252     quit(1);
253     }
254     } else {
255     fprintf(stderr, "%s: bad # file arguments\n", progname);
256     quit(1);
257     }
258 greg 1.9 /* get header */
259 greg 1.16 getheader(fin, headline, NULL);
260     if (wrongformat) {
261     fprintf(stderr, "%s: input must be a Radiance picture\n",
262     progname);
263     quit(1);
264     }
265 greg 1.1 /* add new header info. */
266     printargs(i, argv, stdout);
267     /* get picture size */
268 greg 1.19 if ((order = fgetresolu(&xres, &yres, fin)) < 0) {
269 greg 1.1 fprintf(stderr, "%s: bad picture size\n", progname);
270     quit(1);
271     }
272 greg 1.19 if (!(order & YMAJOR))
273     inpaspect = 1.0/inpaspect;
274 greg 2.17 /* wrap around for cylindrical view? */
275     wrapfilt = gotview && ourview.type == VT_CYL &&
276     ourview.horiz >= 360.-FTINY && order & YMAJOR;
277 greg 1.9 /* compute output resolution */
278     if (ncols <= 0)
279 greg 1.4 ncols = x_c*xres + .5;
280 greg 1.9 if (nrows <= 0)
281 greg 1.4 nrows = y_r*yres + .5;
282 greg 1.9 if (outaspect > .01) {
283     d = inpaspect * yres/xres / outaspect;
284     if (d * ncols > nrows)
285     ncols = nrows / d;
286     else
287     nrows = ncols * d;
288     }
289     x_c = (double)ncols/xres;
290     y_r = (double)nrows/yres;
291 greg 1.1
292 greg 1.9 if (singlepass) { /* skip exposure, etc. */
293 greg 1.1 pass1default();
294     pass2(fin);
295     quit(0);
296     }
297    
298     fpos = ftell(fin); /* save input file position */
299    
300     pass1(fin);
301    
302     if (fseek(fin, fpos, 0) == -1) {
303     fprintf(stderr, "%s: seek fail\n", progname);
304     quit(1);
305     }
306     pass2(fin);
307    
308 greg 2.18 quit(estatus);
309 greg 1.1 }
310    
311    
312 greg 2.15 double
313     rgb_bright(clr)
314     COLOR clr;
315     {
316     return(bright(clr));
317     }
318    
319    
320     double
321     xyz_bright(clr)
322     COLOR clr;
323     {
324     return(clr[CIEY]);
325     }
326    
327    
328     double (*ourbright)() = rgb_bright;
329    
330    
331 gwlarson 2.20 int
332 greg 1.9 headline(s) /* process line from header */
333     char *s;
334     {
335 greg 1.16 char fmt[32];
336    
337 greg 1.9 fputs(s, stdout); /* copy to output */
338     if (isaspect(s)) /* get aspect ratio */
339     inpaspect *= aspectval(s);
340 greg 2.15 else if (isexpos(s)) /* get exposure */
341 greg 2.8 hotlvl *= exposval(s);
342 greg 2.15 else if (formatval(fmt, s)) { /* get format */
343     wrongformat = 0;
344     if (!strcmp(COLRFMT, fmt))
345     ourbright = rgb_bright;
346     else if (!strcmp(CIEFMT, fmt))
347     ourbright = xyz_bright;
348     else
349     wrongformat = !globmatch(PICFMT, fmt);
350 greg 2.17 } else if (isview(s) && sscanview(&ourview, s) > 0)
351     gotview++;
352 gwlarson 2.20 return(0);
353 greg 1.9 }
354    
355    
356 greg 1.1 copyfile(in, out) /* copy a file */
357     register FILE *in, *out;
358     {
359     register int c;
360    
361     while ((c = getc(in)) != EOF)
362     putc(c, out);
363    
364     if (ferror(out)) {
365     fprintf(stderr, "%s: write error in copyfile\n", progname);
366     quit(1);
367     }
368     }
369    
370    
371     pass1(in) /* first pass of picture file */
372     FILE *in;
373     {
374     int i;
375     COLOR *scan;
376    
377     pass1init();
378    
379     scan = (COLOR *)malloc(xres*sizeof(COLOR));
380     if (scan == NULL) {
381     fprintf(stderr, "%s: out of memory\n", progname);
382     quit(1);
383     }
384     for (i = 0; i < yres; i++) {
385     if (freadscan(scan, xres, in) < 0) {
386 greg 2.7 nrows = (long)nrows * i / yres; /* adjust frame */
387 greg 1.1 if (nrows <= 0) {
388     fprintf(stderr, "%s: empty frame\n", progname);
389     quit(1);
390     }
391     fprintf(stderr, "%s: warning - partial frame (%d%%)\n",
392 greg 2.7 progname, (int)(100L*i/yres));
393 greg 1.1 yres = i;
394 greg 1.11 y_r = (double)nrows/yres;
395 greg 2.18 estatus++;
396 greg 1.1 break;
397     }
398     pass1scan(scan, i);
399     }
400 greg 2.21 free((void *)scan);
401 greg 1.1 }
402    
403    
404     pass2(in) /* last pass on file, write to stdout */
405     FILE *in;
406     {
407     int yread;
408     int ycent, xcent;
409     int r, c;
410 greg 2.4
411 greg 1.1 pass2init();
412     scan2init();
413     yread = 0;
414     for (r = 0; r < nrows; r++) {
415 greg 2.19 ycent = (r+.5)*yres/nrows;
416 greg 1.1 while (yread <= ycent+yrad) {
417     if (yread < yres) {
418     if (freadscan(scanin[yread%barsize],
419     xres, in) < 0) {
420     fprintf(stderr,
421 greg 2.14 "%s: truncated input (y=%d)\n",
422 greg 1.1 progname, yres-1-yread);
423     quit(1);
424     }
425     pass2scan(scanin[yread%barsize], yread);
426     }
427     yread++;
428     }
429 greg 2.9 if (obarsize > 0)
430     scan2sync(r);
431 greg 1.1 for (c = 0; c < ncols; c++) {
432 greg 2.19 xcent = (c+.5)*xres/ncols;
433 greg 2.9 if (thresh > FTINY)
434     dothresh(xcent, ycent, c, r);
435     else if (rad > FTINY)
436     dogauss(scanout[c], xcent, ycent, c, r);
437     else
438 greg 1.1 dobox(scanout[c], xcent, ycent, c, r);
439     }
440 greg 2.9 if (scanout != NULL && fwritescan(scanout, ncols, stdout) < 0) {
441 greg 1.1 fprintf(stderr, "%s: write error in pass2\n", progname);
442     quit(1);
443     }
444     }
445 greg 2.9 /* skip leftover input */
446 greg 1.10 while (yread < yres) {
447     if (freadscan(scanin[0], xres, in) < 0)
448     break;
449     yread++;
450     }
451 greg 2.9 scan2flush(); /* flush output */
452 greg 1.1 }
453    
454    
455     scan2init() /* prepare scanline arrays */
456     {
457 greg 1.15 COLOR ctmp;
458 greg 2.4 double d;
459 greg 1.1 register int i;
460    
461 greg 2.9 xbrad = xres/ncols/2 + 1;
462     ybrad = yres/nrows/2 + 1;
463     if (rad > FTINY) {
464 greg 1.1 if (nrows >= yres && ncols >= xres)
465     rad *= (y_r + x_c)/2.0;
466    
467 greg 2.9 if (thresh > FTINY) {
468     orad = CHECKRAD*THRESHRAD*rad + 1;
469 greg 2.16 xrad = orad/x_c + xbrad;
470     yrad = orad/y_r + ybrad;
471 greg 2.9 obarsize = 2*orad + 1;
472     } else {
473     xrad = CHECKRAD*rad/x_c + 1;
474     yrad = CHECKRAD*rad/y_r + 1;
475     }
476 greg 1.1 initmask(); /* initialize filter table */
477 greg 2.9 } else {
478     xrad = xbrad;
479     yrad = ybrad;
480 greg 1.1 }
481 greg 1.17 barsize = 2*yrad + 1;
482 greg 1.1 scanin = (COLOR **)malloc(barsize*sizeof(COLOR *));
483 greg 2.10 if (scanin == NULL)
484     goto memerr;
485 greg 1.1 for (i = 0; i < barsize; i++) {
486     scanin[i] = (COLOR *)malloc(xres*sizeof(COLOR));
487 greg 2.10 if (scanin[i] == NULL)
488     goto memerr;
489 greg 1.1 }
490 greg 2.9 if (obarsize > 0) {
491     scoutbar = (COLOR **)malloc(obarsize*sizeof(COLOR *));
492     greybar = (float **)malloc(obarsize*sizeof(float *));
493 schorsch 2.26 if ((scoutbar == NULL) | (greybar == NULL))
494 greg 2.10 goto memerr;
495 greg 2.9 for (i = 0; i < obarsize; i++) {
496     scoutbar[i] = (COLOR *)malloc(ncols*sizeof(COLOR));
497     greybar[i] = (float *)malloc(ncols*sizeof(float));
498 schorsch 2.26 if ((scoutbar[i] == NULL) | (greybar[i] == NULL))
499 greg 2.10 goto memerr;
500 greg 2.9 }
501     } else {
502     scanout = (COLOR *)malloc(ncols*sizeof(COLOR));
503 greg 2.10 if (scanout == NULL)
504     goto memerr;
505 greg 1.1 }
506 greg 1.15 /* record pixel aspect ratio */
507 greg 1.12 if (!correctaspect) {
508 greg 1.19 d = order & YMAJOR ? x_c/y_r : y_r/x_c ;
509 greg 1.15 if (!FEQ(d,1.0))
510 greg 1.12 fputaspect(d, stdout);
511     }
512 greg 1.15 /* record exposure */
513 greg 2.15 d = (*ourbright)(exposure);
514 greg 1.15 if (!FEQ(d,1.0))
515 greg 1.9 fputexpos(d, stdout);
516 greg 1.15 /* record color correction */
517     copycolor(ctmp, exposure);
518     scalecolor(ctmp, 1.0/d);
519     if (!FEQ(colval(ctmp,RED),colval(ctmp,GRN)) ||
520     !FEQ(colval(ctmp,GRN),colval(ctmp,BLU)))
521     fputcolcor(ctmp, stdout);
522 greg 1.1 printf("\n");
523 greg 1.15 /* write out resolution */
524 greg 1.19 fputresolu(order, ncols, nrows, stdout);
525 greg 2.10 return;
526     memerr:
527     fprintf(stderr, "%s: out of memory\n", progname);
528     quit(1);
529 greg 2.9 }
530    
531    
532     scan2sync(r) /* synchronize grey averages and output scan */
533     int r;
534     {
535     static int nextrow = 0;
536     COLOR ctmp;
537     int ybot;
538     register int c;
539     /* average input scanlines */
540 greg 2.16 while (nextrow <= r+orad && nextrow < nrows) {
541 greg 2.19 ybot = (nextrow+.5)*yres/nrows;
542 greg 2.9 for (c = 0; c < ncols; c++) {
543 greg 2.19 dobox(ctmp, (int)((c+.5)*xres/ncols),ybot, c,nextrow);
544 greg 2.15 greybar[nextrow%obarsize][c] = (*ourbright)(ctmp);
545 greg 2.9 }
546     /* and zero output scanline */
547 schorsch 2.25 memset((char *)scoutbar[nextrow%obarsize], '\0', ncols*sizeof(COLOR));
548 greg 2.9 nextrow++;
549     }
550     /* point to top scanline for output */
551     if (r-orad >= 0)
552     scanout = scoutbar[(r-orad)%obarsize];
553     else
554     scanout = NULL;
555     }
556    
557    
558     scan2flush() /* flush output buffer */
559     {
560     register int r;
561    
562     for (r = nrows-orad; r < nrows; r++)
563     if (fwritescan(scoutbar[r%obarsize], ncols, stdout) < 0)
564     break;
565     if (fflush(stdout) < 0) {
566     fprintf(stderr, "%s: write error at end of pass2\n", progname);
567 greg 2.18 quit(1);
568 greg 2.9 }
569 greg 1.1 }
570    
571    
572 greg 2.21 void
573 greg 1.1 quit(code) /* remove temporary file and exit */
574     int code;
575     {
576     if (tfname != NULL)
577     unlink(tfname);
578     exit(code);
579     }