Logo Search packages:      
Sourcecode: radiance version File versions  Download package

ra_tiff.c

#ifndef lint
static const char RCSid[] = "$Id: ra_tiff.c,v 2.32 2005/08/19 02:31:32 greg Exp $";
#endif
/*
 *  Program to convert between RADIANCE and TIFF files.
 *  Added LogLuv encodings 7/97 (GWL).
 *  Added white-balance adjustment 10/01 (GW).
 */

#include  <stdio.h>
#include  <math.h>
#include  <ctype.h>
#include  <time.h>
#include  <string.h>

#include  "tiffio.h"
#include  "color.h"
#include  "resolu.h"

#define  GAMCOR         2.2         /* default gamma */

                        /* conversion flags */
#define C_CXFM          0x1         /* needs color transformation */
#define C_GAMUT         0x2         /* needs gamut mapping */
#define C_GAMMA         0x4         /* needs gamma correction */
#define C_GRY           0x8         /* TIFF is greyscale */
#define C_XYZE          0x10        /* Radiance is XYZE */
#define C_RFLT          0x20        /* Radiance data is float */
#define C_TFLT          0x40        /* TIFF data is float */
#define C_TWRD          0x80        /* TIFF data is 16-bit */
#define C_PRIM          0x100       /* has assigned primaries */

typedef void colcvf_t(uint32 y);

struct {
      uint16      flags;            /* conversion flags (defined above) */
      char  capdate[20];      /* capture date/time */
      char  owner[256]; /* content owner */
      uint16      comp;       /* TIFF compression type */
      uint16      phot;       /* TIFF photometric type */
      uint16      pconf;            /* TIFF planar configuration */
      float gamcor;           /* gamma correction value */
      short bradj;            /* Radiance exposure adjustment (stops) */
      uint16      orient;           /* visual orientation (TIFF spec.) */
      double      stonits;    /* input conversion to nits */
      float pixrat;           /* pixel aspect ratio */
      FILE  *rfp;       /* Radiance stream pointer */
      TIFF  *tif;       /* TIFF pointer */
      uint32      xmax, ymax; /* image dimensions */
      COLORMAT    cmat; /* color transformation matrix */
      RGBPRIMS    prims;      /* RGB primaries */
      union {
            COLR  *colrs;           /* 4-byte ???E pointer */
            COLOR *colors;    /* float array pointer */
            char  *p;         /* generic pointer */
      } r;              /* Radiance scanline */
      union {
            uint8 *bp;        /* byte pointer */
            uint16      *wp;        /* word pointer */
            float *fp;        /* float pointer */
            char  *p;         /* generic pointer */
      } t;              /* TIFF scanline */
      colcvf_t *tf;     /* translation procedure */
}     cvts = {    /* conversion structure */
      0, "", "", COMPRESSION_NONE, PHOTOMETRIC_RGB,
      PLANARCONFIG_CONTIG, GAMCOR, 0, 1, 1., 1.,
};

#define CHK(f)          (cvts.flags & (f))
#define SET(f)          (cvts.flags |= (f))
#define CLR(f)          (cvts.flags &= ~(f))
#define TGL(f)          (cvts.flags ^= (f))

static colcvf_t Luv2Color, L2Color, RGB2Colr, Gry2Colr;
static colcvf_t Color2Luv, Color2L, Colr2RGB, Colr2Gry;
static colcvf_t RRGGBB2Color, GGry2Color, Color2RRGGBB, Color2GGry;

static gethfunc headline;
static void quiterr(char *err);
static void allocbufs(void);
static void initfromtif(void);
static void tiff2ra(int  ac, char  *av[]);
static void initfromrad(void);
static void ra2tiff(int  ac, char  *av[]);



#define RfGfBf2Color    Luv2Color
#define Gryf2Color      L2Color
#define     Color2Gryf  Color2L
#define Color2RfGfBf    Color2Luv

short ortab[8] = {            /* orientation conversion table */
      YMAJOR|YDECR,
      YMAJOR|YDECR|XDECR,
      YMAJOR|XDECR,
      YMAJOR,
      YDECR,
      XDECR|YDECR,
      XDECR,
      0
};

#define pixorder()      ortab[cvts.orient-1]

extern char TMSTR[];    /* "CAPDATE=" from header.c */
char        OWNSTR[] = "OWNER=";

char  *progname;


