ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_bmp.c
Revision: 2.6
Committed: Fri Apr 30 17:56:06 2004 UTC (20 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.5: +2 -4 lines
Log Message:
Fixed - option for reading from stdin

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: ra_bmp.c,v 2.5 2004/04/30 17:30:33 greg Exp $";
3 #endif
4 /*
5 * program to convert between RADIANCE and Windows BMP file
6 */
7
8 #include <stdio.h>
9 #include <string.h>
10
11 #include "platform.h"
12 #include "color.h"
13 #include "tonemap.h"
14 #include "resolu.h"
15 #include "bmpfile.h"
16
17 int bradj = 0; /* brightness adjustment */
18
19 double gamcor = 2.2; /* gamma correction value */
20
21 char *progname;
22
23 static void quiterr(const char *err);
24 static void tmap2bmp(char *fnin, char *fnout, char *expec,
25 RGBPRIMP monpri, double gamval);
26 static void rad2bmp(FILE *rfp, BMPWriter *bwr, int inv, int gry);
27 static void bmp2rad(BMPReader *brd, FILE *rfp, int inv);
28
29
30 int
31 main(int argc, char *argv[])
32 {
33 char *inpfile=NULL, *outfile=NULL;
34 char *expec = NULL;
35 int reverse = 0;
36 RGBPRIMP rgbp = stdprims;
37 RGBPRIMS myprims;
38 RESOLU rs;
39 int i;
40
41 progname = argv[0];
42
43 for (i = 1; i < argc; i++)
44 if (argv[i][0] == '-' && argv[i][1])
45 switch (argv[i][1]) {
46 case 'b':
47 rgbp = NULL;
48 break;
49 case 'g':
50 gamcor = atof(argv[++i]);
51 break;
52 case 'e':
53 if (argv[i+1][0] != '+' && argv[i+1][0] != '-')
54 expec = argv[++i];
55 else
56 bradj = atoi(argv[++i]);
57 break;
58 case 'p':
59 if (argc-i < 9)
60 goto userr;
61 myprims[RED][CIEX] = atof(argv[++i]);
62 myprims[RED][CIEY] = atof(argv[++i]);
63 myprims[GRN][CIEX] = atof(argv[++i]);
64 myprims[GRN][CIEY] = atof(argv[++i]);
65 myprims[BLU][CIEX] = atof(argv[++i]);
66 myprims[BLU][CIEY] = atof(argv[++i]);
67 myprims[WHT][CIEX] = atof(argv[++i]);
68 myprims[WHT][CIEY] = atof(argv[++i]);
69 if (rgbp == stdprims)
70 rgbp = myprims;
71 break;
72 case 'r':
73 reverse = !reverse;
74 break;
75 default:
76 goto userr;
77 }
78 else
79 break;
80
81 if (i < argc-2)
82 goto userr;
83
84 SET_FILE_BINARY(stdin);
85 SET_FILE_BINARY(stdout);
86 SET_DEFAULT_BINARY();
87
88 if (i <= argc-1 && strcmp(argv[i], "-"))
89 inpfile = argv[i];
90
91 if (i == argc-2 && strcmp(argv[i+1], "-"))
92 outfile = argv[i+1];
93 /* check for tone-mapping */
94 if (expec != NULL) {
95 if (reverse)
96 goto userr;
97 tmap2bmp(inpfile, outfile, expec, rgbp, gamcor);
98 return(0);
99 }
100
101 setcolrgam(gamcor); /* set up conversion */
102
103 if (reverse) {
104 BMPReader *rdr;
105 /* open BMP file or stream */
106 if (inpfile != NULL)
107 rdr = BMPopenInputFile(inpfile);
108 else
109 rdr = BMPopenInputStream(stdin);
110
111 if (rdr == NULL) {
112 fprintf(stderr, "%s: cannot open or recognize BMP\n",
113 inpfile != NULL ? inpfile : "<stdin>");
114 exit(1);
115 }
116 /* open Radiance output */
117 if (outfile != NULL && freopen(outfile, "w", stdout) == NULL) {
118 fprintf(stderr, "%s: cannot open for output\n",
119 outfile);
120 exit(1);
121 }
122 /* put Radiance header */
123 newheader("RADIANCE", stdout);
124 printargs(i, argv, stdout);
125 fputformat(COLRFMT, stdout);
126 putchar('\n');
127 rs.xr = rdr->hdr->width;
128 rs.yr = rdr->hdr->height;
129 rs.rt = YMAJOR;
130 /* write scans downward if we can */
131 if (rdr->hdr->yIsDown || inpfile != NULL)
132 rs.rt |= YDECR;
133 fputsresolu(&rs, stdout);
134 /* convert file */
135 bmp2rad(rdr, stdout, !rdr->hdr->yIsDown && inpfile!=NULL);
136 /* flush output */
137 BMPcloseInput(rdr);
138 if (fflush(stdout) < 0)
139 quiterr("error writing Radiance output");
140 } else {
141 BMPHeader *hdr;
142 BMPWriter *wtr;
143 /* open Radiance input */
144 if (inpfile != NULL && freopen(inpfile, "r", stdin) == NULL) {
145 fprintf(stderr, "%s: cannot open input file\n",
146 inpfile);
147 exit(1);
148 }
149 /* get header info. */
150 if (checkheader(stdin, COLRFMT, NULL) < 0 ||
151 !fgetsresolu(&rs, stdin))
152 quiterr("bad Radiance picture format");
153 /* initialize BMP header */
154 if (rgbp == NULL) {
155 hdr = BMPmappedHeader(scanlen(&rs),
156 numscans(&rs), 0, 256);
157 if (outfile != NULL)
158 hdr->compr = BI_RLE8;
159 } else
160 hdr = BMPtruecolorHeader(scanlen(&rs),
161 numscans(&rs), 0);
162 if (hdr == NULL)
163 quiterr("cannot initialize BMP header");
164 /* set up output direction */
165 hdr->yIsDown = (rs.rt & YDECR) &&
166 ((outfile == NULL) | (hdr->compr == BI_RLE8));
167 /* open BMP output */
168 if (outfile != NULL)
169 wtr = BMPopenOutputFile(outfile, hdr);
170 else
171 wtr = BMPopenOutputStream(stdout, hdr);
172 if (wtr == NULL)
173 quiterr("cannot allocate writer structure");
174 /* convert file */
175 rad2bmp(stdin, wtr, !hdr->yIsDown && rs.rt&YDECR, rgbp==NULL);
176 /* flush output */
177 if (fflush((FILE *)wtr->c_data) < 0)
178 quiterr("error writing BMP output");
179 BMPcloseOutput(wtr);
180 }
181 return(0); /* success */
182 userr:
183 fprintf(stderr,
184 "Usage: %s [-b][-g gamma][-e spec][-p xr yr xg yg xb yb xw yw] [input|- [output]]\n",
185 progname);
186 fprintf(stderr,
187 " or: %s -r [-g gamma][-e +/-stops] [input|- [output]]\n",
188 progname);
189 return(1);
190 }
191
192 /* print message and exit */
193 static void
194 quiterr(const char *err)
195 {
196 if (err != NULL) {
197 fprintf(stderr, "%s: %s\n", progname, err);
198 exit(1);
199 }
200 exit(0);
201 }
202
203 /* convert Radiance picture to BMP */
204 static void
205 rad2bmp(FILE *rfp, BMPWriter *bwr, int inv, int gry)
206 {
207 COLR *scanin;
208 int y, yend, ystp;
209 int x;
210 /* allocate scanline */
211 scanin = (COLR *)malloc(bwr->hdr->width*sizeof(COLR));
212 if (scanin == NULL)
213 quiterr("out of memory in rad2bmp");
214 /* convert image */
215 if (inv) {
216 y = bwr->hdr->height - 1;
217 ystp = -1; yend = -1;
218 } else {
219 y = 0;
220 ystp = 1; yend = bwr->hdr->height;
221 }
222 /* convert each scanline */
223 for ( ; y != yend; y += ystp) {
224 if (freadcolrs(scanin, bwr->hdr->width, rfp) < 0)
225 quiterr("error reading Radiance picture");
226 if (bradj)
227 shiftcolrs(scanin, bwr->hdr->width, bradj);
228 for (x = gry ? bwr->hdr->width : 0; x--; )
229 scanin[x][GRN] = normbright(scanin[x]);
230 colrs_gambs(scanin, bwr->hdr->width);
231 if (gry)
232 for (x = bwr->hdr->width; x--; )
233 bwr->scanline[x] = scanin[x][GRN];
234 else
235 for (x = bwr->hdr->width; x--; ) {
236 bwr->scanline[3*x] = scanin[x][BLU];
237 bwr->scanline[3*x+1] = scanin[x][GRN];
238 bwr->scanline[3*x+2] = scanin[x][RED];
239 }
240 bwr->yscan = y;
241 x = BMPwriteScanline(bwr);
242 if (x != BIR_OK)
243 quiterr(BMPerrorMessage(x));
244 }
245 /* free scanline */
246 free((void *)scanin);
247 }
248
249 /* convert BMP file to Radiance */
250 static void
251 bmp2rad(BMPReader *brd, FILE *rfp, int inv)
252 {
253 COLR *scanout;
254 int y, yend, ystp;
255 int x;
256 /* allocate scanline */
257 scanout = (COLR *)malloc(brd->hdr->width*sizeof(COLR));
258 if (scanout == NULL)
259 quiterr("out of memory in bmp2rad");
260 /* convert image */
261 if (inv) {
262 y = brd->hdr->height - 1;
263 ystp = -1; yend = -1;
264 } else {
265 y = 0;
266 ystp = 1; yend = brd->hdr->height;
267 }
268 /* convert each scanline */
269 for ( ; y != yend; y += ystp) {
270 x = BMPseekScanline(y, brd);
271 if (x != BIR_OK)
272 quiterr(BMPerrorMessage(x));
273 for (x = brd->hdr->width; x--; ) {
274 RGBquad rgbq = BMPdecodePixel(x, brd);
275 scanout[x][RED] = rgbq.r;
276 scanout[x][GRN] = rgbq.g;
277 scanout[x][BLU] = rgbq.b;
278 }
279 gambs_colrs(scanout, brd->hdr->width);
280 if (bradj)
281 shiftcolrs(scanout, brd->hdr->width, bradj);
282 if (fwritecolrs(scanout, brd->hdr->width, rfp) < 0)
283 quiterr("error writing Radiance picture");
284 }
285 /* clean up */
286 free((void *)scanout);
287 }
288
289 /* Tone-map and convert Radiance picture */
290 static void
291 tmap2bmp(char *fnin, char *fnout, char *expec, RGBPRIMP monpri, double gamval)
292 {
293 int tmflags;
294 BMPHeader *hdr;
295 BMPWriter *wtr;
296 RESOLU rs;
297 FILE *fp;
298 int xr, yr;
299 BYTE *pa;
300 int i;
301 /* check tone-mapping spec */
302 i = strlen(expec);
303 if (i && !strncmp(expec, "auto", i))
304 tmflags = TM_F_CAMERA;
305 else if (i && !strncmp(expec, "human", i))
306 tmflags = TM_F_HUMAN & ~TM_F_UNIMPL;
307 else if (i && !strncmp(expec, "linear", i))
308 tmflags = TM_F_LINEAR;
309 else
310 quiterr("illegal exposure specification (auto|human|linear)");
311 if (monpri == NULL) {
312 tmflags |= TM_F_BW;
313 monpri = stdprims;
314 }
315 /* open Radiance input */
316 if (fnin == NULL)
317 fp = stdin;
318 else if ((fp = fopen(fnin, "r")) == NULL) {
319 fprintf(stderr, "%s: cannot open\n", fnin);
320 exit(1);
321 }
322 /* get picture orientation */
323 if (fnin != NULL) {
324 if (getheader(fp, NULL, NULL) < 0 || !fgetsresolu(&rs, fp))
325 quiterr("bad Radiance picture format");
326 rewind(fp);
327 } else /* assume stdin has normal orient */
328 rs.rt = PIXSTANDARD;
329 /* tone-map picture */
330 if (tmMapPicture(&pa, &xr, &yr, tmflags, monpri, gamval,
331 0., 0., fnin, fp) != TM_E_OK)
332 exit(1);
333 /* initialize BMP header */
334 if (tmflags & TM_F_BW) {
335 hdr = BMPmappedHeader(xr, yr, 0, 256);
336 if (fnout != NULL)
337 hdr->compr = BI_RLE8;
338 } else
339 hdr = BMPtruecolorHeader(xr, yr, 0);
340 if (hdr == NULL)
341 quiterr("cannot initialize BMP header");
342 /* open BMP output */
343 if (fnout != NULL)
344 wtr = BMPopenOutputFile(fnout, hdr);
345 else
346 wtr = BMPopenOutputStream(stdout, hdr);
347 if (wtr == NULL)
348 quiterr("cannot allocate writer structure");
349 /* write to BMP file */
350 while (wtr->yscan < yr) {
351 BYTE *scn = pa + xr*((tmflags & TM_F_BW) ? 1 : 3)*
352 ((rs.rt & YDECR) ?
353 (yr-1 - wtr->yscan) :
354 wtr->yscan);
355 if (tmflags & TM_F_BW)
356 memcpy((void *)wtr->scanline, (void *)scn, xr);
357 else
358 for (i = xr; i--; ) {
359 wtr->scanline[3*i] = scn[3*i+BLU];
360 wtr->scanline[3*i+1] = scn[3*i+GRN];
361 wtr->scanline[3*i+2] = scn[3*i+RED];
362 }
363 if ((i = BMPwriteScanline(wtr)) != BIR_OK)
364 quiterr(BMPerrorMessage(i));
365 }
366 /* flush output */
367 if (fflush((FILE *)wtr->c_data) < 0)
368 quiterr("error writing BMP output");
369 /* clean up */
370 free((void *)pa);
371 BMPcloseOutput(wtr);
372 }