ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_xyze.c
Revision: 2.15
Committed: Tue Oct 1 20:04:44 2024 UTC (7 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.14: +25 -4 lines
Log Message:
perf(ra_xyze): sped up conversion from hyperspectral by a factor of 4 or so

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.15 static const char RCSid[] = "$Id: ra_xyze.c,v 2.14 2024/10/01 01:16:26 greg Exp $";
3 greg 2.1 #endif
4     /*
5     * Program to convert between RADIANCE RGBE and XYZE formats
6 greg 2.6 * Added white-balance adjustment 10/01 (GW).
7 greg 2.1 */
8    
9     #include <math.h>
10 schorsch 2.7
11     #include "platform.h"
12 greg 2.1 #include "color.h"
13     #include "resolu.h"
14 greg 2.11 #include "rtio.h"
15 greg 2.1
16 greg 2.14 enum {InpUNK, InpRGB, InpXYZ, InpSPEC}; /* input format */
17     int infmt = InpUNK;
18 greg 2.1 int rgbout = 0; /* output should be RGBE? */
19     RGBPRIMS inprims = STDPRIMS; /* input primaries */
20     RGBPRIMS outprims = STDPRIMS; /* output primaries */
21     double expcomp = 1.0; /* exposure compensation */
22     int doflat = -1; /* produce flat file? */
23 greg 2.10 double origexp = -1.0; /* original exposure */
24 greg 2.1 char *progname;
25    
26 schorsch 2.8 static gethfunc headline;
27 schorsch 2.9 static void quiterr(char *err);
28 greg 2.14 static void myreadscan(COLOR *scn, int len);
29 schorsch 2.9 static void convert(void);
30    
31 greg 2.1
32 schorsch 2.8
33     static int
34     headline( /* process header line */
35     char *s,
36     void *p
37     )
38 greg 2.1 {
39 greg 2.12 char fmt[MAXFMTLEN];
40 greg 2.1
41     if (formatval(fmt, s)) { /* check if format string */
42     if (!strcmp(fmt,COLRFMT))
43 greg 2.14 infmt = InpRGB;
44 greg 2.1 else if (!strcmp(fmt,CIEFMT))
45 greg 2.14 infmt = InpXYZ;
46     else if (!strcmp(fmt,SPECFMT))
47     infmt = InpSPEC;
48 greg 2.1 else
49 greg 2.14 infmt = InpUNK;
50 gwlarson 2.5 return(0); /* don't echo */
51 greg 2.1 }
52 greg 2.10 if (origexp > 0.0 && isexpos(s)) {
53     origexp *= exposval(s);
54     return(0); /* don't echo */
55     }
56 greg 2.1 if (isprims(s)) { /* get input primaries */
57     primsval(inprims, s);
58 gwlarson 2.5 return(0); /* don't echo */
59 greg 2.1 }
60 greg 2.14 if (iswlsplit(s)) { /* get wavelength limits */
61     wlsplitval(WLPART, s);
62     return(0); /* don't echo */
63     }
64     if (isncomp(s)) { /* number of color samples */
65     NCSAMP = ncompval(s);
66     return(0); /* don't echo */
67     }
68 greg 2.1 /* should I grok colcorr also? */
69 gwlarson 2.5 return(fputs(s, stdout));
70 greg 2.1 }
71    
72    
73 schorsch 2.9 int
74     main(int argc, char *argv[])
75 greg 2.1 {
76     int i;
77 schorsch 2.7 SET_DEFAULT_BINARY();
78     SET_FILE_BINARY(stdin);
79     SET_FILE_BINARY(stdout);
80 greg 2.1 progname = argv[0];
81    
82     for (i = 1; i < argc; i++)
83     if (argv[i][0] == '-')
84     switch (argv[i][1]) {
85     case 'c': /* rle-compressed output */
86     doflat = 0;
87     break;
88     case 'u': /* flat output */
89     doflat = 1;
90     break;
91     case 'r': /* RGBE output */
92     rgbout = 1;
93     break;
94     case 'p': /* RGB primaries */
95 greg 2.2 if (i+8 >= argc)
96 greg 2.1 goto userr;
97     outprims[RED][CIEX] = atof(argv[++i]);
98     outprims[RED][CIEY] = atof(argv[++i]);
99     outprims[GRN][CIEX] = atof(argv[++i]);
100     outprims[GRN][CIEY] = atof(argv[++i]);
101     outprims[BLU][CIEX] = atof(argv[++i]);
102     outprims[BLU][CIEY] = atof(argv[++i]);
103     outprims[WHT][CIEX] = atof(argv[++i]);
104     outprims[WHT][CIEY] = atof(argv[++i]);
105     break;
106 greg 2.10 case 'o': /* original exposure */
107     origexp = 1.0;
108     break;
109 greg 2.1 case 'e': /* exposure compensation */
110     expcomp = atof(argv[++i]);
111     if (argv[i][0] == '+' || argv[i][0] == '-')
112     expcomp = pow(2., expcomp);
113     break;
114     default:
115     goto userr;
116     }
117     else
118     break;
119    
120     if (doflat < 0)
121     doflat = !rgbout;
122     if (i < argc-2)
123     goto userr;
124     if (i <= argc-1 && freopen(argv[i], "r", stdin) == NULL) {
125     fprintf(stderr, "%s: can't open input \"%s\"\n",
126     progname, argv[i]);
127     exit(1);
128     }
129     if (i == argc-2 && freopen(argv[i+1], "w", stdout) == NULL) {
130     fprintf(stderr, "%s: can't open output \"%s\"\n",
131     progname, argv[i+1]);
132     exit(1);
133     }
134     getheader(stdin, headline, NULL);
135 greg 2.14 if (infmt == InpUNK)
136     quiterr("unrecognized/missing input file format");
137 greg 2.15 if (infmt == InpSPEC ? (NCSAMP <= 3) | (NCSAMP > MAXCSAMP) :
138     NCSAMP != 3)
139     quiterr("bad number of color components");
140 greg 2.1 printargs(argc, argv, stdout); /* add to header */
141     convert(); /* convert picture */
142     exit(0);
143     userr:
144 greg 2.10 fprintf(stderr, "Usage: %s [-r][-o][-e exp][-c|-u]", progname);
145 greg 2.1 fprintf(stderr, "[-p rx ry gx gy bx by wx wy] [input [output]]\n");
146     exit(1);
147     }
148    
149    
150 schorsch 2.9 static void
151     quiterr( /* print message and exit */
152     char *err
153     )
154 greg 2.1 {
155     if (err != NULL) {
156     fprintf(stderr, "%s: %s\n", progname, err);
157     exit(1);
158     }
159     exit(0);
160     }
161    
162    
163 schorsch 2.9 static void
164 greg 2.14 myreadscan(COLOR *scn, int len)
165     {
166     if (infmt == InpSPEC) { /* read & convert to XYZ */
167 greg 2.15 static COLOR *scomp = NULL;
168     SCOLR sclr;
169     SCOLOR scol;
170     COLOR xyz;
171     int n;
172     if (scomp == NULL) { /* initialize conversion */
173     scomp = (COLOR *)malloc(sizeof(COLOR)*NCSAMP);
174     if (scomp == NULL)
175     quiterr("out of memory in myreadscan");
176     for (n = NCSAMP; n--; )
177     spec_cie(scomp[n],
178     WLPART[0] + (WLPART[3] - WLPART[0])*(n+1)/NCSAMP,
179     WLPART[0] + (WLPART[3] - WLPART[0])*n/NCSAMP);
180     }
181 greg 2.14 while (len-- > 0) {
182     if (getbinary(sclr, LSCOLR, 1, stdin) != 1)
183     goto readerr;
184     scolr_scolor(scol, sclr);
185 greg 2.15 setcolor(*scn, 0, 0, 0);
186     for (n = NCSAMP; n--; ) {
187     copycolor(xyz, scomp[n]);
188     scalecolor(xyz, scol[n]);
189     addcolor(*scn, xyz);
190     }
191     scn++;
192 greg 2.14 }
193     return;
194     } /* else read as RGBE/XYZE */
195     if (freadscan(scn, len, stdin) >= 0)
196     return;
197     readerr:
198     quiterr("error reading input picture");
199     }
200    
201    
202     static void
203 schorsch 2.9 convert(void) /* convert to XYZE or RGBE picture */
204 greg 2.1 {
205     int order;
206     int xmax, ymax;
207     COLORMAT xfm;
208 greg 2.14 COLOR *scanin;
209     COLR *scanout;
210 greg 2.10 double exp2do = expcomp;
211     double exp2report = expcomp;
212 greg 2.1 int y;
213 greg 2.14 int x;
214 greg 2.10 /* recover original? */
215     if (origexp > 0.0)
216     exp2do /= origexp;
217 greg 2.1 /* compute transform */
218     if (rgbout) {
219 greg 2.14 if (infmt == InpRGB) { /* RGBE -> RGBE */
220 greg 2.6 comprgb2rgbWBmat(xfm, inprims, outprims);
221 greg 2.14 } else { /* XYZE/Spectral -> RGBE */
222 greg 2.6 compxyz2rgbWBmat(xfm, outprims);
223 greg 2.14 }
224     if (infmt == InpXYZ) {
225 greg 2.10 if (origexp > 0.0)
226     exp2do /= WHTEFFICACY;
227     else
228     exp2report *= WHTEFFICACY;
229 greg 2.1 }
230     } else {
231 greg 2.14 if (infmt == InpRGB) { /* RGBE -> XYZE */
232 greg 2.6 comprgb2xyzWBmat(xfm, inprims);
233 greg 2.14 } else { /* XYZE/Spectral -> XYZE */
234     memset(xfm, 0, sizeof(xfm));
235     for (x = 3; x--; )
236     xfm[x][x] = 1.;
237     }
238     if (infmt != InpXYZ) {
239     if (origexp > 0)
240 greg 2.10 exp2do *= WHTEFFICACY;
241     else
242     exp2report /= WHTEFFICACY;
243 greg 2.1 }
244     }
245 gregl 2.4 for (y = 0; y < 3; y++)
246     for (x = 0; x < 3; x++)
247 greg 2.10 xfm[y][x] *= exp2do;
248 greg 2.1 /* get input resolution */
249     if ((order = fgetresolu(&xmax, &ymax, stdin)) < 0)
250     quiterr("bad picture format");
251     /* complete output header */
252 greg 2.10 if ((exp2report < 0.99) | (exp2report > 1.01))
253     fputexpos(exp2report, stdout);
254 greg 2.1 if (rgbout) {
255     fputprims(outprims, stdout);
256     fputformat(COLRFMT, stdout);
257     } else
258     fputformat(CIEFMT, stdout);
259     putc('\n', stdout);
260     fputresolu(order, xmax, ymax, stdout);
261     /* allocate scanline */
262     scanin = (COLOR *)malloc(xmax*sizeof(COLOR));
263     if (scanin == NULL)
264     quiterr("out of memory in convert");
265 greg 2.14 scanout = doflat ? (COLR *)malloc(xmax*sizeof(COLR)) : (COLR *)NULL;
266 greg 2.1 /* convert image */
267     for (y = 0; y < ymax; y++) {
268 greg 2.14 myreadscan(scanin, xmax);
269 greg 2.3 for (x = 0; x < xmax; x++) {
270 greg 2.1 colortrans(scanin[x], xfm, scanin[x]);
271 greg 2.3 if (rgbout)
272     clipgamut(scanin[x], bright(scanin[x]),
273     CGAMUT_LOWER, cblack, cwhite);
274     }
275 greg 2.1 if (scanout != NULL) {
276     for (x = 0; x < xmax; x++)
277     setcolr(scanout[x], colval(scanin[x],RED),
278     colval(scanin[x],GRN),
279     colval(scanin[x],BLU));
280 greg 2.14 putbinary(scanout, sizeof(COLR), xmax, stdout);
281 greg 2.1 } else
282     fwritescan(scanin, xmax, stdout);
283     if (ferror(stdout))
284     quiterr("error writing output picture");
285     }
286     /* free scanline */
287 greg 2.14 free(scanin);
288 greg 2.1 if (scanout != NULL)
289 greg 2.14 free(scanout);
290 greg 2.1 }