int
main(int  argc, char  *argv[])
{
      int  reverse = 0;
      int  i;
      
      progname = argv[0];

      for (i = 1; i < argc; i++)
            if (argv[i][0] == '-')
                  switch (argv[i][1]) {
                  case 'g':         /* gamma correction */
                        cvts.gamcor = atof(argv[++i]);
                        break;
                  case 'x':         /* XYZE Radiance output */
                        TGL(C_XYZE);
                        break;
                  case 'z':         /* LZW compressed output */
                        cvts.comp = COMPRESSION_LZW;
                        break;
                  case 'L':         /* LogLuv 32-bit output */
                        cvts.comp = COMPRESSION_SGILOG;
                        cvts.phot = PHOTOMETRIC_LOGLUV;
                        break;
                  case 'l':         /* LogLuv 24-bit output */
                        cvts.comp = COMPRESSION_SGILOG24;
                        cvts.phot = PHOTOMETRIC_LOGLUV;
                        break;
                  case 'w':         /* 16-bit/primary output? */
                        TGL(C_TWRD);
                        break;
                  case 'f':         /* IEEE float output? */
                        TGL(C_TFLT);
                        break;
                  case 'b':         /* greyscale output? */
                        TGL(C_GRY);
                        break;
                  case 'e':         /* exposure adjustment */
                        if (argv[i+1][0] != '+' && argv[i+1][0] != '-')
                              goto userr;
                        cvts.bradj = atoi(argv[++i]);
                        break;
                  case 'r':         /* reverse conversion? */
                        reverse = !reverse;
                        break;
                  case '\0':
                        goto doneopts;
                  default:
                        goto userr;
                  }
            else
                  break;
doneopts:
      if (reverse) {

            if (i != argc-2 && i != argc-1)
                  goto userr;

            tiff2ra(i, argv);

      } else {

            if (i != argc-2)
                  goto userr;
                                    /* consistency checks */
            if (CHK(C_GRY)) {
                  if (cvts.phot == PHOTOMETRIC_RGB)
                        cvts.phot = PHOTOMETRIC_MINISBLACK;
                  else {
                        cvts.phot = PHOTOMETRIC_LOGL;
                        cvts.comp = COMPRESSION_SGILOG;
                  }
            }
            if (CHK(C_TWRD|C_TFLT) == (C_TWRD|C_TFLT))
                  goto userr;

            ra2tiff(i, argv);
      }

      exit(0);
userr:
      fprintf(stderr,
      "Usage: %s [-z|-L|-l|-f|-w][-b][-e +/-stops][-g gamma] {in.pic|-} out.tif\n",
                  progname);
      fprintf(stderr,
      "   Or: %s -r [-x][-e +/-stops][-g gamma] in.tif [out.pic|-]\n",
                  progname);
      exit(1);
}


static void
quiterr(          /* print message and exit */
      char  *err
)
{
      if (err != NULL) {
            fprintf(stderr, "%s: %s\n", progname, err);
            exit(1);
      }
      exit(0);
}


static void
allocbufs(void)               /* allocate scanline buffers */
{
      int   rsiz, tsiz;

      rsiz = CHK(C_RFLT) ? sizeof(COLOR) : sizeof(COLR);
      tsiz = (CHK(C_TFLT) ? sizeof(float) : 
                  CHK(C_TWRD) ? sizeof(uint16) : sizeof(uint8)) *
                  (CHK(C_GRY) ? 1 : 3);
      cvts.r.p = (char *)malloc(rsiz*cvts.xmax);
      cvts.t.p = (char *)malloc(tsiz*cvts.xmax);
      if ((cvts.r.p == NULL) | (cvts.t.p == NULL))
            quiterr("no memory to allocate scanline buffers");
}


