Back to index

radiance  4R0+20100331
ra_ppm.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: ra_ppm.c,v 2.14 2008/05/26 17:58:33 greg Exp $";
00003 #endif
00004 /*
00005  *  program to convert between RADIANCE and Poskanzer Pixmaps
00006  */
00007 
00008 #include  <stdio.h>
00009 #include  <math.h>
00010 #include  <ctype.h>
00011 #include  <time.h>
00012 
00013 #include  "platform.h"
00014 #include  "color.h"
00015 #include  "resolu.h"
00016 
00017 #define       fltv(i)              (((i)+.5)/(maxval+1.))
00018 int  bradj = 0;                           /* brightness adjustment */
00019 double gamcor = 2.2;               /* gamma correction value */
00020 int  maxval = 255;                 /* maximum primary value */
00021 char  *progname;
00022 int  xmax, ymax;
00023 
00024 typedef int colrscanf_t(COLR *scan, int len, FILE *fp);
00025 typedef int colorscanf_t(COLOR *scan, int len, FILE *fp);
00026 
00027 static colrscanf_t agryscan, bgryscan, aclrscan, bclrscan;
00028 static void ppm2ra(colrscanf_t *getscan);
00029 static void ra2ppm(int  binary, int  grey);
00030 
00031 static colorscanf_t agryscan2, bgryscan2, aclrscan2, bclrscan2;
00032 static void ppm2ra2(colorscanf_t *getscan);
00033 static void ra2ppm2(int  binary, int  grey);
00034 
00035 static int normval(unsigned int  v);
00036 static unsigned int scanint(FILE  *fp);
00037 static unsigned int intv(double    v);
00038 static unsigned int getby2(FILE    *fp);
00039 static void putby2(unsigned int    w, FILE       *fp);
00040 static void quiterr(char  *err);
00041 
00042 
00043 int
00044 main(
00045        int  argc,
00046        char  *argv[]
00047 )
00048 {
00049        char  inpbuf[2];
00050        int  gryflag = 0;
00051        int  binflag = 1;
00052        int  reverse = 0;
00053        int  ptype;
00054        int  i;
00055        
00056        progname = argv[0];
00057 
00058        for (i = 1; i < argc; i++)
00059               if (argv[i][0] == '-')
00060                      switch (argv[i][1]) {
00061                      case 's':
00062                             maxval = atoi(argv[++i]) & 0xffff;
00063                             break;
00064                      case 'b':
00065                             gryflag = 1;
00066                             break;
00067                      case 'g':
00068                             gamcor = atof(argv[++i]);
00069                             break;
00070                      case 'e':
00071                             if (argv[i+1][0] != '+' && argv[i+1][0] != '-')
00072                                    goto userr;
00073                             bradj = atoi(argv[++i]);
00074                             break;
00075                      case 'a':
00076                             binflag = 0;
00077                             break;
00078                      case 'r':
00079                             reverse = !reverse;
00080                             break;
00081                      default:
00082                             goto userr;
00083                      }
00084               else
00085                      break;
00086 
00087        if (i < argc-2)
00088               goto userr;
00089        if (i <= argc-1 && freopen(argv[i], "r", stdin) == NULL) {
00090               fprintf(stderr, "%s: can't open input \"%s\"\n",
00091                             progname, argv[i]);
00092               exit(1);
00093        }
00094        if (i == argc-2 && freopen(argv[i+1], "w", stdout) == NULL) {
00095               fprintf(stderr, "%s: can't open output \"%s\"\n",
00096                             progname, argv[i+1]);
00097               exit(1);
00098        }
00099        if (maxval < 256)
00100               setcolrgam(gamcor);
00101        if (reverse) {
00102                                    /* get header */
00103               if (read(fileno(stdin), inpbuf, 2) != 2 || inpbuf[0] != 'P')
00104                      quiterr("input not a Poskanzer Pixmap");
00105               ptype = inpbuf[1];
00106 #ifdef _WIN32
00107               if (ptype > 4)
00108                      SET_FILE_BINARY(stdin);
00109               SET_FILE_BINARY(stdout);
00110 #endif
00111               xmax = scanint(stdin);
00112               ymax = scanint(stdin);
00113               maxval = scanint(stdin);
00114                                    /* put header */
00115               newheader("RADIANCE", stdout);
00116               printargs(i, argv, stdout);
00117               fputformat(COLRFMT, stdout);
00118               putchar('\n');
00119               fprtresolu(xmax, ymax, stdout);
00120                                    /* convert file */
00121               if (maxval >= 256)
00122                      switch (ptype) {
00123                      case '2':
00124                             ppm2ra2(agryscan2);
00125                             break;
00126                      case '5':
00127                             ppm2ra2(bgryscan2);
00128                             break;
00129                      case '3':
00130                             ppm2ra2(aclrscan2);
00131                             break;
00132                      case '6':
00133                             ppm2ra2(bclrscan2);
00134                             break;
00135                      default:
00136                             quiterr("unsupported Pixmap type");
00137                      }
00138               else
00139                      switch (ptype) {
00140                      case '2':
00141                             ppm2ra(agryscan);
00142                             break;
00143                      case '5':
00144                             ppm2ra(bgryscan);
00145                             break;
00146                      case '3':
00147                             ppm2ra(aclrscan);
00148                             break;
00149                      case '6':
00150                             ppm2ra(bclrscan);
00151                             break;
00152                      default:
00153                             quiterr("unsupported Pixmap type");
00154                      }
00155        } else {
00156 #ifdef _WIN32
00157               SET_FILE_BINARY(stdin);
00158               if (binflag)
00159                      SET_FILE_BINARY(stdout);
00160 #endif
00161                                    /* get header info. */
00162               if (checkheader(stdin, COLRFMT, NULL) < 0 ||
00163                             fgetresolu(&xmax, &ymax, stdin) < 0)
00164                      quiterr("bad picture format");
00165                                    /* write PPM header */
00166               printf("P%1d\n%d %d\n%u\n", (gryflag?2:3)+(binflag?3:0),
00167                             xmax, ymax, maxval);
00168                                    /* convert file */
00169               if (maxval >= 256)
00170                      ra2ppm2(binflag, gryflag);
00171               else
00172                      ra2ppm(binflag, gryflag);
00173        }
00174        exit(0);
00175 userr:
00176        fprintf(stderr,
00177               "Usage: %s [-r][-a][-b][-s maxv][-g gamma][-e +/-stops] [input [output]]\n",
00178                      progname);
00179        exit(1);
00180 }
00181 
00182 
00183 static void
00184 quiterr(             /* print message and exit */
00185        char  *err
00186 )
00187 {
00188        if (err != NULL) {
00189               fprintf(stderr, "%s: %s\n", progname, err);
00190               exit(1);
00191        }
00192        exit(0);
00193 }
00194 
00195 
00196 static void
00197 ppm2ra(              /* convert 1-byte Pixmap to Radiance picture */
00198        colrscanf_t *getscan
00199 )
00200 {
00201        COLR   *scanout;
00202        int    y;
00203                                           /* allocate scanline */
00204        scanout = (COLR *)malloc(xmax*sizeof(COLR));
00205        if (scanout == NULL)
00206               quiterr("out of memory in ppm2ra");
00207                                           /* convert image */
00208        for (y = ymax-1; y >= 0; y--) {
00209               if ((*getscan)(scanout, xmax, stdin) < 0)
00210                      quiterr("error reading Pixmap");
00211               gambs_colrs(scanout, xmax);
00212               if (bradj)
00213                      shiftcolrs(scanout, xmax, bradj);
00214               if (fwritecolrs(scanout, xmax, stdout) < 0)
00215                      quiterr("error writing Radiance picture");
00216        }
00217                                           /* free scanline */
00218        free((void *)scanout);
00219 }
00220 
00221 
00222 static void
00223 ra2ppm(       /* convert Radiance picture to 1-byte/sample Pixmap */
00224        int  binary,
00225        int  grey
00226 )
00227 {
00228        COLR   *scanin;
00229        register int  x;
00230        int    y;
00231                                           /* allocate scanline */
00232        scanin = (COLR *)malloc(xmax*sizeof(COLR));
00233        if (scanin == NULL)
00234               quiterr("out of memory in ra2ppm");
00235                                           /* convert image */
00236        for (y = ymax-1; y >= 0; y--) {
00237               if (freadcolrs(scanin, xmax, stdin) < 0)
00238                      quiterr("error reading Radiance picture");
00239               if (bradj)
00240                      shiftcolrs(scanin, xmax, bradj);
00241               for (x = grey?xmax:0; x--; )
00242                      scanin[x][GRN] = normbright(scanin[x]);
00243               colrs_gambs(scanin, xmax);
00244               if (grey)
00245                      if (binary)
00246                             for (x = 0; x < xmax; x++)
00247                                    putc(scanin[x][GRN], stdout);
00248                      else
00249                             for (x = 0; x < xmax; x++)
00250                                    printf("%d\n", scanin[x][GRN]);
00251               else
00252                      if (binary)
00253                             for (x = 0; x < xmax; x++) {
00254                                    putc(scanin[x][RED], stdout);
00255                                    putc(scanin[x][GRN], stdout);
00256                                    putc(scanin[x][BLU], stdout);
00257                             }
00258                      else
00259                             for (x = 0; x < xmax; x++)
00260                                    printf("%d %d %d\n", scanin[x][RED],
00261                                                  scanin[x][GRN],
00262                                                  scanin[x][BLU]);
00263               if (ferror(stdout))
00264                      quiterr("error writing Pixmap");
00265        }
00266                                           /* free scanline */
00267        free((void *)scanin);
00268 }
00269 
00270 
00271 static void
00272 ppm2ra2(      /* convert 2-byte Pixmap to Radiance picture */
00273        colorscanf_t *getscan
00274 )
00275 {
00276        COLOR  *scanout;
00277        double mult;
00278        int    y;
00279        register int  x;
00280                                           /* allocate scanline */
00281        scanout = (COLOR *)malloc(xmax*sizeof(COLOR));
00282        if (scanout == NULL)
00283               quiterr("out of memory in ppm2ra2");
00284        if (bradj)
00285               mult = pow(2., (double)bradj);
00286                                           /* convert image */
00287        for (y = ymax-1; y >= 0; y--) {
00288               if ((*getscan)(scanout, xmax, stdin) < 0)
00289                      quiterr("error reading Pixmap");
00290               for (x = (gamcor>1.01)|(gamcor<0.99)?xmax:0; x--; ) {
00291                      colval(scanout[x],RED) =
00292                                    pow(colval(scanout[x],RED), gamcor);
00293                      colval(scanout[x],GRN) =
00294                                    pow(colval(scanout[x],GRN), gamcor);
00295                      colval(scanout[x],BLU) =
00296                                    pow(colval(scanout[x],BLU), gamcor);
00297               }
00298               for (x = bradj?xmax:0; x--; )
00299                      scalecolor(scanout[x], mult);
00300               if (fwritescan(scanout, xmax, stdout) < 0)
00301                      quiterr("error writing Radiance picture");
00302        }
00303                                           /* free scanline */
00304        free((void *)scanout);
00305 }
00306 
00307 
00308 static void
00309 ra2ppm2(      /* convert Radiance picture to Pixmap (2-byte) */
00310        int  binary,
00311        int  grey
00312 )
00313 {
00314        COLOR  *scanin;
00315        double mult, d;
00316        register int  x;
00317        int    y;
00318                                           /* allocate scanline */
00319        scanin = (COLOR *)malloc(xmax*sizeof(COLOR));
00320        if (scanin == NULL)
00321               quiterr("out of memory in ra2ppm2");
00322        if (bradj)
00323               mult = pow(2., (double)bradj);
00324                                           /* convert image */
00325        for (y = ymax-1; y >= 0; y--) {
00326               if (freadscan(scanin, xmax, stdin) < 0)
00327                      quiterr("error reading Radiance picture");
00328               for (x = bradj?xmax:0; x--; )
00329                      scalecolor(scanin[x], mult);
00330               for (x = grey?xmax:0; x--; )
00331                      colval(scanin[x],GRN) = bright(scanin[x]);
00332               d = 1./gamcor;
00333               for (x = (d>1.01)|(d<0.99)?xmax:0; x--; ) {
00334                      colval(scanin[x],GRN) = pow(colval(scanin[x],GRN), d);
00335                      if (!grey) {
00336                             colval(scanin[x],RED) =
00337                                           pow(colval(scanin[x],RED), d);
00338                             colval(scanin[x],BLU) =
00339                                           pow(colval(scanin[x],BLU), d);
00340                      }
00341               }
00342               if (grey)
00343                      if (binary)
00344                             for (x = 0; x < xmax; x++)
00345                                    putby2(intv(colval(scanin[x],GRN)),
00346                                                  stdout);
00347                      else
00348                             for (x = 0; x < xmax; x++)
00349                                    printf("%u\n",
00350                                           intv(colval(scanin[x],GRN)));
00351               else
00352                      if (binary)
00353                             for (x = 0; x < xmax; x++) {
00354                                    putby2(intv(colval(scanin[x],RED)),
00355                                                  stdout);
00356                                    putby2(intv(colval(scanin[x],GRN)),
00357                                                  stdout);
00358                                    putby2(intv(colval(scanin[x],BLU)),
00359                                                  stdout);
00360                             }
00361                      else
00362                             for (x = 0; x < xmax; x++)
00363                                    printf("%u %u %u\n",
00364                                           intv(colval(scanin[x],RED)),
00365                                           intv(colval(scanin[x],GRN)),
00366                                           intv(colval(scanin[x],BLU)));
00367               if (ferror(stdout))
00368                      quiterr("error writing Pixmap");
00369        }
00370                                           /* free scanline */
00371        free((void *)scanin);
00372 }
00373 
00374 
00375 static int
00376 agryscan(                   /* get an ASCII greyscale scanline */
00377        register COLR  *scan,
00378        register int  len,
00379        FILE  *fp
00380 )
00381 {
00382        while (len-- > 0) {
00383               scan[0][RED] =
00384               scan[0][GRN] =
00385               scan[0][BLU] = normval(scanint(fp));
00386               scan++;
00387        }
00388        return(0);
00389 }
00390 
00391 
00392 static int
00393 bgryscan(                   /* get a binary greyscale scanline */
00394        register COLR  *scan,
00395        int  len,
00396        register FILE  *fp
00397 )
00398 {
00399        register int  c;
00400 
00401        while (len-- > 0) {
00402               if ((c = getc(fp)) == EOF)
00403                      return(-1);
00404               if (maxval != 255)
00405                      c = normval(c);
00406               scan[0][RED] =
00407               scan[0][GRN] =
00408               scan[0][BLU] = c;
00409               scan++;
00410        }
00411        return(0);
00412 }
00413 
00414 
00415 static int
00416 aclrscan(                   /* get an ASCII color scanline */
00417        register COLR  *scan,
00418        register int  len,
00419        FILE  *fp
00420 )
00421 {
00422        while (len-- > 0) {
00423               scan[0][RED] = normval(scanint(fp));
00424               scan[0][GRN] = normval(scanint(fp));
00425               scan[0][BLU] = normval(scanint(fp));
00426               scan++;
00427        }
00428        return(0);
00429 }
00430 
00431 
00432 static int
00433 bclrscan(                   /* get a binary color scanline */
00434        register COLR  *scan,
00435        int  len,
00436        register FILE  *fp
00437 )
00438 {
00439        int  r, g, b;
00440 
00441        while (len-- > 0) {
00442               r = getc(fp);
00443               g = getc(fp);
00444               if ((b = getc(fp)) == EOF)
00445                      return(-1);
00446               if (maxval == 255) {
00447                      scan[0][RED] = r;
00448                      scan[0][GRN] = g;
00449                      scan[0][BLU] = b;
00450               } else {
00451                      scan[0][RED] = normval(r);
00452                      scan[0][GRN] = normval(g);
00453                      scan[0][BLU] = normval(b);
00454               }
00455               scan++;
00456        }
00457        return(0);
00458 }
00459 
00460 
00461 static int
00462 agryscan2(           /* get an ASCII greyscale scanline */
00463        register COLOR  *scan,
00464        register int  len,
00465        FILE  *fp
00466 )
00467 {
00468        while (len-- > 0) {
00469               colval(scan[0],RED) =
00470               colval(scan[0],GRN) =
00471               colval(scan[0],BLU) = fltv(scanint(fp));
00472               scan++;
00473        }
00474        return(0);
00475 }
00476 
00477 
00478 static int
00479 bgryscan2(           /* get a binary greyscale scanline */
00480        register COLOR  *scan,
00481        int  len,
00482        register FILE  *fp
00483 )
00484 {
00485        register int  c;
00486 
00487        while (len-- > 0) {
00488               if ((c = getby2(fp)) == EOF)
00489                      return(-1);
00490               colval(scan[0],RED) =
00491               colval(scan[0],GRN) =
00492               colval(scan[0],BLU) = fltv(c);
00493               scan++;
00494        }
00495        return(0);
00496 }
00497 
00498 
00499 static int
00500 aclrscan2(           /* get an ASCII color scanline */
00501        register COLOR  *scan,
00502        register int  len,
00503        FILE  *fp
00504 )
00505 {
00506        while (len-- > 0) {
00507               colval(scan[0],RED) = fltv(scanint(fp));
00508               colval(scan[0],GRN) = fltv(scanint(fp));
00509               colval(scan[0],BLU) = fltv(scanint(fp));
00510               scan++;
00511        }
00512        return(0);
00513 }
00514 
00515 
00516 static int
00517 bclrscan2(           /* get a binary color scanline */
00518        register COLOR  *scan,
00519        int  len,
00520        register FILE  *fp
00521 )
00522 {
00523        int  r, g, b;
00524 
00525        while (len-- > 0) {
00526               r = getby2(fp);
00527               g = getby2(fp);
00528               if ((b = getby2(fp)) == EOF)
00529                      return(-1);
00530               scan[0][RED] = fltv(r);
00531               scan[0][GRN] = fltv(g);
00532               scan[0][BLU] = fltv(b);
00533               scan++;
00534        }
00535        return(0);
00536 }
00537 
00538 
00539 static unsigned int
00540 scanint(                    /* scan the next positive integer value */
00541        register FILE  *fp
00542 )
00543 {
00544        register int  c;
00545        register unsigned int  i;
00546 tryagain:
00547        while (isspace(c = getc(fp)))
00548               ;
00549        if (c == EOF)
00550               quiterr("unexpected end of file");
00551        if (c == '#') {             /* comment */
00552               while ((c = getc(fp)) != EOF && c != '\n')
00553                      ;
00554               goto tryagain;
00555        }
00556                             /* should be integer */
00557        i = 0;
00558        do {
00559               if (!isdigit(c))
00560                      quiterr("error reading integer");
00561               i = 10*i + c - '0';
00562               c = getc(fp);
00563        } while (c != EOF && !isspace(c));
00564        return(i);
00565 }
00566 
00567 
00568 static int
00569 normval(                    /* normalize a value to [0,255] */
00570        register unsigned int  v
00571 )
00572 {
00573        if (v >= maxval)
00574               return(255);
00575        if (maxval == 255)
00576               return(v);
00577        return(v*255L/maxval);
00578 }
00579 
00580 
00581 static unsigned int
00582 getby2(                     /* return 2-byte quantity from fp */
00583        register FILE *fp
00584 )
00585 {
00586        register int  lowerb, upperb;
00587 
00588        upperb = getc(fp);
00589        lowerb = getc(fp);
00590        if (lowerb == EOF)
00591               return(EOF);
00592        return(upperb<<8 | lowerb);
00593 }
00594 
00595 
00596 static void
00597 putby2(                     /* put 2-byte quantity to fp */
00598        register unsigned int       w,
00599        register FILE *fp
00600 )
00601 {
00602        putc(w>>8 & 0xff, fp);
00603        putc(w & 0xff, fp);
00604        if (ferror(fp)) {
00605               fprintf(stderr, "%s: write error on PPM output\n", progname);
00606               exit(1);
00607        }
00608 }
00609 
00610 
00611 static unsigned int
00612 intv(                       /* return integer quantity for v */
00613        register double      v
00614 )
00615 {
00616        if (v >= 0.99999)
00617               return(maxval);
00618        if (v <= 0.)
00619               return(0);
00620        return((int)(v*(maxval+1)));
00621 }