ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/tmaptiff.c
Revision: 3.4
Committed: Sun Jul 27 22:12:01 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R6, rad3R6P1
Changes since 3.3: +6 -6 lines
Log Message:
Added grouping parens to reduce ambiguity warnings.

File Contents

# User Rev Content
1 greg 3.1 #ifndef lint
2 schorsch 3.4 static const char RCSid[] = "$Id: tmaptiff.c,v 3.3 2003/07/14 04:56:54 greg Exp $";
3 greg 3.1 #endif
4     /*
5     * Perform tone mapping on TIFF input.
6     *
7     * Externals declared in tmaptiff.h
8     */
9    
10 greg 3.2 #include "copyright.h"
11 greg 3.1
12     #include <stdio.h>
13     #include "tiffio.h"
14     #include "tmprivat.h"
15     #include "tmaptiff.h"
16    
17 greg 3.3 /* input cases we handle */
18     #define TC_LOGLUV32 1
19     #define TC_LOGLUV24 2
20     #define TC_LOGL16 3
21     #define TC_GRYFLOAT 4
22     #define TC_RGBFLOAT 5
23     #define TC_GRYSHORT 6
24     #define TC_RGBSHORT 7
25    
26     /* figure out what kind of TIFF we have and if we can tone-map it */
27     static int
28     getTIFFtype(TIFF *tif)
29     {
30     uint16 comp, phot, pconf;
31     uint16 samp_fmt, bits_samp;
32    
33     TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &pconf);
34     if (pconf != PLANARCONFIG_CONTIG)
35     return(0);
36     TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &phot);
37     TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &comp);
38     TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLEFORMAT, &samp_fmt);
39     TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bits_samp);
40     switch (phot) {
41     case PHOTOMETRIC_LOGLUV:
42     if (comp == COMPRESSION_SGILOG)
43     return(TC_LOGLUV32);
44     if (comp == COMPRESSION_SGILOG24)
45     return(TC_LOGLUV24);
46     return(0);
47     case PHOTOMETRIC_LOGL:
48     if (comp == COMPRESSION_SGILOG)
49     return(TC_LOGL16);
50     return(0);
51     case PHOTOMETRIC_MINISBLACK:
52     if (samp_fmt == SAMPLEFORMAT_UINT) {
53     if (bits_samp == 16)
54     return(TC_GRYSHORT);
55     return(0);
56     }
57     if (samp_fmt == SAMPLEFORMAT_IEEEFP) {
58     if (bits_samp == 8*sizeof(float))
59     return(TC_GRYFLOAT);
60     return(0);
61     }
62     return(0);
63     case PHOTOMETRIC_RGB:
64     if (samp_fmt == SAMPLEFORMAT_UINT) {
65     if (bits_samp == 16)
66     return(TC_RGBSHORT);
67     return(0);
68     }
69     if (samp_fmt == SAMPLEFORMAT_IEEEFP) {
70     if (bits_samp == 8*sizeof(float))
71     return(TC_RGBFLOAT);
72     return(0);
73     }
74     return(0);
75     }
76     return(0);
77     }
78 greg 3.1
79 greg 3.3 /* load and convert TIFF */
80 greg 3.1 int
81 greg 3.3 tmLoadTIFF(TMbright **lpp, BYTE **cpp, int *xp, int *yp, char *fname, TIFF *tp)
82 greg 3.1 {
83     char *funcName = fname==NULL ? "tmLoadTIFF" : fname;
84 greg 3.3 RGBPRIMP inppri = tmTop->monpri;
85     RGBPRIMS myprims;
86     float *fa;
87 greg 3.1 TIFF *tif;
88     int err;
89 greg 3.3 union {uint16 *w; uint32 *l; float *f; MEM_PTR p;} sl;
90 greg 3.1 uint32 width, height;
91 greg 3.3 int tcase;
92 greg 3.1 double stonits;
93     int y;
94     /* check arguments */
95     if (tmTop == NULL)
96     returnErr(TM_E_TMINVAL);
97 schorsch 3.4 if ((lpp == NULL) | (xp == NULL) | (yp == NULL) |
98     ((fname == NULL) & (tp == NULL)))
99 greg 3.1 returnErr(TM_E_ILLEGAL);
100     /* check/get TIFF tags */
101     sl.p = NULL; *lpp = NULL;
102     if (cpp != TM_NOCHROMP) *cpp = TM_NOCHROM;
103     err = TM_E_BADFILE;
104     if ((tif = tp) == NULL && (tif = TIFFOpen(fname, "r")) == NULL)
105     returnErr(TM_E_BADFILE);
106 greg 3.3 tcase = getTIFFtype(tif);
107     if (!tcase)
108     goto done;
109 greg 3.1 if (!TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width) ||
110     !TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height))
111     goto done;
112     *xp = width; *yp = height;
113 greg 3.3 if (TIFFGetField(tif, TIFFTAG_PRIMARYCHROMATICITIES, &fa)) {
114     myprims[RED][CIEX] = fa[0];
115     myprims[RED][CIEY] = fa[1];
116     myprims[GRN][CIEX] = fa[2];
117     myprims[GRN][CIEY] = fa[3];
118     myprims[BLU][CIEX] = fa[4];
119     myprims[BLU][CIEY] = fa[5];
120     myprims[WHT][CIEX] = 1./3.;
121     myprims[WHT][CIEY] = 1./3.;
122     if (TIFFGetField(tif, TIFFTAG_WHITEPOINT, &fa)) {
123     myprims[WHT][CIEX] = fa[0];
124     myprims[WHT][CIEY] = fa[1];
125     }
126     inppri = myprims;
127     }
128 greg 3.1 if (!TIFFGetField(tif, TIFFTAG_STONITS, &stonits))
129     stonits = 1.;
130 greg 3.3 switch (tcase) { /* set up conversion */
131     case TC_LOGLUV32:
132     case TC_LOGLUV24:
133 greg 3.1 TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_RAW);
134     sl.l = (uint32 *)malloc(width*sizeof(uint32));
135 greg 3.3 tmSetSpace(TM_XYZPRIM, stonits);
136     break;
137     case TC_LOGL16:
138 greg 3.1 TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_16BIT);
139     sl.w = (uint16 *)malloc(width*sizeof(uint16));
140 greg 3.3 tmSetSpace(tmTop->monpri, stonits);
141     break;
142     case TC_RGBFLOAT:
143     sl.f = (float *)malloc(width*3*sizeof(float));
144     tmSetSpace(inppri, stonits);
145     break;
146     case TC_GRYFLOAT:
147     sl.f = (float *)malloc(width*sizeof(float));
148     tmSetSpace(tmTop->monpri, stonits);
149     break;
150     case TC_RGBSHORT:
151     sl.w = (uint16 *)malloc(width*3*sizeof(uint16));
152     tmSetSpace(inppri, stonits);
153     break;
154     case TC_GRYSHORT:
155     sl.w = (uint16 *)malloc(width*sizeof(uint16));
156     tmSetSpace(tmTop->monpri, stonits);
157     break;
158     default:
159     err = TM_E_CODERR1;
160 greg 3.1 goto done;
161 greg 3.3 }
162 greg 3.1 *lpp = (TMbright *)malloc(width*height*sizeof(TMbright));
163 schorsch 3.4 if ((sl.p == NULL) | (*lpp == NULL)) {
164 greg 3.1 err = TM_E_NOMEM;
165     goto done;
166     }
167 greg 3.3 switch (tcase) { /* allocate color if needed */
168     case TC_LOGLUV32:
169     case TC_LOGLUV24:
170     case TC_RGBFLOAT:
171     case TC_RGBSHORT:
172     if (cpp == TM_NOCHROMP)
173     break;
174     *cpp = (BYTE *)malloc(width*height*3*sizeof(BYTE));
175     if (*cpp == NULL) {
176     err = TM_E_NOMEM;
177     goto done;
178     }
179     break;
180     }
181 greg 3.1 /* read and convert each scanline */
182     for (y = 0; y < height; y++) {
183     if (TIFFReadScanline(tif, sl.p, y, 0) < 0) {
184     err = TM_E_BADFILE;
185     break;
186     }
187 greg 3.3 switch (tcase) {
188     case TC_LOGLUV32:
189     err = tmCvLuv32(*lpp + y*width,
190     cpp==TM_NOCHROMP ? TM_NOCHROM : *cpp+y*3*width,
191     sl.l, width);
192     break;
193     case TC_LOGLUV24:
194 greg 3.1 err = tmCvLuv24(*lpp + y*width,
195     cpp==TM_NOCHROMP ? TM_NOCHROM : *cpp+y*3*width,
196     sl.l, width);
197 greg 3.3 break;
198     case TC_LOGL16:
199     err = tmCvL16(*lpp + y*width, sl.w, width);
200     break;
201     case TC_RGBFLOAT:
202     err = tmCvColors(*lpp + y*width,
203     cpp==TM_NOCHROMP ? TM_NOCHROM : *cpp+y*3*width,
204     (COLOR *)sl.f, width);
205     break;
206     case TC_GRYFLOAT:
207     err = tmCvGrays(*lpp + y*width, sl.f, width);
208     break;
209     case TC_RGBSHORT:
210     err = tmCvRGB48(*lpp + y*width,
211 greg 3.1 cpp==TM_NOCHROMP ? TM_NOCHROM : *cpp+y*3*width,
212 greg 3.3 (uint16 (*)[3])sl.w, width, DEFGAM);
213     break;
214     case TC_GRYSHORT:
215     err = tmCvGray16(*lpp + y*width, sl.w, width, DEFGAM);
216     break;
217     default:
218     err = TM_E_CODERR1;
219     break;
220     }
221 greg 3.1 if (err != TM_E_OK)
222     break;
223     }
224     done: /* clean up */
225     if (tp == NULL)
226     TIFFClose(tif);
227     if (sl.p != NULL)
228     free(sl.p);
229     if (err != TM_E_OK) { /* free buffers on error */
230     if (*lpp != NULL)
231     free((MEM_PTR)*lpp);
232     *lpp = NULL;
233     if (cpp != TM_NOCHROMP) {
234     if (*cpp != TM_NOCHROM)
235     free((MEM_PTR)*cpp);
236     *cpp = NULL;
237     }
238     *xp = *yp = 0;
239     returnErr(err);
240     }
241     returnOK;
242     }
243    
244    
245     /*
246     * Load and tone-map a SGILOG TIFF.
247     * Beware of greyscale input -- you must check the PHOTOMETRIC tag to
248     * determine that the returned array contains only grey values, not RGB.
249     * As in tmMapPicture(), grey values are also returned if flags&TM_F_BW.
250     */
251     int
252 greg 3.3 tmMapTIFF(BYTE **psp, int *xp, int *yp, int flags, RGBPRIMP monpri,
253     double gamval, double Lddyn, double Ldmax, char *fname, TIFF *tp)
254 greg 3.1 {
255     char *funcName = fname==NULL ? "tmMapTIFF" : fname;
256     TMbright *lp;
257     BYTE *cp;
258     int err;
259     /* check arguments */
260 schorsch 3.4 if ((psp == NULL) | (xp == NULL) | (yp == NULL) | (monpri == NULL) |
261     ((fname == NULL) & (tp == NULL)))
262 greg 3.1 returnErr(TM_E_ILLEGAL);
263     if (gamval < MINGAM) gamval = DEFGAM;
264     if (Lddyn < MINLDDYN) Lddyn = DEFLDDYN;
265     if (Ldmax < MINLDMAX) Ldmax = DEFLDMAX;
266     if (flags & TM_F_BW) monpri = stdprims;
267     /* initialize tone mapping */
268     if (tmInit(flags, monpri, gamval) == NULL)
269     returnErr(TM_E_NOMEM);
270     /* load and convert TIFF */
271     cp = TM_NOCHROM;
272     err = tmLoadTIFF(&lp, flags&TM_F_BW ? TM_NOCHROMP : &cp,
273     xp, yp, fname, tp);
274     if (err != TM_E_OK) {
275     tmDone(NULL);
276     return(err);
277     }
278     if (cp == TM_NOCHROM) {
279     *psp = (BYTE *)malloc(*xp * *yp * sizeof(BYTE));
280     if (*psp == NULL) {
281     free((MEM_PTR)lp);
282     tmDone(NULL);
283     returnErr(TM_E_NOMEM);
284     }
285     } else
286     *psp = cp;
287     /* compute color mapping */
288     err = tmAddHisto(lp, *xp * *yp, 1);
289     if (err != TM_E_OK)
290     goto done;
291     err = tmComputeMapping(gamval, Lddyn, Ldmax);
292     if (err != TM_E_OK)
293     goto done;
294     /* map pixels */
295     err = tmMapPixels(*psp, lp, cp, *xp * *yp);
296    
297     done: /* clean up */
298     free((MEM_PTR)lp);
299     tmDone(NULL);
300     if (err != TM_E_OK) { /* free memory on error */
301     free((MEM_PTR)*psp);
302     *psp = NULL;
303     *xp = *yp = 0;
304     returnErr(err);
305     }
306     returnOK;
307     }