static void
initfromtif(void)       /* initialize conversion from TIFF input */
{
      uint16      hi;
      char  *cp;
      float *fa, f1, f2;

      CLR(C_GRY|C_GAMMA|C_PRIM|C_RFLT|C_TFLT|C_TWRD|C_CXFM);

      TIFFGetFieldDefaulted(cvts.tif, TIFFTAG_PLANARCONFIG, &cvts.pconf);

      if (TIFFGetField(cvts.tif, TIFFTAG_PRIMARYCHROMATICITIES, &fa)) {
            cvts.prims[RED][CIEX] = fa[0];
            cvts.prims[RED][CIEY] = fa[1];
            cvts.prims[GRN][CIEX] = fa[2];
            cvts.prims[GRN][CIEY] = fa[3];
            cvts.prims[BLU][CIEX] = fa[4];
            cvts.prims[BLU][CIEY] = fa[5];
            cvts.prims[WHT][CIEX] = 1./3.;
            cvts.prims[WHT][CIEY] = 1./3.;
            if (TIFFGetField(cvts.tif, TIFFTAG_WHITEPOINT, &fa)) {
                  cvts.prims[WHT][CIEX] = fa[0];
                  cvts.prims[WHT][CIEY] = fa[1];
            }
            SET(C_PRIM);
      }

      if (!TIFFGetField(cvts.tif, TIFFTAG_COMPRESSION, &cvts.comp))
            cvts.comp = COMPRESSION_NONE;

      if (TIFFGetField(cvts.tif, TIFFTAG_XRESOLUTION, &f1) &&
                  TIFFGetField(cvts.tif, TIFFTAG_YRESOLUTION, &f2))
            cvts.pixrat = f1/f2;

      TIFFGetFieldDefaulted(cvts.tif, TIFFTAG_ORIENTATION, &cvts.orient);

      if (!TIFFGetFieldDefaulted(cvts.tif, TIFFTAG_PHOTOMETRIC, &cvts.phot))
            quiterr("TIFF has unspecified photometric type");

      switch (cvts.phot) {
      case PHOTOMETRIC_LOGLUV:
            SET(C_RFLT|C_TFLT);
            if (!CHK(C_XYZE)) {
                  cpcolormat(cvts.cmat, xyz2rgbmat);
                  SET(C_CXFM|C_GAMUT);
            } else if (cvts.comp == COMPRESSION_SGILOG)
                  SET(C_GAMUT);           /* may be outside XYZ gamut */
            if (cvts.pconf != PLANARCONFIG_CONTIG)
                  quiterr("cannot handle separate Luv planes");
            TIFFSetField(cvts.tif, TIFFTAG_SGILOGDATAFMT,
                        SGILOGDATAFMT_FLOAT);
            cvts.tf = Luv2Color;
            break;
      case PHOTOMETRIC_LOGL:
            SET(C_GRY|C_RFLT|C_TFLT|C_GAMUT);
            cvts.pconf = PLANARCONFIG_CONTIG;
            TIFFSetField(cvts.tif, TIFFTAG_SGILOGDATAFMT,
                        SGILOGDATAFMT_FLOAT);
            cvts.tf = L2Color;
            break;
      case PHOTOMETRIC_YCBCR:
            if (cvts.comp == COMPRESSION_JPEG &&
                        cvts.pconf == PLANARCONFIG_CONTIG) {
                  TIFFSetField(cvts.tif, TIFFTAG_JPEGCOLORMODE,
                              JPEGCOLORMODE_RGB);
                  cvts.phot = PHOTOMETRIC_RGB;
            } else
                  quiterr("unsupported photometric type");
            /* fall through */
      case PHOTOMETRIC_RGB:
            SET(C_GAMMA);
            setcolrgam(cvts.gamcor);
            if (CHK(C_XYZE)) {
                  comprgb2xyzWBmat(cvts.cmat,
                              CHK(C_PRIM) ? cvts.prims : stdprims);
                  SET(C_CXFM);
            }
            if (!TIFFGetField(cvts.tif, TIFFTAG_SAMPLESPERPIXEL, &hi) ||
                        hi != 3)
                  quiterr("unsupported samples per pixel for RGB");
            if (!TIFFGetField(cvts.tif, TIFFTAG_BITSPERSAMPLE, &hi))
                  hi = -1;
            switch (hi) {
            case 8:
                  cvts.tf = RGB2Colr;
                  break;
            case 16:
                  cvts.tf = RRGGBB2Color;
                  SET(C_RFLT|C_TWRD);
                  break;
            case 32:
                  cvts.tf = RfGfBf2Color;
                  SET(C_RFLT|C_TFLT);
                  break;
            default:
                  quiterr("unsupported bits per sample for RGB");
            }
            break;
      case PHOTOMETRIC_MINISBLACK:
            SET(C_GRY|C_GAMMA);
            setcolrgam(cvts.gamcor);
            cvts.pconf = PLANARCONFIG_CONTIG;
            if (!TIFFGetField(cvts.tif, TIFFTAG_SAMPLESPERPIXEL, &hi) ||
                        hi != 1)
                  quiterr("unsupported samples per pixel for greyscale");
            if (!TIFFGetField(cvts.tif, TIFFTAG_BITSPERSAMPLE, &hi))
                  hi = -1;
            switch (hi) {
            case 8:
                  cvts.tf = Gry2Colr;
                  break;
            case 16:
                  cvts.tf = GGry2Color;
                  SET(C_RFLT|C_TWRD);
                  break;
            case 32:
                  cvts.tf = Gryf2Color;
                  SET(C_RFLT|C_TFLT);
                  break;
            default:
                  quiterr("unsupported bits per sample for Gray");
            }
            break;
      default:
            quiterr("unsupported photometric type");
            break;
      }

      if (!TIFFGetField(cvts.tif, TIFFTAG_IMAGEWIDTH, &cvts.xmax) ||
            !TIFFGetField(cvts.tif, TIFFTAG_IMAGELENGTH, &cvts.ymax))
            quiterr("unknown input image resolution");

      if (!TIFFGetField(cvts.tif, TIFFTAG_STONITS, &cvts.stonits))
            cvts.stonits = -1.;

      if (!TIFFGetField(cvts.tif, TIFFTAG_DATETIME, &cp))
            cvts.capdate[0] = '\0';
      else {
            strncpy(cvts.capdate, cp, 19);
            cvts.capdate[19] = '\0';
      }
      if (!TIFFGetField(cvts.tif, TIFFTAG_ARTIST, &cp))
            cvts.owner[0] = '\0';
      else {
            strncpy(cvts.owner, cp, sizeof(cvts.owner));
            cvts.owner[sizeof(cvts.owner)-1] = '\0';
      }
                              /* add to Radiance header */
      if (cvts.pixrat < .99 || cvts.pixrat > 1.01)
            fputaspect(cvts.pixrat, cvts.rfp);
      if (CHK(C_XYZE)) {
            if (cvts.stonits > .0)
                  fputexpos(pow(2.,(double)cvts.bradj)/cvts.stonits, cvts.rfp);
            fputformat(CIEFMT, cvts.rfp);
      } else {
            if (CHK(C_PRIM))
                  fputprims(cvts.prims, cvts.rfp);
            if (cvts.stonits > .0)
                  fputexpos(WHTEFFICACY*pow(2.,(double)cvts.bradj)/cvts.stonits,
                              cvts.rfp);
            fputformat(COLRFMT, cvts.rfp);
      }
      if (cvts.capdate[0])
            fprintf(cvts.rfp, "%s %s\n", TMSTR, cvts.capdate);
      if (cvts.owner[0])
            fprintf(cvts.rfp, "%s %s\n", OWNSTR, cvts.owner);

      allocbufs();                  /* allocate scanline buffers */
}


