--- ray/src/px/ra_ppm.c 1991/08/16 12:41:59 1.1 +++ ray/src/px/ra_ppm.c 2003/07/27 22:12:03 2.11 @@ -1,25 +1,31 @@ -/* Copyright (c) 1991 Regents of the University of California */ - #ifndef lint -static char SCCSid[] = "$SunId$ LBL"; +static const char RCSid[] = "$Id: ra_ppm.c,v 2.11 2003/07/27 22:12:03 schorsch Exp $"; #endif - /* * program to convert between RADIANCE and Poskanzer Pixmaps */ #include - +#include #include +#include +#include "platform.h" #include "color.h" +#include "resolu.h" -extern double atof(), pow(); int agryscan(), bgryscan(), aclrscan(), bclrscan(); +int agryscan2(), bgryscan2(), aclrscan2(), bclrscan2(); +int normval(); +unsigned int scanint(), intv(), getby2(); +#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; @@ -31,7 +37,8 @@ main(argc, argv) int argc; char *argv[]; { - double gamma = 2.2; + char inpbuf[2]; + int gryflag = 0; int binflag = 1; int reverse = 0; int ptype; @@ -42,8 +49,14 @@ char *argv[]; 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': - gamma = atof(argv[++i]); + gamcor = atof(argv[++i]); break; case 'e': if (argv[i+1][0] != '+' && argv[i+1][0] != '-') @@ -70,56 +83,89 @@ char *argv[]; exit(1); } if (i == argc-2 && freopen(argv[i+1], "w", stdout) == NULL) { - fprintf(stderr, "can't open output \"%s\"\n", + fprintf(stderr, "%s: can't open output \"%s\"\n", progname, argv[i+1]); exit(1); } - setcolrgam(gamma); + if (maxval < 256) + setcolrgam(gamcor); if (reverse) { /* get header */ - if (getc(stdin) != 'P') + if (read(fileno(stdin), inpbuf, 2) != 2 || inpbuf[0] != 'P') quiterr("input not a Poskanzer Pixmap"); - ptype = getc(stdin); + 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'); - fputresolu(YMAJOR|YDECR, xmax, ymax, stdout); + fprtresolu(xmax, ymax, stdout); /* convert file */ - 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"); - } + 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) != (YMAJOR|YDECR)) + fgetresolu(&xmax, &ymax, stdin) < 0) quiterr("bad picture format"); /* write PPM header */ - printf("P%c\n%d %d\n%d\n", binflag ? '6' : '3', + printf("P%1d\n%d %d\n%u\n", (gryflag?2:3)+(binflag?3:0), xmax, ymax, maxval); /* convert file */ - ra2ppm(binflag); + if (maxval >= 256) + ra2ppm2(binflag, gryflag); + else + ra2ppm(binflag, gryflag); } exit(0); userr: fprintf(stderr, - "Usage: %s [-r][-a][-g gamma][-e +/-stops] [input [output]]\n", + "Usage: %s [-r][-a][-b][-s maxv][-g gamma][-e +/-stops] [input [output]]\n", progname); exit(1); } @@ -136,11 +182,10 @@ char *err; } -ppm2ra(getscan) /* convert color Pixmap to Radiance picture */ +ppm2ra(getscan) /* convert 1-byte Pixmap to Radiance picture */ int (*getscan)(); { COLR *scanout; - register int x; int y; /* allocate scanline */ scanout = (COLR *)malloc(xmax*sizeof(COLR)); @@ -157,12 +202,12 @@ int (*getscan)(); quiterr("error writing Radiance picture"); } /* free scanline */ - free((char *)scanout); + free((void *)scanout); } -ra2ppm(binary) /* convert Radiance picture to Pixmap */ -int binary; +ra2ppm(binary, grey) /* convert Radiance picture to Pixmap */ +int binary, grey; { COLR *scanin; register int x; @@ -170,30 +215,139 @@ int binary; /* allocate scanline */ scanin = (COLR *)malloc(xmax*sizeof(COLR)); if (scanin == NULL) - quiterr("out of memory in ra2pr"); + 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 (binary) - for (x = 0; x < xmax; x++) { - putc(scanin[x][RED], stdout); - putc(scanin[x][GRN], stdout); - putc(scanin[x][BLU], stdout); + 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); +} + + +ppm2ra2(getscan) /* convert 2-byte Pixmap to Radiance picture */ +int (*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); +} + + +ra2ppm2(binary, grey) /* convert Radiance picture to Pixmap (2-byte) */ +int binary, 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 - for (x = 0; x < xmax; x++) - printf("%d %d %d\n", scanin[x][RED], - scanin[x][GRN], - scanin[x][BLU]); + 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((char *)scanin); + free((void *)scanin); } @@ -275,11 +429,82 @@ register FILE *fp; } -int +agryscan2(scan, len, fp) /* 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); +} + + +bgryscan2(scan, len, fp) /* 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); +} + + +aclrscan2(scan, len, fp) /* 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); +} + + +bclrscan2(scan, len, fp) /* 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); +} + + +unsigned int scanint(fp) /* scan the next positive integer value */ register FILE *fp; { - register int i, c; + register int c; + register unsigned int i; tryagain: while (isspace(c = getc(fp))) ; @@ -304,11 +529,50 @@ tryagain: int normval(v) /* normalize a value to [0,255] */ -register int v; +register unsigned int v; { if (v >= maxval) return(255); if (maxval == 255) return(v); return(v*255L/maxval); +} + + +unsigned int +getby2(fp) /* return 2-byte quantity from fp */ +register FILE *fp; +{ + register int lowerb, upperb; + + lowerb = getc(fp); + upperb = getc(fp); + if (upperb == EOF) + return(EOF); + return(upperb<<8 | lowerb); +} + + +putby2(w, fp) /* put 2-byte quantity to fp */ +register unsigned int w; +register FILE *fp; +{ + putc(w & 0xff, fp); + putc(w>>8 & 0xff, fp); + if (ferror(fp)) { + fprintf(stderr, "%s: write error on PPM output\n", progname); + exit(1); + } +} + + +unsigned int +intv(v) /* return integer quantity for v */ +register double v; +{ + if (v >= 0.99999) + return(maxval); + if (v <= 0.) + return(0); + return((int)(v*(maxval+1))); }