Back to index

radiance  4R0+20100331
tmaptiff.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: tmaptiff.c,v 3.8 2009/02/09 20:48:08 greg Exp $";
00003 #endif
00004 /*
00005  * Perform tone mapping on TIFF input.
00006  *
00007  * Externals declared in tmaptiff.h
00008  */
00009 
00010 #include "copyright.h"
00011 
00012 #include <stdio.h>
00013 #include <stdlib.h>
00014 #include "tmprivat.h"
00015 #include "tiffio.h"
00016 #include "tmaptiff.h"
00017 
00018                                    /* input cases we handle */
00019 #define TC_LOGLUV32  1
00020 #define TC_LOGLUV24  2
00021 #define TC_LOGL16    3
00022 #define TC_GRYFLOAT  4
00023 #define TC_RGBFLOAT  5
00024 #define TC_GRYSHORT  6
00025 #define TC_RGBSHORT  7
00026 
00027 /* figure out what kind of TIFF we have and if we can tone-map it */
00028 static int
00029 getTIFFtype(TIFF *tif)
00030 {
00031        uint16 comp, phot, pconf;
00032        uint16 samp_fmt, bits_samp;
00033        
00034        TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &pconf);
00035        if (pconf != PLANARCONFIG_CONTIG)
00036               return(0);
00037        TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &phot);
00038        TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &comp);
00039        TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLEFORMAT, &samp_fmt);
00040        TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bits_samp);
00041        switch (phot) {
00042        case PHOTOMETRIC_LOGLUV:
00043               if (comp == COMPRESSION_SGILOG)
00044                      return(TC_LOGLUV32);
00045               if (comp == COMPRESSION_SGILOG24)
00046                      return(TC_LOGLUV24);
00047               return(0);
00048        case PHOTOMETRIC_LOGL:
00049               if (comp == COMPRESSION_SGILOG)
00050                      return(TC_LOGL16);
00051               return(0);
00052        case PHOTOMETRIC_MINISBLACK:
00053               if (samp_fmt == SAMPLEFORMAT_UINT) {
00054                      if (bits_samp == 16)
00055                             return(TC_GRYSHORT);
00056                      return(0);
00057               }
00058               if (samp_fmt == SAMPLEFORMAT_IEEEFP) {
00059                      if (bits_samp == 8*sizeof(float))
00060                             return(TC_GRYFLOAT);
00061                      return(0);
00062               }
00063               return(0);
00064        case PHOTOMETRIC_RGB:
00065               if (samp_fmt == SAMPLEFORMAT_UINT) {
00066                      if (bits_samp == 16)
00067                             return(TC_RGBSHORT);
00068                      return(0);
00069               }
00070               if (samp_fmt == SAMPLEFORMAT_IEEEFP) {
00071                      if (bits_samp == 8*sizeof(float))
00072                             return(TC_RGBFLOAT);
00073                      return(0);
00074               }
00075               return(0);
00076        }
00077        return(0);
00078 }
00079 
00080 /* load and convert TIFF */
00081 int
00082 tmLoadTIFF(TMstruct *tms, TMbright **lpp, BYTE **cpp,
00083               int *xp, int *yp, char *fname, TIFF *tp)
00084 {
00085        char   *funcName = fname==NULL ? "tmLoadTIFF" : fname;
00086        RGBPRIMP      inppri = tms->monpri;
00087        RGBPRIMS      myprims;
00088        float  *fa;
00089        TIFF   *tif;
00090        int    err;
00091        union {uint16 *w; uint32 *l; float *f; MEM_PTR p;} sl;
00092        uint32 width, height;
00093        int    tcase;
00094        double stonits;
00095        int    y;
00096                                    /* check arguments */
00097        if (tms == NULL)
00098               returnErr(TM_E_TMINVAL);
00099        if ((lpp == NULL) | (xp == NULL) | (yp == NULL) |
00100                      ((fname == NULL) & (tp == NULL)))
00101               returnErr(TM_E_ILLEGAL);
00102                                    /* check/get TIFF tags */
00103        sl.p = NULL; *lpp = NULL;
00104        if (cpp != TM_NOCHROMP) *cpp = TM_NOCHROM;
00105        err = TM_E_BADFILE;
00106        if ((tif = tp) == NULL && (tif = TIFFOpen(fname, "r")) == NULL)
00107               returnErr(TM_E_BADFILE);
00108        tcase = getTIFFtype(tif);
00109        if (!tcase)
00110               goto done;
00111        if (!TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width) ||
00112                      !TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height))
00113               goto done;
00114        *xp = width; *yp = height;
00115        if (TIFFGetField(tif, TIFFTAG_PRIMARYCHROMATICITIES, &fa)) {
00116               myprims[RED][CIEX] = fa[0];
00117               myprims[RED][CIEY] = fa[1];
00118               myprims[GRN][CIEX] = fa[2];
00119               myprims[GRN][CIEY] = fa[3];
00120               myprims[BLU][CIEX] = fa[4];
00121               myprims[BLU][CIEY] = fa[5];
00122               myprims[WHT][CIEX] = 1./3.;
00123               myprims[WHT][CIEY] = 1./3.;
00124               if (TIFFGetField(tif, TIFFTAG_WHITEPOINT, &fa)) {
00125                      myprims[WHT][CIEX] = fa[0];
00126                      myprims[WHT][CIEY] = fa[1];
00127               }
00128               inppri = myprims;
00129        }
00130        if (!TIFFGetField(tif, TIFFTAG_STONITS, &stonits))
00131               stonits = 1.;
00132        switch (tcase) {            /* set up conversion */
00133        case TC_LOGLUV32:
00134        case TC_LOGLUV24:
00135               TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_RAW);
00136               sl.l = (uint32 *)malloc(width*sizeof(uint32));
00137               tmSetSpace(tms, TM_XYZPRIM, stonits, NULL);
00138               break;
00139        case TC_LOGL16:
00140               TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_16BIT);
00141               sl.w = (uint16 *)malloc(width*sizeof(uint16));
00142               tmSetSpace(tms, tms->monpri, stonits, NULL);
00143               break;
00144        case TC_RGBFLOAT:
00145               sl.f = (float *)malloc(width*3*sizeof(float));
00146               tmSetSpace(tms, inppri, stonits, NULL);
00147               break;
00148        case TC_GRYFLOAT:
00149               sl.f = (float *)malloc(width*sizeof(float));
00150               tmSetSpace(tms, tms->monpri, stonits, NULL);
00151               break;
00152        case TC_RGBSHORT:
00153               sl.w = (uint16 *)malloc(width*3*sizeof(uint16));
00154               tmSetSpace(tms, inppri, stonits, NULL);
00155               break;
00156        case TC_GRYSHORT:
00157               sl.w = (uint16 *)malloc(width*sizeof(uint16));
00158               tmSetSpace(tms, tms->monpri, stonits, NULL);
00159               break;
00160        default:
00161               err = TM_E_CODERR1;
00162               goto done;
00163        }
00164        *lpp = (TMbright *)malloc(width*height*sizeof(TMbright));
00165        if ((sl.p == NULL) | (*lpp == NULL)) {
00166               err = TM_E_NOMEM;
00167               goto done;
00168        }
00169        switch (tcase) {            /* allocate color if needed */
00170        case TC_LOGLUV32:
00171        case TC_LOGLUV24:
00172        case TC_RGBFLOAT:
00173        case TC_RGBSHORT:
00174               if (cpp == TM_NOCHROMP)
00175                      break;
00176               *cpp = (BYTE *)malloc(width*height*3*sizeof(BYTE));
00177               if (*cpp == NULL) {
00178                      err = TM_E_NOMEM;
00179                      goto done;
00180               }
00181               break;
00182        }
00183                                    /* read and convert each scanline */
00184        for (y = 0; y < height; y++) {
00185               if (TIFFReadScanline(tif, sl.p, y, 0) < 0) {
00186                      err = TM_E_BADFILE;
00187                      break;
00188               }
00189               switch (tcase) {
00190               case TC_LOGLUV32:
00191                      err = tmCvLuv32(tms, *lpp + y*width,
00192                             cpp==TM_NOCHROMP ? TM_NOCHROM : *cpp+y*3*width,
00193                                    sl.l, width);
00194                      break;
00195               case TC_LOGLUV24:
00196                      err = tmCvLuv24(tms, *lpp + y*width,
00197                             cpp==TM_NOCHROMP ? TM_NOCHROM : *cpp+y*3*width,
00198                                    sl.l, width);
00199                      break;
00200               case TC_LOGL16:
00201                      err = tmCvL16(tms, *lpp + y*width, sl.w, width);
00202                      break;
00203               case TC_RGBFLOAT:
00204                      err = tmCvColors(tms, *lpp + y*width,
00205                             cpp==TM_NOCHROMP ? TM_NOCHROM : *cpp+y*3*width,
00206                                    (COLOR *)sl.f, width);
00207                      break;
00208               case TC_GRYFLOAT:
00209                      err = tmCvGrays(tms, *lpp + y*width, sl.f, width);
00210                      break;
00211               case TC_RGBSHORT:
00212                      err = tmCvRGB48(tms, *lpp + y*width,
00213                             cpp==TM_NOCHROMP ? TM_NOCHROM : *cpp+y*3*width,
00214                                    (uint16 (*)[3])sl.w, width, DEFGAM);
00215                      break;
00216               case TC_GRYSHORT:
00217                      err = tmCvGray16(tms, *lpp + y*width,
00218                                    sl.w, width, DEFGAM);
00219                      break;
00220               default:
00221                      err = TM_E_CODERR1;
00222                      break;
00223               }
00224               if (err != TM_E_OK)
00225                      break;
00226        }
00227 done:                              /* clean up */
00228        if (tp == NULL)
00229               TIFFClose(tif);
00230        if (sl.p != NULL)
00231               free(sl.p);
00232        if (err != TM_E_OK) {              /* free buffers on error */
00233               if (*lpp != NULL)
00234                      free((MEM_PTR)*lpp);
00235               *lpp = NULL;
00236               if (cpp != TM_NOCHROMP) {
00237                      if (*cpp != TM_NOCHROM)
00238                             free((MEM_PTR)*cpp);
00239                      *cpp = NULL;
00240               }
00241               *xp = *yp = 0;
00242               returnErr(err);
00243        }
00244        returnOK;
00245 }
00246 
00247 
00248 /*
00249  * Load and tone-map a SGILOG TIFF.
00250  * Beware of greyscale input -- you must check the PHOTOMETRIC tag to
00251  * determine that the returned array contains only grey values, not RGB.
00252  * As in tmMapPicture(), grey values are also returned if flags&TM_F_BW.
00253  */
00254 int
00255 tmMapTIFF(BYTE **psp, int *xp, int *yp, int flags, RGBPRIMP monpri,
00256        double gamval, double Lddyn, double Ldmax, char *fname, TIFF *tp)
00257 {
00258        char   *funcName = fname==NULL ? "tmMapTIFF" : fname;
00259        TMstruct      *tms;
00260        TMbright      *lp;
00261        BYTE   *cp;
00262        int    err;
00263                                    /* check arguments */
00264        if ((psp == NULL) | (xp == NULL) | (yp == NULL) | (monpri == NULL) |
00265                      ((fname == NULL) & (tp == NULL)))
00266               returnErr(TM_E_ILLEGAL);
00267        if (gamval < MINGAM) gamval = DEFGAM;
00268        if (Lddyn < MINLDDYN) Lddyn = DEFLDDYN;
00269        if (Ldmax < MINLDMAX) Ldmax = DEFLDMAX;
00270        if (flags & TM_F_BW) monpri = stdprims;
00271                                    /* initialize tone mapping */
00272        if ((tms = tmInit(flags, monpri, gamval)) == NULL)
00273               returnErr(TM_E_NOMEM);
00274                                    /* load and convert TIFF */
00275        cp = TM_NOCHROM;
00276        err = tmLoadTIFF(tms, &lp, flags&TM_F_BW ? TM_NOCHROMP : &cp,
00277                      xp, yp, fname, tp);
00278        if (err != TM_E_OK) {
00279               tmDone(tms);
00280               return(err);
00281        }
00282        if (cp == TM_NOCHROM) {
00283               *psp = (BYTE *)malloc(*xp * *yp * sizeof(BYTE));
00284               if (*psp == NULL) {
00285                      free((MEM_PTR)lp);
00286                      tmDone(tms);
00287                      returnErr(TM_E_NOMEM);
00288               }
00289        } else
00290               *psp = cp;
00291                                    /* compute color mapping */
00292        err = tmAddHisto(tms, lp, *xp * *yp, 1);
00293        if (err != TM_E_OK)
00294               goto done;
00295        err = tmComputeMapping(tms, gamval, Lddyn, Ldmax);
00296        if (err != TM_E_OK)
00297               goto done;
00298                                    /* map pixels */
00299        err = tmMapPixels(tms, *psp, lp, cp, *xp * *yp);
00300 
00301 done:                              /* clean up */
00302        free((MEM_PTR)lp);
00303        tmDone(tms);
00304        if (err != TM_E_OK) {              /* free memory on error */
00305               free((MEM_PTR)*psp);
00306               *psp = NULL;
00307               *xp = *yp = 0;
00308               returnErr(err);
00309        }
00310        returnOK;
00311 }