static void
tiff2ra(          /* convert TIFF image to Radiance picture */
      int  ac,
      char  *av[]
)
{
      int32 y;
                              /* open TIFF input */
      if ((cvts.tif = TIFFOpen(av[ac], "r")) == NULL)
            quiterr("cannot open TIFF input");
                              /* open Radiance output */
      if (av[ac+1] == NULL || !strcmp(av[ac+1], "-"))
            cvts.rfp = stdout;
      else if ((cvts.rfp = fopen(av[ac+1], "w")) == NULL)
            quiterr("cannot open Radiance output picture");
                              /* start output header */
      newheader("RADIANCE", cvts.rfp);
      printargs(ac, av, cvts.rfp);

      initfromtif();                /* initialize conversion */

      fputc('\n', cvts.rfp);        /* finish Radiance header */
      fputresolu(pixorder(), (int)cvts.xmax, (int)cvts.ymax, cvts.rfp);

      for (y = 0; y < cvts.ymax; y++)           /* convert image */
            (*cvts.tf)(y);
                                    /* clean up */
      fclose(cvts.rfp);
      TIFFClose(cvts.tif);
}


static int
headline(               /* process Radiance input header line */
      char  *s,
      void  *p
)
{
      static int  tmstrlen = 0;
      static int  ownstrlen = 0;
      char  fmt[32];

      if (!tmstrlen)
            tmstrlen = strlen(TMSTR);
      if (!ownstrlen)
            ownstrlen = strlen(OWNSTR);
      if (formatval(fmt, s)) {
            if (!strcmp(fmt, COLRFMT))
                  CLR(C_XYZE);
            else if (!strcmp(fmt, CIEFMT))
                  SET(C_XYZE);
            else
                  quiterr("unrecognized input picture format");
            return(1);
      }
      if (isexpos(s)) {
            cvts.stonits /= exposval(s);
            return(1);
      }
      if (isaspect(s)) {
            cvts.pixrat *= aspectval(s);
            return(1);
      }
      if (isprims(s)) {
            primsval(cvts.prims, s);
            SET(C_PRIM);
            return(1);
      }
      if (isdate(s)) {
            if (s[tmstrlen] == ' ')
                  strncpy(cvts.capdate, s+tmstrlen+1, 19);
            else
                  strncpy(cvts.capdate, s+tmstrlen, 19);
            cvts.capdate[19] = '\0';
            return(1);
      }
      if (!strncmp(s, OWNSTR, ownstrlen)) {
            register char     *cp = s + ownstrlen;

            while (isspace(*cp))
                  ++cp;
            strncpy(cvts.owner, cp, sizeof(cvts.owner));
            cvts.owner[sizeof(cvts.owner)-1] = '\0';
            for (cp = cvts.owner; *cp; cp++)
                  ;
            while (cp > cvts.owner && isspace(cp[-1]))
                  *--cp = '\0';
            return(1);
      }
      return(0);
}


