ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_xyze.c
Revision: 2.17
Committed: Sat Jun 7 05:09:46 2025 UTC (2 weeks, 4 days ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.16: +1 -2 lines
Log Message:
refactor: Put some declarations into "paths.h" and included in "platform.h"

File Contents

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