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 (5 months, 2 weeks 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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: ra_xyze.c,v 2.14 2024/10/01 01:16:26 greg Exp $";
3 #endif
4 /*
5 * Program to convert between RADIANCE RGBE and XYZE formats
6 * Added white-balance adjustment 10/01 (GW).
7 */
8
9 #include <math.h>
10
11 #include "platform.h"
12 #include "color.h"
13 #include "resolu.h"
14 #include "rtio.h"
15
16 enum {InpUNK, InpRGB, InpXYZ, InpSPEC}; /* input format */
17 int infmt = InpUNK;
18 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 double origexp = -1.0; /* original exposure */
24 char *progname;
25
26 static gethfunc headline;
27 static void quiterr(char *err);
28 static void myreadscan(COLOR *scn, int len);
29 static void convert(void);
30
31
32
33 static int
34 headline( /* process header line */
35 char *s,
36 void *p
37 )
38 {
39 char fmt[MAXFMTLEN];
40
41 if (formatval(fmt, s)) { /* check if format string */
42 if (!strcmp(fmt,COLRFMT))
43 infmt = InpRGB;
44 else if (!strcmp(fmt,CIEFMT))
45 infmt = InpXYZ;
46 else if (!strcmp(fmt,SPECFMT))
47 infmt = InpSPEC;
48 else
49 infmt = InpUNK;
50 return(0); /* don't echo */
51 }
52 if (origexp > 0.0 && isexpos(s)) {
53 origexp *= exposval(s);
54 return(0); /* don't echo */
55 }
56 if (isprims(s)) { /* get input primaries */
57 primsval(inprims, s);
58 return(0); /* don't echo */
59 }
60 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 /* should I grok colcorr also? */
69 return(fputs(s, stdout));
70 }
71
72
73 int
74 main(int argc, char *argv[])
75 {
76 int i;
77 SET_DEFAULT_BINARY();
78 SET_FILE_BINARY(stdin);
79 SET_FILE_BINARY(stdout);
80 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 if (i+8 >= argc)
96 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 case 'o': /* original exposure */
107 origexp = 1.0;
108 break;
109 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 if (infmt == InpUNK)
136 quiterr("unrecognized/missing input file format");
137 if (infmt == InpSPEC ? (NCSAMP <= 3) | (NCSAMP > MAXCSAMP) :
138 NCSAMP != 3)
139 quiterr("bad number of color components");
140 printargs(argc, argv, stdout); /* add to header */
141 convert(); /* convert picture */
142 exit(0);
143 userr:
144 fprintf(stderr, "Usage: %s [-r][-o][-e exp][-c|-u]", progname);
145 fprintf(stderr, "[-p rx ry gx gy bx by wx wy] [input [output]]\n");
146 exit(1);
147 }
148
149
150 static void
151 quiterr( /* print message and exit */
152 char *err
153 )
154 {
155 if (err != NULL) {
156 fprintf(stderr, "%s: %s\n", progname, err);
157 exit(1);
158 }
159 exit(0);
160 }
161
162
163 static void
164 myreadscan(COLOR *scn, int len)
165 {
166 if (infmt == InpSPEC) { /* read & convert to XYZ */
167 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 while (len-- > 0) {
182 if (getbinary(sclr, LSCOLR, 1, stdin) != 1)
183 goto readerr;
184 scolr_scolor(scol, sclr);
185 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 }
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 convert(void) /* convert to XYZE or RGBE picture */
204 {
205 int order;
206 int xmax, ymax;
207 COLORMAT xfm;
208 COLOR *scanin;
209 COLR *scanout;
210 double exp2do = expcomp;
211 double exp2report = expcomp;
212 int y;
213 int x;
214 /* recover original? */
215 if (origexp > 0.0)
216 exp2do /= origexp;
217 /* compute transform */
218 if (rgbout) {
219 if (infmt == InpRGB) { /* RGBE -> RGBE */
220 comprgb2rgbWBmat(xfm, inprims, outprims);
221 } else { /* XYZE/Spectral -> RGBE */
222 compxyz2rgbWBmat(xfm, outprims);
223 }
224 if (infmt == InpXYZ) {
225 if (origexp > 0.0)
226 exp2do /= WHTEFFICACY;
227 else
228 exp2report *= WHTEFFICACY;
229 }
230 } else {
231 if (infmt == InpRGB) { /* RGBE -> XYZE */
232 comprgb2xyzWBmat(xfm, inprims);
233 } 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 exp2do *= WHTEFFICACY;
241 else
242 exp2report /= WHTEFFICACY;
243 }
244 }
245 for (y = 0; y < 3; y++)
246 for (x = 0; x < 3; x++)
247 xfm[y][x] *= exp2do;
248 /* get input resolution */
249 if ((order = fgetresolu(&xmax, &ymax, stdin)) < 0)
250 quiterr("bad picture format");
251 /* complete output header */
252 if ((exp2report < 0.99) | (exp2report > 1.01))
253 fputexpos(exp2report, stdout);
254 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 scanout = doflat ? (COLR *)malloc(xmax*sizeof(COLR)) : (COLR *)NULL;
266 /* convert image */
267 for (y = 0; y < ymax; y++) {
268 myreadscan(scanin, xmax);
269 for (x = 0; x < xmax; x++) {
270 colortrans(scanin[x], xfm, scanin[x]);
271 if (rgbout)
272 clipgamut(scanin[x], bright(scanin[x]),
273 CGAMUT_LOWER, cblack, cwhite);
274 }
275 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 putbinary(scanout, sizeof(COLR), xmax, stdout);
281 } else
282 fwritescan(scanin, xmax, stdout);
283 if (ferror(stdout))
284 quiterr("error writing output picture");
285 }
286 /* free scanline */
287 free(scanin);
288 if (scanout != NULL)
289 free(scanout);
290 }