static void
initfromrad(void)             /* initialize input from a Radiance picture */
{
      int   i1, i2, po;
                                    /* read Radiance header */
      CLR(C_RFLT|C_XYZE|C_PRIM|C_GAMMA|C_CXFM);
      cvts.capdate[0] = '\0';
      cvts.owner[0] = '\0';
      cvts.stonits = 1.;
      cvts.pixrat = 1.;
      cvts.pconf = PLANARCONFIG_CONTIG;
      getheader(cvts.rfp, headline, NULL);
      if ((po = fgetresolu(&i1, &i2, cvts.rfp)) < 0)
            quiterr("bad Radiance picture");
      cvts.xmax = i1; cvts.ymax = i2;
      for (i1 = 0; i1 < 8; i1++)          /* interpret orientation */
            if (ortab[i1] == po) {
                  cvts.orient = i1 + 1;
                  break;
            }
      if (i1 >= 8)
            quiterr("internal error 1 in initfromrad");
      if (!(po & YMAJOR))
            cvts.pixrat = 1./cvts.pixrat;
      if (!CHK(C_XYZE))
            cvts.stonits *= WHTEFFICACY;
                                    /* set up conversion */
      TIFFSetField(cvts.tif, TIFFTAG_COMPRESSION, cvts.comp);
      TIFFSetField(cvts.tif, TIFFTAG_PHOTOMETRIC, cvts.phot);

      switch (cvts.phot) {
      case PHOTOMETRIC_LOGLUV:
            SET(C_RFLT|C_TFLT);
            CLR(C_GRY|C_TWRD);
            if (!CHK(C_XYZE)) {
                  comprgb2xyzWBmat(cvts.cmat,
                              CHK(C_PRIM) ? cvts.prims : stdprims);
                  SET(C_CXFM);
            }
            if (cvts.comp != COMPRESSION_SGILOG &&
                        cvts.comp != COMPRESSION_SGILOG24)
                  quiterr("internal error 2 in initfromrad");
            TIFFSetField(cvts.tif, TIFFTAG_SGILOGDATAFMT,
                        SGILOGDATAFMT_FLOAT);
            cvts.tf = Color2Luv;
            break;
      case PHOTOMETRIC_LOGL:
            SET(C_GRY|C_RFLT|C_TFLT);
            CLR(C_TWRD);
            if (cvts.comp != COMPRESSION_SGILOG)      
                  quiterr("internal error 3 in initfromrad");
            TIFFSetField(cvts.tif, TIFFTAG_SGILOGDATAFMT,
                        SGILOGDATAFMT_FLOAT);
            cvts.tf = Color2L;
            break;
      case PHOTOMETRIC_RGB:
            SET(C_GAMMA|C_GAMUT);
            CLR(C_GRY);
            setcolrgam(cvts.gamcor);
            if (CHK(C_XYZE)) {
                  compxyz2rgbWBmat(cvts.cmat,
                              CHK(C_PRIM) ? cvts.prims : stdprims);
                  SET(C_CXFM);
            }
            if (CHK(C_PRIM)) {
                  TIFFSetField(cvts.tif, TIFFTAG_PRIMARYCHROMATICITIES,
                              (float *)cvts.prims);
                  TIFFSetField(cvts.tif, TIFFTAG_WHITEPOINT,
                              (float *)cvts.prims[WHT]);
            }
            if (CHK(C_TWRD)) {
                  cvts.tf = Color2RRGGBB;
                  SET(C_RFLT);
            } else if (CHK(C_TFLT)) {
                  TIFFSetField(cvts.tif, TIFFTAG_SAMPLEFORMAT,
                              SAMPLEFORMAT_IEEEFP);
                  cvts.tf = Color2RfGfBf;
                  SET(C_RFLT);
                  CLR(C_GAMUT);
            } else
                  cvts.tf = Colr2RGB;
            break;
      case PHOTOMETRIC_MINISBLACK:
            SET(C_GRY|C_GAMMA|C_GAMUT);
            setcolrgam(cvts.gamcor);
            if (CHK(C_TWRD)) {
                  cvts.tf = Color2GGry;
                  SET(C_RFLT);
            } else if (CHK(C_TFLT)) {
                  TIFFSetField(cvts.tif, TIFFTAG_SAMPLEFORMAT,
                              SAMPLEFORMAT_IEEEFP);
                  cvts.tf = Color2Gryf;
                  SET(C_RFLT);
            } else
                  cvts.tf = Colr2Gry;
            break;
      default:
            quiterr("internal error 4 in initfromrad");
            break;
      }
                                    /* set other TIFF fields */
      TIFFSetField(cvts.tif, TIFFTAG_IMAGEWIDTH, cvts.xmax);
      TIFFSetField(cvts.tif, TIFFTAG_IMAGELENGTH, cvts.ymax);
      TIFFSetField(cvts.tif, TIFFTAG_SAMPLESPERPIXEL, CHK(C_GRY) ? 1 : 3);
      TIFFSetField(cvts.tif, TIFFTAG_BITSPERSAMPLE,
                  CHK(C_TFLT) ? 32 : CHK(C_TWRD) ? 16 : 8);
      TIFFSetField(cvts.tif, TIFFTAG_XRESOLUTION, 72.);
      TIFFSetField(cvts.tif, TIFFTAG_YRESOLUTION, 72./cvts.pixrat);
      TIFFSetField(cvts.tif, TIFFTAG_ORIENTATION, cvts.orient);
      TIFFSetField(cvts.tif, TIFFTAG_RESOLUTIONUNIT, 2);
      TIFFSetField(cvts.tif, TIFFTAG_PLANARCONFIG, cvts.pconf);
      TIFFSetField(cvts.tif, TIFFTAG_STONITS,
                  cvts.stonits/pow(2.,(double)cvts.bradj));
      if (cvts.capdate[0])
            TIFFSetField(cvts.tif, TIFFTAG_DATETIME, cvts.capdate);
      if (cvts.owner[0])
            TIFFSetField(cvts.tif, TIFFTAG_ARTIST, cvts.owner);
      if (cvts.comp == COMPRESSION_NONE)
            i1 = TIFFScanlineSize(cvts.tif);
      else
            i1 = 3*cvts.xmax; /* conservative guess */
      i2 = 8192/i1;                       /* compute good strip size */
      if (i2 < 1) i2 = 1;
      TIFFSetField(cvts.tif, TIFFTAG_ROWSPERSTRIP, (uint32)i2);

      allocbufs();                        /* allocate scanline buffers */
}


static void
ra2tiff(          /* convert Radiance picture to TIFF image */
      int  ac,
      char  *av[]
)
{
      uint32      y;
                                    /* open Radiance file */
      if (!strcmp(av[ac], "-"))
            cvts.rfp = stdin;
      else if ((cvts.rfp = fopen(av[ac], "r")) == NULL)
            quiterr("cannot open Radiance input picture");
                                    /* open TIFF file */
      if ((cvts.tif = TIFFOpen(av[ac+1], "w")) == NULL)
            quiterr("cannot open TIFF output");

      initfromrad();                      /* initialize conversion */

      for (y = 0; y < cvts.ymax; y++)           /* convert image */
            (*cvts.tf)(y);
                                    /* clean up */
      TIFFClose(cvts.tif);
      fclose(cvts.rfp);
}


static void
Luv2Color(              /* read/convert/write Luv->COLOR scanline */
      uint32      y
)
{
      register int      x;

      if (CHK(C_RFLT|C_TWRD|C_TFLT|C_GRY) != (C_RFLT|C_TFLT))
            quiterr("internal error 1 in Luv2Color");

      if (cvts.pconf != PLANARCONFIG_CONTIG)
            quiterr("cannot handle separate 32-bit color planes");

      if (TIFFReadScanline(cvts.tif, cvts.t.p, y, 0) < 0)
            quiterr("error reading TIFF input");
                              /* also works for float RGB */
      for (x = cvts.xmax; x--; ) {
            setcolor(cvts.r.colors[x], 
                        cvts.t.fp[3*x],
                        cvts.t.fp[3*x + 1],
                        cvts.t.fp[3*x + 2]);
            if (CHK(C_CXFM))
                  colortrans(cvts.r.colors[x], cvts.cmat,
                              cvts.r.colors[x]);
            if (CHK(C_GAMUT))
                  clipgamut(cvts.r.colors[x], cvts.t.fp[3*x + 1],
                              CGAMUT_LOWER, cblack, cwhite);
      }
      if (cvts.bradj) {
            double      m = pow(2.,(double)cvts.bradj);
            for (x = cvts.xmax; x--; )
                  scalecolor(cvts.r.colors[x], m);
      }

      if (fwritescan(cvts.r.colors, cvts.xmax, cvts.rfp) < 0)
            quiterr("error writing Radiance picture");
}


