Back to index

radiance  4R0+20100331
normtiff.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: normtiff.c,v 3.11 2008/11/10 19:08:19 greg Exp $";
00003 #endif
00004 /*
00005  * Tone map SGILOG TIFF or Radiance picture and output 24-bit RGB TIFF
00006  */
00007 
00008 #include <stdio.h>
00009 #include <math.h>
00010 #include <time.h>
00011 #include <string.h>
00012 
00013 #include "tiffio.h"
00014 #include "color.h"
00015 #include "tonemap.h"
00016 #include "tmaptiff.h"
00017 #include "resolu.h"
00018 
00019 
00020 TIFF   *tifout;                    /* TIFF output */
00021 int    flags = TM_F_CAMERA;        /* tone-mapping flags */
00022 RGBPRIMP      rgbp = stdprims;     /* display primaries */
00023 RGBPRIMS      myprims;             /* overriding display primaries */
00024 double ldmax = 100.;               /* maximum display luminance */
00025 double lddyn = 32.;                /* display dynamic range */
00026 double gamv = 2.2;                 /* display gamma value */
00027 
00028 short  ortab[8] = {         /* orientation conversion table */
00029        YMAJOR|YDECR,
00030        YMAJOR|YDECR|XDECR,
00031        YMAJOR|XDECR,
00032        YMAJOR,
00033        YDECR,
00034        XDECR|YDECR,
00035        XDECR,
00036        0
00037 };
00038 
00039 typedef struct {
00040        FILE   *fp;          /* file pointer */
00041        char   fmt[32];      /* picture format */
00042        double pa;           /* pixel aspect ratio */
00043        RESOLU rs;           /* picture resolution */
00044 } PICTURE;
00045 
00046 uint16 comp = COMPRESSION_NONE;    /* TIFF compression mode */
00047 
00048 #define closepicture(p)            (fclose((p)->fp),free((void *)(p)))
00049 
00050 static gethfunc headline;
00051 
00052 static int headline(char *s, void *pp);
00053 static PICTURE *openpicture(char *fname);
00054 static int tmap_picture(char *fname, PICTURE *pp);
00055 static int tmap_tiff(char *fname, TIFF *tp);
00056 static int putimage(uint16 or, uint32 xs, uint32 ys, float xr, float yr,
00057        uint16 ru, BYTE      *pd);
00058 
00059 
00060 int
00061 main(
00062        int    argc,
00063        char   *argv[]
00064 )
00065 {
00066        PICTURE       *pin = NULL;
00067        TIFF   *tin = NULL;
00068        int    i, rval;
00069 
00070        for (i = 1; i < argc && argv[i][0] == '-'; i++)
00071               switch (argv[i][1]) {
00072               case 'h':                   /* human observer settings */
00073                      flags = TM_F_HUMAN;
00074                      break;
00075               case 's':                   /* toggle human contrast */
00076                      flags ^= TM_F_HCONTR;
00077                      break;
00078               case 'c':                   /* toggle mesopic sens. */
00079                      flags ^= TM_F_MESOPIC;
00080                      break;
00081               case 'l':                   /* toggle linear mapping */
00082                      flags ^= TM_F_LINEAR;
00083                      break;
00084               case 'b':                   /* toggle greyscale output */
00085                      flags ^= TM_F_BW;
00086                      break;
00087               case 'g':                   /* set display gamma */
00088                      if (argc-i < 2) goto userr;
00089                      gamv = atof(argv[++i]);
00090                      break;
00091               case 'u':                   /* set display maximum */
00092                      if (argc-i < 2) goto userr;
00093                      ldmax = atof(argv[++i]);
00094                      break;
00095               case 'd':                   /* set display dynamic range */
00096                      if (argc-i < 2) goto userr;
00097                      lddyn = atof(argv[++i]);
00098                      break;
00099               case 'z':                   /* LZW compression */
00100                      comp = COMPRESSION_LZW;
00101                      break;
00102               case 'p':                   /* set display primaries */
00103                      if (argc-i < 9) goto userr;
00104                      myprims[RED][CIEX] = atof(argv[++i]);
00105                      myprims[RED][CIEY] = atof(argv[++i]);
00106                      myprims[GRN][CIEX] = atof(argv[++i]);
00107                      myprims[GRN][CIEY] = atof(argv[++i]);
00108                      myprims[BLU][CIEX] = atof(argv[++i]);
00109                      myprims[BLU][CIEY] = atof(argv[++i]);
00110                      myprims[WHT][CIEX] = atof(argv[++i]);
00111                      myprims[WHT][CIEY] = atof(argv[++i]);
00112                      rgbp = myprims;
00113                      break;
00114               default:
00115                      goto userr;
00116               }
00117        if (argc-i < 2) goto userr;
00118        if ((pin = openpicture(argv[i])) == NULL &&
00119                      (tin = TIFFOpen(argv[i], "r")) == NULL) {
00120               fprintf(stderr, "%s: cannot open or interpret file \"%s\"\n",
00121                             argv[0], argv[i]);
00122               exit(1);
00123        }
00124        if ((tifout = TIFFOpen(argv[i+1], "w")) == NULL) {
00125               fprintf(stderr, "%s: cannot open output TIFF \"%s\"\n",
00126                             argv[0], argv[i+1]);
00127               exit(1);
00128        }
00129        if (pin != NULL) {
00130               rval = tmap_picture(argv[i], pin);
00131               closepicture(pin);
00132        } else {
00133               rval = tmap_tiff(argv[i], tin);
00134               TIFFClose(tin);
00135        }
00136        TIFFClose(tifout);
00137        exit(rval==0 ? 0 : 1);
00138 userr:
00139        fprintf(stderr,
00140 "Usage: %s [-h][-s][-c][-l][-b][-g gv][-d ld][-u lm][-z][-p xr yr xg yg xb yb xw yw] input.{tif|hdr} output.tif\n",
00141                      argv[0]);
00142        exit(1);
00143 }
00144 
00145 
00146 static int
00147 headline(                          /* process line from header */
00148        char   *s,
00149        void *pp
00150 )
00151 {
00152        register char *cp;
00153 
00154        for (cp = s; *cp; cp++)
00155               if (*cp & 0x80)
00156                      return(-1);   /* non-ascii in header */
00157        if (isaspect(s))
00158               ((PICTURE *)pp)->pa *= aspectval(s);
00159        else
00160               formatval(((PICTURE *)pp)->fmt, s);
00161        return(0);
00162 }
00163 
00164 
00165 static PICTURE *
00166 openpicture(                /* open/check Radiance picture file */
00167        char   *fname
00168 )
00169 {
00170        FILE   *fp;
00171        register PICTURE     *pp;
00172        register char *cp;
00173                                    /* check filename suffix */
00174        if (fname == NULL) return(NULL);
00175        for (cp = fname; *cp; cp++)
00176               ;
00177        while (cp > fname && cp[-1] != '.')
00178               if (*--cp == '/') {
00179                      cp = fname;
00180                      break;
00181               }
00182        if (cp > fname && !strncmp(cp, "tif", 3))
00183               return(NULL);        /* assume it's a TIFF */
00184                                    /* else try opening it */
00185        if ((fp = fopen(fname, "r")) == NULL)
00186               return(NULL);
00187                                    /* allocate struct */
00188        if ((pp = (PICTURE *)malloc(sizeof(PICTURE))) == NULL)
00189               return(NULL);        /* serious error -- should exit? */
00190        pp->fp = fp; pp->fmt[0] = '\0'; pp->pa = 1.;
00191                                    /* load header */
00192        if (getheader(fp, headline, pp) < 0) {
00193               closepicture(pp);
00194               return(NULL);
00195        }
00196        if (!pp->fmt[0])            /* assume RGBE if unspecified */
00197               strcpy(pp->fmt, COLRFMT);
00198        if (!globmatch(PICFMT, pp->fmt) || !fgetsresolu(&pp->rs, fp)) {
00199               closepicture(pp);    /* failed test -- close file */
00200               return(NULL);
00201        }
00202        rewind(fp);                 /* passed test -- rewind file */
00203        return(pp);
00204 }
00205 
00206 
00207 static int
00208 tmap_picture(               /* tone map Radiance picture */
00209        char   *fname,
00210        register PICTURE     *pp
00211 )
00212 {
00213        uint16 orient;
00214        double paspect = (pp->rs.rt & YMAJOR) ? pp->pa : 1./pp->pa;
00215        int    xsiz, ysiz;
00216        BYTE   *pix;
00217                                    /* read and tone map picture */
00218        if (tmMapPicture(&pix, &xsiz, &ysiz, flags,
00219                      rgbp, gamv, lddyn, ldmax, fname, pp->fp) != TM_E_OK)
00220               return(-1);
00221                                    /* figure out TIFF orientation */
00222        for (orient = 8; --orient; )
00223               if (ortab[orient] == pp->rs.rt)
00224                      break;
00225        orient++;
00226                                    /* put out our image */
00227        if (putimage(orient, (uint32)xsiz, (uint32)ysiz,
00228                      72., 72./paspect, 2, pix) != 0)
00229               return(-1);
00230                                    /* free data and we're done */
00231        free((void *)pix);
00232        return(0);
00233 }
00234 
00235 
00236 static int
00237 tmap_tiff(                  /* tone map SGILOG TIFF */
00238        char   *fname,
00239        TIFF   *tp
00240 )
00241 {
00242        float  xres, yres;
00243        uint16 orient, resunit, phot;
00244        int    xsiz, ysiz;
00245        BYTE   *pix;
00246                                    /* check to make sure it's SGILOG */
00247        TIFFGetFieldDefaulted(tp, TIFFTAG_PHOTOMETRIC, &phot);
00248        if ((phot == PHOTOMETRIC_LOGL) | (phot == PHOTOMETRIC_MINISBLACK))
00249               flags |= TM_F_BW;
00250                                    /* read and tone map TIFF */
00251        if (tmMapTIFF(&pix, &xsiz, &ysiz, flags,
00252                      rgbp, gamv, lddyn, ldmax, fname, tp) != TM_E_OK)
00253               return(-1);
00254                                    /* get relevant tags */
00255        TIFFGetFieldDefaulted(tp, TIFFTAG_RESOLUTIONUNIT, &resunit);
00256        TIFFGetFieldDefaulted(tp, TIFFTAG_XRESOLUTION, &xres);
00257        TIFFGetFieldDefaulted(tp, TIFFTAG_YRESOLUTION, &yres);
00258        TIFFGetFieldDefaulted(tp, TIFFTAG_ORIENTATION, &orient);
00259                                    /* put out our image */
00260        if (putimage(orient, (uint32)xsiz, (uint32)ysiz,
00261                      xres, yres, resunit, pix) != 0)
00262               return(-1);
00263                                    /* free data and we're done */
00264        free((void *)pix);
00265        return(0);
00266 }
00267 
00268 
00269 static int
00270 putimage(     /* write out our image */
00271        uint16 or,
00272        uint32 xs,
00273        uint32 ys,
00274        float  xr,
00275        float  yr,
00276        uint16 ru,
00277        BYTE   *pd
00278 )
00279 {
00280        register int  y;
00281        uint32 rowsperstrip;
00282 
00283        TIFFSetField(tifout, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
00284        if (flags & TM_F_BW) {
00285               TIFFSetField(tifout, TIFFTAG_PHOTOMETRIC,
00286                             PHOTOMETRIC_MINISBLACK);
00287               TIFFSetField(tifout, TIFFTAG_SAMPLESPERPIXEL, 1);
00288        } else {
00289               TIFFSetField(tifout, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
00290               TIFFSetField(tifout, TIFFTAG_SAMPLESPERPIXEL, 3);
00291        }
00292        if (rgbp != stdprims) {
00293               TIFFSetField(tifout, TIFFTAG_PRIMARYCHROMATICITIES,
00294                             (float *)rgbp);
00295               TIFFSetField(tifout, TIFFTAG_WHITEPOINT, (float *)rgbp[WHT]);
00296        }
00297        TIFFSetField(tifout, TIFFTAG_BITSPERSAMPLE, 8);
00298        TIFFSetField(tifout, TIFFTAG_IMAGEWIDTH, xs);
00299        TIFFSetField(tifout, TIFFTAG_IMAGELENGTH, ys);
00300        TIFFSetField(tifout, TIFFTAG_RESOLUTIONUNIT, ru);
00301        TIFFSetField(tifout, TIFFTAG_COMPRESSION, comp);
00302        TIFFSetField(tifout, TIFFTAG_XRESOLUTION, xr);
00303        TIFFSetField(tifout, TIFFTAG_YRESOLUTION, yr);
00304        TIFFSetField(tifout, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
00305        TIFFSetField(tifout, TIFFTAG_ORIENTATION, or);
00306                                    /* compute good strip size */
00307        rowsperstrip = 8192/TIFFScanlineSize(tifout);
00308        if (rowsperstrip < 1) rowsperstrip = 1;
00309        TIFFSetField(tifout, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
00310                                    /* write out scanlines */
00311        if (flags & TM_F_BW) {
00312               for (y = 0; y < ys; y++)
00313                      if (TIFFWriteScanline(tifout, pd + y*xs, y, 0) < 0)
00314                             goto writerr;
00315        } else {
00316               for (y = 0; y < ys; y++)
00317                      if (TIFFWriteScanline(tifout, pd + y*3*xs, y, 0) < 0)
00318                             goto writerr;
00319        }
00320        return(0);                  /* all done! */
00321 writerr:
00322        fputs("Error writing TIFF output\n", stderr);
00323        return(-1);
00324 }