ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_bmp.c
(Generate patch)

Comparing ray/src/px/ra_bmp.c (file contents):
Revision 2.1 by greg, Fri Mar 26 03:11:50 2004 UTC vs.
Revision 2.17 by greg, Sat Jun 7 05:09:46 2025 UTC

# Line 5 | Line 5 | static const char RCSid[] = "$Id$";
5   *  program to convert between RADIANCE and Windows BMP file
6   */
7  
8 < #include  <stdio.h>
8 > #include  <math.h>
9 >
10 > #include  "rtio.h"
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 */
17 > int             bradj = 0;              /* brightness adjustment */
18  
19 < double  gamcor = 2.2;                   /* gamma correction value */
19 > double          gamcor = 2.2;           /* gamma correction value */
20  
21 < char  *progname;
21 > static void quiterr(const char *err);
22 > static void tmap2bmp(char *fnin, char *fnout, char *expec,
23 >                                RGBPRIMP monpri, double gamval);
24 > static void rad2bmp(FILE *rfp, BMPWriter *bwr, int inv, RGBPRIMP monpri);
25 > static void bmp2rad(BMPReader *brd, FILE *rfp, int inv);
26  
27 < void    quiterr(const char *);
28 < void    rad2bmp(FILE *rfp, BMPWriter *bwr, int inv, int gry);
22 < void    bmp2rad(BMPReader *brd, FILE *rfp, int inv);
27 > static RGBPRIMP rgbinp = stdprims;      /* RGB input primitives */
28 > static RGBPRIMS myinprims;              /* custom primitives holder */
29  
30 + static gethfunc headline;
31  
32 +
33   int
34   main(int argc, char *argv[])
35   {
36 <        char    *inpfile=NULL, *outfile=NULL;
37 <        int     gryflag = 0;
38 <        int     reverse = 0;
39 <        RESOLU  rs;
40 <        int     i;
36 >        char            *inpfile=NULL, *outfile=NULL;
37 >        char            *expec = NULL;
38 >        int             reverse = 0;
39 >        RGBPRIMP        rgbp = stdprims;
40 >        RGBPRIMS        myprims;
41 >        RESOLU          rs;
42 >        int             i;
43          
44 <        progname = argv[0];
44 >        fixargv0(argv[0]);              /* assigns progname */
45  
46          for (i = 1; i < argc; i++)
47 <                if (argv[i][0] == '-')
47 >                if (argv[i][0] == '-' && argv[i][1])
48                          switch (argv[i][1]) {
49                          case 'b':
50 <                                gryflag = 1;
50 >                                rgbp = NULL;
51                                  break;
52                          case 'g':
53                                  gamcor = atof(argv[++i]);
54                                  break;
55                          case 'e':
56                                  if (argv[i+1][0] != '+' && argv[i+1][0] != '-')
57 +                                        expec = argv[++i];
58 +                                else
59 +                                        bradj = atoi(argv[++i]);
60 +                                break;
61 +                        case 'p':
62 +                                if (argc-i < 9)
63                                          goto userr;
64 <                                bradj = atoi(argv[++i]);
64 >                                myprims[RED][CIEX] = atof(argv[++i]);
65 >                                myprims[RED][CIEY] = atof(argv[++i]);
66 >                                myprims[GRN][CIEX] = atof(argv[++i]);
67 >                                myprims[GRN][CIEY] = atof(argv[++i]);
68 >                                myprims[BLU][CIEX] = atof(argv[++i]);
69 >                                myprims[BLU][CIEY] = atof(argv[++i]);
70 >                                myprims[WHT][CIEX] = atof(argv[++i]);
71 >                                myprims[WHT][CIEY] = atof(argv[++i]);
72 >                                if (rgbp == stdprims)
73 >                                        rgbp = myprims;
74                                  break;
75                          case 'r':
76                                  reverse = !reverse;
77                                  break;
53                        case '\0':
54                                break;
78                          default:
79                                  goto userr;
80                          }
# Line 70 | Line 93 | main(int argc, char *argv[])
93  
94          if (i == argc-2 && strcmp(argv[i+1], "-"))
95                  outfile = argv[i+1];
96 +                                        /* check for tone-mapping */
97 +        if (expec != NULL) {
98 +                if (reverse)
99 +                        goto userr;
100 +                tmap2bmp(inpfile, outfile, expec, rgbp, gamcor);
101 +                return(0);
102 +        }
103  
104          setcolrgam(gamcor);             /* set up conversion */
105  
# Line 100 | Line 130 | main(int argc, char *argv[])
130                  rs.xr = rdr->hdr->width;
131                  rs.yr = rdr->hdr->height;
132                  rs.rt = YMAJOR;
133 +                                        /* write scans downward if we can */
134                  if (rdr->hdr->yIsDown || inpfile != NULL)
135                          rs.rt |= YDECR;
136                  fputsresolu(&rs, stdout);
137                                          /* convert file */
138                  bmp2rad(rdr, stdout, !rdr->hdr->yIsDown && inpfile!=NULL);
139                                          /* flush output */
140 <                BMPcloseInput(rdr);     /* COMMENT OUT LATER */
140 >                BMPcloseInput(rdr);
141                  if (fflush(stdout) < 0)
142                          quiterr("error writing Radiance output");
143          } else {
# Line 119 | Line 150 | main(int argc, char *argv[])
150                          exit(1);
151                  }
152                                          /* get header info. */
153 <                if (checkheader(stdin, COLRFMT, NULL) < 0 ||
153 >                if (getheader(stdin, headline, NULL) < 0 ||
154                                  !fgetsresolu(&rs, stdin))
155                          quiterr("bad Radiance picture format");
156                                          /* initialize BMP header */
157 <                if (gryflag)
158 <                        hdr = BMPmappedHeader(numscans(&rs),
159 <                                                scanlen(&rs), 0, 256);
160 <                else
161 <                        hdr = BMPtruecolorHeader(numscans(&rs),
162 <                                                scanlen(&rs), 0);
157 >                if (rgbp == NULL) {
158 >                        hdr = BMPmappedHeader(scanlen(&rs),
159 >                                                numscans(&rs), 0, 256);
160 >                        /*
161 >                        if (outfile != NULL)
162 >                                hdr->compr = BI_RLE8;
163 >                        */
164 >                } else
165 >                        hdr = BMPtruecolorHeader(scanlen(&rs),
166 >                                                numscans(&rs), 0);
167                  if (hdr == NULL)
168                          quiterr("cannot initialize BMP header");
169 <                hdr->yIsDown = (rs.rt & YDECR) && outfile == NULL;
169 >                                        /* set up output direction */
170 >                hdr->yIsDown = ((outfile == NULL) | (hdr->compr == BI_RLE8));
171                                          /* open BMP output */
172                  if (outfile != NULL)
173                          wtr = BMPopenOutputFile(outfile, hdr);
174                  else
175                          wtr = BMPopenOutputStream(stdout, hdr);
176 +                if (wtr == NULL)
177 +                        quiterr("cannot allocate writer structure");
178                                          /* convert file */
179 <                rad2bmp(stdin, wtr, !hdr->yIsDown && (rs.rt&YDECR), gryflag);
179 >                rad2bmp(stdin, wtr, !hdr->yIsDown, rgbp);
180                                          /* flush output */
181                  if (fflush((FILE *)wtr->c_data) < 0)
182                          quiterr("error writing BMP output");
183 <                BMPcloseOutput(wtr);    /* COMMENT OUT LATER */
183 >                BMPcloseOutput(wtr);
184          }
185 <        exit(0);                        /* success */
185 >        return(0);                      /* success */
186   userr:
187          fprintf(stderr,
188 <                "Usage: %s [-r][-g gamma][-e +/-stops] [input [output]]\n",
188 > "Usage: %s [-b][-g gamma][-e spec][-p xr yr xg yg xb yb xw yw] [input|- [output]]\n",
189                          progname);
190 <        exit(1);
191 <        return(1);      /* to keep compiler happy */
190 >        fprintf(stderr,
191 >                "   or: %s -r [-g gamma][-e +/-stops] [input|- [output]]\n",
192 >                        progname);
193 >        return(1);
194   }
195  
196   /* print message and exit */
197 < void
197 > static void
198   quiterr(const char *err)
199   {
200          if (err != NULL) {
# Line 164 | Line 204 | quiterr(const char *err)
204          exit(0);
205   }
206  
207 + /* process header line (don't echo) */
208 + static int
209 + headline(char *s, void *p)
210 + {
211 +        char    fmt[MAXFMTLEN];
212 +
213 +        if (formatval(fmt, s)) {        /* check if format string */
214 +                if (!strcmp(fmt,COLRFMT))
215 +                        return(0);
216 +                if (!strcmp(fmt,CIEFMT)) {
217 +                        rgbinp = TM_XYZPRIM;
218 +                        return(0);
219 +                }
220 +                if (!strcmp(fmt,SPECFMT))
221 +                        return(0);
222 +                return(-1);
223 +        }
224 +        if (isprims(s)) {               /* get input primaries */
225 +                primsval(myinprims, s);
226 +                rgbinp = myinprims;
227 +                return(0);
228 +        }
229 +        if (isncomp(s)) {
230 +                NCSAMP = ncompval(s);
231 +                return(0);
232 +        }
233 +        if (iswlsplit(s)) {
234 +                wlsplitval(WLPART, s);
235 +                return(0);
236 +        }
237 +                                        /* should I grok colcorr also? */
238 +        return(0);
239 + }
240 +
241 +
242   /* convert Radiance picture to BMP */
243 < void
244 < rad2bmp(FILE *rfp, BMPWriter *bwr, int inv, int gry)
243 > static void
244 > rad2bmp(FILE *rfp, BMPWriter *bwr, int inv, RGBPRIMP monpri)
245   {
246 +        int     usexfm = 0;
247 +        COLORMAT        xfm;
248          COLR    *scanin;
249 +        COLOR   cval;
250          int     y, yend, ystp;
251          int     x;
252                                                  /* allocate scanline */
253          scanin = (COLR *)malloc(bwr->hdr->width*sizeof(COLR));
254          if (scanin == NULL)
255                  quiterr("out of memory in rad2bmp");
256 +                                                /* set up color conversion */
257 +        usexfm = (monpri != NULL ? rgbinp != monpri :
258 +                        rgbinp != TM_XYZPRIM && rgbinp != stdprims);
259 +        if (usexfm) {
260 +                RGBPRIMP        destpri = monpri != NULL ? monpri : stdprims;
261 +                double          expcomp = pow(2.0, (double)bradj);
262 +                if (rgbinp == TM_XYZPRIM)
263 +                        compxyz2rgbWBmat(xfm, destpri);
264 +                else
265 +                        comprgb2rgbWBmat(xfm, rgbinp, destpri);
266 +                for (y = 0; y < 3; y++)
267 +                        for (x = 0; x < 3; x++)
268 +                                xfm[y][x] *= expcomp;
269 +        }
270                                                  /* convert image */
271          if (inv) {
272                  y = bwr->hdr->height - 1;
# Line 185 | Line 277 | rad2bmp(FILE *rfp, BMPWriter *bwr, int inv, int gry)
277          }
278                                                  /* convert each scanline */
279          for ( ; y != yend; y += ystp) {
280 <                if (freadcolrs(scanin, bwr->hdr->width, rfp) < 0)
280 >                if (fread2colrs(scanin, bwr->hdr->width, rfp, NCSAMP, WLPART) < 0)
281                          quiterr("error reading Radiance picture");
282 <                if (bradj)
282 >                if (usexfm)
283 >                        for (x = bwr->hdr->width; x--; ) {
284 >                                colr_color(cval, scanin[x]);
285 >                                colortrans(cval, xfm, cval);
286 >                                setcolr(scanin[x], colval(cval,RED),
287 >                                                colval(cval,GRN),
288 >                                                colval(cval,BLU));
289 >                        }
290 >                else if (bradj)
291                          shiftcolrs(scanin, bwr->hdr->width, bradj);
292 <                for (x = gry ? bwr->hdr->width : 0; x--; )
293 <                        scanin[x][GRN] = normbright(scanin[x]);
292 >                if (monpri == NULL && rgbinp != TM_XYZPRIM)
293 >                        for (x = bwr->hdr->width; x--; )
294 >                                scanin[x][GRN] = normbright(scanin[x]);
295                  colrs_gambs(scanin, bwr->hdr->width);
296 <                if (gry)
296 >                if (monpri == NULL)
297                          for (x = bwr->hdr->width; x--; )
298                                  bwr->scanline[x] = scanin[x][GRN];
299                  else
# Line 211 | Line 312 | rad2bmp(FILE *rfp, BMPWriter *bwr, int inv, int gry)
312   }
313  
314   /* convert BMP file to Radiance */
315 < void
315 > static void
316   bmp2rad(BMPReader *brd, FILE *rfp, int inv)
317   {
318          COLR    *scanout;
# Line 248 | Line 349 | bmp2rad(BMPReader *brd, FILE *rfp, int inv)
349          }
350                                                  /* clean up */
351          free((void *)scanout);
352 + }
353 +
354 + /* Tone-map and convert Radiance picture */
355 + static void
356 + tmap2bmp(char *fnin, char *fnout, char *expec, RGBPRIMP monpri, double gamval)
357 + {
358 +        int             tmflags;
359 +        BMPHeader       *hdr;
360 +        BMPWriter       *wtr;
361 +        FILE            *fp;
362 +        int             xr, yr;
363 +        uby8            *pa;
364 +        int             i;
365 +                                        /* check tone-mapping spec */
366 +        i = strlen(expec);
367 +        if (i && !strncmp(expec, "auto", i))
368 +                tmflags = TM_F_CAMERA;
369 +        else if (i && !strncmp(expec, "human", i))
370 +                tmflags = TM_F_HUMAN & ~TM_F_UNIMPL;
371 +        else if (i && !strncmp(expec, "linear", i))
372 +                tmflags = TM_F_LINEAR;
373 +        else
374 +                quiterr("illegal exposure specification (auto|human|linear)");
375 +        if (monpri == NULL) {
376 +                tmflags |= TM_F_BW;
377 +                monpri = stdprims;
378 +        }
379 +                                        /* open Radiance input */
380 +        if (fnin == NULL)
381 +                fp = stdin;
382 +        else if ((fp = fopen(fnin, "r")) == NULL) {
383 +                fprintf(stderr, "%s: cannot open\n", fnin);
384 +                exit(1);
385 +        }
386 +                                        /* tone-map picture */
387 +        if (tmMapPicture(&pa, &xr, &yr, tmflags, monpri, gamval,
388 +                        0., 0., fnin, fp) != TM_E_OK)
389 +                exit(1);
390 +                                        /* initialize BMP header */
391 +        if (tmflags & TM_F_BW) {
392 +                hdr = BMPmappedHeader(xr, yr, 0, 256);
393 +                if (fnout != NULL)
394 +                        hdr->compr = BI_RLE8;
395 +        } else
396 +                hdr = BMPtruecolorHeader(xr, yr, 0);
397 +        if (hdr == NULL)
398 +                quiterr("cannot initialize BMP header");
399 +                                        /* open BMP output */
400 +        if (fnout != NULL)
401 +                wtr = BMPopenOutputFile(fnout, hdr);
402 +        else
403 +                wtr = BMPopenOutputStream(stdout, hdr);
404 +        if (wtr == NULL)
405 +                quiterr("cannot allocate writer structure");
406 +                                        /* write to BMP file */
407 +        while (wtr->yscan < yr) {
408 +                uby8    *scn = pa + xr*((tmflags & TM_F_BW) ? 1 : 3)*
409 +                                                (yr-1 - wtr->yscan);
410 +                if (tmflags & TM_F_BW)
411 +                        memcpy((void *)wtr->scanline, (void *)scn, xr);
412 +                else
413 +                        for (i = xr; i--; ) {
414 +                                wtr->scanline[3*i] = scn[3*i+BLU];
415 +                                wtr->scanline[3*i+1] = scn[3*i+GRN];
416 +                                wtr->scanline[3*i+2] = scn[3*i+RED];
417 +                        }
418 +                if ((i = BMPwriteScanline(wtr)) != BIR_OK)
419 +                        quiterr(BMPerrorMessage(i));
420 +        }
421 +                                        /* flush output */
422 +        if (fflush((FILE *)wtr->c_data) < 0)
423 +                quiterr("error writing BMP output");
424 +                                        /* clean up */
425 +        if (fnin != NULL)
426 +                fclose(fp);
427 +        free((void *)pa);
428 +        BMPcloseOutput(wtr);
429   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines