Back to index

radiance  4R0+20100331
pcond.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: pcond.c,v 3.24 2006/06/07 17:52:04 schorsch Exp $";
00003 #endif
00004 /*
00005  * Condition Radiance picture for display/output
00006  *  Added white-balance adjustment 10/01 (GW).
00007  */
00008 
00009 #include "platform.h"
00010 #include "paths.h"
00011 #include "rtprocess.h"
00012 #include "pcond.h"
00013 
00014 
00015 #define       LDMAX         100           /* default max. display luminance */
00016 #define LDDYN        32            /* default dynamic range */
00017 
00018 int    what2do = 0;                /* desired adjustments */
00019 
00020 double ldmax = LDMAX;                     /* maximum output luminance */
00021 double lddyn = LDDYN;                     /* display dynamic range */
00022 double Bldmin, Bldmax;                    /* Bl(ldmax/lddyn) and Bl(ldmax) */
00023 
00024 char   *progname;                  /* global argv[0] */
00025 
00026 char   *infn;                      /* input file name */
00027 FILE   *infp;                      /* input stream */
00028 FILE   *mapfp = NULL;                     /* tone-mapping function stream */
00029 VIEW   ourview = STDVIEW;          /* picture view */
00030 int    gotview = 0;                /* picture has view */
00031 double pixaspect = 1.0;            /* pixel aspect ratio */
00032 double fixfrac = 0.;               /* histogram share due to fixations */
00033 RESOLU inpres;                            /* input picture resolution */
00034 
00035 COLOR  *fovimg;                    /* foveal (1 degree) averaged image */
00036 int    fvxr, fvyr;                 /* foveal image resolution */
00037 float  *crfimg;                    /* contrast reduction factors */
00038 short  (*fixlst)[2];               /* fixation history list */
00039 int    nfixations;                 /* number of fixation points */
00040 double bwhist[HISTRES];            /* luminance histogram */
00041 double histot;                            /* total count of histogram */
00042 double bwmin, bwmax;               /* histogram limits */
00043 double bwavg;                      /* mean brightness */
00044 
00045 double scalef = 0.;                /* linear scaling factor */
00046 
00047 static gethfunc headline;
00048 static void getahead(void);
00049 static void mapimage(void);
00050 static void getfovimg(void);
00051 static void check2do(void);
00052 
00053 
00054 
00055 int
00056 main(
00057        int    argc,
00058        char   *argv[]
00059 )
00060 {
00061        static RGBPRIMS      outprimS;
00062        int    i;
00063 #define       bool(flg)            switch (argv[i][2]) { \
00064                             case '\0': what2do ^= flg; break; \
00065                             case 'y': case 'Y': case 't': case 'T': \
00066                             case '+': case '1': what2do |= flg; break; \
00067                             case 'n': case 'N': case 'f': case 'F': \
00068                             case '-': case '0': what2do &= ~(flg); break; \
00069                             default: goto userr; }
00070 
00071        progname = argv[0];
00072 
00073        for (i = 1; i < argc && argv[i][0] == '-'; i++)
00074               switch (argv[i][1]) {
00075               case 'h':
00076                      bool(DO_HUMAN);
00077                      break;
00078               case 'a':
00079                      bool(DO_ACUITY);
00080                      break;
00081               case 'v':
00082                      bool(DO_VEIL);
00083                      break;
00084               case 's':
00085                      bool(DO_HSENS);
00086                      break;
00087               case 'c':
00088                      bool(DO_COLOR);
00089                      break;
00090               case 'w':
00091                      bool(DO_CWEIGHT);
00092                      break;
00093               case 'i':
00094                      if (i+1 >= argc) goto userr;
00095                      fixfrac = atof(argv[++i]);
00096                      if (fixfrac > FTINY) what2do |= DO_FIXHIST;
00097                      else what2do &= ~DO_FIXHIST;
00098                      break;
00099               case 'I':
00100                      bool(DO_PREHIST);
00101                      break;
00102               case 'l':
00103                      bool(DO_LINEAR);
00104                      break;
00105               case 'p':
00106                      if (i+8 >= argc) goto userr;
00107                      outprimS[RED][CIEX] = atof(argv[++i]);
00108                      outprimS[RED][CIEY] = atof(argv[++i]);
00109                      outprimS[GRN][CIEX] = atof(argv[++i]);
00110                      outprimS[GRN][CIEY] = atof(argv[++i]);
00111                      outprimS[BLU][CIEX] = atof(argv[++i]);
00112                      outprimS[BLU][CIEY] = atof(argv[++i]);
00113                      outprimS[WHT][CIEX] = atof(argv[++i]);
00114                      outprimS[WHT][CIEY] = atof(argv[++i]);
00115                      outprims = outprimS;
00116                      break;
00117               case 'e':
00118                      if (i+1 >= argc) goto userr;
00119                      scalef = atof(argv[++i]);
00120                      if ((argv[i][0] == '+') | (argv[i][0] == '-'))
00121                             scalef = pow(2.0, scalef);
00122                      what2do |= DO_LINEAR;
00123                      break;
00124               case 'f':
00125                      if (i+1 >= argc) goto userr;
00126                      mbcalfile = argv[++i];
00127                      break;
00128               case 'm':
00129                      if (i+1 >= argc) goto userr;
00130                      cwarpfile = argv[++i];
00131                      break;
00132               case 'u':
00133                      if (i+1 >= argc) goto userr;
00134                      ldmax = atof(argv[++i]);
00135                      if (ldmax <= FTINY)
00136                             goto userr;
00137                      break;
00138               case 'd':
00139                      if (i+1 >= argc) goto userr;
00140                      lddyn = atof(argv[++i]);
00141                      break;
00142               case 'x':
00143                      if (i+1 >= argc) goto userr;
00144                      if ((mapfp = fopen(argv[++i], "w")) == NULL) {
00145                             fprintf(stderr,
00146                                    "%s: cannot open for writing\n",
00147                                           argv[i]);
00148                             exit(1);
00149                      }
00150                      break;
00151               default:
00152                      goto userr;
00153               }
00154        if ((what2do & (DO_FIXHIST|DO_PREHIST)) == (DO_FIXHIST|DO_PREHIST)) {
00155               fprintf(stderr, "%s: only one of -i or -I option\n", progname);
00156               exit(1);
00157        }
00158        if ((mbcalfile != NULL) + (cwarpfile != NULL) +
00159                      (outprims != stdprims) > 1) {
00160               fprintf(stderr,
00161                      "%s: only one of -p, -m or -f option supported\n",
00162                             progname);
00163               exit(1);
00164        }
00165        if ((outprims == stdprims) & (inprims != stdprims))
00166               outprims = inprims;
00167        Bldmin = Bl(ldmax/lddyn);
00168        Bldmax = Bl(ldmax);
00169        if (i >= argc || i+2 < argc)
00170               goto userr;
00171                                    /* open input file */
00172        if ((infp = fopen(infn=argv[i], "r")) == NULL)
00173               syserror(infn);
00174                                    /* open output file */
00175        if (i+2 == argc && freopen(argv[i+1], "w", stdout) == NULL)
00176               syserror(argv[i+1]);
00177        SET_FILE_BINARY(infp);
00178        SET_FILE_BINARY(stdout);
00179        getahead();                 /* load input header */
00180        printargs(argc, argv, stdout);     /* add to output header */
00181        if ((mbcalfile == NULL) & (outprims != stdprims))
00182               fputprims(outprims, stdout);
00183        if ((what2do & (DO_PREHIST|DO_VEIL|DO_ACUITY)) != DO_PREHIST)
00184               getfovimg();         /* get foveal sample image? */
00185        if (what2do&DO_PREHIST)            /* get histogram? */
00186               gethisto(stdin);
00187        else if (what2do&DO_FIXHIST)       /* get fixation history? */
00188               getfixations(stdin);
00189        mapimage();                 /* map the picture */
00190        if (mapfp != NULL)          /* write out basic mapping */
00191               putmapping(mapfp);
00192        exit(0);
00193 userr:
00194        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",
00195                      progname);
00196        exit(1);
00197        return 1; /* pro forma return */
00198 #undef bool
00199 }
00200 
00201 
00202 extern void
00203 syserror(                          /* report system error and exit */
00204        char   *s
00205 )
00206 {
00207        fprintf(stderr, "%s: ", progname);
00208        perror(s);
00209        exit(2);
00210 }
00211 
00212 
00213 static int
00214 headline(                          /* process header line */
00215        char   *s,
00216        void   *p
00217 )
00218 {
00219        static RGBPRIMS      inprimS;
00220        char   fmt[32];
00221 
00222        if (formatval(fmt, s)) {    /* check if format string */
00223               if (!strcmp(fmt,COLRFMT)) lumf = rgblum;
00224               else if (!strcmp(fmt,CIEFMT)) lumf = cielum;
00225               else lumf = NULL;
00226               return(0);           /* don't echo */
00227        }
00228        if (isprims(s)) {           /* get input primaries */
00229               primsval(inprimS, s);
00230               inprims= inprimS;
00231               return(0);           /* don't echo */
00232        }
00233        if (isexpos(s)) {           /* picture exposure */
00234               inpexp *= exposval(s);
00235               return(0);           /* don't echo */
00236        }
00237        if (isaspect(s))            /* pixel aspect ratio */
00238               pixaspect *= aspectval(s);
00239        if (isview(s))                     /* image view */
00240               gotview += sscanview(&ourview, s);
00241        return(fputs(s, stdout));
00242 }
00243 
00244 
00245 static void
00246 getahead(void)                     /* load picture header */
00247 {
00248        char   *err;
00249 
00250        getheader(infp, headline, NULL);
00251        if (lumf == NULL || !fgetsresolu(&inpres, infp)) {
00252               fprintf(stderr, "%s: %s: not a Radiance picture\n",
00253                      progname, infn);
00254               exit(1);
00255        }
00256        if (lumf == rgblum)
00257               comprgb2xyzWBmat(inrgb2xyz, inprims);
00258        else if (mbcalfile != NULL) {
00259               fprintf(stderr, "%s: macbethcal only works with RGB pictures\n",
00260                             progname);
00261               exit(1);
00262        }
00263        if (!gotview || ourview.type == VT_PAR ||
00264                      (ourview.horiz <= 5.) | (ourview.vert <= 5.)) {
00265               ourview = stdview;
00266               ourview.type = VT_PER;
00267               if (pixaspect*inpres.yr < inpres.xr) {
00268                      ourview.horiz = 40.0;
00269                      ourview.vert = 2.*180./PI *
00270                             atan(.3639702*pixaspect*inpres.yr/inpres.xr);
00271               } else {
00272                      ourview.vert = 40.0;
00273                      ourview.horiz = 2.*180./PI *
00274                             atan(.3639702*inpres.xr/pixaspect/inpres.yr);
00275               }
00276        }
00277        if ((err = setview(&ourview)) != NULL) {
00278               fprintf(stderr, "%s: view error in picture \"%s\": %s\n",
00279                      progname, infn, err);
00280               exit(1);
00281        }
00282 }
00283 
00284 
00285 static void
00286 mapimage(void)                            /* map picture and send to stdout */
00287 {
00288        COLOR  *scan;
00289 
00290        comphist();                 /* generate adaptation histogram */
00291        check2do();                 /* modify what2do flags */
00292        if (what2do&DO_VEIL)
00293               compveil();          /* compute veil image */
00294        if (!(what2do&DO_LINEAR))
00295               if (mkbrmap() < 0)   /* make tone map */
00296                      what2do |= DO_LINEAR;       /* failed! -- use linear */
00297 #if ADJ_VEIL
00298               else if (what2do&DO_VEIL)
00299                      adjveil();    /* else adjust veil image */
00300 #endif
00301        if (what2do&DO_LINEAR) {
00302               if (scalef <= FTINY) {
00303                      if (what2do&DO_HSENS)
00304                             scalef = htcontrs(Lb(0.5*(Bldmax+Bldmin))) /
00305                                           htcontrs(Lb(bwavg));
00306                      else
00307                             scalef = Lb(0.5*(Bldmax+Bldmin)) / Lb(bwavg);
00308                      scalef *= WHTEFFICACY/(inpexp*ldmax);
00309               }
00310               fputexpos(inpexp*scalef, stdout);  /* record exposure */
00311               if (lumf == cielum) scalef /= WHTEFFICACY;
00312        }
00313        fputformat(COLRFMT, stdout);       /* complete header */
00314        putchar('\n');
00315        fputsresolu(&inpres, stdout);      /* resolution doesn't change */
00316                                    /* condition our image */
00317        for (scan = firstscan(); scan != NULL; scan = nextscan())
00318               if (fwritescan(scan, scanlen(&inpres), stdout) < 0) {
00319                      fprintf(stderr, "%s: scanline write error\n",
00320                                    progname);
00321                      exit(1);
00322               }
00323 }
00324 
00325 
00326 static void
00327 getfovimg(void)                    /* load foveal sampled image */
00328 {
00329        char   combuf[PATH_MAX];
00330        FILE   *fp;
00331        int    x, y;
00332                                           /* compute image size */
00333        fvxr = sqrt(ourview.hn2)/FOVDIA + 0.5;
00334        if (fvxr < 2) fvxr = 2;
00335        fvyr = sqrt(ourview.vn2)/FOVDIA + 0.5;
00336        if (fvyr < 2) fvyr = 2;
00337        if (!(inpres.rt & YMAJOR)) {              /* picture is rotated? */
00338               y = fvyr;
00339               fvyr = fvxr;
00340               fvxr = y;
00341        }
00342        if ((fovimg = (COLOR *)malloc(fvxr*fvyr*sizeof(COLOR))) == NULL)
00343               syserror("malloc");
00344        sprintf(combuf, "pfilt -1 -b -pa 0 -x %d -y %d \"%s\"", fvxr, fvyr, infn);
00345        if ((fp = popen(combuf, "r")) == NULL)
00346               syserror("popen");
00347        getheader(fp, NULL, NULL);  /* skip header */
00348        if (fgetresolu(&x, &y, fp) < 0 || (x != fvxr) | (y != fvyr))
00349               goto readerr;
00350        for (y = 0; y < fvyr; y++)
00351               if (freadscan(fovscan(y), fvxr, fp) < 0)
00352                      goto readerr;
00353        pclose(fp);
00354        return;
00355 readerr:
00356        fprintf(stderr, "%s: error reading from pfilt process in fovimage\n",
00357                      progname);
00358        exit(1);
00359 }
00360 
00361 
00362 static void
00363 check2do(void)              /* check histogram to see what isn't worth doing */
00364 {
00365        double sum;
00366        double b, l;
00367        register int  i;
00368 
00369                                    /* check for within display range */
00370        if (bwmax - bwmin <= Bldmax - Bldmin)
00371               what2do |= DO_LINEAR;
00372                                    /* determine if veiling significant */
00373        if (bwmax - bwmin < 4.5)           /* heuristic */
00374               what2do &= ~DO_VEIL;
00375 
00376        if (!(what2do & (DO_ACUITY|DO_COLOR)))
00377               return;
00378                                    /* find 5th percentile */
00379        sum = histot*0.05;
00380        for (i = 0; i < HISTRES; i++)
00381               if ((sum -= bwhist[i]) <= 0)
00382                      break;
00383        b = (i+.5)*(bwmax-bwmin)/HISTRES + bwmin;
00384        l = Lb(b);
00385                                    /* determine if acuity adj. useful */
00386        if (what2do&DO_ACUITY &&
00387                      hacuity(l) >= (inpres.xr/sqrt(ourview.hn2) +
00388                      inpres.yr/sqrt(ourview.vn2))/(2.*180./PI))
00389               what2do &= ~DO_ACUITY;
00390                                    /* color sensitivity loss? */
00391        if (l >= TopMesopic)
00392               what2do &= ~DO_COLOR;
00393 }