ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_bmp.c
Revision: 2.9
Committed: Thu Sep 23 18:00:54 2004 UTC (19 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.8: +68 -12 lines
Log Message:
Enabled -p option (display primaries) and XYZE reading to ra_bmp

File Contents

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