Back to index

radiance  4R0+20100331
pcomb.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: pcomb.c,v 2.44 2009/08/10 04:26:38 greg Exp $";
00003 #endif
00004 /*
00005  *  Combine picture files according to calcomp functions.
00006  *
00007  *     1/4/89
00008  */
00009 
00010 #include "platform.h"
00011 #include "standard.h"
00012 #include "rtprocess.h"
00013 #include "color.h"
00014 #include "calcomp.h"
00015 #include "view.h"
00016 
00017 #define MAXINP              1024          /* maximum number of input files */
00018 #define WINSIZ              64            /* scanline window size */
00019 #define MIDSCN              ((WINSIZ-1)/2+1)
00020 
00021 struct {
00022        char   *name;        /* file or command name */
00023        FILE   *fp;          /* stream pointer */
00024        VIEW   vw;           /* view for picture */
00025        RESOLU rs;           /* image resolution and orientation */
00026        float  pa;           /* pixel aspect ratio */
00027        COLOR  *scan[WINSIZ];       /* input scanline window */
00028        COLOR  coef;         /* coefficient */
00029        COLOR  expos;        /* recorded exposure */
00030 }      input[MAXINP];                     /* input pictures */
00031 
00032 int    nfiles;                            /* number of input files */
00033 
00034 char   ourfmt[LPICFMT+1] = PICFMT; /* input picture format */
00035 
00036 char   StandardInput[] = "<stdin>";
00037 char   Command[] = "<Command>";
00038 char   vcolin[3][4] = {"ri", "gi", "bi"};
00039 char   vcolout[3][4] = {"ro", "go", "bo"};
00040 char   vbrtin[] = "li";
00041 char   vbrtout[] = "lo";
00042 char   vcolexp[3][4] = {"re", "ge", "be"};
00043 char   vbrtexp[] = "le";
00044 char   vpixaspect[] = "pa";
00045 
00046 char   vray[7][4] = {"Ox", "Oy", "Oz", "Dx", "Dy", "Dz", "T"};
00047 
00048 char   vpsize[] = "S";
00049 
00050 char   vnfiles[] = "nfiles";
00051 char   vwhteff[] = "WE";
00052 char   vxmax[] = "xmax";
00053 char   vymax[] = "ymax";
00054 char   vxres[] = "xres";
00055 char   vyres[] = "yres";
00056 char   vxpos[] = "x";
00057 char   vypos[] = "y";
00058 
00059 int    nowarn = 0;                 /* no warning messages? */
00060 
00061 int    xmax = 0, ymax = 0;         /* input resolution */
00062 
00063 int    xscan, yscan;               /* input position */
00064 
00065 int    xres, yres;                 /* output resolution */
00066 
00067 int    xpos, ypos;                 /* output position */
00068 
00069 char   *progname;                  /* global argv[0] */
00070 
00071 int    echoheader = 1;
00072 int    wrongformat = 0;
00073 int    gotview;
00074 
00075 
00076 static gethfunc headline;
00077 static void checkfile(void);
00078 static double rgb_bright(COLOR  clr);
00079 static double xyz_bright(COLOR  clr);
00080 static void init(void);
00081 static void combine(void);
00082 static void advance(void);
00083 static double l_expos(char  *nam);
00084 static double l_pixaspect(char *nm);
00085 static double l_colin(char  *nam);
00086 static double l_ray(char    *nam);
00087 static double l_psize(char *nm);
00088 
00089 
00090 int
00091 main(
00092        int    argc,
00093        char   *argv[]
00094 )
00095 {
00096        int    original;
00097        double f;
00098        int    a;
00099        SET_DEFAULT_BINARY();
00100        SET_FILE_BINARY(stdin);
00101        SET_FILE_BINARY(stdout);
00102        progname = argv[0];
00103                                           /* scan options */
00104        for (a = 1; a < argc; a++) {
00105               if (argv[a][0] == '-')
00106                      switch (argv[a][1]) {
00107                      case 'x':
00108                      case 'y':
00109                             a++;
00110                             continue;
00111                      case 'w':
00112                             nowarn = !nowarn;
00113                             continue;
00114                      case 'h':
00115                             echoheader = !echoheader;
00116                             continue;
00117                      case 'f':
00118                      case 'e':
00119                             a++;
00120                             continue;
00121                      }
00122               break;
00123        }
00124        newheader("RADIANCE", stdout);     /* start header */
00125        fputnow(stdout);
00126                                    /* process files */
00127        for (nfiles = 0; nfiles < MAXINP; nfiles++) {
00128               setcolor(input[nfiles].coef, 1.0, 1.0, 1.0);
00129               setcolor(input[nfiles].expos, 1.0, 1.0, 1.0);
00130               input[nfiles].vw = stdview;
00131               input[nfiles].pa = 1.0;
00132        }
00133        nfiles = 0;
00134        original = 0;
00135        for ( ; a < argc; a++) {
00136               if (nfiles >= MAXINP) {
00137                      eputs(argv[0]);
00138                      eputs(": too many picture files\n");
00139                      quit(1);
00140               }
00141               if (argv[a][0] == '-')
00142                      switch (argv[a][1]) {
00143                      case '\0':
00144                             input[nfiles].name = StandardInput;
00145                             input[nfiles].fp = stdin;
00146                             break;
00147                      case 'o':
00148                             original++;
00149                             continue;
00150                      case 's':
00151                             f = atof(argv[++a]);
00152                             scalecolor(input[nfiles].coef, f);
00153                             continue;
00154                      case 'c':
00155                             colval(input[nfiles].coef,RED)*=atof(argv[++a]);
00156                             colval(input[nfiles].coef,GRN)*=atof(argv[++a]);
00157                             colval(input[nfiles].coef,BLU)*=atof(argv[++a]);
00158                             continue;
00159                      default:
00160                             goto usage;
00161                      }
00162               else {
00163                      if (argv[a][0] == '!') {
00164                             input[nfiles].name = Command;
00165                             input[nfiles].fp = popen(argv[a]+1, "r");
00166                      } else {
00167                             input[nfiles].name = argv[a];
00168                             input[nfiles].fp = fopen(argv[a], "r");
00169                      }
00170                      if (input[nfiles].fp == NULL) {
00171                             perror(argv[a]);
00172                             quit(1);
00173                      }
00174               }
00175               checkfile();
00176               if (original) {
00177                      colval(input[nfiles].coef,RED) /=
00178                                    colval(input[nfiles].expos,RED);
00179                      colval(input[nfiles].coef,GRN) /=
00180                                    colval(input[nfiles].expos,GRN);
00181                      colval(input[nfiles].coef,BLU) /=
00182                                    colval(input[nfiles].expos,BLU);
00183                      setcolor(input[nfiles].expos, 1.0, 1.0, 1.0);
00184               }
00185               nfiles++;
00186               original = 0;
00187        }
00188        init();                            /* set constants */
00189                                    /* go back and get expressions */
00190        for (a = 1; a < argc; a++) {
00191               if (argv[a][0] == '-')
00192                      switch (argv[a][1]) {
00193                      case 'x':
00194                             varset(vxres, ':', eval(argv[++a]));
00195                             continue;
00196                      case 'y':
00197                             varset(vyres, ':', eval(argv[++a]));
00198                             continue;
00199                      case 'w':
00200                             continue;
00201                      case 'h':
00202                             continue;
00203                      case 'f':
00204                             fcompile(argv[++a]);
00205                             continue;
00206                      case 'e':
00207                             scompile(argv[++a], NULL, 0);
00208                             continue;
00209                      }
00210               break;
00211        }
00212                                           /* set/get output resolution */
00213        if (!vardefined(vxres))
00214               varset(vxres, ':', (double)xmax);
00215        if (!vardefined(vyres))
00216               varset(vyres, ':', (double)ymax);
00217        xres = varvalue(vxres) + .5;
00218        yres = varvalue(vyres) + .5;
00219        if (xres <= 0 || yres <= 0) {
00220               eputs(argv[0]);
00221               eputs(": illegal output resolution\n");
00222               quit(1);
00223        }
00224                                           /* complete header */
00225        printargs(argc, argv, stdout);
00226        if (strcmp(ourfmt, PICFMT))
00227               fputformat(ourfmt, stdout); /* print format if known */
00228        putchar('\n');
00229        fprtresolu(xres, yres, stdout);
00230                                           /* combine pictures */
00231        combine();
00232        quit(0);
00233 usage:
00234        eputs("Usage: ");
00235        eputs(argv[0]);
00236        eputs(
00237 " [-w][-h][-x xr][-y yr][-e expr][-f file] [ [-o][-s f][-c r g b] hdr ..]\n");
00238        quit(1);
00239        return 1; /* pro forma return */
00240 }
00241 
00242 
00243 static int
00244 headline(                   /* check header line & echo if requested */
00245        char   *s,
00246        void   *p
00247 )
00248 {
00249        char   fmt[32];
00250        double d;
00251        COLOR  ctmp;
00252 
00253        if (isheadid(s))                   /* header id */
00254               return(0);    /* don't echo */
00255        if (formatval(fmt, s)) {           /* check format */
00256               if (globmatch(ourfmt, fmt)) {
00257                      wrongformat = 0;
00258                      strcpy(ourfmt, fmt);
00259               } else
00260                      wrongformat = globmatch(PICFMT, fmt) ? 1 : -1;
00261               return(0);    /* don't echo */
00262        }
00263        if (isexpos(s)) {                  /* exposure */
00264               d = exposval(s);
00265               scalecolor(input[nfiles].expos, d);
00266        } else if (iscolcor(s)) {          /* color correction */
00267               colcorval(ctmp, s);
00268               multcolor(input[nfiles].expos, ctmp);
00269        } else if (isaspect(s))
00270               input[nfiles].pa *= aspectval(s);
00271        else if (isview(s) && sscanview(&input[nfiles].vw, s) > 0)
00272               gotview++;
00273 
00274        if (echoheader) {                  /* echo line */
00275               putchar('\t');
00276               return(fputs(s, stdout));
00277        }
00278        return(0);
00279 }
00280 
00281 
00282 static void
00283 checkfile(void)                    /* ready a file */
00284 {
00285        register int  i;
00286                                    /* process header */
00287        gotview = 0;
00288        if (echoheader) {
00289               fputs(input[nfiles].name, stdout);
00290               fputs(":\n", stdout);
00291        }
00292        getheader(input[nfiles].fp, headline, NULL);
00293        if (wrongformat < 0) {
00294               eputs(input[nfiles].name);
00295               eputs(": not a Radiance picture\n");
00296               quit(1);
00297        }
00298        if (wrongformat > 0) {
00299               wputs(input[nfiles].name);
00300               wputs(": warning -- incompatible picture format\n");
00301        }
00302        if (!gotview || setview(&input[nfiles].vw) != NULL)
00303               input[nfiles].vw.type = 0;
00304        if (!fgetsresolu(&input[nfiles].rs, input[nfiles].fp)) {
00305               eputs(input[nfiles].name);
00306               eputs(": bad picture size\n");
00307               quit(1);
00308        }
00309        if (xmax == 0 && ymax == 0) {
00310               xmax = scanlen(&input[nfiles].rs);
00311               ymax = numscans(&input[nfiles].rs);
00312        } else if (scanlen(&input[nfiles].rs) != xmax ||
00313                      numscans(&input[nfiles].rs) != ymax) {
00314               eputs(input[nfiles].name);
00315               eputs(": resolution mismatch\n");
00316               quit(1);
00317        }
00318                                    /* allocate scanlines */
00319        for (i = 0; i < WINSIZ; i++)
00320               input[nfiles].scan[i] = (COLOR *)emalloc(xmax*sizeof(COLOR));
00321 }
00322 
00323 
00324 static double
00325 rgb_bright(
00326        COLOR  clr
00327 )
00328 {
00329        return(bright(clr));
00330 }
00331 
00332 
00333 static double
00334 xyz_bright(
00335        COLOR  clr
00336 )
00337 {
00338        return(clr[CIEY]);
00339 }
00340 
00341 
00342 double (*ourbright)() = rgb_bright;
00343 
00344 
00345 static void
00346 init(void)                                /* perform final setup */
00347 {
00348        register int  i;
00349                                           /* define constants */
00350        varset("PI", ':', PI);
00351        varset(vnfiles, ':', (double)nfiles);
00352        varset(vxmax, ':', (double)xmax);
00353        varset(vymax, ':', (double)ymax);
00354                                           /* set functions */
00355        for (i = 0; i < 3; i++) {
00356               funset(vcolexp[i], 1, ':', l_expos);
00357               funset(vcolin[i], 1, '=', l_colin);
00358        }
00359        funset(vbrtexp, 1, ':', l_expos);
00360        funset(vbrtin, 1, '=', l_colin);
00361        funset(vpixaspect, 1, ':', l_pixaspect);
00362        for (i = 0; i < 7; i++)
00363               funset(vray[i], 1, '=', l_ray);
00364        funset(vpsize, 1, '=', l_psize);
00365                                           /* set brightness function */
00366        if (!strcmp(ourfmt, CIEFMT)) {
00367               varset(vwhteff, ':', 1.0);
00368               ourbright = xyz_bright;
00369        } else
00370               varset(vwhteff, ':', WHTEFFICACY);
00371 }
00372 
00373 
00374 static void
00375 combine(void)               /* combine pictures */
00376 {
00377        EPNODE *coldef[3], *brtdef;
00378        COLOR  *scanout;
00379        double d;
00380        register int  i, j;
00381                                           /* check defined variables */
00382        for (j = 0; j < 3; j++) {
00383               if (vardefined(vcolout[j]))
00384                      coldef[j] = eparse(vcolout[j]);
00385               else
00386                      coldef[j] = NULL;
00387        }
00388        if (vardefined(vbrtout))
00389               brtdef = eparse(vbrtout);
00390        else
00391               brtdef = NULL;
00392                                           /* allocate scanline */
00393        scanout = (COLOR *)emalloc(xres*sizeof(COLOR));
00394                                           /* set input position */
00395        yscan = ymax+MIDSCN;
00396                                           /* combine files */
00397        for (ypos = yres-1; ypos >= 0; ypos--) {
00398            advance();
00399            varset(vypos, '=', (double)ypos);
00400            for (xpos = 0; xpos < xres; xpos++) {
00401               xscan = (xpos+.5)*xmax/xres;
00402               varset(vxpos, '=', (double)xpos);
00403               eclock++;
00404               if (brtdef != NULL) {
00405                   d = evalue(brtdef);
00406                   if (d < 0.0)
00407                      d = 0.0;
00408                   setcolor(scanout[xpos], d, d, d);
00409               } else {
00410                   for (j = 0; j < 3; j++) {
00411                      if (coldef[j] != NULL) {
00412                             d = evalue(coldef[j]);
00413                      } else {
00414                          d = 0.0;
00415                          for (i = 0; i < nfiles; i++)
00416                             d += colval(input[i].scan[MIDSCN][xscan],j);
00417                      }
00418                      if (d < 0.0)
00419                          d = 0.0;
00420                      colval(scanout[xpos],j) = d;
00421                   }
00422               }
00423            }
00424            if (fwritescan(scanout, xres, stdout) < 0) {
00425                   perror("write error");
00426                   quit(1);
00427            }
00428        }
00429        efree((char *)scanout);
00430 }
00431 
00432 
00433 static void
00434 advance(void)               /* read in data for next scanline */
00435 {
00436        int    ytarget;
00437        register COLOR       *st;
00438        register int  i, j;
00439 
00440        for (ytarget = (ypos+.5)*ymax/yres; yscan > ytarget; yscan--)
00441               for (i = 0; i < nfiles; i++) {
00442                      st = input[i].scan[WINSIZ-1];
00443                      for (j = WINSIZ-1; j > 0; j--)     /* rotate window */
00444                             input[i].scan[j] = input[i].scan[j-1];
00445                      input[i].scan[0] = st;
00446                      if (yscan <= MIDSCN)        /* hit bottom? */
00447                             continue;
00448                      if (freadscan(st, xmax, input[i].fp) < 0) {  /* read */
00449                             eputs(input[i].name);
00450                             eputs(": read error\n");
00451                             quit(1);
00452                      }
00453                      for (j = 0; j < xmax; j++)  /* adjust color */
00454                             multcolor(st[j], input[i].coef);
00455               }
00456 }
00457 
00458 
00459 static double
00460 l_expos(                    /* return picture exposure */
00461        char   *nam
00462 )
00463 {
00464        int    fn, n;
00465        double d;
00466 
00467        d = argument(1);
00468        if (d <= -0.5 || d >= nfiles+0.5) {
00469               errno = EDOM;
00470               return(0.0);
00471        }
00472        if (d < 0.5)
00473               return((double)nfiles);
00474        fn = d - 0.5;
00475        if (nam == vbrtexp)
00476               return((*ourbright)(input[fn].expos));
00477        n = 3;
00478        while (n--)
00479               if (nam == vcolexp[n])
00480                      return(colval(input[fn].expos,n));
00481        eputs("Bad call to l_expos()!\n");
00482        quit(1);
00483        return 1; /* pro forma return */
00484 }
00485 
00486 
00487 static double
00488 l_pixaspect(char *nm)              /* return pixel aspect ratio */
00489 {
00490        int    fn;
00491        double d;
00492 
00493        d = argument(1);
00494        if (d <= -0.5 || d >= nfiles+0.5) {
00495               errno = EDOM;
00496               return(0.0);
00497        }
00498        if (d < 0.5)
00499               return((double)nfiles);
00500        fn = d - 0.5;
00501        return(input[fn].pa);
00502 }
00503 
00504 
00505 static double
00506 l_colin(                    /* return color value for picture */
00507        register char *nam
00508 )
00509 {
00510        int    fn;
00511        register int  n, xoff, yoff;
00512        double d;
00513 
00514        d = argument(1);
00515        if (d <= -0.5 || d >= nfiles+0.5) {
00516               errno = EDOM;
00517               return(0.0);
00518        }
00519        if (d < 0.5)
00520               return((double)nfiles);
00521        fn = d - 0.5;
00522        xoff = yoff = 0;
00523        n = nargum();
00524        if (n >= 2) {
00525               d = argument(2);
00526               if (d < 0.0) {
00527                      xoff = d-.5;
00528                      if (xscan+xoff < 0)
00529                             xoff = -xscan;
00530               } else {
00531                      xoff = d+.5;
00532                      if (xscan+xoff >= xmax)
00533                             xoff = xmax-1-xscan;
00534               }
00535        }
00536        if (n >= 3) {
00537               d = argument(3);
00538               if (d < 0.0) {
00539                      yoff = d-.5;
00540                      if (yoff+MIDSCN < 0)
00541                             yoff = -MIDSCN;
00542                      if (yscan+yoff < 0)
00543                             yoff = -yscan;
00544               } else {
00545                      yoff = d+.5;
00546                      if (yoff+MIDSCN >= WINSIZ)
00547                             yoff = WINSIZ-1-MIDSCN;
00548                      if (yscan+yoff >= ymax)
00549                             yoff = ymax-1-yscan;
00550               }
00551        }
00552        if (nam == vbrtin)
00553               return((*ourbright)(input[fn].scan[MIDSCN+yoff][xscan+xoff]));
00554        n = 3;
00555        while (n--)
00556            if (nam == vcolin[n])
00557               return(colval(input[fn].scan[MIDSCN+yoff][xscan+xoff],n));
00558        eputs("Bad call to l_colin()!\n");
00559        quit(1);
00560        return 1; /* pro forma return */
00561 }
00562 
00563 
00564 static double
00565 l_ray(        /* return ray origin or direction */
00566        register char *nam
00567 )
00568 {
00569        static unsigned long ltick[MAXINP];
00570        static FVECT  lorg[MAXINP], ldir[MAXINP];
00571        static double ldist[MAXINP];
00572        RREAL  loc[2];
00573        double d;
00574        int    fn;
00575        register int  i;
00576 
00577        d = argument(1);
00578        if (d <= -0.5 || d >= nfiles+0.5) {
00579               errno = EDOM;
00580               return(0.0);
00581        }
00582        if (d < 0.5)
00583               return((double)nfiles);
00584        fn = d - 0.5;
00585        if (ltick[fn] != eclock) {         /* need to compute? */
00586               lorg[fn][0] = lorg[fn][1] = lorg[fn][2] = 0.0;
00587               ldir[fn][0] = ldir[fn][1] = ldir[fn][2] = 0.0;
00588               ldist[fn] = -1.0;
00589               if (input[fn].vw.type == 0)
00590                      errno = EDOM;
00591               else {
00592                      pix2loc(loc, &input[fn].rs, xscan, ymax-1-yscan);
00593                      ldist[fn] = viewray(lorg[fn], ldir[fn],
00594                                    &input[fn].vw, loc[0], loc[1]);
00595               }
00596               ltick[fn] = eclock;
00597        }
00598        if (nam == vray[i=6])
00599               return(ldist[fn]);
00600        while (i--)
00601               if (nam == vray[i])
00602                      return(i < 3 ? lorg[fn][i] : ldir[fn][i-3]);
00603        eputs("Bad call to l_ray()!\n");
00604        quit(1);
00605        return 1; /* pro forma return */
00606 }
00607 
00608 
00609 static double
00610 l_psize(char *nm)           /* compute pixel size in steradians */
00611 {
00612        static unsigned long ltick[MAXINP];
00613        static double psize[MAXINP];
00614        FVECT  dir0, org, dirx, diry;
00615        RREAL  locx[2], locy[2];
00616        double d;
00617        int    fn;
00618        register int  i;
00619 
00620        d = argument(1);
00621        if (d <= -0.5 || d >= nfiles+0.5) {
00622               errno = EDOM;
00623               return(0.0);
00624        }
00625        if (d < 0.5)
00626               return((double)nfiles);
00627        fn = d - 0.5;
00628        if (ltick[fn] != eclock) {         /* need to compute? */
00629               psize[fn] = 0.0;
00630               if (input[fn].vw.type == 0)
00631                      errno = EDOM;
00632               else if (input[fn].vw.type != VT_PAR &&
00633                             funvalue(vray[6], 1, &d) >= -FTINY) {
00634                      for (i = 0; i < 3; i++)
00635                             dir0[i] = funvalue(vray[3+i], 1, &d);
00636                      pix2loc(locx, &input[fn].rs, xscan+1, ymax-1-yscan);
00637                      pix2loc(locy, &input[fn].rs, xscan, ymax-yscan);
00638                      if (viewray(org, dirx, &input[fn].vw,
00639                                    locx[0], locx[1]) >= -FTINY &&
00640                                    viewray(org, diry, &input[fn].vw,
00641                                    locy[0], locy[1]) >= -FTINY) {
00642                                           /* approximate solid angle */
00643                             for (i = 0; i < 3; i++) {
00644                                    dirx[i] -= dir0[i];
00645                                    diry[i] -= dir0[i];
00646                             }
00647                             fcross(dir0, dirx, diry);
00648                             psize[fn] = VLEN(dir0);
00649                      }
00650               }
00651               ltick[fn] = eclock;
00652        }
00653        return(psize[fn]);
00654 }
00655 
00656 
00657 extern void
00658 wputs(char    *msg)
00659 {
00660        if (!nowarn)
00661               eputs(msg);
00662 }
00663 
00664 
00665 extern void
00666 eputs(char *msg)
00667 {
00668        fputs(msg, stderr);
00669 }
00670 
00671 
00672 extern void
00673 quit(int code)              /* exit gracefully */
00674 {
00675        register int  i;
00676                             /* close input files */
00677        for (i = 0; i < nfiles; i++)
00678               if (input[i].name == Command)
00679                      pclose(input[i].fp);
00680               else
00681                      fclose(input[i].fp);
00682        exit(code);
00683 }