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.17 by greg, Sat Jun 7 05:09:46 2025 UTC vs.
Revision 2.18 by greg, Sun Sep 14 04:39:53 2025 UTC

# Line 18 | Line 18 | int            bradj = 0;              /* brightness adjustment */
18  
19   double          gamcor = 2.2;           /* gamma correction value */
20  
21 < static void quiterr(const char *err);
22 < static void tmap2bmp(char *fnin, char *fnout, char *expec,
21 > char            *info = "";             /* information header string */
22 > int             infolen = 0;            /* information header length */
23 >
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, RGBPRIMP monpri);
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 < static RGBPRIMP rgbinp = stdprims;      /* RGB input primitives */
35 < static RGBPRIMS myinprims;              /* custom primitives holder */
34 > #define add2info(s)     strcpy(growInfo(strlen(s)), s)
35 > #define clearInfo()     growInfo(-infolen)
36  
37 < static gethfunc headline;
37 > RGBPRIMP        rgbinp = stdprims;      /* RGB input primitives */
38 > RGBPRIMS        myinprims;              /* custom primitives holder */
39  
40  
41   int
# Line 93 | 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          }
103
104        setcolrgam(gamcor);             /* set up conversion */
105
111          if (reverse) {
112                  BMPReader       *rdr;
113                                          /* open BMP file or stream */
# Line 124 | 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 134 | 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 149 | Line 157 | main(int argc, char *argv[])
157                                          inpfile);
158                          exit(1);
159                  }
160 <                                        /* get header info. */
160 >                                        /* get/save header info. */
161                  if (getheader(stdin, headline, NULL) < 0 ||
162 <                                !fgetsresolu(&rs, stdin))
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 175 | 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);
195                                          /* flush output */
# Line 194 | 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 204 | 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 < static int
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);
# Line 226 | Line 269 | headline(char *s, void *p)
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);
# Line 234 | Line 281 | headline(char *s, void *p)
281                  wlsplitval(WLPART, s);
282                  return(0);
283          }
284 <                                        /* should I grok colcorr also? */
285 <        return(0);
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
334 > void
335   rad2bmp(FILE *rfp, BMPWriter *bwr, int inv, RGBPRIMP monpri)
336   {
337          int     usexfm = 0;
# Line 254 | Line 345 | rad2bmp(FILE *rfp, BMPWriter *bwr, int inv, RGBPRIMP m
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);
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);
# Line 307 | Line 398 | rad2bmp(FILE *rfp, BMPWriter *bwr, int inv, RGBPRIMP m
398                  if (x != BIR_OK)
399                          quiterr(BMPerrorMessage(x));
400          }
401 <                                                /* free scanline */
311 <        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 347 | 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 */
351 <        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 387 | 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 408 | Line 505 | tmap2bmp(char *fnin, char *fnout, char *expec, RGBPRIM
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 424 | 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