ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_bmp.c
Revision: 2.4
Committed: Fri Apr 30 17:00:29 2004 UTC (20 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.3: +132 -19 lines
Log Message:
Added tone-mapping to ra_bmp and fixed but in RLE8 BMP encoding

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.4 static const char RCSid[] = "$Id: ra_bmp.c,v 2.3 2004/03/28 20:33:14 schorsch Exp $";
3 greg 2.1 #endif
4     /*
5     * program to convert between RADIANCE and Windows BMP file
6     */
7    
8     #include <stdio.h>
9 schorsch 2.3 #include <string.h>
10    
11 greg 2.1 #include "platform.h"
12     #include "color.h"
13 greg 2.4 #include "tonemap.h"
14 greg 2.1 #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 greg 2.4 static void quiterr(const char *err);
24     static void tmap2bmp(char *fnin, char *fnout, char *expec,
25     RGBPRIMP monpri, double gamval);
26 schorsch 2.3 static void rad2bmp(FILE *rfp, BMPWriter *bwr, int inv, int gry);
27     static void bmp2rad(BMPReader *brd, FILE *rfp, int inv);
28 greg 2.1
29    
30     int
31     main(int argc, char *argv[])
32     {
33 greg 2.4 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 greg 2.1
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 greg 2.4 rgbp = NULL;
48 greg 2.1 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 greg 2.4 expec = argv[++i];
55     else
56     bradj = atoi(argv[++i]);
57     break;
58     case 'p':
59     if (argc-i < 9)
60 greg 2.1 goto userr;
61 greg 2.4 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 greg 2.1 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 greg 2.4 /* 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 greg 2.1
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 greg 2.2 /* write scans downward if we can */
133 greg 2.1 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 greg 2.2 BMPcloseInput(rdr);
140 greg 2.1 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 greg 2.4 if (rgbp == NULL) {
157     hdr = BMPmappedHeader(scanlen(&rs),
158     numscans(&rs), 0, 256);
159 greg 2.2 if (outfile != NULL)
160     hdr->compr = BI_RLE8;
161     } else
162 greg 2.4 hdr = BMPtruecolorHeader(scanlen(&rs),
163     numscans(&rs), 0);
164 greg 2.1 if (hdr == NULL)
165     quiterr("cannot initialize BMP header");
166 greg 2.2 /* set up output direction */
167     hdr->yIsDown = (rs.rt & YDECR) &&
168 schorsch 2.3 ((outfile == NULL) | (hdr->compr == BI_RLE8));
169 greg 2.1 /* open BMP output */
170     if (outfile != NULL)
171     wtr = BMPopenOutputFile(outfile, hdr);
172     else
173     wtr = BMPopenOutputStream(stdout, hdr);
174 greg 2.2 if (wtr == NULL)
175     quiterr("cannot allocate writer structure");
176 greg 2.1 /* convert file */
177 greg 2.4 rad2bmp(stdin, wtr, !hdr->yIsDown && rs.rt&YDECR, rgbp==NULL);
178 greg 2.1 /* flush output */
179     if (fflush((FILE *)wtr->c_data) < 0)
180     quiterr("error writing BMP output");
181 greg 2.2 BMPcloseOutput(wtr);
182 greg 2.1 }
183 greg 2.4 return(0); /* success */
184 greg 2.1 userr:
185     fprintf(stderr,
186 greg 2.4 "Usage: %s [-b][-g gamma][-e spec][-p xr yr xg yg xb yb xw yw] [input|- [output]]\n",
187 greg 2.1 progname);
188 greg 2.4 fprintf(stderr,
189     " or: %s -r [-g gamma][-e +/-stops] [input|- [output]]\n",
190     progname);
191     return(1);
192 greg 2.1 }
193    
194     /* print message and exit */
195 schorsch 2.3 static void
196 greg 2.1 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 schorsch 2.3 static void
207 greg 2.1 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 schorsch 2.3 static void
253 greg 2.1 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 greg 2.4
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     hdr->compr = BI_RLE8;
339     } else
340     hdr = BMPtruecolorHeader(xr, yr, 0);
341     if (hdr == NULL)
342     quiterr("cannot initialize BMP header");
343     /* open BMP output */
344     if (fnout != NULL)
345     wtr = BMPopenOutputFile(fnout, hdr);
346     else
347     wtr = BMPopenOutputStream(stdout, hdr);
348     if (wtr == NULL)
349     quiterr("cannot allocate writer structure");
350     /* write to BMP file */
351     while (wtr->yscan < yr) {
352     BYTE *scn = pa + xr*((tmflags & TM_F_BW) ? 1 : 3)*
353     ((rs.rt & YDECR) ?
354     (yr-1 - wtr->yscan) :
355     wtr->yscan);
356     if (tmflags & TM_F_BW)
357     memcpy((void *)wtr->scanline, (void *)scn, xr);
358     else
359     for (i = xr; i--; ) {
360     wtr->scanline[3*i] = scn[3*i+BLU];
361     wtr->scanline[3*i+1] = scn[3*i+GRN];
362     wtr->scanline[3*i+2] = scn[3*i+RED];
363     }
364     if ((i = BMPwriteScanline(wtr)) != BIR_OK)
365     quiterr(BMPerrorMessage(i));
366     }
367     /* flush output */
368     if (fflush((FILE *)wtr->c_data) < 0)
369     quiterr("error writing BMP output");
370     /* clean up */
371     free((void *)pa);
372     BMPcloseOutput(wtr);
373     }