static void
RRGGBB2Color(                 /* read/convert/write RGB16->COLOR scanline */
      uint32      y
)
{
      int   dogamma = (cvts.gamcor < 0.99) | (cvts.gamcor > 1.01);
      register double   d;
      register int      x;

      if (CHK(C_RFLT|C_TWRD|C_TFLT|C_GRY) != (C_TWRD|C_RFLT))
            quiterr("internal error 1 in RRGGBB2Color");

      if (cvts.pconf != PLANARCONFIG_CONTIG)
            quiterr("cannot handle separate 16-bit color planes");

      if (TIFFReadScanline(cvts.tif, cvts.t.p, y, 0) < 0)
            quiterr("error reading TIFF input");
      
      for (x = cvts.xmax; x--; ) {
            d = (cvts.t.wp[3*x] + 0.5)*(1./(1L<<16));
            if (dogamma) d = pow(d, cvts.gamcor);
            colval(cvts.r.colors[x],RED) = d;
            d = (cvts.t.wp[3*x + 1] + 0.5)*(1./(1L<<16));
            if (dogamma) d = pow(d, cvts.gamcor);
            colval(cvts.r.colors[x],GRN) = d;
            d = (cvts.t.wp[3*x + 2] + 0.5)*(1./(1L<<16));
            if (dogamma) d = pow(d, cvts.gamcor);
            colval(cvts.r.colors[x],BLU) = d;
            if (CHK(C_CXFM))
                  colortrans(cvts.r.colors[x], cvts.cmat,
                              cvts.r.colors[x]);
      }
      if (cvts.bradj) {
            d = pow(2.,(double)cvts.bradj);
            for (x = cvts.xmax; x--; )
                  scalecolor(cvts.r.colors[x], d);
      }

      if (fwritescan(cvts.r.colors, cvts.xmax, cvts.rfp) < 0)
            quiterr("error writing Radiance picture");
}


static void
L2Color(                /* read/convert/write Lfloat->COLOR scanline */
      uint32      y
)
{
      float m = pow(2., (double)cvts.bradj);
      register int      x;

      if (CHK(C_RFLT|C_TWRD|C_TFLT|C_GRY) != (C_RFLT|C_TFLT|C_GRY))
            quiterr("internal error 1 in L2Color");

      if (TIFFReadScanline(cvts.tif, cvts.t.p, y, 0) < 0)
            quiterr("error reading TIFF input");
                              /* also works for float greyscale */
      for (x = cvts.xmax; x--; ) {
            register float    f = cvts.t.fp[x];
            if (cvts.bradj) f *= m;
            setcolor(cvts.r.colors[x], f, f, f);
      }
      if (fwritescan(cvts.r.colors, cvts.xmax, cvts.rfp) < 0)
            quiterr("error writing Radiance picture");
}


static void
RGB2Colr(               /* read/convert/write RGB->COLR scanline */
      uint32      y
)
{
      COLOR ctmp;
      register int      x;

      if (CHK(C_RFLT|C_TWRD|C_TFLT|C_GRY))
            quiterr("internal error 1 in RGB2Colr");

      if (cvts.pconf == PLANARCONFIG_CONTIG) {
            if (TIFFReadScanline(cvts.tif, cvts.t.p, y, 0) < 0)
                  goto readerr;
            for (x = cvts.xmax; x--; ) {
                  cvts.r.colrs[x][RED] = cvts.t.bp[3*x];
                  cvts.r.colrs[x][GRN] = cvts.t.bp[3*x + 1];
                  cvts.r.colrs[x][BLU] = cvts.t.bp[3*x + 2];
            }
      } else {
            if (TIFFReadScanline(cvts.tif, cvts.t.p, y, 0) < 0)
                  goto readerr;
            if (TIFFReadScanline(cvts.tif,
                        (tdata_t)(cvts.t.bp + cvts.xmax), y, 1) < 0)
                  goto readerr;
            if (TIFFReadScanline(cvts.tif,
                        (tdata_t)(cvts.t.bp + 2*cvts.xmax), y, 2) < 0)
                  goto readerr;
            for (x = cvts.xmax; x--; ) {
                  cvts.r.colrs[x][RED] = cvts.t.bp[x];
                  cvts.r.colrs[x][GRN] = cvts.t.bp[cvts.xmax + x];
                  cvts.r.colrs[x][BLU] = cvts.t.bp[2*cvts.xmax + x];
            }
      }

      gambs_colrs(cvts.r.colrs, cvts.xmax);
      if (CHK(C_CXFM))
            for (x = cvts.xmax; x--; ) {
                  colr_color(ctmp, cvts.r.colrs[x]);
                  colortrans(ctmp, cvts.cmat, ctmp);
                  if (CHK(C_GAMUT)) /* !CHK(C_XYZE) */
                        clipgamut(ctmp, bright(ctmp), CGAMUT_LOWER,
                                    cblack, cwhite);
                  setcolr(cvts.r.colrs[x], colval(ctmp,RED),
                              colval(ctmp,GRN), colval(ctmp,BLU));
            }
      if (cvts.bradj)
            shiftcolrs(cvts.r.colrs, cvts.xmax, cvts.bradj);

      if (fwritecolrs(cvts.r.colrs, cvts.xmax, cvts.rfp) < 0)
            quiterr("error writing Radiance picture");
      return;
readerr:
      quiterr("error reading TIFF input");
}


