home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 8 / CDASC08.ISO / NEWS / RADIANCE / SRC / PX / PFILT.C < prev    next >
C/C++ Source or Header  |  1993-10-07  |  10KB  |  456 lines

  1. /* Copyright (c) 1992 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)pfilt.c 2.6 11/3/92 LBL";
  5. #endif
  6.  
  7. /*
  8.  *  pfilt.c - program to post-process picture file.
  9.  *
  10.  *     9/26/85
  11.  */
  12.  
  13. #include  "standard.h"
  14.  
  15. #include  <signal.h>
  16.  
  17. #include  "color.h"
  18.  
  19. #include  "resolu.h"
  20.  
  21. #include  "paths.h"
  22.  
  23. extern float  *matchlamp();
  24.  
  25. #define     FEQ(a,b)    ((a) >= .98*(b) && (a) <= 1.02*(b))
  26.  
  27. #define     CHECKRAD    1.5    /* radius to check for filtering */
  28.  
  29. COLOR  exposure = WHTCOLOR;    /* exposure for the frame */
  30.  
  31. double    rad = 0.0;        /* output pixel radius for filtering */
  32.  
  33. int  nrows = 0;            /* number of rows for output */
  34. int  ncols = 0;            /* number of columns for output */
  35.  
  36. double    x_c = 1.0;        /* ratio of output x size to input */
  37. double    y_r = 1.0;        /* ratio of output y size to input */
  38.  
  39. int  singlepass = 0;        /* true means skip first pass */
  40.  
  41. int  avghot = 0;        /* true means average in bright spots */
  42.  
  43. double    hotlvl = 1000.0;    /* level considered "hot" */
  44.  
  45. int  npts = 0;            /* (half) number of points for stars */
  46.  
  47. double    spread = 1e-4;        /* spread for star points */
  48.  
  49. char  *tfname = NULL;
  50.  
  51. char  *lampdat = "lamp.tab";    /* lamp data file */
  52.  
  53. int  order;            /* scanline ordering of input */
  54. int  xres, yres;        /* resolution of input */
  55. double    inpaspect = 1.0;    /* pixel aspect ratio of input */
  56. int  correctaspect = 0;        /* aspect ratio correction? */
  57.  
  58. int  wrongformat = 0;
  59.  
  60. int  xrad;            /* x window size */
  61. int  yrad;            /* y window size */
  62.  
  63. int  barsize;            /* size of input scan bar */
  64. COLOR  **scanin;        /* input scan bar */
  65. COLOR  *scanout;        /* output scan line */
  66.  
  67. char  *progname;
  68.  
  69.  
  70. main(argc, argv)
  71. int  argc;
  72. char  **argv;
  73. {
  74.     extern long  ftell();
  75.     extern int  quit(), headline();
  76.     FILE  *fin;
  77.     float  *lampcolor;
  78.     char  *lamptype = NULL;
  79.     long  fpos;
  80.     double    outaspect = 0.0;
  81.     double    d;
  82.     int  i, j;
  83. #ifdef MSDOS
  84.     extern int  _fmode;
  85.     _fmode = O_BINARY;
  86.     setmode(fileno(stdin), O_BINARY);
  87.     setmode(fileno(stdout), O_BINARY);
  88. #endif
  89.     if (signal(SIGINT, quit) == SIG_IGN)
  90.         signal(SIGINT, SIG_IGN);
  91.     if (signal(SIGHUP, quit) == SIG_IGN)
  92.         signal(SIGINT, SIG_IGN);
  93.     signal(SIGTERM, quit);
  94.     signal(SIGPIPE, quit);
  95. #ifdef    SIGXCPU
  96.     signal(SIGXCPU, quit);
  97.     signal(SIGXFSZ, quit);
  98. #endif
  99.  
  100.     progname = argv[0] = fixargv0(argv[0]);
  101.  
  102.     for (i = 1; i < argc; i++)
  103.         if (argv[i][0] == '-')
  104.             switch (argv[i][1]) {
  105.             case 'x':
  106.                 i++;
  107.                 if (argv[i][0] == '/') {
  108.                     x_c = 1.0/atof(argv[i]+1);
  109.                     ncols = 0;
  110.                 } else
  111.                     ncols = atoi(argv[i]);
  112.                 break;
  113.             case 'y':
  114.                 i++;
  115.                 if (argv[i][0] == '/') {
  116.                     y_r = 1.0/atof(argv[i]+1);
  117.                     nrows = 0;
  118.                 } else
  119.                     nrows = atoi(argv[i]);
  120.                 break;
  121.             case 'c':
  122.                 correctaspect = !correctaspect;
  123.                 break;
  124.             case 'p':
  125.                 i++;
  126.                 outaspect = atof(argv[i]);
  127.                 break;
  128.             case 'e':
  129.                 if (argv[i+1][0] == '+' || argv[i+1][0] == '-')
  130.                     d = pow(2.0, atof(argv[i+1]));
  131.                 else
  132.                     d = atof(argv[i+1]);
  133.                 if (d < 1e-20 || d > 1e20) {
  134.                     fprintf(stderr,
  135.                         "%s: exposure out of range\n",
  136.                             argv[0]);
  137.                     exit(1);
  138.                 }
  139.                 switch (argv[i][2]) {
  140.                 case '\0':
  141.                     scalecolor(exposure, d);
  142.                     break;
  143.                 case 'r':
  144.                     colval(exposure,RED) *= d;
  145.                     break;
  146.                 case 'g':
  147.                     colval(exposure,GRN) *= d;
  148.                     break;
  149.                 case 'b':
  150.                     colval(exposure,BLU) *= d;
  151.                     break;
  152.                 default:
  153.                     goto badopt;
  154.                 }
  155.                 i++;
  156.                 break;
  157.             case 'f':
  158.                 lampdat = argv[++i];
  159.                 break;
  160.             case 't':
  161.                 lamptype = argv[++i];
  162.                 break;
  163.             case '1':
  164.                 singlepass = 1;
  165.                 break;
  166.             case '2':
  167.                 singlepass = 0;
  168.                 break;
  169.             case 'n':
  170.                 npts = atoi(argv[++i]) / 2;
  171.                 break;
  172.             case 's':
  173.                 spread = atof(argv[++i]);
  174.                 break;
  175.             case 'a':
  176.                 avghot = !avghot;
  177.                 break;
  178.             case 'h':
  179.                 hotlvl = atof(argv[++i]);
  180.                 break;
  181.             case 'r':
  182.                 rad = atof(argv[++i]);
  183.                 break;
  184.             case 'b':
  185.                 rad = 0.0;
  186.                 break;
  187.             default:;
  188.             badopt:
  189.                 fprintf(stderr, "%s: unknown option: %s\n",
  190.                         progname, argv[i]);
  191.                 quit(1);
  192.                 break;
  193.             }
  194.         else
  195.             break;
  196.                     /* get lamp data (if necessary) */
  197.     if (lamptype != NULL) {
  198.         if (loadlamps(lampdat) < 0)
  199.             quit(1);
  200.         if ((lampcolor = matchlamp(lamptype)) == NULL) {
  201.             fprintf(stderr, "%s: unknown lamp type\n", lamptype);
  202.             quit(1);
  203.         }
  204.         for (i = 0; i < 3; i++)
  205.             if (lampcolor[i] > 1e-4)
  206.                 colval(exposure,i) /= lampcolor[i];
  207.         freelamps();
  208.     }
  209.                     /* open input file */
  210.     if (i == argc) {
  211.         if (singlepass)
  212.             fin = stdin;
  213.         else {
  214.             tfname = mktemp(TEMPLATE);
  215.             if ((fin = fopen(tfname, "w+")) == NULL) {
  216.                 fprintf(stderr, "%s: can't create ", progname);
  217.                 fprintf(stderr, "temp file \"%s\"\n", tfname);
  218.                 quit(1);
  219.             }
  220.             copyfile(stdin, fin);
  221.             if (fseek(fin, 0L, 0) == -1) {
  222.                 fprintf(stderr, "%s: seek fail\n", progname);
  223.                 quit(1);
  224.             }
  225.         }
  226.     } else if (i == argc-1) {
  227.         if ((fin = fopen(argv[i], "r")) == NULL) {
  228.             fprintf(stderr, "%s: can't open file \"%s\"\n",
  229.                         progname, argv[i]);
  230.             quit(1);
  231.         }
  232.     } else {
  233.         fprintf(stderr, "%s: bad # file arguments\n", progname);
  234.         quit(1);
  235.     }
  236.                     /* get header */
  237.     getheader(fin, headline, NULL);
  238.     if (wrongformat) {
  239.         fprintf(stderr, "%s: input must be a Radiance picture\n",
  240.                 progname);
  241.         quit(1);
  242.     }
  243.                     /* add new header info. */
  244.     printargs(i, argv, stdout);
  245.                     /* get picture size */
  246.     if ((order = fgetresolu(&xres, &yres, fin)) < 0) {
  247.         fprintf(stderr, "%s: bad picture size\n", progname);
  248.         quit(1);
  249.     }
  250.     if (!(order & YMAJOR))
  251.         inpaspect = 1.0/inpaspect;
  252.                     /* compute output resolution */
  253.     if (ncols <= 0)
  254.         ncols = x_c*xres + .5;
  255.     if (nrows <= 0)
  256.         nrows = y_r*yres + .5;
  257.     if (outaspect > .01) {
  258.         d = inpaspect * yres/xres / outaspect;
  259.         if (d * ncols > nrows)
  260.             ncols = nrows / d;
  261.         else
  262.             nrows = ncols * d;
  263.     }
  264.     x_c = (double)ncols/xres;
  265.     y_r = (double)nrows/yres;
  266.  
  267.     if (singlepass) {        /* skip exposure, etc. */
  268.         pass1default();
  269.         pass2(fin);
  270.         quit(0);
  271.     }
  272.  
  273.     fpos = ftell(fin);        /* save input file position */
  274.     
  275.     pass1(fin);
  276.  
  277.     if (fseek(fin, fpos, 0) == -1) {
  278.         fprintf(stderr, "%s: seek fail\n", progname);
  279.         quit(1);
  280.     }
  281.     pass2(fin);
  282.  
  283.     quit(0);
  284. }
  285.  
  286.  
  287. headline(s)                /* process line from header */
  288. char  *s;
  289. {
  290.     char  fmt[32];
  291.  
  292.     fputs(s, stdout);        /* copy to output */
  293.     if (isaspect(s))        /* get aspect ratio */
  294.         inpaspect *= aspectval(s);
  295.     else if (isformat(s)) {
  296.         formatval(fmt, s);
  297.         wrongformat = strcmp(fmt, COLRFMT);
  298.     }
  299. }
  300.  
  301.  
  302. copyfile(in, out)            /* copy a file */
  303. register FILE  *in, *out;
  304. {
  305.     register int  c;
  306.  
  307.     while ((c = getc(in)) != EOF)
  308.         putc(c, out);
  309.  
  310.     if (ferror(out)) {
  311.         fprintf(stderr, "%s: write error in copyfile\n", progname);
  312.         quit(1);
  313.     }
  314. }
  315.  
  316.  
  317. pass1(in)                /* first pass of picture file */
  318. FILE  *in;
  319. {
  320.     int  i;
  321.     COLOR  *scan;
  322.  
  323.     pass1init();
  324.  
  325.     scan = (COLOR *)malloc(xres*sizeof(COLOR));
  326.     if (scan == NULL) {
  327.         fprintf(stderr, "%s: out of memory\n", progname);
  328.         quit(1);
  329.     }
  330.     for (i = 0; i < yres; i++) {
  331.         if (freadscan(scan, xres, in) < 0) {
  332.             nrows = nrows * i / yres;    /* adjust frame */
  333.             if (nrows <= 0) {
  334.                 fprintf(stderr, "%s: empty frame\n", progname);
  335.                 quit(1);
  336.             }
  337.             fprintf(stderr, "%s: warning - partial frame (%d%%)\n",
  338.                     progname, 100*i/yres);
  339.             yres = i;
  340.             y_r = (double)nrows/yres;
  341.             break;
  342.         }
  343.         pass1scan(scan, i);
  344.     }
  345.     free((char *)scan);
  346. }
  347.  
  348.  
  349. pass2(in)            /* last pass on file, write to stdout */
  350. FILE  *in;
  351. {
  352.     int  yread;
  353.     int  ycent, xcent;
  354.     int  r, c;
  355.     
  356.     pass2init();
  357.     scan2init();
  358.     yread = 0;
  359.     for (r = 0; r < nrows; r++) {
  360.         ycent = (long)r*yres/nrows;
  361.         while (yread <= ycent+yrad) {
  362.             if (yread < yres) {
  363.                 if (freadscan(scanin[yread%barsize],
  364.                         xres, in) < 0) {
  365.                     fprintf(stderr,
  366.                         "%s: bad read (y=%d)\n",
  367.                         progname, yres-1-yread);
  368.                     quit(1);
  369.                 }
  370.                 pass2scan(scanin[yread%barsize], yread);
  371.             }
  372.             yread++;
  373.         }
  374.         for (c = 0; c < ncols; c++) {
  375.             xcent = (long)c*xres/ncols;
  376.             if (rad <= 0.0)
  377.                 dobox(scanout[c], xcent, ycent, c, r);
  378.             else
  379.                 dogauss(scanout[c], xcent, ycent, c, r);
  380.         }
  381.         if (fwritescan(scanout, ncols, stdout) < 0) {
  382.             fprintf(stderr, "%s: write error in pass2\n", progname);
  383.             quit(1);
  384.         }
  385.     }
  386.                     /* skip leftovers */
  387.     while (yread < yres) {
  388.         if (freadscan(scanin[0], xres, in) < 0)
  389.             break;
  390.         yread++;
  391.     }
  392. }
  393.  
  394.  
  395. scan2init()            /* prepare scanline arrays */
  396. {
  397.     COLOR    ctmp;
  398.     double    d;
  399.     register int  i;
  400.  
  401.     if (rad <= 0.0) {
  402.         xrad = xres/ncols/2 + 1;
  403.         yrad = yres/nrows/2 + 1;
  404.     } else {
  405.         if (nrows >= yres && ncols >= xres)
  406.             rad *= (y_r + x_c)/2.0;
  407.  
  408.         xrad = CHECKRAD*rad/x_c + 1;
  409.         yrad = CHECKRAD*rad/y_r + 1;
  410.  
  411.         initmask();        /* initialize filter table */
  412.     }
  413.     barsize = 2*yrad + 1;
  414.     scanin = (COLOR **)malloc(barsize*sizeof(COLOR *));
  415.     for (i = 0; i < barsize; i++) {
  416.         scanin[i] = (COLOR *)malloc(xres*sizeof(COLOR));
  417.         if (scanin[i] == NULL) {
  418.             fprintf(stderr, "%s: out of memory\n", progname);
  419.             quit(1);
  420.         }
  421.     }
  422.     scanout = (COLOR *)malloc(ncols*sizeof(COLOR));
  423.     if (scanout == NULL) {
  424.         fprintf(stderr, "%s: out of memory\n", progname);
  425.         quit(1);
  426.     }
  427.                     /* record pixel aspect ratio */
  428.     if (!correctaspect) {
  429.         d = order & YMAJOR ? x_c/y_r : y_r/x_c ;
  430.         if (!FEQ(d,1.0))
  431.             fputaspect(d, stdout);
  432.     }
  433.                     /* record exposure */
  434.     d = bright(exposure);
  435.     if (!FEQ(d,1.0))
  436.         fputexpos(d, stdout);
  437.                     /* record color correction */
  438.     copycolor(ctmp, exposure);
  439.     scalecolor(ctmp, 1.0/d);
  440.     if (!FEQ(colval(ctmp,RED),colval(ctmp,GRN)) ||
  441.             !FEQ(colval(ctmp,GRN),colval(ctmp,BLU)))
  442.         fputcolcor(ctmp, stdout);
  443.     printf("\n");
  444.                     /* write out resolution */
  445.     fputresolu(order, ncols, nrows, stdout);
  446. }
  447.  
  448.  
  449. quit(code)        /* remove temporary file and exit */
  450. int  code;
  451. {
  452.     if (tfname != NULL)
  453.         unlink(tfname);
  454.     exit(code);
  455. }
  456.