Back to index

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