static void
Gry2Colr(               /* read/convert/write G8->COLR scanline */
      uint32      y
)
{
      register int      x;

      if (CHK(C_RFLT|C_TWRD|C_TFLT|C_GRY) != C_GRY)
            quiterr("internal error 1 in Gry2Colr");

      if (TIFFReadScanline(cvts.tif, cvts.t.p, y, 0) < 0)
            quiterr("error reading TIFF input");

      for (x = cvts.xmax; x--; )
            cvts.r.colrs[x][RED] =
            cvts.r.colrs[x][GRN] =
            cvts.r.colrs[x][BLU] = cvts.t.bp[x];

      gambs_colrs(cvts.r.colrs, cvts.xmax);
      if (cvts.bradj)
            shiftcolrs(cvts.r.colrs, cvts.xmax, cvts.bradj);

      if (fwritecolrs(cvts.r.colrs, cvts.xmax, cvts.rfp) < 0)
            quiterr("error writing Radiance picture");
}


static void
GGry2Color(             /* read/convert/write G16->COLOR scanline */
      uint32      y
)
{
      int   dogamma = (cvts.gamcor < 0.99) | (cvts.gamcor > 1.01);
      double      m;
      register double   d;
      register int      x;

      if (CHK(C_TFLT|C_TWRD|C_GRY|C_RFLT) != (C_GRY|C_RFLT|C_TWRD))
            quiterr("internal error 1 in GGry2Color");

      if (TIFFReadScanline(cvts.tif, cvts.t.p, y, 0) < 0)
            quiterr("error reading TIFF input");

      if (cvts.bradj)
            m = pow(2., (double)cvts.bradj);
      for (x = cvts.xmax; x--; ) {
            d = (cvts.t.wp[x] + 0.5)*(1./(1L<<16));
            if (dogamma) d = pow(d, cvts.gamcor);
            if (cvts.bradj) d *= m;
            colval(cvts.r.colors[x],RED) =
            colval(cvts.r.colors[x],GRN) =
            colval(cvts.r.colors[x],BLU) = d;
      }
      if (fwritescan(cvts.r.colors, cvts.xmax, cvts.rfp) < 0)
            quiterr("error writing Radiance picture");
}


static void
Color2GGry(             /* read/convert/write COLOR->G16 scanline */
      uint32      y
)
{
      int   dogamma = (cvts.gamcor < 0.99) | (cvts.gamcor > 1.01);
      float m = pow(2.,(double)cvts.bradj);
      register int      x;

      if (CHK(C_RFLT|C_TFLT|C_TWRD|C_GRY) != (C_RFLT|C_TWRD|C_GRY))
            quiterr("internal error 1 in Color2GGry");

      if (freadscan(cvts.r.colors, cvts.xmax, cvts.rfp) < 0)
            quiterr("error reading Radiance picture");

      for (x = cvts.xmax; x--; ) {
            register float    f = m*( CHK(C_XYZE) ?
                                    colval(cvts.r.colors[x],CIEY)
                                    : bright(cvts.r.colors[x]) );
            if (f <= 0)
                  cvts.t.wp[x] = 0;
            else if (f >= 1)
                  cvts.t.wp[x] = 0xffff;
            else if (dogamma)
                  cvts.t.wp[x] = (int)((float)(1L<<16) *
                                    pow(f, 1./cvts.gamcor));
            else
                  cvts.t.wp[x] = (int)((float)(1L<<16) * f);
      }

      if (TIFFWriteScanline(cvts.tif, cvts.t.p, y, 0) < 0)
            quiterr("error writing TIFF output");
}


static void
Color2L(                /* read/convert/write COLOR->Lfloat scanline */
      uint32      y
)
{
      float m = pow(2.,(double)cvts.bradj);
      register int      x;

      if (CHK(C_RFLT|C_TFLT|C_TWRD|C_GRY) != (C_RFLT|C_TFLT|C_GRY))
            quiterr("internal error 1 in Color2L");

      if (freadscan(cvts.r.colors, cvts.xmax, cvts.rfp) < 0)
            quiterr("error reading Radiance picture");

      for (x = cvts.xmax; x--; )
            cvts.t.fp[x] = m*( CHK(C_XYZE) ? colval(cvts.r.colors[x],CIEY)
                                    : bright(cvts.r.colors[x]) );

      if (TIFFWriteScanline(cvts.tif, cvts.t.p, y, 0) < 0)
            quiterr("error writing TIFF output");
}


