ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_tiff.c
Revision: 2.34
Committed: Sat Dec 4 00:24:43 2010 UTC (13 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad4R2P2, rad5R0, rad5R1, rad4R2, rad4R1, rad4R2P1
Changes since 2.33: +4 -1 lines
Log Message:
Added binary mode setting

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.34 static const char RCSid[] = "$Id: ra_tiff.c,v 2.33 2008/11/10 19:08:19 greg Exp $";
3 greg 1.1 #endif
4     /*
5 gregl 2.9 * Program to convert between RADIANCE and TIFF files.
6 greg 2.20 * Added LogLuv encodings 7/97 (GWL).
7     * Added white-balance adjustment 10/01 (GW).
8 greg 1.1 */
9    
10     #include <stdio.h>
11 greg 2.3 #include <math.h>
12 greg 2.22 #include <ctype.h>
13 greg 2.24 #include <time.h>
14 schorsch 2.27 #include <string.h>
15    
16 greg 2.34 #include "platform.h"
17 greg 1.1 #include "tiffio.h"
18     #include "color.h"
19 greg 1.6 #include "resolu.h"
20    
21 greg 2.8 #define GAMCOR 2.2 /* default gamma */
22    
23 gregl 2.9 /* conversion flags */
24     #define C_CXFM 0x1 /* needs color transformation */
25     #define C_GAMUT 0x2 /* needs gamut mapping */
26     #define C_GAMMA 0x4 /* needs gamma correction */
27     #define C_GRY 0x8 /* TIFF is greyscale */
28     #define C_XYZE 0x10 /* Radiance is XYZE */
29     #define C_RFLT 0x20 /* Radiance data is float */
30     #define C_TFLT 0x40 /* TIFF data is float */
31 gwlarson 2.19 #define C_TWRD 0x80 /* TIFF data is 16-bit */
32     #define C_PRIM 0x100 /* has assigned primaries */
33 greg 1.1
34 schorsch 2.28 typedef void colcvf_t(uint32 y);
35    
36 gregl 2.9 struct {
37     uint16 flags; /* conversion flags (defined above) */
38 greg 2.22 char capdate[20]; /* capture date/time */
39     char owner[256]; /* content owner */
40 gregl 2.9 uint16 comp; /* TIFF compression type */
41 gregl 2.10 uint16 phot; /* TIFF photometric type */
42 gregl 2.9 uint16 pconf; /* TIFF planar configuration */
43     float gamcor; /* gamma correction value */
44     short bradj; /* Radiance exposure adjustment (stops) */
45     uint16 orient; /* visual orientation (TIFF spec.) */
46 gregl 2.11 double stonits; /* input conversion to nits */
47 gregl 2.9 float pixrat; /* pixel aspect ratio */
48     FILE *rfp; /* Radiance stream pointer */
49     TIFF *tif; /* TIFF pointer */
50     uint32 xmax, ymax; /* image dimensions */
51     COLORMAT cmat; /* color transformation matrix */
52     RGBPRIMS prims; /* RGB primaries */
53     union {
54     COLR *colrs; /* 4-byte ???E pointer */
55     COLOR *colors; /* float array pointer */
56     char *p; /* generic pointer */
57     } r; /* Radiance scanline */
58     union {
59     uint8 *bp; /* byte pointer */
60 gwlarson 2.18 uint16 *wp; /* word pointer */
61 gregl 2.9 float *fp; /* float pointer */
62     char *p; /* generic pointer */
63     } t; /* TIFF scanline */
64 schorsch 2.28 colcvf_t *tf; /* translation procedure */
65 gregl 2.9 } cvts = { /* conversion structure */
66 greg 2.22 0, "", "", COMPRESSION_NONE, PHOTOMETRIC_RGB,
67 gregl 2.10 PLANARCONFIG_CONTIG, GAMCOR, 0, 1, 1., 1.,
68 gregl 2.9 };
69 greg 1.4
70 gregl 2.9 #define CHK(f) (cvts.flags & (f))
71     #define SET(f) (cvts.flags |= (f))
72     #define CLR(f) (cvts.flags &= ~(f))
73     #define TGL(f) (cvts.flags ^= (f))
74 greg 1.5
75 schorsch 2.28 static colcvf_t Luv2Color, L2Color, RGB2Colr, Gry2Colr;
76     static colcvf_t Color2Luv, Color2L, Colr2RGB, Colr2Gry;
77     static colcvf_t RRGGBB2Color, GGry2Color, Color2RRGGBB, Color2GGry;
78    
79     static gethfunc headline;
80     static void quiterr(char *err);
81     static void allocbufs(void);
82     static void initfromtif(void);
83     static void tiff2ra(int ac, char *av[]);
84     static void initfromrad(void);
85     static void ra2tiff(int ac, char *av[]);
86    
87    
88 greg 2.21
89     #define RfGfBf2Color Luv2Color
90     #define Gryf2Color L2Color
91     #define Color2Gryf Color2L
92     #define Color2RfGfBf Color2Luv
93 greg 1.1
94 gregl 2.9 short ortab[8] = { /* orientation conversion table */
95     YMAJOR|YDECR,
96     YMAJOR|YDECR|XDECR,
97     YMAJOR|XDECR,
98     YMAJOR,
99     YDECR,
100     XDECR|YDECR,
101     XDECR,
102     0
103     };
104 greg 1.1
105 gregl 2.9 #define pixorder() ortab[cvts.orient-1]
106    
107 greg 2.22 extern char TMSTR[]; /* "CAPDATE=" from header.c */
108     char OWNSTR[] = "OWNER=";
109    
110 greg 1.1 char *progname;
111    
112 schorsch 2.27
113 schorsch 2.28 int
114     main(int argc, char *argv[])
115 greg 1.1 {
116     int reverse = 0;
117     int i;
118    
119     progname = argv[0];
120    
121     for (i = 1; i < argc; i++)
122     if (argv[i][0] == '-')
123     switch (argv[i][1]) {
124 gregl 2.9 case 'g': /* gamma correction */
125     cvts.gamcor = atof(argv[++i]);
126 greg 1.1 break;
127 gregl 2.9 case 'x': /* XYZE Radiance output */
128     TGL(C_XYZE);
129 greg 1.4 break;
130 gregl 2.9 case 'z': /* LZW compressed output */
131     cvts.comp = COMPRESSION_LZW;
132 greg 1.5 break;
133 gregl 2.9 case 'L': /* LogLuv 32-bit output */
134 gregl 2.10 cvts.comp = COMPRESSION_SGILOG;
135     cvts.phot = PHOTOMETRIC_LOGLUV;
136 gregl 2.9 break;
137     case 'l': /* LogLuv 24-bit output */
138 gregl 2.10 cvts.comp = COMPRESSION_SGILOG24;
139     cvts.phot = PHOTOMETRIC_LOGLUV;
140 gregl 2.9 break;
141 greg 2.21 case 'w': /* 16-bit/primary output? */
142     TGL(C_TWRD);
143     break;
144     case 'f': /* IEEE float output? */
145     TGL(C_TFLT);
146     break;
147 gregl 2.9 case 'b': /* greyscale output? */
148     TGL(C_GRY);
149     break;
150     case 'e': /* exposure adjustment */
151 greg 1.1 if (argv[i+1][0] != '+' && argv[i+1][0] != '-')
152     goto userr;
153 gregl 2.9 cvts.bradj = atoi(argv[++i]);
154 greg 1.1 break;
155 gregl 2.9 case 'r': /* reverse conversion? */
156 greg 1.1 reverse = !reverse;
157     break;
158     case '\0':
159     goto doneopts;
160     default:
161     goto userr;
162     }
163     else
164     break;
165     doneopts:
166 gregl 2.9 if (reverse) {
167 greg 1.1
168     if (i != argc-2 && i != argc-1)
169     goto userr;
170 gregl 2.9
171     tiff2ra(i, argv);
172    
173     } else {
174    
175 greg 1.1 if (i != argc-2)
176     goto userr;
177 greg 2.21 /* consistency checks */
178 schorsch 2.25 if (CHK(C_GRY)) {
179 gregl 2.10 if (cvts.phot == PHOTOMETRIC_RGB)
180     cvts.phot = PHOTOMETRIC_MINISBLACK;
181     else {
182     cvts.phot = PHOTOMETRIC_LOGL;
183     cvts.comp = COMPRESSION_SGILOG;
184     }
185 schorsch 2.25 }
186 greg 2.21 if (CHK(C_TWRD|C_TFLT) == (C_TWRD|C_TFLT))
187     goto userr;
188 gregl 2.9
189     ra2tiff(i, argv);
190     }
191    
192 greg 1.1 exit(0);
193     userr:
194 greg 1.4 fprintf(stderr,
195 greg 2.33 "Usage: %s [-z|-L|-l|-f|-w][-b][-e +/-stops][-g gamma] {in.hdr|-} out.tif\n",
196 greg 1.1 progname);
197 gregl 2.9 fprintf(stderr,
198 greg 2.33 " Or: %s -r [-x][-e +/-stops][-g gamma] in.tif [out.hdr|-]\n",
199 gregl 2.9 progname);
200 greg 1.1 exit(1);
201     }
202    
203    
204 schorsch 2.28 static void
205     quiterr( /* print message and exit */
206     char *err
207     )
208 greg 1.1 {
209     if (err != NULL) {
210     fprintf(stderr, "%s: %s\n", progname, err);
211     exit(1);
212     }
213     exit(0);
214     }
215    
216    
217 schorsch 2.28 static void
218     allocbufs(void) /* allocate scanline buffers */
219 greg 1.1 {
220 gregl 2.9 int rsiz, tsiz;
221    
222     rsiz = CHK(C_RFLT) ? sizeof(COLOR) : sizeof(COLR);
223 gwlarson 2.19 tsiz = (CHK(C_TFLT) ? sizeof(float) :
224     CHK(C_TWRD) ? sizeof(uint16) : sizeof(uint8)) *
225 gregl 2.9 (CHK(C_GRY) ? 1 : 3);
226     cvts.r.p = (char *)malloc(rsiz*cvts.xmax);
227     cvts.t.p = (char *)malloc(tsiz*cvts.xmax);
228 schorsch 2.26 if ((cvts.r.p == NULL) | (cvts.t.p == NULL))
229 gregl 2.9 quiterr("no memory to allocate scanline buffers");
230     }
231    
232    
233 schorsch 2.28 static void
234     initfromtif(void) /* initialize conversion from TIFF input */
235 gregl 2.9 {
236     uint16 hi;
237 greg 2.22 char *cp;
238 gregl 2.9 float *fa, f1, f2;
239    
240 greg 2.21 CLR(C_GRY|C_GAMMA|C_PRIM|C_RFLT|C_TFLT|C_TWRD|C_CXFM);
241 gregl 2.9
242     TIFFGetFieldDefaulted(cvts.tif, TIFFTAG_PLANARCONFIG, &cvts.pconf);
243    
244     if (TIFFGetField(cvts.tif, TIFFTAG_PRIMARYCHROMATICITIES, &fa)) {
245     cvts.prims[RED][CIEX] = fa[0];
246     cvts.prims[RED][CIEY] = fa[1];
247     cvts.prims[GRN][CIEX] = fa[2];
248     cvts.prims[GRN][CIEY] = fa[3];
249     cvts.prims[BLU][CIEX] = fa[4];
250     cvts.prims[BLU][CIEY] = fa[5];
251     cvts.prims[WHT][CIEX] = 1./3.;
252     cvts.prims[WHT][CIEY] = 1./3.;
253     if (TIFFGetField(cvts.tif, TIFFTAG_WHITEPOINT, &fa)) {
254     cvts.prims[WHT][CIEX] = fa[0];
255     cvts.prims[WHT][CIEY] = fa[1];
256     }
257     SET(C_PRIM);
258     }
259    
260     if (!TIFFGetField(cvts.tif, TIFFTAG_COMPRESSION, &cvts.comp))
261     cvts.comp = COMPRESSION_NONE;
262    
263     if (TIFFGetField(cvts.tif, TIFFTAG_XRESOLUTION, &f1) &&
264     TIFFGetField(cvts.tif, TIFFTAG_YRESOLUTION, &f2))
265     cvts.pixrat = f1/f2;
266    
267 gregl 2.10 TIFFGetFieldDefaulted(cvts.tif, TIFFTAG_ORIENTATION, &cvts.orient);
268 gregl 2.9
269 gregl 2.10 if (!TIFFGetFieldDefaulted(cvts.tif, TIFFTAG_PHOTOMETRIC, &cvts.phot))
270     quiterr("TIFF has unspecified photometric type");
271    
272     switch (cvts.phot) {
273     case PHOTOMETRIC_LOGLUV:
274 gregl 2.9 SET(C_RFLT|C_TFLT);
275     if (!CHK(C_XYZE)) {
276     cpcolormat(cvts.cmat, xyz2rgbmat);
277     SET(C_CXFM|C_GAMUT);
278 gregl 2.10 } else if (cvts.comp == COMPRESSION_SGILOG)
279 greg 2.29 SET(C_GAMUT); /* may be outside XYZ gamut */
280 gregl 2.9 if (cvts.pconf != PLANARCONFIG_CONTIG)
281     quiterr("cannot handle separate Luv planes");
282 gregl 2.10 TIFFSetField(cvts.tif, TIFFTAG_SGILOGDATAFMT,
283 gregl 2.12 SGILOGDATAFMT_FLOAT);
284 gregl 2.9 cvts.tf = Luv2Color;
285     break;
286 gregl 2.10 case PHOTOMETRIC_LOGL:
287     SET(C_GRY|C_RFLT|C_TFLT|C_GAMUT);
288     cvts.pconf = PLANARCONFIG_CONTIG;
289     TIFFSetField(cvts.tif, TIFFTAG_SGILOGDATAFMT,
290 gregl 2.12 SGILOGDATAFMT_FLOAT);
291 gregl 2.10 cvts.tf = L2Color;
292     break;
293 gregl 2.11 case PHOTOMETRIC_YCBCR:
294     if (cvts.comp == COMPRESSION_JPEG &&
295     cvts.pconf == PLANARCONFIG_CONTIG) {
296     TIFFSetField(cvts.tif, TIFFTAG_JPEGCOLORMODE,
297     JPEGCOLORMODE_RGB);
298     cvts.phot = PHOTOMETRIC_RGB;
299     } else
300     quiterr("unsupported photometric type");
301     /* fall through */
302 gregl 2.10 case PHOTOMETRIC_RGB:
303 gwlarson 2.18 SET(C_GAMMA);
304 gregl 2.9 setcolrgam(cvts.gamcor);
305     if (CHK(C_XYZE)) {
306 greg 2.20 comprgb2xyzWBmat(cvts.cmat,
307 gregl 2.9 CHK(C_PRIM) ? cvts.prims : stdprims);
308     SET(C_CXFM);
309     }
310     if (!TIFFGetField(cvts.tif, TIFFTAG_SAMPLESPERPIXEL, &hi) ||
311 gregl 2.10 hi != 3)
312     quiterr("unsupported samples per pixel for RGB");
313 greg 2.21 if (!TIFFGetField(cvts.tif, TIFFTAG_BITSPERSAMPLE, &hi))
314     hi = -1;
315     switch (hi) {
316     case 8:
317 gwlarson 2.18 cvts.tf = RGB2Colr;
318 greg 2.21 break;
319     case 16:
320 gwlarson 2.18 cvts.tf = RRGGBB2Color;
321 gwlarson 2.19 SET(C_RFLT|C_TWRD);
322 greg 2.21 break;
323     case 32:
324     cvts.tf = RfGfBf2Color;
325     SET(C_RFLT|C_TFLT);
326     break;
327     default:
328     quiterr("unsupported bits per sample for RGB");
329 gwlarson 2.18 }
330 gregl 2.9 break;
331 gregl 2.10 case PHOTOMETRIC_MINISBLACK:
332 gwlarson 2.18 SET(C_GRY|C_GAMMA);
333 gregl 2.15 setcolrgam(cvts.gamcor);
334 gregl 2.10 cvts.pconf = PLANARCONFIG_CONTIG;
335     if (!TIFFGetField(cvts.tif, TIFFTAG_SAMPLESPERPIXEL, &hi) ||
336     hi != 1)
337     quiterr("unsupported samples per pixel for greyscale");
338 greg 2.21 if (!TIFFGetField(cvts.tif, TIFFTAG_BITSPERSAMPLE, &hi))
339     hi = -1;
340     switch (hi) {
341     case 8:
342 gwlarson 2.18 cvts.tf = Gry2Colr;
343 greg 2.21 break;
344     case 16:
345 gwlarson 2.18 cvts.tf = GGry2Color;
346 gwlarson 2.19 SET(C_RFLT|C_TWRD);
347 greg 2.21 break;
348     case 32:
349     cvts.tf = Gryf2Color;
350     SET(C_RFLT|C_TFLT);
351     break;
352     default:
353     quiterr("unsupported bits per sample for Gray");
354 gwlarson 2.18 }
355 gregl 2.10 break;
356     default:
357     quiterr("unsupported photometric type");
358     break;
359 gregl 2.9 }
360    
361     if (!TIFFGetField(cvts.tif, TIFFTAG_IMAGEWIDTH, &cvts.xmax) ||
362     !TIFFGetField(cvts.tif, TIFFTAG_IMAGELENGTH, &cvts.ymax))
363 greg 1.1 quiterr("unknown input image resolution");
364 gregl 2.9
365     if (!TIFFGetField(cvts.tif, TIFFTAG_STONITS, &cvts.stonits))
366 greg 2.32 cvts.stonits = -1.;
367 greg 2.22
368     if (!TIFFGetField(cvts.tif, TIFFTAG_DATETIME, &cp))
369     cvts.capdate[0] = '\0';
370     else {
371     strncpy(cvts.capdate, cp, 19);
372     cvts.capdate[19] = '\0';
373     }
374     if (!TIFFGetField(cvts.tif, TIFFTAG_ARTIST, &cp))
375     cvts.owner[0] = '\0';
376     else {
377     strncpy(cvts.owner, cp, sizeof(cvts.owner));
378     cvts.owner[sizeof(cvts.owner)-1] = '\0';
379     }
380 gregl 2.9 /* add to Radiance header */
381     if (cvts.pixrat < .99 || cvts.pixrat > 1.01)
382     fputaspect(cvts.pixrat, cvts.rfp);
383     if (CHK(C_XYZE)) {
384 greg 2.32 if (cvts.stonits > .0)
385     fputexpos(pow(2.,(double)cvts.bradj)/cvts.stonits, cvts.rfp);
386 gregl 2.9 fputformat(CIEFMT, cvts.rfp);
387     } else {
388     if (CHK(C_PRIM))
389     fputprims(cvts.prims, cvts.rfp);
390 greg 2.32 if (cvts.stonits > .0)
391     fputexpos(WHTEFFICACY*pow(2.,(double)cvts.bradj)/cvts.stonits,
392     cvts.rfp);
393 gregl 2.9 fputformat(COLRFMT, cvts.rfp);
394     }
395 greg 2.22 if (cvts.capdate[0])
396     fprintf(cvts.rfp, "%s %s\n", TMSTR, cvts.capdate);
397     if (cvts.owner[0])
398     fprintf(cvts.rfp, "%s %s\n", OWNSTR, cvts.owner);
399 gregl 2.9
400     allocbufs(); /* allocate scanline buffers */
401     }
402    
403    
404 schorsch 2.28 static void
405     tiff2ra( /* convert TIFF image to Radiance picture */
406     int ac,
407     char *av[]
408     )
409 gregl 2.9 {
410     int32 y;
411     /* open TIFF input */
412     if ((cvts.tif = TIFFOpen(av[ac], "r")) == NULL)
413     quiterr("cannot open TIFF input");
414     /* open Radiance output */
415     if (av[ac+1] == NULL || !strcmp(av[ac+1], "-"))
416     cvts.rfp = stdout;
417     else if ((cvts.rfp = fopen(av[ac+1], "w")) == NULL)
418     quiterr("cannot open Radiance output picture");
419 greg 2.34 SET_FILE_BINARY(cvts.rfp);
420 gregl 2.9 /* start output header */
421     newheader("RADIANCE", cvts.rfp);
422     printargs(ac, av, cvts.rfp);
423    
424     initfromtif(); /* initialize conversion */
425    
426     fputc('\n', cvts.rfp); /* finish Radiance header */
427     fputresolu(pixorder(), (int)cvts.xmax, (int)cvts.ymax, cvts.rfp);
428    
429     for (y = 0; y < cvts.ymax; y++) /* convert image */
430     (*cvts.tf)(y);
431     /* clean up */
432     fclose(cvts.rfp);
433     TIFFClose(cvts.tif);
434     }
435    
436    
437 schorsch 2.27 static int
438     headline( /* process Radiance input header line */
439     char *s,
440     void *p
441     )
442 gregl 2.9 {
443 greg 2.22 static int tmstrlen = 0;
444     static int ownstrlen = 0;
445 gregl 2.9 char fmt[32];
446    
447 greg 2.22 if (!tmstrlen)
448     tmstrlen = strlen(TMSTR);
449     if (!ownstrlen)
450     ownstrlen = strlen(OWNSTR);
451 gregl 2.9 if (formatval(fmt, s)) {
452     if (!strcmp(fmt, COLRFMT))
453     CLR(C_XYZE);
454     else if (!strcmp(fmt, CIEFMT))
455     SET(C_XYZE);
456     else
457     quiterr("unrecognized input picture format");
458 gwlarson 2.17 return(1);
459 gregl 2.9 }
460     if (isexpos(s)) {
461     cvts.stonits /= exposval(s);
462 gwlarson 2.17 return(1);
463 gregl 2.9 }
464     if (isaspect(s)) {
465     cvts.pixrat *= aspectval(s);
466 gwlarson 2.17 return(1);
467 gregl 2.9 }
468     if (isprims(s)) {
469     primsval(cvts.prims, s);
470     SET(C_PRIM);
471 gwlarson 2.17 return(1);
472 gregl 2.9 }
473 greg 2.22 if (isdate(s)) {
474     if (s[tmstrlen] == ' ')
475     strncpy(cvts.capdate, s+tmstrlen+1, 19);
476     else
477     strncpy(cvts.capdate, s+tmstrlen, 19);
478     cvts.capdate[19] = '\0';
479     return(1);
480     }
481     if (!strncmp(s, OWNSTR, ownstrlen)) {
482     register char *cp = s + ownstrlen;
483    
484     while (isspace(*cp))
485     ++cp;
486     strncpy(cvts.owner, cp, sizeof(cvts.owner));
487     cvts.owner[sizeof(cvts.owner)-1] = '\0';
488     for (cp = cvts.owner; *cp; cp++)
489     ;
490     while (cp > cvts.owner && isspace(cp[-1]))
491     *--cp = '\0';
492     return(1);
493     }
494 gwlarson 2.17 return(0);
495 gregl 2.9 }
496    
497    
498 schorsch 2.28 static void
499     initfromrad(void) /* initialize input from a Radiance picture */
500 gregl 2.9 {
501     int i1, i2, po;
502     /* read Radiance header */
503 greg 2.21 CLR(C_RFLT|C_XYZE|C_PRIM|C_GAMMA|C_CXFM);
504 greg 2.22 cvts.capdate[0] = '\0';
505     cvts.owner[0] = '\0';
506 gregl 2.9 cvts.stonits = 1.;
507     cvts.pixrat = 1.;
508     cvts.pconf = PLANARCONFIG_CONTIG;
509     getheader(cvts.rfp, headline, NULL);
510     if ((po = fgetresolu(&i1, &i2, cvts.rfp)) < 0)
511     quiterr("bad Radiance picture");
512     cvts.xmax = i1; cvts.ymax = i2;
513     for (i1 = 0; i1 < 8; i1++) /* interpret orientation */
514     if (ortab[i1] == po) {
515     cvts.orient = i1 + 1;
516     break;
517 greg 1.1 }
518 gregl 2.9 if (i1 >= 8)
519     quiterr("internal error 1 in initfromrad");
520     if (!(po & YMAJOR))
521     cvts.pixrat = 1./cvts.pixrat;
522     if (!CHK(C_XYZE))
523     cvts.stonits *= WHTEFFICACY;
524     /* set up conversion */
525     TIFFSetField(cvts.tif, TIFFTAG_COMPRESSION, cvts.comp);
526 gregl 2.10 TIFFSetField(cvts.tif, TIFFTAG_PHOTOMETRIC, cvts.phot);
527 gregl 2.9
528 gregl 2.10 switch (cvts.phot) {
529     case PHOTOMETRIC_LOGLUV:
530 gregl 2.9 SET(C_RFLT|C_TFLT);
531 greg 2.21 CLR(C_GRY|C_TWRD);
532 gregl 2.9 if (!CHK(C_XYZE)) {
533 greg 2.20 comprgb2xyzWBmat(cvts.cmat,
534     CHK(C_PRIM) ? cvts.prims : stdprims);
535 gregl 2.9 SET(C_CXFM);
536     }
537 gregl 2.10 if (cvts.comp != COMPRESSION_SGILOG &&
538     cvts.comp != COMPRESSION_SGILOG24)
539     quiterr("internal error 2 in initfromrad");
540     TIFFSetField(cvts.tif, TIFFTAG_SGILOGDATAFMT,
541 gregl 2.12 SGILOGDATAFMT_FLOAT);
542 gregl 2.9 cvts.tf = Color2Luv;
543     break;
544 gregl 2.10 case PHOTOMETRIC_LOGL:
545     SET(C_GRY|C_RFLT|C_TFLT);
546 greg 2.21 CLR(C_TWRD);
547 gregl 2.10 if (cvts.comp != COMPRESSION_SGILOG)
548     quiterr("internal error 3 in initfromrad");
549     TIFFSetField(cvts.tif, TIFFTAG_SGILOGDATAFMT,
550 gregl 2.12 SGILOGDATAFMT_FLOAT);
551 gregl 2.10 cvts.tf = Color2L;
552     break;
553     case PHOTOMETRIC_RGB:
554 gregl 2.9 SET(C_GAMMA|C_GAMUT);
555 gregl 2.10 CLR(C_GRY);
556 gregl 2.9 setcolrgam(cvts.gamcor);
557     if (CHK(C_XYZE)) {
558 greg 2.20 compxyz2rgbWBmat(cvts.cmat,
559 gregl 2.9 CHK(C_PRIM) ? cvts.prims : stdprims);
560     SET(C_CXFM);
561     }
562     if (CHK(C_PRIM)) {
563     TIFFSetField(cvts.tif, TIFFTAG_PRIMARYCHROMATICITIES,
564     (float *)cvts.prims);
565     TIFFSetField(cvts.tif, TIFFTAG_WHITEPOINT,
566     (float *)cvts.prims[WHT]);
567     }
568 greg 2.21 if (CHK(C_TWRD)) {
569     cvts.tf = Color2RRGGBB;
570     SET(C_RFLT);
571     } else if (CHK(C_TFLT)) {
572 greg 2.23 TIFFSetField(cvts.tif, TIFFTAG_SAMPLEFORMAT,
573     SAMPLEFORMAT_IEEEFP);
574 greg 2.21 cvts.tf = Color2RfGfBf;
575     SET(C_RFLT);
576 greg 2.29 CLR(C_GAMUT);
577 greg 2.21 } else
578     cvts.tf = Colr2RGB;
579 gregl 2.9 break;
580 gregl 2.10 case PHOTOMETRIC_MINISBLACK:
581     SET(C_GRY|C_GAMMA|C_GAMUT);
582     setcolrgam(cvts.gamcor);
583 greg 2.21 if (CHK(C_TWRD)) {
584     cvts.tf = Color2GGry;
585     SET(C_RFLT);
586     } else if (CHK(C_TFLT)) {
587 greg 2.23 TIFFSetField(cvts.tif, TIFFTAG_SAMPLEFORMAT,
588     SAMPLEFORMAT_IEEEFP);
589 greg 2.21 cvts.tf = Color2Gryf;
590     SET(C_RFLT);
591     } else
592     cvts.tf = Colr2Gry;
593 gregl 2.10 break;
594     default:
595     quiterr("internal error 4 in initfromrad");
596     break;
597 greg 1.1 }
598 gregl 2.9 /* set other TIFF fields */
599     TIFFSetField(cvts.tif, TIFFTAG_IMAGEWIDTH, cvts.xmax);
600     TIFFSetField(cvts.tif, TIFFTAG_IMAGELENGTH, cvts.ymax);
601     TIFFSetField(cvts.tif, TIFFTAG_SAMPLESPERPIXEL, CHK(C_GRY) ? 1 : 3);
602 greg 2.21 TIFFSetField(cvts.tif, TIFFTAG_BITSPERSAMPLE,
603     CHK(C_TFLT) ? 32 : CHK(C_TWRD) ? 16 : 8);
604 gregl 2.9 TIFFSetField(cvts.tif, TIFFTAG_XRESOLUTION, 72.);
605     TIFFSetField(cvts.tif, TIFFTAG_YRESOLUTION, 72./cvts.pixrat);
606     TIFFSetField(cvts.tif, TIFFTAG_ORIENTATION, cvts.orient);
607     TIFFSetField(cvts.tif, TIFFTAG_RESOLUTIONUNIT, 2);
608     TIFFSetField(cvts.tif, TIFFTAG_PLANARCONFIG, cvts.pconf);
609     TIFFSetField(cvts.tif, TIFFTAG_STONITS,
610     cvts.stonits/pow(2.,(double)cvts.bradj));
611 greg 2.22 if (cvts.capdate[0])
612     TIFFSetField(cvts.tif, TIFFTAG_DATETIME, cvts.capdate);
613     if (cvts.owner[0])
614     TIFFSetField(cvts.tif, TIFFTAG_ARTIST, cvts.owner);
615 gregl 2.10 if (cvts.comp == COMPRESSION_NONE)
616     i1 = TIFFScanlineSize(cvts.tif);
617     else
618     i1 = 3*cvts.xmax; /* conservative guess */
619 gregl 2.9 i2 = 8192/i1; /* compute good strip size */
620     if (i2 < 1) i2 = 1;
621     TIFFSetField(cvts.tif, TIFFTAG_ROWSPERSTRIP, (uint32)i2);
622    
623     allocbufs(); /* allocate scanline buffers */
624     }
625    
626    
627 schorsch 2.28 static void
628     ra2tiff( /* convert Radiance picture to TIFF image */
629     int ac,
630     char *av[]
631     )
632 gregl 2.9 {
633     uint32 y;
634     /* open Radiance file */
635     if (!strcmp(av[ac], "-"))
636     cvts.rfp = stdin;
637     else if ((cvts.rfp = fopen(av[ac], "r")) == NULL)
638     quiterr("cannot open Radiance input picture");
639 greg 2.34 SET_FILE_BINARY(cvts.rfp);
640 gregl 2.9 /* open TIFF file */
641     if ((cvts.tif = TIFFOpen(av[ac+1], "w")) == NULL)
642     quiterr("cannot open TIFF output");
643    
644     initfromrad(); /* initialize conversion */
645    
646     for (y = 0; y < cvts.ymax; y++) /* convert image */
647     (*cvts.tf)(y);
648 greg 1.1 /* clean up */
649 gregl 2.9 TIFFClose(cvts.tif);
650     fclose(cvts.rfp);
651     }
652    
653    
654 schorsch 2.28 static void
655     Luv2Color( /* read/convert/write Luv->COLOR scanline */
656     uint32 y
657     )
658 gregl 2.9 {
659     register int x;
660    
661 gwlarson 2.19 if (CHK(C_RFLT|C_TWRD|C_TFLT|C_GRY) != (C_RFLT|C_TFLT))
662 gregl 2.9 quiterr("internal error 1 in Luv2Color");
663    
664 greg 2.31 if (cvts.pconf != PLANARCONFIG_CONTIG)
665     quiterr("cannot handle separate 32-bit color planes");
666    
667 gregl 2.9 if (TIFFReadScanline(cvts.tif, cvts.t.p, y, 0) < 0)
668     quiterr("error reading TIFF input");
669 greg 2.21 /* also works for float RGB */
670 gregl 2.9 for (x = cvts.xmax; x--; ) {
671 greg 2.21 setcolor(cvts.r.colors[x],
672     cvts.t.fp[3*x],
673     cvts.t.fp[3*x + 1],
674     cvts.t.fp[3*x + 2]);
675 gregl 2.9 if (CHK(C_CXFM))
676     colortrans(cvts.r.colors[x], cvts.cmat,
677     cvts.r.colors[x]);
678     if (CHK(C_GAMUT))
679     clipgamut(cvts.r.colors[x], cvts.t.fp[3*x + 1],
680     CGAMUT_LOWER, cblack, cwhite);
681     }
682     if (cvts.bradj) {
683     double m = pow(2.,(double)cvts.bradj);
684     for (x = cvts.xmax; x--; )
685     scalecolor(cvts.r.colors[x], m);
686     }
687    
688     if (fwritescan(cvts.r.colors, cvts.xmax, cvts.rfp) < 0)
689     quiterr("error writing Radiance picture");
690     }
691    
692    
693 schorsch 2.28 static void
694     RRGGBB2Color( /* read/convert/write RGB16->COLOR scanline */
695     uint32 y
696     )
697 gwlarson 2.18 {
698 schorsch 2.26 int dogamma = (cvts.gamcor < 0.99) | (cvts.gamcor > 1.01);
699 gwlarson 2.18 register double d;
700     register int x;
701    
702 gwlarson 2.19 if (CHK(C_RFLT|C_TWRD|C_TFLT|C_GRY) != (C_TWRD|C_RFLT))
703 gwlarson 2.18 quiterr("internal error 1 in RRGGBB2Color");
704    
705 greg 2.31 if (cvts.pconf != PLANARCONFIG_CONTIG)
706     quiterr("cannot handle separate 16-bit color planes");
707    
708 gwlarson 2.18 if (TIFFReadScanline(cvts.tif, cvts.t.p, y, 0) < 0)
709     quiterr("error reading TIFF input");
710    
711     for (x = cvts.xmax; x--; ) {
712     d = (cvts.t.wp[3*x] + 0.5)*(1./(1L<<16));
713     if (dogamma) d = pow(d, cvts.gamcor);
714     colval(cvts.r.colors[x],RED) = d;
715     d = (cvts.t.wp[3*x + 1] + 0.5)*(1./(1L<<16));
716     if (dogamma) d = pow(d, cvts.gamcor);
717     colval(cvts.r.colors[x],GRN) = d;
718     d = (cvts.t.wp[3*x + 2] + 0.5)*(1./(1L<<16));
719     if (dogamma) d = pow(d, cvts.gamcor);
720     colval(cvts.r.colors[x],BLU) = d;
721     if (CHK(C_CXFM))
722     colortrans(cvts.r.colors[x], cvts.cmat,
723     cvts.r.colors[x]);
724     }
725     if (cvts.bradj) {
726     d = pow(2.,(double)cvts.bradj);
727     for (x = cvts.xmax; x--; )
728     scalecolor(cvts.r.colors[x], d);
729     }
730    
731     if (fwritescan(cvts.r.colors, cvts.xmax, cvts.rfp) < 0)
732     quiterr("error writing Radiance picture");
733     }
734    
735    
736 schorsch 2.28 static void
737     L2Color( /* read/convert/write Lfloat->COLOR scanline */
738     uint32 y
739     )
740 gregl 2.9 {
741 greg 2.21 float m = pow(2., (double)cvts.bradj);
742 gregl 2.9 register int x;
743    
744 gwlarson 2.19 if (CHK(C_RFLT|C_TWRD|C_TFLT|C_GRY) != (C_RFLT|C_TFLT|C_GRY))
745 gregl 2.9 quiterr("internal error 1 in L2Color");
746    
747     if (TIFFReadScanline(cvts.tif, cvts.t.p, y, 0) < 0)
748     quiterr("error reading TIFF input");
749 greg 2.21 /* also works for float greyscale */
750     for (x = cvts.xmax; x--; ) {
751     register float f = cvts.t.fp[x];
752     if (cvts.bradj) f *= m;
753     setcolor(cvts.r.colors[x], f, f, f);
754     }
755 gregl 2.9 if (fwritescan(cvts.r.colors, cvts.xmax, cvts.rfp) < 0)
756     quiterr("error writing Radiance picture");
757     }
758    
759    
760 schorsch 2.28 static void
761     RGB2Colr( /* read/convert/write RGB->COLR scanline */
762     uint32 y
763     )
764 gregl 2.9 {
765     COLOR ctmp;
766     register int x;
767    
768 gwlarson 2.19 if (CHK(C_RFLT|C_TWRD|C_TFLT|C_GRY))
769 gregl 2.9 quiterr("internal error 1 in RGB2Colr");
770    
771     if (cvts.pconf == PLANARCONFIG_CONTIG) {
772     if (TIFFReadScanline(cvts.tif, cvts.t.p, y, 0) < 0)
773     goto readerr;
774     for (x = cvts.xmax; x--; ) {
775     cvts.r.colrs[x][RED] = cvts.t.bp[3*x];
776     cvts.r.colrs[x][GRN] = cvts.t.bp[3*x + 1];
777     cvts.r.colrs[x][BLU] = cvts.t.bp[3*x + 2];
778     }
779     } else {
780     if (TIFFReadScanline(cvts.tif, cvts.t.p, y, 0) < 0)
781     goto readerr;
782     if (TIFFReadScanline(cvts.tif,
783 gregl 2.14 (tdata_t)(cvts.t.bp + cvts.xmax), y, 1) < 0)
784 gregl 2.9 goto readerr;
785     if (TIFFReadScanline(cvts.tif,
786 gregl 2.14 (tdata_t)(cvts.t.bp + 2*cvts.xmax), y, 2) < 0)
787 gregl 2.9 goto readerr;
788     for (x = cvts.xmax; x--; ) {
789     cvts.r.colrs[x][RED] = cvts.t.bp[x];
790     cvts.r.colrs[x][GRN] = cvts.t.bp[cvts.xmax + x];
791     cvts.r.colrs[x][BLU] = cvts.t.bp[2*cvts.xmax + x];
792     }
793     }
794    
795     gambs_colrs(cvts.r.colrs, cvts.xmax);
796     if (CHK(C_CXFM))
797     for (x = cvts.xmax; x--; ) {
798     colr_color(ctmp, cvts.r.colrs[x]);
799     colortrans(ctmp, cvts.cmat, ctmp);
800     if (CHK(C_GAMUT)) /* !CHK(C_XYZE) */
801     clipgamut(ctmp, bright(ctmp), CGAMUT_LOWER,
802     cblack, cwhite);
803     setcolr(cvts.r.colrs[x], colval(ctmp,RED),
804     colval(ctmp,GRN), colval(ctmp,BLU));
805     }
806     if (cvts.bradj)
807     shiftcolrs(cvts.r.colrs, cvts.xmax, cvts.bradj);
808    
809     if (fwritecolrs(cvts.r.colrs, cvts.xmax, cvts.rfp) < 0)
810     quiterr("error writing Radiance picture");
811 greg 1.1 return;
812     readerr:
813     quiterr("error reading TIFF input");
814     }
815    
816    
817 schorsch 2.28 static void
818     Gry2Colr( /* read/convert/write G8->COLR scanline */
819     uint32 y
820     )
821 greg 1.1 {
822     register int x;
823 gregl 2.9
824 gwlarson 2.19 if (CHK(C_RFLT|C_TWRD|C_TFLT|C_GRY) != C_GRY)
825 gregl 2.9 quiterr("internal error 1 in Gry2Colr");
826    
827     if (TIFFReadScanline(cvts.tif, cvts.t.p, y, 0) < 0)
828     quiterr("error reading TIFF input");
829    
830     for (x = cvts.xmax; x--; )
831     cvts.r.colrs[x][RED] =
832     cvts.r.colrs[x][GRN] =
833     cvts.r.colrs[x][BLU] = cvts.t.bp[x];
834    
835     gambs_colrs(cvts.r.colrs, cvts.xmax);
836     if (cvts.bradj)
837     shiftcolrs(cvts.r.colrs, cvts.xmax, cvts.bradj);
838    
839     if (fwritecolrs(cvts.r.colrs, cvts.xmax, cvts.rfp) < 0)
840     quiterr("error writing Radiance picture");
841     }
842    
843    
844 schorsch 2.28 static void
845     GGry2Color( /* read/convert/write G16->COLOR scanline */
846     uint32 y
847     )
848 gwlarson 2.18 {
849 schorsch 2.26 int dogamma = (cvts.gamcor < 0.99) | (cvts.gamcor > 1.01);
850 gwlarson 2.18 double m;
851     register double d;
852     register int x;
853    
854 gwlarson 2.19 if (CHK(C_TFLT|C_TWRD|C_GRY|C_RFLT) != (C_GRY|C_RFLT|C_TWRD))
855 gwlarson 2.18 quiterr("internal error 1 in GGry2Color");
856    
857     if (TIFFReadScanline(cvts.tif, cvts.t.p, y, 0) < 0)
858     quiterr("error reading TIFF input");
859    
860     if (cvts.bradj)
861     m = pow(2., (double)cvts.bradj);
862     for (x = cvts.xmax; x--; ) {
863     d = (cvts.t.wp[x] + 0.5)*(1./(1L<<16));
864     if (dogamma) d = pow(d, cvts.gamcor);
865     if (cvts.bradj) d *= m;
866     colval(cvts.r.colors[x],RED) =
867     colval(cvts.r.colors[x],GRN) =
868     colval(cvts.r.colors[x],BLU) = d;
869     }
870     if (fwritescan(cvts.r.colors, cvts.xmax, cvts.rfp) < 0)
871     quiterr("error writing Radiance picture");
872     }
873    
874    
875 schorsch 2.28 static void
876     Color2GGry( /* read/convert/write COLOR->G16 scanline */
877     uint32 y
878     )
879 greg 2.21 {
880 schorsch 2.26 int dogamma = (cvts.gamcor < 0.99) | (cvts.gamcor > 1.01);
881 greg 2.21 float m = pow(2.,(double)cvts.bradj);
882     register int x;
883    
884     if (CHK(C_RFLT|C_TFLT|C_TWRD|C_GRY) != (C_RFLT|C_TWRD|C_GRY))
885     quiterr("internal error 1 in Color2GGry");
886    
887     if (freadscan(cvts.r.colors, cvts.xmax, cvts.rfp) < 0)
888     quiterr("error reading Radiance picture");
889    
890     for (x = cvts.xmax; x--; ) {
891     register float f = m*( CHK(C_XYZE) ?
892     colval(cvts.r.colors[x],CIEY)
893     : bright(cvts.r.colors[x]) );
894     if (f <= 0)
895     cvts.t.wp[x] = 0;
896     else if (f >= 1)
897     cvts.t.wp[x] = 0xffff;
898     else if (dogamma)
899     cvts.t.wp[x] = (int)((float)(1L<<16) *
900     pow(f, 1./cvts.gamcor));
901     else
902     cvts.t.wp[x] = (int)((float)(1L<<16) * f);
903     }
904    
905     if (TIFFWriteScanline(cvts.tif, cvts.t.p, y, 0) < 0)
906     quiterr("error writing TIFF output");
907     }
908    
909    
910 schorsch 2.28 static void
911     Color2L( /* read/convert/write COLOR->Lfloat scanline */
912     uint32 y
913     )
914 gregl 2.9 {
915 greg 2.21 float m = pow(2.,(double)cvts.bradj);
916 gregl 2.9 register int x;
917    
918 gwlarson 2.19 if (CHK(C_RFLT|C_TFLT|C_TWRD|C_GRY) != (C_RFLT|C_TFLT|C_GRY))
919 gregl 2.9 quiterr("internal error 1 in Color2L");
920    
921     if (freadscan(cvts.r.colors, cvts.xmax, cvts.rfp) < 0)
922     quiterr("error reading Radiance picture");
923    
924     for (x = cvts.xmax; x--; )
925     cvts.t.fp[x] = m*( CHK(C_XYZE) ? colval(cvts.r.colors[x],CIEY)
926     : bright(cvts.r.colors[x]) );
927    
928     if (TIFFWriteScanline(cvts.tif, cvts.t.p, y, 0) < 0)
929     quiterr("error writing TIFF output");
930     }
931    
932    
933 schorsch 2.28 static void
934     Color2Luv( /* read/convert/write COLOR->Luv scanline */
935     uint32 y
936     )
937 gregl 2.9 {
938     register int x;
939    
940 gwlarson 2.19 if (CHK(C_RFLT|C_TWRD|C_TFLT|C_GRY) != (C_RFLT|C_TFLT))
941 gregl 2.9 quiterr("internal error 1 in Color2Luv");
942    
943     if (freadscan(cvts.r.colors, cvts.xmax, cvts.rfp) < 0)
944     quiterr("error reading Radiance picture");
945    
946     if (CHK(C_CXFM))
947     for (x = cvts.xmax; x--; )
948     colortrans(cvts.r.colors[x], cvts.cmat,
949     cvts.r.colors[x]);
950     if (cvts.bradj) {
951     double m = pow(2.,(double)cvts.bradj);
952     for (x = cvts.xmax; x--; )
953     scalecolor(cvts.r.colors[x], m);
954     }
955 greg 2.21 /* also works for float RGB */
956 gregl 2.9 for (x = cvts.xmax; x--; ) {
957 gwlarson 2.16 cvts.t.fp[3*x] = colval(cvts.r.colors[x],CIEX);
958     cvts.t.fp[3*x+1] = colval(cvts.r.colors[x],CIEY);
959     cvts.t.fp[3*x+2] = colval(cvts.r.colors[x],CIEZ);
960 gregl 2.9 }
961    
962     if (TIFFWriteScanline(cvts.tif, cvts.t.p, y, 0) < 0)
963     quiterr("error writing TIFF output");
964     }
965    
966    
967 schorsch 2.28 static void
968     Color2RRGGBB( /* read/convert/write COLOR->RGB16 scanline */
969     uint32 y
970     )
971 greg 2.21 {
972 schorsch 2.26 int dogamma = (cvts.gamcor < 0.99) | (cvts.gamcor > 1.01);
973 greg 2.21 float m = pow(2.,(double)cvts.bradj);
974     register int x, i;
975    
976     if (CHK(C_RFLT|C_TFLT|C_TWRD|C_GRY) != (C_RFLT|C_TWRD))
977     quiterr("internal error 1 in Color2RRGGBB");
978    
979     if (freadscan(cvts.r.colors, cvts.xmax, cvts.rfp) < 0)
980     quiterr("error reading Radiance picture");
981    
982 greg 2.29 for (x = cvts.xmax; x--; ) {
983     if (CHK(C_CXFM)) {
984     colortrans(cvts.r.colors[x], cvts.cmat,
985     cvts.r.colors[x]);
986     if (CHK(C_GAMUT))
987 greg 2.30 clipgamut(cvts.r.colors[x], bright(cvts.r.colors[x]),
988 greg 2.29 CGAMUT_LOWER, cblack, cwhite);
989     }
990 greg 2.21 for (i = 3; i--; ) {
991     register float f = m*colval(cvts.r.colors[x],i);
992     if (f <= 0)
993     cvts.t.wp[3*x + i] = 0;
994     else if (f >= 1)
995     cvts.t.wp[3*x + i] = 0xffff;
996     else if (dogamma)
997     cvts.t.wp[3*x + i] = (int)((float)(1L<<16) *
998     pow(f, 1./cvts.gamcor));
999     else
1000     cvts.t.wp[3*x + i] = (int)((float)(1L<<16)*f);
1001     }
1002 greg 2.29 }
1003 greg 2.21
1004     if (TIFFWriteScanline(cvts.tif, cvts.t.p, y, 0) < 0)
1005     quiterr("error writing TIFF output");
1006     }
1007    
1008    
1009 schorsch 2.28 static void
1010     Colr2Gry( /* read/convert/write COLR->RGB scanline */
1011     uint32 y
1012     )
1013 gregl 2.9 {
1014     register int x;
1015    
1016 gwlarson 2.19 if (CHK(C_RFLT|C_TWRD|C_TFLT|C_GRY) != C_GRY)
1017 gregl 2.9 quiterr("internal error 1 in Colr2Gry");
1018    
1019     if (freadcolrs(cvts.r.colrs, cvts.xmax, cvts.rfp) < 0)
1020     quiterr("error reading Radiance picture");
1021    
1022     if (cvts.bradj)
1023     shiftcolrs(cvts.r.colrs, cvts.xmax, cvts.bradj);
1024     for (x = cvts.xmax; x--; )
1025     colval(cvts.r.colrs[x],CIEY) = normbright(cvts.r.colrs[x]);
1026     colrs_gambs(cvts.r.colrs, cvts.xmax);
1027    
1028     for (x = cvts.xmax; x--; )
1029     cvts.t.bp[x] = colval(cvts.r.colrs[x],CIEY);
1030    
1031     if (TIFFWriteScanline(cvts.tif, cvts.t.p, y, 0) < 0)
1032     quiterr("error writing TIFF output");
1033     }
1034    
1035    
1036 schorsch 2.28 static void
1037     Colr2RGB( /* read/convert/write COLR->RGB scanline */
1038     uint32 y
1039     )
1040 gregl 2.9 {
1041     COLOR ctmp;
1042     register int x;
1043    
1044 gwlarson 2.19 if (CHK(C_RFLT|C_TFLT|C_TWRD|C_GRY))
1045 gregl 2.9 quiterr("internal error 1 in Colr2RGB");
1046    
1047     if (freadcolrs(cvts.r.colrs, cvts.xmax, cvts.rfp) < 0)
1048     quiterr("error reading Radiance picture");
1049    
1050     if (cvts.bradj)
1051     shiftcolrs(cvts.r.colrs, cvts.xmax, cvts.bradj);
1052     if (CHK(C_CXFM))
1053     for (x = cvts.xmax; x--; ) {
1054     colr_color(ctmp, cvts.r.colrs[x]);
1055     colortrans(ctmp, cvts.cmat, ctmp);
1056     if (CHK(C_GAMUT))
1057     clipgamut(ctmp, bright(ctmp), CGAMUT,
1058     cblack, cwhite);
1059     setcolr(cvts.r.colrs[x], colval(ctmp,RED),
1060     colval(ctmp,GRN), colval(ctmp,BLU));
1061 greg 1.1 }
1062 gregl 2.9 colrs_gambs(cvts.r.colrs, cvts.xmax);
1063    
1064     for (x = cvts.xmax; x--; ) {
1065     cvts.t.bp[3*x] = cvts.r.colrs[x][RED];
1066     cvts.t.bp[3*x+1] = cvts.r.colrs[x][GRN];
1067     cvts.t.bp[3*x+2] = cvts.r.colrs[x][BLU];
1068 greg 1.1 }
1069 gregl 2.9
1070     if (TIFFWriteScanline(cvts.tif, cvts.t.p, y, 0) < 0)
1071     quiterr("error writing TIFF output");
1072 greg 1.1 }