Logo Search packages:      
Sourcecode: radiance version File versions  Download package

ra_ppm.c

#ifndef lint
static const char RCSid[] = "$Id: ra_ppm.c,v 2.13 2006/01/06 06:40:53 greg Exp $";
#endif
/*
 *  program to convert between RADIANCE and Poskanzer Pixmaps
 */

#include  <stdio.h>
#include  <math.h>
#include  <ctype.h>
#include  <time.h>

#include  "platform.h"
#include  "color.h"
#include  "resolu.h"

#define     fltv(i)           (((i)+.5)/(maxval+1.))
int  bradj = 0;                     /* brightness adjustment */
double      gamcor = 2.2;                 /* gamma correction value */
int  maxval = 255;                  /* maximum primary value */
char  *progname;
int  xmax, ymax;

typedef int colrscanf_t(COLR *scan, int len, FILE *fp);
typedef int colorscanf_t(COLOR *scan, int len, FILE *fp);

static colrscanf_t agryscan, bgryscan, aclrscan, bclrscan;
static void ppm2ra(colrscanf_t *getscan);
static void ra2ppm(int  binary, int  grey);

static colorscanf_t agryscan2, bgryscan2, aclrscan2, bclrscan2;
static void ppm2ra2(colorscanf_t *getscan);
static void ra2ppm2(int  binary, int  grey);

static int normval(unsigned int  v);
static unsigned int scanint(FILE  *fp);
static unsigned int intv(double     v);
static unsigned int getby2(FILE     *fp);
static void putby2(unsigned int     w, FILE     *fp);
static void quiterr(char  *err);


int
main(
      int  argc,
      char  *argv[]
)
{
      char  inpbuf[2];
      int  gryflag = 0;
      int  binflag = 1;
      int  reverse = 0;
      int  ptype;
      int  i;
      
      progname = argv[0];

      for (i = 1; i < argc; i++)
            if (argv[i][0] == '-')
                  switch (argv[i][1]) {
                  case 's':
                        maxval = atoi(argv[++i]) & 0xffff;
                        break;
                  case 'b':
                        gryflag = 1;
                        break;
                  case 'g':
                        gamcor = atof(argv[++i]);
                        break;
                  case 'e':
                        if (argv[i+1][0] != '+' && argv[i+1][0] != '-')
                              goto userr;
                        bradj = atoi(argv[++i]);
                        break;
                  case 'a':
                        binflag = 0;
                        break;
                  case 'r':
                        reverse = !reverse;
                        break;
                  default:
                        goto userr;
                  }
            else
                  break;

      if (i < argc-2)
            goto userr;
      if (i <= argc-1 && freopen(argv[i], "r", stdin) == NULL) {
            fprintf(stderr, "%s: can't open input \"%s\"\n",
                        progname, argv[i]);
            exit(1);
      }
      if (i == argc-2 && freopen(argv[i+1], "w", stdout) == NULL) {
            fprintf(stderr, "%s: can't open output \"%s\"\n",
                        progname, argv[i+1]);
            exit(1);
      }
      if (maxval < 256)
            setcolrgam(gamcor);
      if (reverse) {
                              /* get header */
            if (read(fileno(stdin), inpbuf, 2) != 2 || inpbuf[0] != 'P')
                  quiterr("input not a Poskanzer Pixmap");
            ptype = inpbuf[1];
#ifdef _WIN32
            if (ptype > 4)
                  SET_FILE_BINARY(stdin);
            SET_FILE_BINARY(stdout);
#endif
            xmax = scanint(stdin);
            ymax = scanint(stdin);
            maxval = scanint(stdin);
                              /* put header */
            newheader("RADIANCE", stdout);
            printargs(i, argv, stdout);
            fputformat(COLRFMT, stdout);
            putchar('\n');
            fprtresolu(xmax, ymax, stdout);
                              /* convert file */
            if (maxval >= 256)
                  switch (ptype) {
                  case '2':
                        ppm2ra2(agryscan2);
                        break;
                  case '5':
                        ppm2ra2(bgryscan2);
                        break;
                  case '3':
                        ppm2ra2(aclrscan2);
                        break;
                  case '6':
                        ppm2ra2(bclrscan2);
                        break;
                  default:
                        quiterr("unsupported Pixmap type");
                  }
            else
                  switch (ptype) {
                  case '2':
                        ppm2ra(agryscan);
                        break;
                  case '5':
                        ppm2ra(bgryscan);
                        break;
                  case '3':
                        ppm2ra(aclrscan);
                        break;
                  case '6':
                        ppm2ra(bclrscan);
                        break;
                  default:
                        quiterr("unsupported Pixmap type");
                  }
      } else {
#ifdef _WIN32
            SET_FILE_BINARY(stdin);
            if (binflag)
                  SET_FILE_BINARY(stdout);
#endif
                              /* get header info. */
            if (checkheader(stdin, COLRFMT, NULL) < 0 ||
                        fgetresolu(&xmax, &ymax, stdin) < 0)
                  quiterr("bad picture format");
                              /* write PPM header */
            printf("P%1d\n%d %d\n%u\n", (gryflag?2:3)+(binflag?3:0),
                        xmax, ymax, maxval);
                              /* convert file */
            if (maxval >= 256)
                  ra2ppm2(binflag, gryflag);
            else
                  ra2ppm(binflag, gryflag);
      }
      exit(0);
userr:
      fprintf(stderr,
            "Usage: %s [-r][-a][-b][-s maxv][-g gamma][-e +/-stops] [input [output]]\n",
                  progname);
      exit(1);
}


