Back to index

radiance  4R0+20100331
ra_t8.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: ra_t8.c,v 2.13 2004/03/28 20:33:14 schorsch Exp $";
00003 #endif
00004 /*
00005  *  ra_t8.c - program to convert between RADIANCE and
00006  *            Targa 8-bit color-mapped images.
00007  *
00008  *     8/22/88              Adapted from ra_pr.c
00009  */
00010 
00011 #include  <stdio.h>
00012 #include  <string.h>
00013 #include  <time.h>
00014 #include  <math.h>
00015 
00016 #include  "platform.h"
00017 #include  "rtmisc.h"
00018 #include  "color.h"
00019 #include  "resolu.h"
00020 #include  "clrtab.h"
00021 #include  "targa.h"
00022 
00023 
00024 #define        goodpic(h)   (my_imType(h) && my_mapType(h))
00025 #define        my_imType(h) (((h)->dataType==IM_CMAP || (h)->dataType==IM_CCMAP) \
00026                             && (h)->dataBits==8 && (h)->imType==0)
00027 #define        my_mapType(h)       ((h)->mapType==CM_HASMAP && \
00028                             ((h)->CMapBits==24 || (h)->CMapBits==32))
00029 
00030 #define        taralloc(h)  (BYTE *)emalloc((h)->x*(h)->y)
00031 
00032 BYTE  clrtab[256][3];
00033 extern int    samplefac;
00034 double gamv = 2.2;                 /* gamv correction */
00035 int  bradj = 0;                           /* brightness adjustment */
00036 char  *progname;
00037 char  errmsg[128];
00038 COLR   *inl;
00039 BYTE   *tarData;
00040 int  xmax, ymax;
00041 
00042 static int getint2(FILE     *fp);
00043 static void putint2(int  i, FILE   *fp);
00044 static void quiterr(char  *err);
00045 static int getthead(struct hdStruct        *hp, char  *ip, FILE  *fp);
00046 static int putthead(struct hdStruct        *hp, char  *ip, FILE  *fp);
00047 static int getrhead(struct hdStruct  *h, FILE  *fp);
00048 static void tg2ra(struct hdStruct   *hp);
00049 static void getmapped(int  nc, int  dith);
00050 static void getgrey(int  nc);
00051 static void writetarga(struct hdStruct     *h, BYTE  *d, FILE  *fp);
00052 static void readtarga(struct hdStruct      *h, BYTE  *data, FILE  *fp);
00053 
00054 
00055 int
00056 main(
00057        int  argc,
00058        char  *argv[]
00059 )
00060 {
00061        struct hdStruct       head;
00062        int  dither = 1;
00063        int  reverse = 0;
00064        int  ncolors = 256;
00065        int  greyscale = 0;
00066        int  i;
00067        SET_DEFAULT_BINARY();
00068        SET_FILE_BINARY(stdin);
00069        SET_FILE_BINARY(stdout);
00070        progname = argv[0];
00071        samplefac = 0;
00072 
00073        for (i = 1; i < argc; i++)
00074               if (argv[i][0] == '-')
00075                      switch (argv[i][1]) {
00076                      case 'd':
00077                             dither = !dither;
00078                             break;
00079                      case 'g':
00080                             gamv = atof(argv[++i]);
00081                             break;
00082                      case 'r':
00083                             reverse = !reverse;
00084                             break;
00085                      case 'b':
00086                             greyscale = 1;
00087                             break;
00088                      case 'e':
00089                             if (argv[i+1][0] != '+' && argv[i+1][0] != '-')
00090                                    goto userr;
00091                             bradj = atoi(argv[++i]);
00092                             break;
00093                      case 'c':
00094                             ncolors = atoi(argv[++i]);
00095                             break;
00096                      case 'n':
00097                             samplefac = atoi(argv[++i]);
00098                             break;
00099                      default:
00100                             goto userr;
00101                      }
00102               else
00103                      break;
00104 
00105        if (i < argc-2)
00106               goto userr;
00107        if (i <= argc-1 && freopen(argv[i], "r", stdin) == NULL) {
00108               sprintf(errmsg, "cannot open input \"%s\"", argv[i]);
00109               quiterr(errmsg);
00110        }
00111        if (i == argc-2 && freopen(argv[i+1], "w", stdout) == NULL) {
00112               sprintf(errmsg, "cannot open output \"%s\"", argv[i+1]);
00113               quiterr(errmsg);
00114        }
00115        if (reverse) {
00116                                    /* get header */
00117               if (getthead(&head, NULL, stdin) < 0)
00118                      quiterr("bad targa file");
00119               if (!goodpic(&head))
00120                      quiterr("incompatible format");
00121               xmax = head.x;
00122               ymax = head.y;
00123                                    /* put header */
00124               newheader("RADIANCE", stdout);
00125               printargs(i, argv, stdout);
00126               fputformat(COLRFMT, stdout);
00127               putchar('\n');
00128               fprtresolu(xmax, ymax, stdout);
00129                                    /* convert file */
00130               tg2ra(&head);
00131        } else {
00132               if (getrhead(&head, stdin) < 0)
00133                      quiterr("bad Radiance input");
00134                                    /* write header */
00135               putthead(&head, NULL, stdout);
00136                                    /* convert file */
00137               if (greyscale)
00138                      getgrey(ncolors);
00139               else
00140                      getmapped(ncolors, dither);
00141                                    /* write data */
00142               writetarga(&head, tarData, stdout);
00143        }
00144        quiterr(NULL);
00145 userr:
00146        fprintf(stderr,
00147        "Usage: %s [-d][-n samp][-c ncolors][-b][-g gamv][-e +/-stops] input [output]\n",
00148                      progname);
00149        fprintf(stderr, "   Or: %s -r [-g gamv][-e +/-stops] [input [output]]\n",
00150                      progname);
00151        exit(1);
00152 }
00153 
00154 
00155 static int
00156 getint2(                    /* get a 2-byte positive integer */
00157        register FILE *fp
00158 )
00159 {
00160        register int  b1, b2;
00161 
00162        if ((b1 = getc(fp)) == EOF || (b2 = getc(fp)) == EOF)
00163               quiterr("read error");
00164 
00165        return(b1 | b2<<8);
00166 }
00167 
00168 
00169 static void
00170 putint2(                    /* put a 2-byte positive integer */
00171        register int  i,
00172        register FILE *fp
00173 )
00174 {
00175        putc(i&0xff, fp);
00176        putc(i>>8&0xff, fp);
00177 }
00178 
00179 
00180 static void
00181 quiterr(             /* print message and exit */
00182        char  *err
00183 )
00184 {
00185        if (err != NULL) {
00186               fprintf(stderr, "%s: %s\n", progname, err);
00187               exit(1);
00188        }
00189        exit(0);
00190 }
00191 
00192 
00193 void
00194 eputs(s)
00195 char *s;
00196 {
00197        fputs(s, stderr);
00198 }
00199 
00200 
00201 void
00202 quit(code)
00203 int code;
00204 {
00205        exit(code);
00206 }
00207 
00208 
00209 static int
00210 getthead(            /* read header from input */
00211        struct hdStruct       *hp,
00212        char  *ip,
00213        register FILE  *fp
00214 )
00215 {
00216        int    nidbytes;
00217 
00218        if ((nidbytes = getc(fp)) == EOF)
00219               return(-1);
00220        hp->mapType = getc(fp);
00221        hp->dataType = getc(fp);
00222        hp->mapOrig = getint2(fp);
00223        hp->mapLength = getint2(fp);
00224        hp->CMapBits = getc(fp);
00225        hp->XOffset = getint2(fp);
00226        hp->YOffset = getint2(fp);
00227        hp->x = getint2(fp);
00228        hp->y = getint2(fp);
00229        hp->dataBits = getc(fp);
00230        hp->imType = getc(fp);
00231 
00232        if (ip != NULL)
00233               if (nidbytes)
00234                      fread((char *)ip, nidbytes, 1, fp);
00235               else
00236                      *ip = '\0';
00237        else if (nidbytes)
00238               fseek(fp, (long)nidbytes, 1);
00239 
00240        return(feof(fp) || ferror(fp) ? -1 : 0);
00241 }
00242 
00243 
00244 static int
00245 putthead(            /* write header to output */
00246        struct hdStruct       *hp,
00247        char  *ip,
00248        register FILE  *fp
00249 )
00250 {
00251        if (ip != NULL)
00252               putc(strlen(ip), fp);
00253        else
00254               putc(0, fp);
00255        putc(hp->mapType, fp);
00256        putc(hp->dataType, fp);
00257        putint2(hp->mapOrig, fp);
00258        putint2(hp->mapLength, fp);
00259        putc(hp->CMapBits, fp);
00260        putint2(hp->XOffset, fp);
00261        putint2(hp->YOffset, fp);
00262        putint2(hp->x, fp);
00263        putint2(hp->y, fp);
00264        putc(hp->dataBits, fp);
00265        putc(hp->imType, fp);
00266 
00267        if (ip != NULL)
00268               fputs(ip, fp);
00269 
00270        return(ferror(fp) ? -1 : 0);
00271 }
00272 
00273 
00274 static int
00275 getrhead(                   /* load RADIANCE input file header */
00276        register struct hdStruct  *h,
00277        FILE  *fp
00278 )
00279 {
00280                                    /* get header info. */
00281        if (checkheader(fp, COLRFMT, NULL) < 0 ||
00282                      fgetresolu(&xmax, &ymax, fp) < 0)
00283               return(-1);
00284                                    /* assign header */
00285        h->textSize = 0;
00286        h->mapType = CM_HASMAP;
00287        h->dataType = IM_CMAP;
00288        h->mapOrig = 0;
00289        h->mapLength = 256;
00290        h->CMapBits = 24;
00291        h->XOffset = 0;
00292        h->YOffset = 0;
00293        h->x = xmax;
00294        h->y = ymax;
00295        h->dataBits = 8;
00296        h->imType = 0;
00297                                    /* allocate scanline */
00298        inl = (COLR *)emalloc(xmax*sizeof(COLR));
00299                                    /* allocate targa data */
00300        tarData = taralloc(h);
00301 
00302        return(0);
00303 }
00304 
00305 
00306 static void
00307 tg2ra(               /* targa file to RADIANCE file */
00308        struct hdStruct       *hp
00309 )
00310 {
00311        union {
00312               BYTE  c3[256][3];
00313               BYTE  c4[256][4];
00314        } map;
00315        COLR  ctab[256];
00316        COLR  *scanline;
00317        register int  i, j;
00318 
00319                                    /* get color table */
00320        if ((hp->CMapBits==24 ? fread((char *)(map.c3+hp->mapOrig),
00321                             3*hp->mapLength,1,stdin) :
00322                      fread((char *)(map.c4+hp->mapOrig),
00323                             4*hp->mapLength,1,stdin)) != 1)
00324               quiterr("error reading color table");
00325                                    /* convert table */
00326        for (i = hp->mapOrig; i < hp->mapOrig+hp->mapLength; i++)
00327               if (hp->CMapBits == 24)
00328                      setcolr(ctab[i],
00329                                    pow((map.c3[i][2]+.5)/256.,gamv),
00330                                    pow((map.c3[i][1]+.5)/256.,gamv),
00331                                    pow((map.c3[i][0]+.5)/256.,gamv));
00332               else
00333                      setcolr(ctab[i],
00334                                    pow((map.c4[i][3]+.5)/256.,gamv),
00335                                    pow((map.c4[i][2]+.5)/256.,gamv),
00336                                    pow((map.c4[i][1]+.5)/256.,gamv));
00337        if (bradj)
00338               shiftcolrs(ctab, 256, bradj);
00339                                    /* allocate targa data */
00340        tarData = taralloc(hp);
00341                                    /* get data */
00342        readtarga(hp, tarData, stdin);
00343                                    /* allocate input scanline */
00344        scanline = (COLR *)emalloc(xmax*sizeof(COLR));
00345                                    /* convert file */
00346        for (i = ymax-1; i >= 0; i--) {
00347               for (j = 0; j < xmax; j++)
00348                      copycolr(scanline[j], ctab[tarData[i*xmax+j]]);
00349               if (fwritecolrs(scanline, xmax, stdout) < 0)
00350                      quiterr("error writing RADIANCE file");
00351        }
00352        free((void *)scanline);
00353        free((void *)tarData);
00354 }
00355 
00356 
00357 static void
00358 getmapped(           /* read in and quantize image */
00359        int  nc,             /* number of colors to use */
00360        int  dith            /* use dithering? */
00361 )
00362 {
00363        long  fpos;
00364        register int  y;
00365 
00366        setcolrgam(gamv);
00367        fpos = ftell(stdin);
00368        if ((samplefac ? neu_init(xmax*ymax) : new_histo(xmax*ymax)) == -1)
00369               quiterr("cannot initialized histogram");
00370        for (y = ymax-1; y >= 0; y--) {
00371               if (freadcolrs(inl, xmax, stdin) < 0)
00372                      quiterr("error reading Radiance input");
00373               if (bradj)
00374                      shiftcolrs(inl, xmax, bradj);
00375               colrs_gambs(inl, xmax);
00376               if (samplefac)
00377                      neu_colrs(inl, xmax);
00378               else
00379                      cnt_colrs(inl, xmax);
00380        }
00381        if (fseek(stdin, fpos, 0) == EOF)
00382               quiterr("Radiance input must be from a file");
00383        if (samplefac)                     /* map colors */
00384               neu_clrtab(nc);
00385        else
00386               new_clrtab(nc);
00387        for (y = ymax-1; y >= 0; y--) {
00388               if (freadcolrs(inl, xmax, stdin) < 0)
00389                      quiterr("error reading Radiance input");
00390               if (bradj)
00391                      shiftcolrs(inl, xmax, bradj);
00392               colrs_gambs(inl, xmax);
00393               if (samplefac)
00394                      if (dith)
00395                             neu_dith_colrs(tarData+y*xmax, inl, xmax);
00396                      else
00397                             neu_map_colrs(tarData+y*xmax, inl, xmax);
00398               else
00399                      if (dith)
00400                             dith_colrs(tarData+y*xmax, inl, xmax);
00401                      else
00402                             map_colrs(tarData+y*xmax, inl, xmax);
00403        }
00404 }
00405 
00406 
00407 static void
00408 getgrey(                    /* read in and convert to greyscale image */
00409        int  nc              /* number of colors to use */
00410 )
00411 {
00412        int  y;
00413        register BYTE  *dp;
00414        register int  x;
00415 
00416        setcolrgam(gamv);
00417        dp = tarData+xmax*ymax;;
00418        for (y = ymax-1; y >= 0; y--) {
00419               if (freadcolrs(inl, xmax, stdin) < 0)
00420                      quiterr("error reading Radiance input");
00421               if (bradj)
00422                      shiftcolrs(inl, xmax, bradj);
00423               x = xmax;
00424               while (x--)
00425                      inl[x][GRN] = normbright(inl[x]);
00426               colrs_gambs(inl, xmax);
00427               x = xmax;
00428               if (nc < 256)
00429                      while (x--)
00430                             *--dp = ((long)inl[x][GRN]*nc+nc/2)>>8;
00431               else
00432                      while (x--)
00433                             *--dp = inl[x][GRN];
00434        }
00435        for (x = 0; x < nc; x++)
00436               clrtab[x][RED] = clrtab[x][GRN] =
00437                      clrtab[x][BLU] = ((long)x*256+128)/nc;
00438 }
00439 
00440 
00441 static void
00442 writetarga(          /* write out targa data */
00443        struct hdStruct       *h,
00444        BYTE  *d,
00445        FILE  *fp
00446 )
00447 {
00448        register int  i, j;
00449 
00450        for (i = 0; i < h->mapLength; i++) /* write color map */
00451               for (j = 2; j >= 0; j--)
00452                      putc(clrtab[i][j], fp);
00453        if (h->dataType == IM_CMAP) {             /* uncompressed */
00454               if (fwrite((char *)d,h->x*sizeof(BYTE),h->y,fp) != h->y)
00455                      quiterr("error writing targa file");
00456               return;
00457        }
00458        quiterr("unsupported output type");
00459 }
00460 
00461 
00462 static void
00463 readtarga(           /* read in targa data */
00464        struct hdStruct       *h,
00465        BYTE  *data,
00466        FILE  *fp
00467 )
00468 {
00469        register int  cnt, c;
00470        register BYTE *dp;
00471 
00472        if (h->dataType == IM_CMAP) {             /* uncompressed */
00473               if (fread((char *)data,h->x*sizeof(BYTE),h->y,fp) != h->y)
00474                      goto readerr;
00475               return;
00476        }
00477        for (dp = data; dp < data+h->x*h->y; ) {
00478               if ((c = getc(fp)) == EOF)
00479                      goto readerr;
00480               cnt = (c & 0x7f) + 1;
00481               if (c & 0x80) {                    /* repeated pixel */
00482                      if ((c = getc(fp)) == EOF)
00483                             goto readerr;
00484                      while (cnt--)
00485                             *dp++ = c;
00486               } else                      /* non-repeating pixels */
00487                      while (cnt--) {
00488                             if ((c = getc(fp)) == EOF)
00489                                    goto readerr;
00490                             *dp++ = c;
00491                      }
00492        }
00493        return;
00494 readerr:
00495        quiterr("error reading targa file");
00496 }