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

Comparing src/px/ra_bmp.c (file contents):
Revision 2.8 by greg, Tue Jul 20 03:08:42 2004 UTC vs.
Revision 2.18 by greg, Sun Sep 14 04:39:53 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>
9 < #include  <string.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 > char            *info = "";             /* information header string */
22 > int             infolen = 0;            /* information header length */
23  
24 < static void quiterr(const char *err);
25 < static void tmap2bmp(char *fnin, char *fnout, char *expec,
24 > extern void quiterr(const char *err);
25 > extern void addBMPcspace(RGBPRIMP pp, double gamma);
26 > extern void tmap2bmp(char *fnin, char *fnout, char *expec,
27                                  RGBPRIMP monpri, double gamval);
28 < static void rad2bmp(FILE *rfp, BMPWriter *bwr, int inv, int gry);
29 < static void bmp2rad(BMPReader *brd, FILE *rfp, int inv);
28 > extern void rad2bmp(FILE *rfp, BMPWriter *bwr, int inv, RGBPRIMP monpri);
29 > extern void bmp2rad(BMPReader *brd, FILE *rfp, int inv);
30 > extern void info2rad(char *infs, int len, FILE *fout);
31 > extern char *growInfo(int n);
32 > extern gethfunc headline;
33  
34 + #define add2info(s)     strcpy(growInfo(strlen(s)), s)
35 + #define clearInfo()     growInfo(-infolen)
36  
37 + RGBPRIMP        rgbinp = stdprims;      /* RGB input primitives */
38 + RGBPRIMS        myinprims;              /* custom primitives holder */
39 +
40 +
41   int
42   main(int argc, char *argv[])
43   {
# Line 38 | Line 49 | main(int argc, char *argv[])
49          RESOLU          rs;
50          int             i;
51          
52 <        progname = argv[0];
52 >        fixargv0(argv[0]);              /* assigns progname */
53  
54          for (i = 1; i < argc; i++)
55                  if (argv[i][0] == '-' && argv[i][1])
# Line 90 | Line 101 | main(int argc, char *argv[])
101  
102          if (i == argc-2 && strcmp(argv[i+1], "-"))
103                  outfile = argv[i+1];
104 <                                        /* check for tone-mapping */
105 <        if (expec != NULL) {
104 >
105 >        if (expec != NULL) {            /* check for tone-mapping */
106                  if (reverse)
107                          goto userr;
108                  tmap2bmp(inpfile, outfile, expec, rgbp, gamcor);
109                  return(0);
110          }
100
101        setcolrgam(gamcor);             /* set up conversion */
102
111          if (reverse) {
112                  BMPReader       *rdr;
113                                          /* open BMP file or stream */
# Line 121 | Line 129 | main(int argc, char *argv[])
129                  }
130                                          /* put Radiance header */
131                  newheader("RADIANCE", stdout);
132 +                info2rad(BMPinfo(rdr->hdr), rdr->hdr->infoSiz, stdout);
133                  printargs(i, argv, stdout);
134                  fputformat(COLRFMT, stdout);
135                  putchar('\n');
# Line 131 | Line 140 | main(int argc, char *argv[])
140                  if (rdr->hdr->yIsDown || inpfile != NULL)
141                          rs.rt |= YDECR;
142                  fputsresolu(&rs, stdout);
143 +                                        /* set up conversion */
144 +                setcolrgam(gamcor);
145                                          /* convert file */
146 <                bmp2rad(rdr, stdout, !rdr->hdr->yIsDown && inpfile!=NULL);
146 >                bmp2rad(rdr, stdout, !rdr->hdr->yIsDown & (inpfile!=NULL));
147                                          /* flush output */
148                  BMPcloseInput(rdr);
149                  if (fflush(stdout) < 0)
# Line 146 | Line 157 | main(int argc, char *argv[])
157                                          inpfile);
158                          exit(1);
159                  }
160 <                                        /* get header info. */
161 <                if (checkheader(stdin, COLRFMT, NULL) < 0 ||
162 <                                !fgetsresolu(&rs, stdin))
160 >                                        /* get/save header info. */
161 >                if (getheader(stdin, headline, NULL) < 0 ||
162 >                                        !fgetsresolu(&rs, stdin))
163                          quiterr("bad Radiance picture format");
164 <                                        /* initialize BMP header */
164 >                                        /* record color space */
165 >                addBMPcspace(rgbp, gamcor);
166 >                                        /* open output/write BMP header */
167                  if (rgbp == NULL) {
168                          hdr = BMPmappedHeader(scanlen(&rs),
169 <                                                numscans(&rs), 0, 256);
169 >                                                numscans(&rs), infolen+1, 256);
170 >                        /*
171                          if (outfile != NULL)
172                                  hdr->compr = BI_RLE8;
173 +                        */
174                  } else
175                          hdr = BMPtruecolorHeader(scanlen(&rs),
176 <                                                numscans(&rs), 0);
176 >                                                numscans(&rs), infolen+1);
177                  if (hdr == NULL)
178 <                        quiterr("cannot initialize BMP header");
178 >                        quiterr("cannot create BMP output");
179 >                                        /* copy info to BMP header */
180 >                strcpy(BMPinfo(hdr), info);
181 >                clearInfo();
182                                          /* set up output direction */
183                  hdr->yIsDown = ((outfile == NULL) | (hdr->compr == BI_RLE8));
184                                          /* open BMP output */
# Line 170 | Line 188 | main(int argc, char *argv[])
188                          wtr = BMPopenOutputStream(stdout, hdr);
189                  if (wtr == NULL)
190                          quiterr("cannot allocate writer structure");
191 +                                        /* set up conversion */
192 +                setcolrgam(gamcor);
193                                          /* convert file */
194 <                rad2bmp(stdin, wtr, !hdr->yIsDown, rgbp==NULL);
194 >                rad2bmp(stdin, wtr, !hdr->yIsDown, rgbp);
195                                          /* flush output */
196                  if (fflush((FILE *)wtr->c_data) < 0)
197                          quiterr("error writing BMP output");
# Line 189 | Line 209 | userr:
209   }
210  
211   /* print message and exit */
212 < static void
212 > void
213   quiterr(const char *err)
214   {
215          if (err != NULL) {
# Line 199 | Line 219 | quiterr(const char *err)
219          exit(0);
220   }
221  
222 + /* grow (or shrink) saved info header string */
223 + char *
224 + growInfo(int n)
225 + {
226 +        char    *ns = NULL;
227 +
228 +        if (infolen + n <= 0) {
229 +                if (info) free(info);
230 +                info = "";
231 +                infolen = 0;
232 +                return(NULL);
233 +        }
234 +        if (infolen)
235 +                info = (char *)realloc(info, infolen+n+1);
236 +        else
237 +                info = (char *)malloc(n+1);
238 +
239 +        if (info == NULL)
240 +                quiterr("out of memory in growInfo()");
241 +
242 +        if (n > 0) memset(ns = info+infolen, 0, n+1);
243 +
244 +        infolen += n;
245 +        return(ns);
246 + }
247 +
248 + /* process header line (don't echo) */
249 + int
250 + headline(char *s, void *p)
251 + {
252 +        char    fmt[MAXFMTLEN];
253 +
254 +        if (isheadid(s))                /* skip header magic ID */
255 +                return(0);
256 +        if (formatval(fmt, s)) {        /* check if format string */
257 +                if (!strcmp(fmt,COLRFMT))
258 +                        return(0);
259 +                if (!strcmp(fmt,CIEFMT)) {
260 +                        rgbinp = TM_XYZPRIM;
261 +                        return(0);
262 +                }
263 +                if (!strcmp(fmt,SPECFMT))
264 +                        return(0);
265 +                return(-1);
266 +        }
267 +        if (isprims(s)) {               /* get input primaries */
268 +                primsval(myinprims, s);
269 +                rgbinp = myinprims;
270 +                return(0);
271 +        }
272 +        if (isexpos(s))
273 +                return(0);              /* ignore this on input */
274 +        if (!strncmp(s, "GAMMA=", 6))
275 +                return(0);              /* should not be here! */
276 +        if (isncomp(s)) {
277 +                NCSAMP = ncompval(s);
278 +                return(0);
279 +        }
280 +        if (iswlsplit(s)) {
281 +                wlsplitval(WLPART, s);
282 +                return(0);
283 +        }
284 +        add2info(s);                    /* else save info string */
285 +        return(1);
286 + }
287 +
288 + /* add BMP output color space to info string */
289 + void
290 + addBMPcspace(RGBPRIMP pp, double gamma)
291 + {
292 +        char    ibuf[128];
293 +
294 +        if (pp != NULL) {
295 +                sprintf(ibuf,
296 +                        "%s %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f\n",
297 +                                PRIMARYSTR,
298 +                                pp[RED][CIEX],pp[RED][CIEY],
299 +                                pp[GRN][CIEX],pp[GRN][CIEY],
300 +                                pp[BLU][CIEX],pp[BLU][CIEY],
301 +                                pp[WHT][CIEX],pp[WHT][CIEY]);
302 +                add2info(ibuf);
303 +        }
304 +        sprintf(ibuf, "GAMMA=%.2f\n", gamma);
305 +        add2info(ibuf);
306 + }
307 +
308 + /* write out Radiance header from BMP info string */
309 + void
310 + info2rad(char *infs, int len, FILE *fout)
311 + {
312 +        char    *cp;
313 +                                        /* must fit metadata profile */
314 +        if (len < 3 || infs[0] == '\n' ||
315 +                        infs[--len] != '\0' || infs[len-1] != '\n')
316 +                return;                 /* not what we expected */
317 +        if (strlen(infs) < len || strstr(infs, "\n\n") != NULL)
318 +                return;                 /* also not cool */
319 +                                        /* check for gamma */
320 +        if ((cp = strstr(infs, "GAMMA=")) != NULL) {
321 +                                        /* copy what came before */
322 +                fwrite(infs, cp-infs, 1, fout);
323 +                cp += 6;
324 +                gamcor = atof(cp);      /* record setting */
325 +                while (*cp++ != '\n')
326 +                        ;
327 +                len -= cp - infs;
328 +                infs = cp;              /* & elide from output */
329 +        }
330 +        fputs(infs, fout);              /* copy the remainder */
331 + }
332 +
333   /* convert Radiance picture to BMP */
334 < static void
335 < rad2bmp(FILE *rfp, BMPWriter *bwr, int inv, int gry)
334 > void
335 > rad2bmp(FILE *rfp, BMPWriter *bwr, int inv, RGBPRIMP monpri)
336   {
337 +        int     usexfm = 0;
338 +        COLORMAT        xfm;
339          COLR    *scanin;
340 +        COLOR   cval;
341          int     y, yend, ystp;
342          int     x;
343                                                  /* allocate scanline */
344          scanin = (COLR *)malloc(bwr->hdr->width*sizeof(COLR));
345          if (scanin == NULL)
346                  quiterr("out of memory in rad2bmp");
347 +                                                /* set up color conversion */
348 +        usexfm = (monpri != NULL) ? (rgbinp != monpri) :
349 +                        ((rgbinp != TM_XYZPRIM) & (rgbinp != stdprims));
350 +        if (usexfm) {
351 +                RGBPRIMP        destpri = monpri != NULL ? monpri : stdprims;
352 +                double          expcomp = pow(2.0, (double)bradj);
353 +                if (rgbinp == TM_XYZPRIM)
354 +                        compxyz2rgbWBmat(xfm, destpri);
355 +                else
356 +                        comprgb2rgbWBmat(xfm, rgbinp, destpri);
357 +                for (y = 0; y < 3; y++)
358 +                        for (x = 0; x < 3; x++)
359 +                                xfm[y][x] *= expcomp;
360 +        }
361                                                  /* convert image */
362          if (inv) {
363                  y = bwr->hdr->height - 1;
# Line 220 | Line 368 | rad2bmp(FILE *rfp, BMPWriter *bwr, int inv, int gry)
368          }
369                                                  /* convert each scanline */
370          for ( ; y != yend; y += ystp) {
371 <                if (freadcolrs(scanin, bwr->hdr->width, rfp) < 0)
371 >                if (fread2colrs(scanin, bwr->hdr->width, rfp, NCSAMP, WLPART) < 0)
372                          quiterr("error reading Radiance picture");
373 <                if (bradj)
373 >                if (usexfm)
374 >                        for (x = bwr->hdr->width; x--; ) {
375 >                                colr_color(cval, scanin[x]);
376 >                                colortrans(cval, xfm, cval);
377 >                                setcolr(scanin[x], colval(cval,RED),
378 >                                                colval(cval,GRN),
379 >                                                colval(cval,BLU));
380 >                        }
381 >                else if (bradj)
382                          shiftcolrs(scanin, bwr->hdr->width, bradj);
383 <                for (x = gry ? bwr->hdr->width : 0; x--; )
384 <                        scanin[x][GRN] = normbright(scanin[x]);
383 >                if (monpri == NULL && rgbinp != TM_XYZPRIM)
384 >                        for (x = bwr->hdr->width; x--; )
385 >                                scanin[x][GRN] = normbright(scanin[x]);
386                  colrs_gambs(scanin, bwr->hdr->width);
387 <                if (gry)
387 >                if (monpri == NULL)
388                          for (x = bwr->hdr->width; x--; )
389                                  bwr->scanline[x] = scanin[x][GRN];
390                  else
# Line 241 | Line 398 | rad2bmp(FILE *rfp, BMPWriter *bwr, int inv, int gry)
398                  if (x != BIR_OK)
399                          quiterr(BMPerrorMessage(x));
400          }
401 <                                                /* free scanline */
245 <        free((void *)scanin);
401 >        free(scanin);                           /* free scanline */
402   }
403  
404   /* convert BMP file to Radiance */
405 < static void
405 > void
406   bmp2rad(BMPReader *brd, FILE *rfp, int inv)
407   {
408          COLR    *scanout;
# Line 281 | Line 437 | bmp2rad(BMPReader *brd, FILE *rfp, int inv)
437                  if (fwritecolrs(scanout, brd->hdr->width, rfp) < 0)
438                          quiterr("error writing Radiance picture");
439          }
440 <                                                /* clean up */
285 <        free((void *)scanout);
440 >        free(scanout);                          /* clean up */
441   }
442  
443   /* Tone-map and convert Radiance picture */
444 < static void
444 > void
445   tmap2bmp(char *fnin, char *fnout, char *expec, RGBPRIMP monpri, double gamval)
446   {
447          int             tmflags;
# Line 294 | Line 449 | tmap2bmp(char *fnin, char *fnout, char *expec, RGBPRIM
449          BMPWriter       *wtr;
450          FILE            *fp;
451          int             xr, yr;
452 <        BYTE            *pa;
452 >        uby8            *pa;
453          int             i;
454                                          /* check tone-mapping spec */
455          i = strlen(expec);
# Line 321 | Line 476 | tmap2bmp(char *fnin, char *fnout, char *expec, RGBPRIM
476          if (tmMapPicture(&pa, &xr, &yr, tmflags, monpri, gamval,
477                          0., 0., fnin, fp) != TM_E_OK)
478                  exit(1);
479 +                                        /* try to retrieve info */
480 +        if (fseek(fp, 0L, SEEK_SET) == 0)
481 +                getheader(fp, headline, NULL);
482 +                                        /* add output color space */
483 +        addBMPcspace(monpri, gamval);
484                                          /* initialize BMP header */
485          if (tmflags & TM_F_BW) {
486 <                hdr = BMPmappedHeader(xr, yr, 0, 256);
486 >                hdr = BMPmappedHeader(xr, yr, infolen+1, 256);
487                  if (fnout != NULL)
488                          hdr->compr = BI_RLE8;
489          } else
490 <                hdr = BMPtruecolorHeader(xr, yr, 0);
490 >                hdr = BMPtruecolorHeader(xr, yr, infolen+1);
491          if (hdr == NULL)
492                  quiterr("cannot initialize BMP header");
493 +
494 +        strcpy(BMPinfo(hdr), info);     /* copy info if any */
495 +        clearInfo();
496                                          /* open BMP output */
497          if (fnout != NULL)
498                  wtr = BMPopenOutputFile(fnout, hdr);
# Line 339 | Line 502 | tmap2bmp(char *fnin, char *fnout, char *expec, RGBPRIM
502                  quiterr("cannot allocate writer structure");
503                                          /* write to BMP file */
504          while (wtr->yscan < yr) {
505 <                BYTE    *scn = pa + xr*((tmflags & TM_F_BW) ? 1 : 3)*
505 >                uby8    *scn = pa + xr*((tmflags & TM_F_BW) ? 1 : 3)*
506                                                  (yr-1 - wtr->yscan);
507                  if (tmflags & TM_F_BW)
508 <                        memcpy((void *)wtr->scanline, (void *)scn, xr);
508 >                        memcpy(wtr->scanline, scn, xr);
509                  else
510                          for (i = xr; i--; ) {
511                                  wtr->scanline[3*i] = scn[3*i+BLU];
# Line 358 | Line 521 | tmap2bmp(char *fnin, char *fnout, char *expec, RGBPRIM
521                                          /* clean up */
522          if (fnin != NULL)
523                  fclose(fp);
524 <        free((void *)pa);
524 >        free(pa);
525          BMPcloseOutput(wtr);
526   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines