--- ray/src/px/ra_tiff.c 1995/10/30 10:56:57 2.8 +++ ray/src/px/ra_tiff.c 1997/07/24 11:47:05 2.9 @@ -1,36 +1,85 @@ -/* Copyright (c) 1991 Regents of the University of California */ +/* Copyright (c) 1997 Silicon Graphics, Inc. */ #ifndef lint -static char SCCSid[] = "$SunId$ LBL"; +static char SCCSid[] = "$SunId$ SGI"; #endif /* - * program to convert between RADIANCE and 24-bit TIFF files. + * Program to convert between RADIANCE and TIFF files. + * Added experimental LogLuv encodings 7/97 (GWL). */ #include - #include - #include "tiffio.h" - #include "color.h" - #include "resolu.h" - #define GAMCOR 2.2 /* default gamma */ -extern char *malloc(), *realloc(); +#ifndef malloc +extern char *malloc(); +#endif + /* 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_PRIM 0x80 /* has assigned primaries */ -int lzcomp = 0; /* use Lempel-Ziv compression? */ +struct { + uint16 flags; /* conversion flags (defined above) */ + uint16 comp; /* TIFF compression type */ + uint16 pconf; /* TIFF planar configuration */ + float gamcor; /* gamma correction value */ + short bradj; /* Radiance exposure adjustment (stops) */ + uint16 orient; /* visual orientation (TIFF spec.) */ + float 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 */ + float *fp; /* float pointer */ + char *p; /* generic pointer */ + } t; /* TIFF scanline */ + int (*tf)(); /* translation procedure */ +} cvts = { /* conversion structure */ + 0, COMPRESSION_NONE, PLANARCONFIG_CONTIG, GAMCOR, 0, +}; -int greyscale = 0; /* produce greyscale image? */ +#define CHK(f) (cvts.flags & (f)) +#define SET(f) (cvts.flags |= (f)) +#define CLR(f) (cvts.flags &= ~(f)) +#define TGL(f) (cvts.flags ^= (f)) -double gamcor = GAMCOR; /* gamma correction */ +int Luv2Color(), L2Color(), RGB2Colr(), Gry2Colr(); +int Color2Luv(), Color2L(), Colr2RGB(), Colr2Gry(); -int bradj = 0; /* brightness adjustment */ +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] + char *progname; @@ -46,21 +95,30 @@ char *argv[]; for (i = 1; i < argc; i++) if (argv[i][0] == '-') switch (argv[i][1]) { - case 'g': - gamcor = atof(argv[++i]); + case 'g': /* gamma correction */ + cvts.gamcor = atof(argv[++i]); break; - case 'z': - lzcomp = !lzcomp; + case 'x': /* XYZE Radiance output */ + TGL(C_XYZE); break; - case 'b': - greyscale = !greyscale; + case 'z': /* LZW compressed output */ + cvts.comp = COMPRESSION_LZW; break; - case 'e': + case 'L': /* LogLuv 32-bit output */ + cvts.comp = COMPRESSION_LOGLUV32; + break; + case 'l': /* LogLuv 24-bit output */ + cvts.comp = COMPRESSION_LOGLUV24; + break; + case 'b': /* greyscale output? */ + TGL(C_GRY); + break; + case 'e': /* exposure adjustment */ if (argv[i+1][0] != '+' && argv[i+1][0] != '-') goto userr; - bradj = atoi(argv[++i]); + cvts.bradj = atoi(argv[++i]); break; - case 'r': + case 'r': /* reverse conversion? */ reverse = !reverse; break; case '\0': @@ -71,24 +129,33 @@ char *argv[]; else break; doneopts: - setcolrgam(gamcor); + if (reverse) { - if (reverse) if (i != argc-2 && i != argc-1) goto userr; - else - tiff2ra(argv[i], argv[i+1]); - else + + tiff2ra(i, argv); + + } else { + if (i != argc-2) goto userr; - else - ra2tiff(argv[i], argv[i+1]); + if (CHK(C_GRY) && (cvts.comp == COMPRESSION_LOGLUV24 || + cvts.comp == COMPRESSION_LOGLUV32)) + cvts.comp = COMPRESSION_LOGL16; + + ra2tiff(i, argv); + } + exit(0); userr: fprintf(stderr, - "Usage: %s [-r][-b][-z][-e +/-stops][-g gamma] input output\n", + "Usage: %s [-z|-L|-l][-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); } @@ -104,162 +171,563 @@ char *err; } -tiff2ra(inpf, outf) /* convert TIFF file to Radiance picture */ -char *inpf, *outf; +allocbufs() /* allocate scanline buffers */ { - unsigned long xmax, ymax; - TIFF *tif; - unsigned short pconfig, nsamps; - unsigned short hi; - register BYTE *scanin; - register COLR *scanout; - register int x; - int y; - /* open/check TIFF file */ - if ((tif = TIFFOpen(inpf, "r")) == NULL) - quiterr("cannot open TIFF input"); - if (!TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &nsamps) || - (nsamps != 1 && nsamps != 3)) - quiterr("unsupported samples per pixel"); - if (!TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &hi) || hi != 8) - quiterr("unsupported bits per sample"); - if (TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &hi) && - hi != (nsamps==1 ? PHOTOMETRIC_MINISBLACK : - PHOTOMETRIC_RGB)) + int rsiz, tsiz; + + rsiz = CHK(C_RFLT) ? sizeof(COLOR) : sizeof(COLR); + tsiz = (CHK(C_TFLT) ? sizeof(float) : 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"); +} + + +initfromtif() /* initialize conversion from TIFF input */ +{ + uint16 hi; + float *fa, f1, f2; + + CLR(C_GRY|C_GAMMA|C_PRIM|C_RFLT|C_TFLT|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; + else + cvts.pixrat = 1.; + + if (!TIFFGetFieldDefaulted(cvts.tif, TIFFTAG_ORIENTATION, &cvts.orient)) + cvts.orient = 1; + + switch (cvts.comp) { + case COMPRESSION_LOGL16: + SET(C_GRY|C_RFLT|C_TFLT|C_GAMUT); + cvts.pconf = PLANARCONFIG_CONTIG; + TIFFSetField(cvts.tif, TIFFTAG_LOGLUVDATAFMT, + LOGLUVDATAFMT_FLTY); + TIFFSetField(cvts.tif, TIFFTAG_SAMPLEFORMAT, + SAMPLEFORMAT_IEEEFP); + cvts.tf = L2Color; + break; + case COMPRESSION_LOGLUV24: + case COMPRESSION_LOGLUV32: + SET(C_RFLT|C_TFLT); + if (!CHK(C_XYZE)) { + cpcolormat(cvts.cmat, xyz2rgbmat); + SET(C_CXFM|C_GAMUT); + } else if (cvts.comp == COMPRESSION_LOGLUV32) + SET(C_GAMUT); + if (cvts.pconf != PLANARCONFIG_CONTIG) + quiterr("cannot handle separate Luv planes"); + TIFFSetField(cvts.tif, TIFFTAG_LOGLUVDATAFMT, + LOGLUVDATAFMT_FLTXYZ); + TIFFSetField(cvts.tif, TIFFTAG_SAMPLEFORMAT, + SAMPLEFORMAT_IEEEFP); + cvts.tf = Luv2Color; + break; + default: + SET(C_GAMMA|C_GAMUT); + setcolrgam(cvts.gamcor); + if (CHK(C_XYZE)) { + comprgb2xyzmat(cvts.cmat, + CHK(C_PRIM) ? cvts.prims : stdprims); + SET(C_CXFM); + } + if (!TIFFGetField(cvts.tif, TIFFTAG_SAMPLESPERPIXEL, &hi) || + (hi != 1 && hi != 3)) + quiterr("unsupported samples per pixel"); + if (hi == 1) { + SET(C_GRY); + cvts.pconf = PLANARCONFIG_CONTIG; + cvts.tf = Gry2Colr; + } else + cvts.tf = RGB2Colr; + if (!TIFFGetField(cvts.tif, TIFFTAG_BITSPERSAMPLE, &hi) || + hi != 8) + quiterr("unsupported bits per sample"); + break; + } + + if (TIFFGetField(cvts.tif, TIFFTAG_PHOTOMETRIC, &hi) && + hi != (CHK(C_GRY) ? PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_RGB)) quiterr("unsupported photometric interpretation"); - if (!TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &pconfig) || - (pconfig != PLANARCONFIG_CONTIG && - pconfig != PLANARCONFIG_SEPARATE)) - quiterr("unsupported planar configuration"); - if (!TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &xmax) || - !TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &ymax)) + + if (!TIFFGetField(cvts.tif, TIFFTAG_IMAGEWIDTH, &cvts.xmax) || + !TIFFGetField(cvts.tif, TIFFTAG_IMAGELENGTH, &cvts.ymax)) quiterr("unknown input image resolution"); - /* allocate scanlines */ - scanin = (BYTE *)malloc(TIFFScanlineSize(tif)); - scanout = (COLR *)malloc(xmax*sizeof(COLR)); - if (scanin == NULL || scanout == NULL) - quiterr("out of memory in tiff2ra"); - /* open output and write header */ - if (outf != NULL && strcmp(outf, "-") && - freopen(outf, "w", stdout) == NULL) - quiterr("cannot open Radiance output file"); - newheader("RADIANCE", stdout); - fputs(progname, stdout); - if (bradj) - printf(" -e %+d", bradj); - if (gamcor != GAMCOR) - printf(" -g %f", gamcor); - fputs(" -r\n", stdout); - fputformat(COLRFMT, stdout); - putchar('\n'); - fprtresolu((int)xmax, (int)ymax, stdout); - /* convert image */ - if (nsamps == 1) - pconfig = 1; - for (y = 0; y < ymax; y++) { - if (pconfig == 1) { - if (TIFFReadScanline(tif, scanin, y, 0) < 0) - goto readerr; - if (nsamps == 1) - for (x = 0; x < xmax; x++) - scanout[x][RED] = - scanout[x][GRN] = - scanout[x][BLU] = scanin[x]; - else - for (x = 0; x < xmax; x++) { - scanout[x][RED] = scanin[3*x]; - scanout[x][GRN] = scanin[3*x+1]; - scanout[x][BLU] = scanin[3*x+2]; - } - } else { - if (TIFFReadScanline(tif, scanin, y, 0) < 0) - goto readerr; - for (x = 0; x < xmax; x++) - scanout[x][RED] = scanin[x]; - if (TIFFReadScanline(tif, scanin, y, 1) < 0) - goto readerr; - for (x = 0; x < xmax; x++) - scanout[x][GRN] = scanin[x]; - if (TIFFReadScanline(tif, scanin, y, 2) < 0) - goto readerr; - for (x = 0; x < xmax; x++) - scanout[x][BLU] = scanin[x]; + + if (!TIFFGetField(cvts.tif, TIFFTAG_STONITS, &cvts.stonits)) + cvts.stonits = 1.; + /* add to Radiance header */ + if (cvts.pixrat < .99 || cvts.pixrat > 1.01) + fputaspect(cvts.pixrat, cvts.rfp); + if (CHK(C_XYZE)) { + fputexpos(pow(2.,(double)cvts.bradj)/cvts.stonits, cvts.rfp); + fputformat(CIEFMT, cvts.rfp); + } else { + if (CHK(C_PRIM)) + fputprims(cvts.prims, cvts.rfp); + fputexpos(WHTEFFICACY*pow(2.,(double)cvts.bradj)/cvts.stonits, + cvts.rfp); + fputformat(COLRFMT, cvts.rfp); + } + + allocbufs(); /* allocate scanline buffers */ +} + + +tiff2ra(ac, av) /* 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); +} + + +int +headline(s) /* process Radiance input header line */ +char *s; +{ + char fmt[32]; + + 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; + } + if (isexpos(s)) { + cvts.stonits /= exposval(s); + return; + } + if (isaspect(s)) { + cvts.pixrat *= aspectval(s); + return; + } + if (isprims(s)) { + primsval(cvts.prims, s); + SET(C_PRIM); + return; + } +} + + +initfromrad() /* initialize input from a Radiance picture */ +{ + int i1, i2, po; + /* read Radiance header */ + CLR(C_RFLT|C_TFLT|C_XYZE|C_PRIM|C_GAMMA|C_CXFM); + 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; } - gambs_colrs(scanout, xmax); - if (bradj) - shiftcolrs(scanout, xmax, bradj); - if (fwritecolrs(scanout, xmax, stdout) < 0) - quiterr("error writing Radiance picture"); + 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); + + switch (cvts.comp) { + case COMPRESSION_LOGL16: + SET(C_GRY|C_RFLT|C_TFLT); + TIFFSetField(cvts.tif, TIFFTAG_LOGLUVDATAFMT, + LOGLUVDATAFMT_FLTY); + TIFFSetField(cvts.tif, TIFFTAG_SAMPLEFORMAT, + SAMPLEFORMAT_IEEEFP); + cvts.tf = Color2L; + break; + case COMPRESSION_LOGLUV24: + case COMPRESSION_LOGLUV32: + SET(C_RFLT|C_TFLT); + CLR(C_GRY); + if (!CHK(C_XYZE)) { + cpcolormat(cvts.cmat, rgb2xyzmat); + SET(C_CXFM); + } + TIFFSetField(cvts.tif, TIFFTAG_LOGLUVDATAFMT, + LOGLUVDATAFMT_FLTXYZ); + TIFFSetField(cvts.tif, TIFFTAG_SAMPLEFORMAT, + SAMPLEFORMAT_IEEEFP); + cvts.tf = Color2Luv; + break; + default: + SET(C_GAMMA|C_GAMUT); + setcolrgam(cvts.gamcor); + if (CHK(C_XYZE)) { + compxyz2rgbmat(cvts.cmat, + CHK(C_PRIM) ? cvts.prims : stdprims); + SET(C_CXFM); + } + if (CHK(C_GRY)) + cvts.tf = Colr2Gry; + else + cvts.tf = Colr2RGB; + if (CHK(C_PRIM)) { + TIFFSetField(cvts.tif, TIFFTAG_PRIMARYCHROMATICITIES, + (float *)cvts.prims); + TIFFSetField(cvts.tif, TIFFTAG_WHITEPOINT, + (float *)cvts.prims[WHT]); + } + 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 : 8); + TIFFSetField(cvts.tif, TIFFTAG_PHOTOMETRIC, + CHK(C_GRY) ? PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_RGB); + 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)); + i1 = TIFFScanlineSize(cvts.tif); + i2 = 8192/i1; /* compute good strip size */ + if (i2 < 1) i2 = 1; + TIFFSetField(cvts.tif, TIFFTAG_ROWSPERSTRIP, (uint32)i2); + + allocbufs(); /* allocate scanline buffers */ +} + + +ra2tiff(ac, av) /* 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 */ - free((char *)scanin); - free((char *)scanout); - TIFFClose(tif); + TIFFClose(cvts.tif); + fclose(cvts.rfp); +} + + +int +Luv2Color(y) /* read/convert/write Luv->COLOR scanline */ +uint32 y; +{ + register int x; + + if (CHK(C_RFLT|C_TFLT) != (C_RFLT|C_TFLT) | CHK(C_GRY)) + quiterr("internal error 1 in Luv2Color"); + + if (TIFFReadScanline(cvts.tif, cvts.t.p, y, 0) < 0) + quiterr("error reading TIFF input"); + + for (x = cvts.xmax; x--; ) { + cvts.r.colors[x][RED] = cvts.t.fp[3*x]; + cvts.r.colors[x][GRN] = cvts.t.fp[3*x + 1]; + cvts.r.colors[x][BLU] = 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"); +} + + +int +L2Color(y) /* read/convert/write L16->COLOR scanline */ +uint32 y; +{ + register int x; + + if (CHK(C_RFLT|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"); + + for (x = cvts.xmax; x--; ) + cvts.r.colors[x][RED] = + cvts.r.colors[x][GRN] = + cvts.r.colors[x][BLU] = cvts.t.fp[x] > 0. ? cvts.t.fp[x] : 0.; + + if (fwritescan(cvts.r.colors, cvts.xmax, cvts.rfp) < 0) + quiterr("error writing Radiance picture"); +} + + +int +RGB2Colr(y) /* read/convert/write RGB->COLR scanline */ +uint32 y; +{ + COLOR ctmp; + register int x; + + if (CHK(C_RFLT|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, + (tidata_t)(cvts.t.bp + cvts.xmax), y, 1) < 0) + goto readerr; + if (TIFFReadScanline(cvts.tif, + (tidata_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"); } -ra2tiff(inpf, outf) /* convert Radiance file to 24-bit TIFF */ -char *inpf, *outf; +int +Gry2Colr(y) /* read/convert/write G8->COLR scanline */ +uint32 y; { - TIFF *tif; - int xmax, ymax; - BYTE *scanout; - COLR *scanin; register int x; - int y; - /* open Radiance file */ - if (strcmp(inpf, "-") && freopen(inpf, "r", stdin) == NULL) - quiterr("cannot open Radiance input file"); - if (checkheader(stdin, COLRFMT, NULL) < 0 || - fgetresolu(&xmax, &ymax, stdin) < 0) - quiterr("bad Radiance picture"); - /* open TIFF file */ - if ((tif = TIFFOpen(outf, "w")) == NULL) - quiterr("cannot open TIFF output"); - TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (unsigned long)xmax); - TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (unsigned long)ymax); - TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, greyscale ? 1 : 3); - TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); - TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, - greyscale ? PHOTOMETRIC_MINISBLACK : - PHOTOMETRIC_RGB); - TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); - if (lzcomp) - TIFFSetField(tif, TIFFTAG_COMPRESSION, - (unsigned short)COMPRESSION_LZW); - /* allocate scanlines */ - scanin = (COLR *)malloc(xmax*sizeof(COLR)); - scanout = (BYTE *)malloc(TIFFScanlineSize(tif)); - if (scanin == NULL || scanout == NULL) - quiterr("out of memory in ra2tiff"); - /* convert image */ - for (y = 0; y < ymax; y++) { - if (freadcolrs(scanin, xmax, stdin) < 0) - quiterr("error reading Radiance picture"); - if (bradj) - shiftcolrs(scanin, xmax, bradj); - if (greyscale) { - for (x = 0; x < xmax; x++) - scanin[x][GRN] = normbright(scanin[x]); - colrs_gambs(scanin, xmax); - for (x = 0; x < xmax; x++) - scanout[x] = scanin[x][GRN]; - } else { - colrs_gambs(scanin, xmax); - for (x = 0; x < xmax; x++) { - scanout[3*x] = scanin[x][RED]; - scanout[3*x+1] = scanin[x][GRN]; - scanout[3*x+2] = scanin[x][BLU]; - } + + if (CHK(C_RFLT|C_TFLT) | !CHK(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"); +} + + +int +Color2L(y) /* read/convert/write COLOR->L16 scanline */ +uint32 y; +{ + double m = pow(2.,(double)cvts.bradj); + register int x; + + if (CHK(C_RFLT|C_TFLT) != (C_RFLT|C_TFLT) | !CHK(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"); +} + + +int +Color2Luv(y) /* read/convert/write COLOR->Luv scanline */ +uint32 y; +{ + register int x; + + if (CHK(C_RFLT|C_TFLT) != (C_RFLT|C_TFLT) | CHK(C_GRY)) + 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); + } + + for (x = cvts.xmax; x--; ) { + cvts.t.fp[3*x] = colval(cvts.r.colors[x],RED); + cvts.t.fp[3*x+1] = colval(cvts.r.colors[x],GRN); + cvts.t.fp[3*x+2] = colval(cvts.r.colors[x],BLU); + } + + if (TIFFWriteScanline(cvts.tif, cvts.t.p, y, 0) < 0) + quiterr("error writing TIFF output"); +} + + +int +Colr2Gry(y) /* read/convert/write COLR->RGB scanline */ +uint32 y; +{ + register int x; + + if (CHK(C_RFLT|C_TFLT) | !CHK(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"); +} + + +int +Colr2RGB(y) /* read/convert/write COLR->RGB scanline */ +uint32 y; +{ + COLOR ctmp; + register int x; + + if (CHK(C_RFLT|C_TFLT|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)); } - if (TIFFWriteScanline(tif, scanout, y, 0) < 0) - quiterr("error writing TIFF output"); + 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]; } - /* clean up */ - free((char *)scanin); - free((char *)scanout); - TIFFClose(tif); + + if (TIFFWriteScanline(cvts.tif, cvts.t.p, y, 0) < 0) + quiterr("error writing TIFF output"); }