static void
quiterr(          /* print message and exit */
      char  *err
)
{
      if (err != NULL) {
            fprintf(stderr, "%s: %s\n", progname, err);
            exit(1);
      }
      exit(0);
}


static void
ppm2ra(           /* convert 1-byte Pixmap to Radiance picture */
      colrscanf_t *getscan
)
{
      COLR  *scanout;
      int   y;
                                    /* allocate scanline */
      scanout = (COLR *)malloc(xmax*sizeof(COLR));
      if (scanout == NULL)
            quiterr("out of memory in ppm2ra");
                                    /* convert image */
      for (y = ymax-1; y >= 0; y--) {
            if ((*getscan)(scanout, xmax, stdin) < 0)
                  quiterr("error reading Pixmap");
            gambs_colrs(scanout, xmax);
            if (bradj)
                  shiftcolrs(scanout, xmax, bradj);
            if (fwritecolrs(scanout, xmax, stdout) < 0)
                  quiterr("error writing Radiance picture");
      }
                                    /* free scanline */
      free((void *)scanout);
}


static void
ra2ppm(     /* convert Radiance picture to 1-byte/sample Pixmap */
      int  binary,
      int  grey
)
{
      COLR  *scanin;
      register int      x;
      int   y;
                                    /* allocate scanline */
      scanin = (COLR *)malloc(xmax*sizeof(COLR));
      if (scanin == NULL)
            quiterr("out of memory in ra2ppm");
                                    /* convert image */
      for (y = ymax-1; y >= 0; y--) {
            if (freadcolrs(scanin, xmax, stdin) < 0)
                  quiterr("error reading Radiance picture");
            if (bradj)
                  shiftcolrs(scanin, xmax, bradj);
            for (x = grey?xmax:0; x--; )
                  scanin[x][GRN] = normbright(scanin[x]);
            colrs_gambs(scanin, xmax);
            if (grey)
                  if (binary)
                        for (x = 0; x < xmax; x++)
                              putc(scanin[x][GRN], stdout);
                  else
                        for (x = 0; x < xmax; x++)
                              printf("%d\n", scanin[x][GRN]);
            else
                  if (binary)
                        for (x = 0; x < xmax; x++) {
                              putc(scanin[x][RED], stdout);
                              putc(scanin[x][GRN], stdout);
                              putc(scanin[x][BLU], stdout);
                        }
                  else
                        for (x = 0; x < xmax; x++)
                              printf("%d %d %d\n", scanin[x][RED],
                                          scanin[x][GRN],
                                          scanin[x][BLU]);
            if (ferror(stdout))
                  quiterr("error writing Pixmap");
      }
                                    /* free scanline */
      free((void *)scanin);
}


