Back to index

radiance  4R0+20100331
pcond2.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: pcond2.c,v 3.17 2005/09/08 22:29:47 greg Exp $";
00003 #endif
00004 /*
00005  * Input and output conditioning routines for pcond.
00006  *  Added white-balance adjustment 10/01 (GW).
00007  */
00008 
00009 #include "pcond.h"
00010 #include "warp3d.h"
00011 
00012 
00013 RGBPRIMP      inprims = stdprims;  /* input primaries */
00014 COLORMAT      inrgb2xyz;           /* convert input RGB to XYZ */
00015 RGBPRIMP      outprims = stdprims; /* output primaries */
00016 
00017 double (*lumf)() = rgblum;         /* input luminance function */
00018 double inpexp = 1.0;               /* input exposure value */
00019 
00020 char   *mbcalfile = NULL;          /* macbethcal mapping file */
00021 char   *cwarpfile = NULL;          /* color space warping file */
00022 
00023 static struct mbc {
00024        COLORMAT      cmat;
00025        float  xa[3][6], ya[3][6];
00026        COLOR  cmin, cmax;
00027 }      mbcond;                            /* macbethcal conditioning struct */
00028 
00029 static WARP3D *cwarp;                     /* color warping structure */
00030 
00031 static COLOR  *scanbuf;            /* scanline processing buffer */
00032 static int    nread;               /* number of scanlines processed */
00033 
00034 static void sfscan(COLOR *sl, int len, double sf);
00035 static void matscan(COLOR *sl, int len, COLORMAT mat);
00036 static void mbscan(COLOR *sl, int len, struct mbc *mb);
00037 static void cwscan(COLOR *sl, int len, WARP3D *wp);
00038 static void getmbcalfile(char *fn, struct mbc *mb);
00039 
00040 
00041 extern double
00042 rgblum(              /* compute (scotopic) luminance of RGB color */
00043        COLOR  clr,
00044        int    scotopic
00045 )
00046 {
00047        if (scotopic)        /* approximate */
00048               return( WHTSEFFICACY * (colval(clr,RED)*.062 +
00049                      colval(clr,GRN)*.608 + colval(clr,BLU)*.330) );
00050        return( WHTEFFICACY * (colval(clr,RED)*inrgb2xyz[1][0] +
00051                      colval(clr,GRN)*inrgb2xyz[1][1] +
00052                      colval(clr,BLU)*inrgb2xyz[1][2]) );
00053 }
00054 
00055 
00056 extern double
00057 cielum(              /* compute (scotopic) luminance of CIE color */
00058        COLOR  xyz,
00059        int    scotopic
00060 )
00061 {
00062        if (scotopic)        /* approximate */
00063               return(colval(xyz,CIEY) *
00064                      (1.33*(1. + (colval(xyz,CIEY)+colval(xyz,CIEZ))/
00065                      colval(xyz,CIEX)) - 1.68));
00066        return(colval(xyz,CIEY));
00067 }
00068 
00069 
00070 extern COLOR *
00071 nextscan(void)                            /* read and condition next scanline */
00072 {
00073        if (nread >= numscans(&inpres)) {
00074               if (cwarpfile != NULL)
00075                      free3dw(cwarp);
00076               free((void *)scanbuf);
00077               return(scanbuf = NULL);
00078        }
00079        if (what2do&DO_ACUITY)
00080               acuscan(scanbuf, nread);
00081        else if (freadscan(scanbuf, scanlen(&inpres), infp) < 0) {
00082               fprintf(stderr, "%s: %s: scanline read error\n",
00083                             progname, infn);
00084               exit(1);
00085        }
00086        if (what2do&DO_VEIL)               /* add veiling */
00087               addveil(scanbuf, nread);
00088        if (what2do&DO_COLOR)                     /* scotopic color loss */
00089               scotscan(scanbuf, scanlen(&inpres));
00090        if (what2do&DO_LINEAR)                    /* map luminances */
00091               sfscan(scanbuf, scanlen(&inpres), scalef);
00092        else
00093               mapscan(scanbuf, scanlen(&inpres));
00094        if (mbcalfile != NULL)                    /* device color correction */
00095               mbscan(scanbuf, scanlen(&inpres), &mbcond);
00096        else if (cwarpfile != NULL)        /* device color space warp */
00097               cwscan(scanbuf, scanlen(&inpres), cwarp);
00098        else if ((lumf == cielum) | (inprims != outprims))
00099               matscan(scanbuf, scanlen(&inpres), mbcond.cmat);
00100        nread++;
00101        return(scanbuf);
00102 }
00103 
00104 
00105 extern COLOR *
00106 firstscan(void)                           /* return first processed scanline */
00107 {
00108        if (mbcalfile != NULL)             /* load macbethcal file */
00109               getmbcalfile(mbcalfile, &mbcond);
00110        else if (cwarpfile != NULL) {
00111               if ((cwarp = load3dw(cwarpfile, NULL)) == NULL)
00112                      syserror(cwarpfile);
00113        } else
00114               if (lumf == rgblum)
00115                      comprgb2rgbWBmat(mbcond.cmat, inprims, outprims);
00116               else
00117                      compxyz2rgbWBmat(mbcond.cmat, outprims);
00118        if (what2do&DO_ACUITY)
00119               initacuity();
00120        scanbuf = (COLOR *)malloc(scanlen(&inpres)*sizeof(COLOR));
00121        if (scanbuf == NULL)
00122               syserror("malloc");
00123        nread = 0;
00124        return(nextscan());
00125 }
00126 
00127 
00128 static void
00129 sfscan(                     /* apply scalefactor to scanline */
00130        register COLOR       *sl,
00131        int    len,
00132        double sf
00133 )
00134 {
00135        while (len--) {
00136               scalecolor(sl[0], sf);
00137               sl++;
00138        }
00139 }
00140 
00141 
00142 static double
00143 greypoint(                  /* compute gamut mapping grey target */
00144        COLOR col
00145 )
00146 {
00147        COLOR  gryc;
00148        int    i;
00149                             /* improves saturated color rendering */
00150        copycolor(gryc, col);
00151        for (i = 3; i--; )
00152               if (gryc[i] > 1)
00153                      gryc[i] = 1;
00154               else if (gryc[i] < 0)
00155                      gryc[i] = 0;
00156        return(bright(gryc));
00157 }
00158 
00159 
00160 static void
00161 matscan(                    /* apply color matrix to scaline */
00162        register COLOR       *sl,
00163        int    len,
00164        COLORMAT      mat
00165 )
00166 {
00167        while (len--) {
00168               colortrans(sl[0], mat, sl[0]);
00169               clipgamut(sl[0], greypoint(sl[0]), CGAMUT, cblack, cwhite);
00170               sl++;
00171        }
00172 }
00173 
00174 
00175 static void
00176 mbscan(                     /* apply macbethcal adj. to scaline */
00177        COLOR  *sl,
00178        int    len,
00179        register struct mbc  *mb
00180 )
00181 {
00182        double d;
00183        register int  i, j;
00184 
00185        while (len--) {
00186               colortrans(sl[0], mb->cmat, sl[0]);
00187               clipgamut(sl[0], greypoint(sl[0]), CGAMUT, mb->cmin, mb->cmax);
00188               for (i = 0; i < 3; i++) {
00189                      d = colval(sl[0],i);
00190                      for (j = 0; j < 4 && mb->xa[i][j+1] <= d; j++)
00191                             ;
00192                      colval(sl[0],i) = ( (mb->xa[i][j+1] - d)*mb->ya[i][j] +
00193                                    (d - mb->xa[i][j])*mb->ya[i][j+1] ) /
00194                                    (mb->xa[i][j+1] - mb->xa[i][j]);
00195               }
00196               sl++;
00197        }
00198 }
00199 
00200 
00201 static void
00202 cwscan(                     /* apply color space warp to scaline */
00203        COLOR  *sl,
00204        int    len,
00205        WARP3D *wp
00206 )
00207 {
00208        int    rval;
00209 
00210        while (len--) {
00211               rval = warp3d(sl[0], sl[0], wp);
00212               if (rval & W3ERROR)
00213                      syserror("warp3d");
00214               if (rval & W3BADMAP) {
00215                      fprintf(stderr, "%s: %s: bad color space map\n",
00216                                    progname, cwarpfile);
00217                      exit(1);
00218               }
00219               clipgamut(sl[0], greypoint(sl[0]), CGAMUT, cblack, cwhite);
00220               sl++;
00221        }
00222 }
00223 
00224 
00225 static void
00226 getmbcalfile(               /* load macbethcal file */
00227        char   *fn,
00228        register struct mbc  *mb
00229 )
00230 {
00231        char   buf[128];
00232        FILE   *fp;
00233        int    inpflags = 0;
00234        register int  i;
00235 
00236        if ((fp = fopen(fn, "r")) == NULL)
00237               syserror(fn);
00238        while (fgets(buf, sizeof(buf), fp) != NULL) {
00239               if (!(inpflags & 01) &&
00240                             sscanf(buf,
00241                             "rxa(i) : select(i,%f,%f,%f,%f,%f,%f)",
00242                             &mb->xa[0][0], &mb->xa[0][1],
00243                             &mb->xa[0][2], &mb->xa[0][3],
00244                             &mb->xa[0][4], &mb->xa[0][5]
00245                             ) == 6)
00246                      inpflags |= 01;
00247               else if (!(inpflags & 02) &&
00248                             sscanf(buf,
00249                             "rya(i) : select(i,%f,%f,%f,%f,%f,%f)",
00250                             &mb->ya[0][0], &mb->ya[0][1],
00251                             &mb->ya[0][2], &mb->ya[0][3],
00252                             &mb->ya[0][4], &mb->ya[0][5]
00253                             ) == 6)
00254                      inpflags |= 02;
00255               else if (!(inpflags & 04) &&
00256                             sscanf(buf,
00257                             "gxa(i) : select(i,%f,%f,%f,%f,%f,%f)",
00258                             &mb->xa[1][0], &mb->xa[1][1],
00259                             &mb->xa[1][2], &mb->xa[1][3],
00260                             &mb->xa[1][4], &mb->xa[1][5]
00261                             ) == 6)
00262                      inpflags |= 04;
00263               else if (!(inpflags & 010) &&
00264                             sscanf(buf,
00265                             "gya(i) : select(i,%f,%f,%f,%f,%f,%f)",
00266                             &mb->ya[1][0], &mb->ya[1][1],
00267                             &mb->ya[1][2], &mb->ya[1][3],
00268                             &mb->ya[1][4], &mb->ya[1][5]
00269                             ) == 6)
00270                      inpflags |= 010;
00271               else if (!(inpflags & 020) &&
00272                             sscanf(buf,
00273                             "bxa(i) : select(i,%f,%f,%f,%f,%f,%f)",
00274                             &mb->xa[2][0], &mb->xa[2][1],
00275                             &mb->xa[2][2], &mb->xa[2][3],
00276                             &mb->xa[2][4], &mb->xa[2][5]
00277                             ) == 6)
00278                      inpflags |= 020;
00279               else if (!(inpflags & 040) &&
00280                             sscanf(buf,
00281                             "bya(i) : select(i,%f,%f,%f,%f,%f,%f)",
00282                             &mb->ya[2][0], &mb->ya[2][1],
00283                             &mb->ya[2][2], &mb->ya[2][3],
00284                             &mb->ya[2][4], &mb->ya[2][5]
00285                             ) == 6)
00286                      inpflags |= 040;
00287               else if (!(inpflags & 0100) &&
00288                             sscanf(buf,
00289                             "ro = %f*rn + %f*gn + %f*bn",
00290                             &mb->cmat[0][0], &mb->cmat[0][1],
00291                             &mb->cmat[0][2]) == 3)
00292                      inpflags |= 0100;
00293               else if (!(inpflags & 0200) &&
00294                             sscanf(buf,
00295                             "go = %f*rn + %f*gn + %f*bn",
00296                             &mb->cmat[1][0], &mb->cmat[1][1],
00297                             &mb->cmat[1][2]) == 3)
00298                      inpflags |= 0200;
00299               else if (!(inpflags & 0400) &&
00300                             sscanf(buf,
00301                             "bo = %f*rn + %f*gn + %f*bn",
00302                             &mb->cmat[2][0], &mb->cmat[2][1],
00303                             &mb->cmat[2][2]) == 3)
00304                      inpflags |= 0400;
00305        }
00306        if (inpflags != 0777) {
00307               fprintf(stderr,
00308               "%s: cannot grok macbethcal file \"%s\" (inpflags==0%o)\n",
00309                      progname, fn, inpflags);
00310               exit(1);
00311        }
00312        fclose(fp);
00313                                    /* compute gamut */
00314        for (i = 0; i < 3; i++) {
00315               colval(mb->cmin,i) = mb->xa[i][0] -
00316                             mb->ya[i][0] *
00317                             (mb->xa[i][1]-mb->xa[i][0]) /
00318                             (mb->ya[i][1]-mb->ya[i][0]);
00319               colval(mb->cmax,i) = mb->xa[i][4] +
00320                             (1.-mb->ya[i][4]) *
00321                             (mb->xa[i][5] - mb->xa[i][4]) /
00322                             (mb->ya[i][5] - mb->ya[i][4]);
00323        }
00324 }