home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / radsrc22 / src / px / pcomb.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-02  |  10.2 KB  |  482 lines

  1. /* Copyright (c) 1992 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)pcomb.c 2.8 10/2/92 LBL";
  5. #endif
  6.  
  7. /*
  8.  *  Combine picture files according to calcomp functions.
  9.  *
  10.  *    1/4/89
  11.  */
  12.  
  13. #include <stdio.h>
  14.  
  15. #ifdef MSDOS
  16. #include <fcntl.h>
  17. #endif
  18.  
  19. #include <math.h>
  20.  
  21. #include <errno.h>
  22.  
  23. #include "color.h"
  24.  
  25. #include "resolu.h"
  26.  
  27. #include "calcomp.h"
  28.  
  29. #define MAXINP        32        /* maximum number of input files */
  30. #define WINSIZ        9        /* scanline window size */
  31. #define MIDSCN        4        /* current scan position */
  32.  
  33. struct {
  34.     char    *name;        /* file or command name */
  35.     FILE    *fp;        /* stream pointer */
  36.     COLOR    *scan[WINSIZ];    /* input scanline window */
  37.     COLOR    coef;        /* coefficient */
  38.     COLOR    expos;        /* recorded exposure */
  39. }    input[MAXINP];            /* input pictures */
  40.  
  41. int    nfiles;                /* number of input files */
  42.  
  43. char    Command[] = "<Command>";
  44. char    vcolin[3][4] = {"ri", "gi", "bi"};
  45. char    vcolout[3][4] = {"ro", "go", "bo"};
  46. char    vbrtin[] = "li";
  47. char    vbrtout[] = "lo";
  48. char    vcolexp[3][4] = {"re", "ge", "be"};
  49. char    vbrtexp[] = "le";
  50.  
  51. char    vnfiles[] = "nfiles";
  52. char    vxmax[] = "xmax";
  53. char    vymax[] = "ymax";
  54. char    vxres[] = "xres";
  55. char    vyres[] = "yres";
  56. char    vxpos[] = "x";
  57. char    vypos[] = "y";
  58.  
  59. int    nowarn = 0;            /* no warning messages? */
  60.  
  61. int    xmax = 0, ymax = 0;        /* input resolution */
  62.  
  63. int    xscan, yscan;            /* input position */
  64.  
  65. int    xres, yres;            /* output resolution */
  66.  
  67. int    xpos, ypos;            /* output position */
  68.  
  69. int    wrongformat = 0;
  70.  
  71. FILE    *popen();
  72.  
  73. extern char    *emalloc();
  74.  
  75.  
  76. main(argc, argv)
  77. int    argc;
  78. char    *argv[];
  79. {
  80.     int    original;
  81.     double    f;
  82.     int    a, i;
  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.                         /* scan options */
  90.     for (a = 1; a < argc; a++) {
  91.         if (argv[a][0] == '-')
  92.             switch (argv[a][1]) {
  93.             case 'x':
  94.             case 'y':
  95.                 a++;
  96.                 continue;
  97.             case 'w':
  98.                 nowarn = !nowarn;
  99.                 continue;
  100.             case 'f':
  101.             case 'e':
  102.                 a++;
  103.                 continue;
  104.             }
  105.         break;
  106.     }
  107.                     /* process files */
  108.     for (nfiles = 0; nfiles < MAXINP; nfiles++) {
  109.         setcolor(input[nfiles].coef, 1.0, 1.0, 1.0);
  110.         setcolor(input[nfiles].expos, 1.0, 1.0, 1.0);
  111.     }
  112.     nfiles = 0;
  113.     original = 0;
  114.     for ( ; a < argc; a++) {
  115.         if (nfiles >= MAXINP) {
  116.             eputs(argv[0]);
  117.             eputs(": too many picture files\n");
  118.             quit(1);
  119.         }
  120.         if (argv[a][0] == '-')
  121.             switch (argv[a][1]) {
  122.             case '\0':
  123.                 input[nfiles].name = "<stdin>";
  124.                 input[nfiles].fp = stdin;
  125.                 break;
  126.             case 'o':
  127.                 original++;
  128.                 continue;
  129.             case 's':
  130.                 f = atof(argv[++a]);
  131.                 scalecolor(input[nfiles].coef, f);
  132.                 continue;
  133.             case 'c':
  134.                 colval(input[nfiles].coef,RED)*=atof(argv[++a]);
  135.                 colval(input[nfiles].coef,GRN)*=atof(argv[++a]);
  136.                 colval(input[nfiles].coef,BLU)*=atof(argv[++a]);
  137.                 continue;
  138.             default:
  139.                 goto usage;
  140.             }
  141.         else {
  142.             if (argv[a][0] == '!') {
  143.                 input[nfiles].name = Command;
  144.                 input[nfiles].fp = popen(argv[a]+1, "r");
  145.             } else {
  146.                 input[nfiles].name = argv[a];
  147.                 input[nfiles].fp = fopen(argv[a], "r");
  148.             }
  149.             if (input[nfiles].fp == NULL) {
  150.                 perror(argv[a]);
  151.                 quit(1);
  152.             }
  153.         }
  154.         checkfile();
  155.         if (original) {
  156.             colval(input[nfiles].coef,RED) /=
  157.                     colval(input[nfiles].expos,RED);
  158.             colval(input[nfiles].coef,GRN) /=
  159.                     colval(input[nfiles].expos,GRN);
  160.             colval(input[nfiles].coef,BLU) /=
  161.                     colval(input[nfiles].expos,BLU);
  162.         }
  163.         nfiles++;
  164.         original = 0;
  165.     }
  166.     init();                /* set constants */
  167.                     /* go back and get expressions */
  168.     for (a = 1; a < argc; a++) {
  169.         if (argv[a][0] == '-')
  170.             switch (argv[a][1]) {
  171.             case 'x':
  172.                 varset(vxres, ':', eval(argv[++a]));
  173.                 continue;
  174.             case 'y':
  175.                 varset(vyres, ':', eval(argv[++a]));
  176.                 continue;
  177.             case 'w':
  178.                 continue;
  179.             case 'f':
  180.                 fcompile(argv[++a]);
  181.                 continue;
  182.             case 'e':
  183.                 scompile(argv[++a], NULL, 0);
  184.                 continue;
  185.             }
  186.         break;
  187.     }
  188.                         /* set/get output resolution */
  189.     if (!vardefined(vxres))
  190.         varset(vxres, ':', (double)xmax);
  191.     if (!vardefined(vyres))
  192.         varset(vyres, ':', (double)ymax);
  193.     xres = varvalue(vxres) + .5;
  194.     yres = varvalue(vyres) + .5;
  195.     if (xres <= 0 || yres <= 0) {
  196.         eputs(argv[0]);
  197.         eputs(": illegal output resolution\n");
  198.         quit(1);
  199.     }
  200.                         /* complete header */
  201.     printargs(argc, argv, stdout);
  202.     fputformat(COLRFMT, stdout);
  203.     putchar('\n');
  204.     fprtresolu(xres, yres, stdout);
  205.                         /* combine pictures */
  206.     combine();
  207.     quit(0);
  208. usage:
  209.     eputs("Usage: ");
  210.     eputs(argv[0]);
  211.     eputs(
  212. " [-w][-x xr][-y yr][-e expr][-f file] [ [-s f][-c r g b] pic ..]\n");
  213.     quit(1);
  214. }
  215.  
  216.  
  217. tputs(s)            /* put out string preceded by a tab */
  218. char    *s;
  219. {
  220.     char    fmt[32];
  221.     double    d;
  222.     COLOR    ctmp;
  223.  
  224.     if (isformat(s)) {            /* check format */
  225.         formatval(fmt, s);
  226.         wrongformat = strcmp(fmt, COLRFMT);
  227.         return;        /* don't echo */
  228.     }
  229.     if (isexpos(s)) {            /* exposure */
  230.         d = exposval(s);
  231.         scalecolor(input[nfiles].expos, d);
  232.     } else if (iscolcor(s)) {        /* color correction */
  233.         colcorval(ctmp, s);
  234.         multcolor(input[nfiles].expos, ctmp);
  235.     }
  236.                         /* echo line */
  237.     putchar('\t');
  238.     fputs(s, stdout);
  239. }
  240.  
  241.  
  242. checkfile()            /* ready a file */
  243. {
  244.     int    xinp, yinp;
  245.     register int    i;
  246.                     /* process header */
  247.     fputs(input[nfiles].name, stdout);
  248.     fputs(":\n", stdout);
  249.     getheader(input[nfiles].fp, tputs, NULL);
  250.     if (wrongformat) {
  251.         eputs(input[nfiles].name);
  252.         eputs(": not in Radiance picture format\n");
  253.         quit(1);
  254.     }
  255.     if (fgetresolu(&xinp, &yinp, input[nfiles].fp) < 0) {
  256.         eputs(input[nfiles].name);
  257.         eputs(": bad picture size\n");
  258.         quit(1);
  259.     }
  260.     if (xmax == 0 && ymax == 0) {
  261.         xmax = xinp;
  262.         ymax = yinp;
  263.     } else if (xinp != xmax || yinp != ymax) {
  264.         eputs(input[nfiles].name);
  265.         eputs(": resolution mismatch\n");
  266.         quit(1);
  267.     }
  268.                     /* allocate scanlines */
  269.     for (i = 0; i < WINSIZ; i++)
  270.         input[nfiles].scan[i] = (COLOR *)emalloc(xmax*sizeof(COLOR));
  271. }
  272.  
  273.  
  274. init()                    /* perform final setup */
  275. {
  276.     double    l_colin(), l_expos();
  277.     register int    i;
  278.                         /* define constants */
  279.     varset(vnfiles, ':', (double)nfiles);
  280.     varset(vxmax, ':', (double)xmax);
  281.     varset(vymax, ':', (double)ymax);
  282.                         /* set functions */
  283.     for (i = 0; i < 3; i++) {
  284.         funset(vcolexp[i], 1, ':', l_expos);
  285.         funset(vcolin[i], 1, '=', l_colin);
  286.     }
  287.     funset(vbrtexp, 1, ':', l_expos);
  288.     funset(vbrtin, 1, '=', l_colin);
  289. }
  290.  
  291.  
  292. combine()            /* combine pictures */
  293. {
  294.     EPNODE    *coldef[3], *brtdef;
  295.     COLOR    *scanout;
  296.     double    d;
  297.     register int    i, j;
  298.                         /* check defined variables */
  299.     for (j = 0; j < 3; j++) {
  300.         if (vardefined(vcolout[j]))
  301.             coldef[j] = eparse(vcolout[j]);
  302.         else
  303.             coldef[j] = NULL;
  304.     }
  305.     if (vardefined(vbrtout))
  306.         brtdef = eparse(vbrtout);
  307.     else
  308.         brtdef = NULL;
  309.                         /* allocate scanline */
  310.     scanout = (COLOR *)emalloc(xres*sizeof(COLOR));
  311.                         /* set input position */
  312.     yscan = ymax+MIDSCN;
  313.                         /* combine files */
  314.     for (ypos = yres-1; ypos >= 0; ypos--) {
  315.         advance();
  316.         varset(vypos, '=', (double)ypos);
  317.         for (xpos = 0; xpos < xres; xpos++) {
  318.         xscan = (long)xpos*xmax/xres;
  319.         varset(vxpos, '=', (double)xpos);
  320.         eclock++;
  321.         if (brtdef != NULL) {
  322.             d = evalue(brtdef);
  323.             if (d < 0.0)
  324.             d = 0.0;
  325.             setcolor(scanout[xpos], d, d, d);
  326.         } else {
  327.             for (j = 0; j < 3; j++) {
  328.             if (coldef[j] != NULL) {
  329.                 d = evalue(coldef[j]);
  330.             } else {
  331.                 d = 0.0;
  332.                 for (i = 0; i < nfiles; i++)
  333.                 d += colval(input[i].scan[MIDSCN][xscan],j);
  334.             }
  335.             if (d < 0.0)
  336.                 d = 0.0;
  337.             colval(scanout[xpos],j) = d;
  338.             }
  339.         }
  340.         }
  341.         if (fwritescan(scanout, xres, stdout) < 0) {
  342.             perror("write error");
  343.             quit(1);
  344.         }
  345.     }
  346.     efree(scanout);
  347. }
  348.  
  349.  
  350. advance()            /* read in data for next scanline */
  351. {
  352.     int    ytarget;
  353.     register COLOR    *st;
  354.     register int    i, j;
  355.  
  356.     for (ytarget = (long)ypos*ymax/yres; yscan > ytarget; yscan--)
  357.         for (i = 0; i < nfiles; i++) {
  358.             st = input[i].scan[WINSIZ-1];
  359.             for (j = WINSIZ-1; j > 0; j--)    /* rotate window */
  360.                 input[i].scan[j] = input[i].scan[j-1];
  361.             input[i].scan[0] = st;
  362.             if (yscan <= MIDSCN)        /* hit bottom? */
  363.                 continue;
  364.             if (freadscan(st, xmax, input[i].fp) < 0) {  /* read */
  365.                 eputs(input[i].name);
  366.                 eputs(": read error\n");
  367.                 quit(1);
  368.             }
  369.             if (fabs(colval(input[i].coef,RED)-1.0) > 1e-3 ||
  370.                 fabs(colval(input[i].coef,GRN)-1.0) > 1e-3 ||
  371.                 fabs(colval(input[i].coef,BLU)-1.0) > 1e-3)
  372.                 for (j = 0; j < xmax; j++)  /* adjust color */
  373.                     multcolor(st[j], input[i].coef);
  374.         }
  375. }
  376.  
  377.  
  378. double
  379. l_expos(nam)            /* return picture exposure */
  380. register char    *nam;
  381. {
  382.     register int    fn, n;
  383.  
  384.     fn = argument(1) - .5;
  385.     if (fn < 0 || fn >= nfiles)
  386.         return(1.0);
  387.     if (nam == vbrtexp)
  388.         return(bright(input[fn].expos));
  389.     n = 3;
  390.     while (n--)
  391.         if (nam == vcolexp[n])
  392.             return(colval(input[fn].expos,n));
  393.     eputs("Bad call to l_expos()!\n");
  394.     quit(1);
  395. }
  396.  
  397.  
  398. double
  399. l_colin(nam)            /* return color value for picture */
  400. register char    *nam;
  401. {
  402.     int    fn;
  403.     register int    n, xoff, yoff;
  404.     double    d;
  405.  
  406.     d = argument(1);
  407.     if (d > -.5 && d < .5)
  408.         return((double)nfiles);
  409.     fn = d - .5;
  410.     if (fn < 0 || fn >= nfiles) {
  411.         errno = EDOM;
  412.         return(0.0);
  413.     }
  414.     xoff = yoff = 0;
  415.     n = nargum();
  416.     if (n >= 2) {
  417.         d = argument(2);
  418.         if (d < 0.0) {
  419.             xoff = d-.5;
  420.             if (xscan+xoff < 0)
  421.                 xoff = -xscan;
  422.         } else {
  423.             xoff = d+.5;
  424.             if (xscan+xoff >= xmax)
  425.                 xoff = xmax-1-xscan;
  426.         }
  427.     }
  428.     if (n >= 3) {
  429.         d = argument(3);
  430.         if (d < 0.0) {
  431.             yoff = d-.5;
  432.             if (yoff+MIDSCN < 0)
  433.                 yoff = -MIDSCN;
  434.             if (yscan+yoff < 0)
  435.                 yoff = -yscan;
  436.         } else {
  437.             yoff = d+.5;
  438.             if (yoff+MIDSCN >= WINSIZ)
  439.                 yoff = WINSIZ-1-MIDSCN;
  440.             if (yscan+yoff >= ymax)
  441.                 yoff = ymax-1-yscan;
  442.         }
  443.     }
  444.     if (nam == vbrtin)
  445.         return(bright(input[fn].scan[MIDSCN+yoff][xscan+xoff]));
  446.     n = 3;
  447.     while (n--)
  448.         if (nam == vcolin[n])
  449.         return(colval(input[fn].scan[MIDSCN+yoff][xscan+xoff],n));
  450.     eputs("Bad call to l_colin()!\n");
  451.     quit(1);
  452. }
  453.  
  454.  
  455. wputs(msg)
  456. char    *msg;
  457. {
  458.     if (!nowarn)
  459.         eputs(msg);
  460. }
  461.  
  462.  
  463. eputs(msg)
  464. char    *msg;
  465. {
  466.     fputs(msg, stderr);
  467. }
  468.  
  469.  
  470. quit(code)        /* exit gracefully */
  471. int  code;
  472. {
  473.     register int  i;
  474.                 /* close input files */
  475.     for (i = 0; i < nfiles; i++)
  476.         if (input[i].name == Command)
  477.             pclose(input[i].fp);
  478.         else
  479.             fclose(input[i].fp);
  480.     exit(code);
  481. }
  482.