static void
ppm2ra2(    /* convert 2-byte Pixmap to Radiance picture */
      colorscanf_t *getscan
)
{
      COLOR *scanout;
      double      mult;
      int   y;
      register int      x;
                                    /* allocate scanline */
      scanout = (COLOR *)malloc(xmax*sizeof(COLOR));
      if (scanout == NULL)
            quiterr("out of memory in ppm2ra2");
      if (bradj)
            mult = pow(2., (double)bradj);
                                    /* convert image */
      for (y = ymax-1; y >= 0; y--) {
            if ((*getscan)(scanout, xmax, stdin) < 0)
                  quiterr("error reading Pixmap");
            for (x = (gamcor>1.01)|(gamcor<0.99)?xmax:0; x--; ) {
                  colval(scanout[x],RED) =
                              pow(colval(scanout[x],RED), gamcor);
                  colval(scanout[x],GRN) =
                              pow(colval(scanout[x],GRN), gamcor);
                  colval(scanout[x],BLU) =
                              pow(colval(scanout[x],BLU), gamcor);
            }
            for (x = bradj?xmax:0; x--; )
                  scalecolor(scanout[x], mult);
            if (fwritescan(scanout, xmax, stdout) < 0)
                  quiterr("error writing Radiance picture");
      }
                                    /* free scanline */
      free((void *)scanout);
}


static void
ra2ppm2(    /* convert Radiance picture to Pixmap (2-byte) */
      int  binary,
      int  grey
)
{
      COLOR *scanin;
      double      mult, d;
      register int      x;
      int   y;
                                    /* allocate scanline */
      scanin = (COLOR *)malloc(xmax*sizeof(COLOR));
      if (scanin == NULL)
            quiterr("out of memory in ra2ppm2");
      if (bradj)
            mult = pow(2., (double)bradj);
                                    /* convert image */
      for (y = ymax-1; y >= 0; y--) {
            if (freadscan(scanin, xmax, stdin) < 0)
                  quiterr("error reading Radiance picture");
            for (x = bradj?xmax:0; x--; )
                  scalecolor(scanin[x], mult);
            for (x = grey?xmax:0; x--; )
                  colval(scanin[x],GRN) = bright(scanin[x]);
            d = 1./gamcor;
            for (x = (d>1.01)|(d<0.99)?xmax:0; x--; ) {
                  colval(scanin[x],GRN) = pow(colval(scanin[x],GRN), d);
                  if (!grey) {
                        colval(scanin[x],RED) =
                                    pow(colval(scanin[x],RED), d);
                        colval(scanin[x],BLU) =
                                    pow(colval(scanin[x],BLU), d);
                  }
            }
            if (grey)
                  if (binary)
                        for (x = 0; x < xmax; x++)
                              putby2(intv(colval(scanin[x],GRN)),
                                          stdout);
                  else
                        for (x = 0; x < xmax; x++)
                              printf("%u\n",
                                    intv(colval(scanin[x],GRN)));
            else
                  if (binary)
                        for (x = 0; x < xmax; x++) {
                              putby2(intv(colval(scanin[x],RED)),
                                          stdout);
                              putby2(intv(colval(scanin[x],GRN)),
                                          stdout);
                              putby2(intv(colval(scanin[x],BLU)),
                                          stdout);
                        }
                  else
                        for (x = 0; x < xmax; x++)
                              printf("%u %u %u\n",
                                    intv(colval(scanin[x],RED)),
                                    intv(colval(scanin[x],GRN)),
                                    intv(colval(scanin[x],BLU)));
            if (ferror(stdout))
                  quiterr("error writing Pixmap");
      }
                                    /* free scanline */
      free((void *)scanin);
}


static int
agryscan(               /* get an ASCII greyscale scanline */
      register COLR  *scan,
      register int  len,
      FILE  *fp
)
{
      while (len-- > 0) {
            scan[0][RED] =
            scan[0][GRN] =
            scan[0][BLU] = normval(scanint(fp));
            scan++;
      }
      return(0);
}


static int
bgryscan(               /* get a binary greyscale scanline */
      register COLR  *scan,
      int  len,
      register FILE  *fp
)
{
      register int  c;

      while (len-- > 0) {
            if ((c = getc(fp)) == EOF)
                  return(-1);
            if (maxval != 255)
                  c = normval(c);
            scan[0][RED] =
            scan[0][GRN] =
            scan[0][BLU] = c;
            scan++;
      }
      return(0);
}


static int
aclrscan(               /* get an ASCII color scanline */
      register COLR  *scan,
      register int  len,
      FILE  *fp
)
{
      while (len-- > 0) {
            scan[0][RED] = normval(scanint(fp));
            scan[0][GRN] = normval(scanint(fp));
            scan[0][BLU] = normval(scanint(fp));
            scan++;
      }
      return(0);
}