static void
Color2Luv(              /* read/convert/write COLOR->Luv scanline */
      uint32      y
)
{
      register int      x;

      if (CHK(C_RFLT|C_TWRD|C_TFLT|C_GRY) != (C_RFLT|C_TFLT))
            quiterr("internal error 1 in Color2Luv");

      if (freadscan(cvts.r.colors, cvts.xmax, cvts.rfp) < 0)
            quiterr("error reading Radiance picture");

      if (CHK(C_CXFM))
            for (x = cvts.xmax; x--; )
                  colortrans(cvts.r.colors[x], cvts.cmat,
                              cvts.r.colors[x]);
      if (cvts.bradj) {
            double      m = pow(2.,(double)cvts.bradj);
            for (x = cvts.xmax; x--; )
                  scalecolor(cvts.r.colors[x], m);
      }
                              /* also works for float RGB */
      for (x = cvts.xmax; x--; ) {
            cvts.t.fp[3*x] = colval(cvts.r.colors[x],CIEX);
            cvts.t.fp[3*x+1] = colval(cvts.r.colors[x],CIEY);
            cvts.t.fp[3*x+2] = colval(cvts.r.colors[x],CIEZ);
      }

      if (TIFFWriteScanline(cvts.tif, cvts.t.p, y, 0) < 0)
            quiterr("error writing TIFF output");
}


static void
Color2RRGGBB(                 /* read/convert/write COLOR->RGB16 scanline */
      uint32      y
)
{
      int   dogamma = (cvts.gamcor < 0.99) | (cvts.gamcor > 1.01);
      float m = pow(2.,(double)cvts.bradj);
      register int      x, i;

      if (CHK(C_RFLT|C_TFLT|C_TWRD|C_GRY) != (C_RFLT|C_TWRD))
            quiterr("internal error 1 in Color2RRGGBB");

      if (freadscan(cvts.r.colors, cvts.xmax, cvts.rfp) < 0)
            quiterr("error reading Radiance picture");

      for (x = cvts.xmax; x--; ) {
          if (CHK(C_CXFM)) {
                  colortrans(cvts.r.colors[x], cvts.cmat,
                              cvts.r.colors[x]);
            if (CHK(C_GAMUT))
                  clipgamut(cvts.r.colors[x], bright(cvts.r.colors[x]),
                              CGAMUT_LOWER, cblack, cwhite);
          }
          for (i = 3; i--; ) {
            register float    f = m*colval(cvts.r.colors[x],i);
            if (f <= 0)
                  cvts.t.wp[3*x + i] = 0;
            else if (f >= 1)
                  cvts.t.wp[3*x + i] = 0xffff;
            else if (dogamma)
                  cvts.t.wp[3*x + i] = (int)((float)(1L<<16) *
                                    pow(f, 1./cvts.gamcor));
            else
                  cvts.t.wp[3*x + i] = (int)((float)(1L<<16)*f);
          }
      }

      if (TIFFWriteScanline(cvts.tif, cvts.t.p, y, 0) < 0)
            quiterr("error writing TIFF output");
}


static void
Colr2Gry(               /* read/convert/write COLR->RGB scanline */
      uint32      y
)
{
      register int      x;

      if (CHK(C_RFLT|C_TWRD|C_TFLT|C_GRY) != C_GRY)
            quiterr("internal error 1 in Colr2Gry");

      if (freadcolrs(cvts.r.colrs, cvts.xmax, cvts.rfp) < 0)
            quiterr("error reading Radiance picture");

      if (cvts.bradj)
            shiftcolrs(cvts.r.colrs, cvts.xmax, cvts.bradj);
      for (x = cvts.xmax; x--; )
            colval(cvts.r.colrs[x],CIEY) = normbright(cvts.r.colrs[x]);
      colrs_gambs(cvts.r.colrs, cvts.xmax);

      for (x = cvts.xmax; x--; )
            cvts.t.bp[x] = colval(cvts.r.colrs[x],CIEY);

      if (TIFFWriteScanline(cvts.tif, cvts.t.p, y, 0) < 0)
            quiterr("error writing TIFF output");
}


static void
Colr2RGB(               /* read/convert/write COLR->RGB scanline */
      uint32      y
)
{
      COLOR ctmp;
      register int      x;

      if (CHK(C_RFLT|C_TFLT|C_TWRD|C_GRY))
            quiterr("internal error 1 in Colr2RGB");

      if (freadcolrs(cvts.r.colrs, cvts.xmax, cvts.rfp) < 0)
            quiterr("error reading Radiance picture");

      if (cvts.bradj)
            shiftcolrs(cvts.r.colrs, cvts.xmax, cvts.bradj);
      if (CHK(C_CXFM))
            for (x = cvts.xmax; x--; ) {
                  colr_color(ctmp, cvts.r.colrs[x]);
                  colortrans(ctmp, cvts.cmat, ctmp);
                  if (CHK(C_GAMUT))
                        clipgamut(ctmp, bright(ctmp), CGAMUT,
                                    cblack, cwhite);
                  setcolr(cvts.r.colrs[x], colval(ctmp,RED),
                              colval(ctmp,GRN), colval(ctmp,BLU));
            }
      colrs_gambs(cvts.r.colrs, cvts.xmax);

      for (x = cvts.xmax; x--; ) {
            cvts.t.bp[3*x] = cvts.r.colrs[x][RED];
            cvts.t.bp[3*x+1] = cvts.r.colrs[x][GRN];
            cvts.t.bp[3*x+2] = cvts.r.colrs[x][BLU];
      }

      if (TIFFWriteScanline(cvts.tif, cvts.t.p, y, 0) < 0)
            quiterr("error writing TIFF output");
}

Generated by  Doxygen 1.6.0   Back to index