ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_bmp.c
Revision: 2.5
Committed: Fri Apr 30 17:30:33 2004 UTC (20 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.4: +3 -2 lines
Log Message:
Fixed minor problem with RLE8 output

File Contents

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