static int
bclrscan(               /* get a binary color scanline */
      register COLR  *scan,
      int  len,
      register FILE  *fp
)
{
      int  r, g, b;

      while (len-- > 0) {
            r = getc(fp);
            g = getc(fp);
            if ((b = getc(fp)) == EOF)
                  return(-1);
            if (maxval == 255) {
                  scan[0][RED] = r;
                  scan[0][GRN] = g;
                  scan[0][BLU] = b;
            } else {
                  scan[0][RED] = normval(r);
                  scan[0][GRN] = normval(g);
                  scan[0][BLU] = normval(b);
            }
            scan++;
      }
      return(0);
}


static int
agryscan2(        /* get an ASCII greyscale scanline */
      register COLOR  *scan,
      register int  len,
      FILE  *fp
)
{
      while (len-- > 0) {
            colval(scan[0],RED) =
            colval(scan[0],GRN) =
            colval(scan[0],BLU) = fltv(scanint(fp));
            scan++;
      }
      return(0);
}


static int
bgryscan2(        /* get a binary greyscale scanline */
      register COLOR  *scan,
      int  len,
      register FILE  *fp
)
{
      register int  c;

      while (len-- > 0) {
            if ((c = getby2(fp)) == EOF)
                  return(-1);
            colval(scan[0],RED) =
            colval(scan[0],GRN) =
            colval(scan[0],BLU) = fltv(c);
            scan++;
      }
      return(0);
}


static int
aclrscan2(        /* get an ASCII color scanline */
      register COLOR  *scan,
      register int  len,
      FILE  *fp
)
{
      while (len-- > 0) {
            colval(scan[0],RED) = fltv(scanint(fp));
            colval(scan[0],GRN) = fltv(scanint(fp));
            colval(scan[0],BLU) = fltv(scanint(fp));
            scan++;
      }
      return(0);
}


static int
bclrscan2(        /* get a binary color scanline */
      register COLOR  *scan,
      int  len,
      register FILE  *fp
)
{
      int  r, g, b;

      while (len-- > 0) {
            r = getby2(fp);
            g = getby2(fp);
            if ((b = getby2(fp)) == EOF)
                  return(-1);
            scan[0][RED] = fltv(r);
            scan[0][GRN] = fltv(g);
            scan[0][BLU] = fltv(b);
            scan++;
      }
      return(0);
}


static unsigned int
scanint(                /* scan the next positive integer value */
      register FILE  *fp
)
{
      register int  c;
      register unsigned int  i;
tryagain:
      while (isspace(c = getc(fp)))
            ;
      if (c == EOF)
            quiterr("unexpected end of file");
      if (c == '#') {         /* comment */
            while ((c = getc(fp)) != EOF && c != '\n')
                  ;
            goto tryagain;
      }
                        /* should be integer */
      i = 0;
      do {
            if (!isdigit(c))
                  quiterr("error reading integer");
            i = 10*i + c - '0';
            c = getc(fp);
      } while (c != EOF && !isspace(c));
      return(i);
}


static int
normval(                /* normalize a value to [0,255] */
      register unsigned int  v
)
{
      if (v >= maxval)
            return(255);
      if (maxval == 255)
            return(v);
      return(v*255L/maxval);
}


static unsigned int
getby2(                 /* return 2-byte quantity from fp */
      register FILE     *fp
)
{
      register int      lowerb, upperb;

      upperb = getc(fp);
      lowerb = getc(fp);
      if (upperb == EOF)
            return(EOF);
      return(upperb<<8 | lowerb);
}


static void
putby2(                 /* put 2-byte quantity to fp */
      register unsigned int   w,
      register FILE     *fp
)
{
      putc(w>>8 & 0xff, fp);
      putc(w & 0xff, fp);
      if (ferror(fp)) {
            fprintf(stderr, "%s: write error on PPM output\n", progname);
            exit(1);
      }
}


static unsigned int
intv(                   /* return integer quantity for v */
      register double   v
)
{
      if (v >= 0.99999)
            return(maxval);
      if (v <= 0.)
            return(0);
      return((int)(v*(maxval+1)));
}

Generated by  Doxygen 1.6.0   Back to index