home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / radsrc22 / src / px / ra_t8.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-13  |  9.7 KB  |  461 lines

  1. /* Copyright (c) 1992 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)ra_t8.c 2.4 10/13/92 LBL";
  5. #endif
  6.  
  7. /*
  8.  *  ra_t8.c - program to convert between RADIANCE and
  9.  *        Targa 8-bit color-mapped images.
  10.  *
  11.  *    8/22/88        Adapted from ra_pr.c
  12.  */
  13.  
  14. #include  <stdio.h>
  15.  
  16. #include  "color.h"
  17.  
  18. #include  "resolu.h"
  19.  
  20. #include  "targa.h"
  21.  
  22. #ifdef MSDOS
  23. #include  <fcntl.h>
  24. #endif
  25.  
  26. #include  <math.h>
  27.  
  28. #ifndef     BSD
  29. #define     bcopy(s,d,n)        (void)memcpy(d,s,n)
  30. extern char  *memcpy();
  31. #endif
  32.  
  33. #define     goodpic(h)    (my_imType(h) && my_mapType(h))
  34. #define     my_imType(h)    (((h)->dataType==IM_CMAP || (h)->dataType==IM_CCMAP) \
  35.                 && (h)->dataBits==8 && (h)->imType==0)
  36. #define     my_mapType(h)    ((h)->mapType==CM_HASMAP && \
  37.                 ((h)->CMapBits==24 || (h)->CMapBits==32))
  38.  
  39. #define     taralloc(h)    (BYTE *)emalloc((h)->x*(h)->y)
  40.  
  41. extern BYTE  clrtab[][3];
  42.  
  43. extern char    *ecalloc(), *emalloc();
  44.  
  45. extern long  ftell();
  46.  
  47. double    gamv = 2.2;            /* gamv correction */
  48.  
  49. int  bradj = 0;                /* brightness adjustment */
  50.  
  51. char  *progname;
  52.  
  53. char  errmsg[128];
  54.  
  55. COLR    *inl;
  56.  
  57. BYTE    *tarData;
  58.  
  59. int  xmax, ymax;
  60.  
  61.  
  62. main(argc, argv)
  63. int  argc;
  64. char  *argv[];
  65. {
  66.     struct hdStruct     head;
  67.     int  dither = 1;
  68.     int  reverse = 0;
  69.     int  ncolors = 256;
  70.     int  greyscale = 0;
  71.     int  i;
  72. #ifdef MSDOS
  73.     extern int  _fmode;
  74.     _fmode = O_BINARY;
  75.     setmode(fileno(stdin), O_BINARY);
  76.     setmode(fileno(stdout), O_BINARY);
  77. #endif
  78.     progname = argv[0];
  79.  
  80.     for (i = 1; i < argc; i++)
  81.         if (argv[i][0] == '-')
  82.             switch (argv[i][1]) {
  83.             case 'd':
  84.                 dither = !dither;
  85.                 break;
  86.             case 'g':
  87.                 gamv = atof(argv[++i]);
  88.                 break;
  89.             case 'r':
  90.                 reverse = !reverse;
  91.                 break;
  92.             case 'b':
  93.                 greyscale = 1;
  94.                 break;
  95.             case 'e':
  96.                 if (argv[i+1][0] != '+' && argv[i+1][0] != '-')
  97.                     goto userr;
  98.                 bradj = atoi(argv[++i]);
  99.                 break;
  100.             case 'c':
  101.                 ncolors = atoi(argv[++i]);
  102.                 break;
  103.             default:
  104.                 goto userr;
  105.             }
  106.         else
  107.             break;
  108.  
  109.     if (i < argc-2)
  110.         goto userr;
  111.     if (i <= argc-1 && freopen(argv[i], "r", stdin) == NULL) {
  112.         sprintf(errmsg, "cannot open input \"%s\"", argv[i]);
  113.         quiterr(errmsg);
  114.     }
  115.     if (i == argc-2 && freopen(argv[i+1], "w", stdout) == NULL) {
  116.         sprintf(errmsg, "cannot open output \"%s\"", argv[i+1]);
  117.         quiterr(errmsg);
  118.     }
  119.     if (reverse) {
  120.                     /* get header */
  121.         if (getthead(&head, NULL, stdin) < 0)
  122.             quiterr("bad targa file");
  123.         if (!goodpic(&head))
  124.             quiterr("incompatible format");
  125.         xmax = head.x;
  126.         ymax = head.y;
  127.                     /* put header */
  128.         printargs(i, argv, stdout);
  129.         fputformat(COLRFMT, stdout);
  130.         putchar('\n');
  131.         fprtresolu(xmax, ymax, stdout);
  132.                     /* convert file */
  133.         tg2ra(&head);
  134.     } else {
  135.         if (getrhead(&head, stdin) < 0)
  136.             quiterr("bad Radiance input");
  137.                     /* write header */
  138.         putthead(&head, NULL, stdout);
  139.                     /* convert file */
  140.         if (greyscale)
  141.             getgrey(ncolors);
  142.         else
  143.             getmapped(ncolors, dither);
  144.                     /* write data */
  145.         writetarga(&head, tarData, stdout);
  146.     }
  147.     quiterr(NULL);
  148. userr:
  149.     fprintf(stderr,
  150.     "Usage: %s [-d][-c ncolors][-b][-g gamv][-e +/-stops] input [output]\n",
  151.             progname);
  152.     fprintf(stderr, "   Or: %s -r [-g gamv][-e +/-stops] [input [output]]\n",
  153.             progname);
  154.     exit(1);
  155. }
  156.  
  157.  
  158. int
  159. getint2(fp)            /* get a 2-byte positive integer */
  160. register FILE    *fp;
  161. {
  162.     register int  b1, b2;
  163.  
  164.     if ((b1 = getc(fp)) == EOF || (b2 = getc(fp)) == EOF)
  165.         quiterr("read error");
  166.  
  167.     return(b1 | b2<<8);
  168. }
  169.  
  170.  
  171. putint2(i, fp)            /* put a 2-byte positive integer */
  172. register int  i;
  173. register FILE    *fp;
  174. {
  175.     putc(i&0xff, fp);
  176.     putc(i>>8&0xff, fp);
  177. }
  178.  
  179.  
  180. quiterr(err)        /* print message and exit */
  181. char  *err;
  182. {
  183.     if (err != NULL) {
  184.         fprintf(stderr, "%s: %s\n", progname, err);
  185.         exit(1);
  186.     }
  187.     exit(0);
  188. }
  189.  
  190.  
  191. eputs(s)
  192. char *s;
  193. {
  194.     fputs(s, stderr);
  195. }
  196.  
  197.  
  198. quit(code)
  199. int code;
  200. {
  201.     exit(code);
  202. }
  203.  
  204.  
  205. getthead(hp, ip, fp)        /* read header from input */
  206. struct hdStruct     *hp;
  207. char  *ip;
  208. register FILE  *fp;
  209. {
  210.     int    nidbytes;
  211.  
  212.     if ((nidbytes = getc(fp)) == EOF)
  213.         return(-1);
  214.     hp->mapType = getc(fp);
  215.     hp->dataType = getc(fp);
  216.     hp->mapOrig = getint2(fp);
  217.     hp->mapLength = getint2(fp);
  218.     hp->CMapBits = getc(fp);
  219.     hp->XOffset = getint2(fp);
  220.     hp->YOffset = getint2(fp);
  221.     hp->x = getint2(fp);
  222.     hp->y = getint2(fp);
  223.     hp->dataBits = getc(fp);
  224.     hp->imType = getc(fp);
  225.  
  226.     if (ip != NULL)
  227.         if (nidbytes)
  228.             fread((char *)ip, nidbytes, 1, fp);
  229.         else
  230.             *ip = '\0';
  231.     else if (nidbytes)
  232.         fseek(fp, (long)nidbytes, 1);
  233.  
  234.     return(feof(fp) || ferror(fp) ? -1 : 0);
  235. }
  236.  
  237.  
  238. putthead(hp, ip, fp)        /* write header to output */
  239. struct hdStruct     *hp;
  240. char  *ip;
  241. register FILE  *fp;
  242. {
  243.     if (ip != NULL)
  244.         putc(strlen(ip), fp);
  245.     else
  246.         putc(0, fp);
  247.     putc(hp->mapType, fp);
  248.     putc(hp->dataType, fp);
  249.     putint2(hp->mapOrig, fp);
  250.     putint2(hp->mapLength, fp);
  251.     putc(hp->CMapBits, fp);
  252.     putint2(hp->XOffset, fp);
  253.     putint2(hp->YOffset, fp);
  254.     putint2(hp->x, fp);
  255.     putint2(hp->y, fp);
  256.     putc(hp->dataBits, fp);
  257.     putc(hp->imType, fp);
  258.  
  259.     if (ip != NULL)
  260.         fputs(ip, fp);
  261.  
  262.     return(ferror(fp) ? -1 : 0);
  263. }
  264.  
  265.  
  266. getrhead(h, fp)            /* load RADIANCE input file header */
  267. register struct hdStruct  *h;
  268. FILE  *fp;
  269. {
  270.                     /* get header info. */
  271.     if (checkheader(fp, COLRFMT, NULL) < 0 ||
  272.             fgetresolu(&xmax, &ymax, fp) < 0)
  273.         return(-1);
  274.                     /* assign header */
  275.     h->textSize = 0;
  276.     h->mapType = CM_HASMAP;
  277.     h->dataType = IM_CMAP;
  278.     h->mapOrig = 0;
  279.     h->mapLength = 256;
  280.     h->CMapBits = 24;
  281.     h->XOffset = 0;
  282.     h->YOffset = 0;
  283.     h->x = xmax;
  284.     h->y = ymax;
  285.     h->dataBits = 8;
  286.     h->imType = 0;
  287.                     /* allocate scanline */
  288.     inl = (COLR *)emalloc(xmax*sizeof(COLR));
  289.                     /* allocate targa data */
  290.     tarData = taralloc(h);
  291.  
  292.     return(0);
  293. }
  294.  
  295.  
  296. tg2ra(hp)            /* targa file to RADIANCE file */
  297. struct hdStruct     *hp;
  298. {
  299.     union {
  300.         BYTE  c3[256][3];
  301.         BYTE  c4[256][4];
  302.     } map;
  303.     COLR  ctab[256];
  304.     COLR  *scanline;
  305.     register int  i, j;
  306.  
  307.                     /* get color table */
  308.     if ((hp->CMapBits==24 ? fread((char *)(map.c3+hp->mapOrig),
  309.                 3*hp->mapLength,1,stdin) :
  310.             fread((char *)(map.c4+hp->mapOrig),
  311.                 4*hp->mapLength,1,stdin)) != 1)
  312.         quiterr("error reading color table");
  313.                     /* convert table */
  314.     for (i = hp->mapOrig; i < hp->mapOrig+hp->mapLength; i++)
  315.         if (hp->CMapBits == 24)
  316.             setcolr(ctab[i],
  317.                     pow((map.c3[i][2]+.5)/256.,gamv),
  318.                     pow((map.c3[i][1]+.5)/256.,gamv),
  319.                     pow((map.c3[i][0]+.5)/256.,gamv));
  320.         else
  321.             setcolr(ctab[i],
  322.                     pow((map.c4[i][3]+.5)/256.,gamv),
  323.                     pow((map.c4[i][2]+.5)/256.,gamv),
  324.                     pow((map.c4[i][1]+.5)/256.,gamv));
  325.     if (bradj)
  326.         shiftcolrs(ctab, 256, bradj);
  327.                     /* allocate targa data */
  328.     tarData = taralloc(hp);
  329.                     /* get data */
  330.     readtarga(hp, tarData, stdin);
  331.                     /* allocate input scanline */
  332.     scanline = (COLR *)emalloc(xmax*sizeof(COLR));
  333.                     /* convert file */
  334.     for (i = ymax-1; i >= 0; i--) {
  335.         for (j = 0; j < xmax; j++)
  336.             copycolr(scanline[j], ctab[tarData[i*xmax+j]]);
  337.         if (fwritecolrs(scanline, xmax, stdout) < 0)
  338.             quiterr("error writing RADIANCE file");
  339.     }
  340.     free((char *)scanline);
  341.     free((char *)tarData);
  342. }
  343.  
  344.  
  345. getmapped(nc, dith)        /* read in and quantize image */
  346. int  nc;        /* number of colors to use */
  347. int  dith;        /* use dithering? */
  348. {
  349.     long  fpos;
  350.     register int  y;
  351.  
  352.     setcolrgam(gamv);
  353.     fpos = ftell(stdin);
  354.     new_histo();            /* build histogram */
  355.     for (y = ymax-1; y >= 0; y--) {
  356.         if (freadcolrs(inl, xmax, stdin) < 0)
  357.             quiterr("error reading Radiance input");
  358.         if (bradj)
  359.             shiftcolrs(inl, xmax, bradj);
  360.         colrs_gambs(inl, xmax);
  361.         cnt_colrs(inl, xmax);
  362.     }
  363.     if (fseek(stdin, fpos, 0) == EOF)
  364.         quiterr("Radiance input must be from a file");
  365.     new_clrtab(nc);            /* map colors */
  366.     for (y = ymax-1; y >= 0; y--) {
  367.         if (freadcolrs(inl, xmax, stdin) < 0)
  368.             quiterr("error reading Radiance input");
  369.         if (bradj)
  370.             shiftcolrs(inl, xmax, bradj);
  371.         colrs_gambs(inl, xmax);
  372.         if (dith)
  373.             dith_colrs(tarData+y*xmax, inl, xmax);
  374.         else
  375.             map_colrs(tarData+y*xmax, inl, xmax);
  376.     }
  377. }
  378.  
  379.  
  380. getgrey(nc)            /* read in and convert to greyscale image */
  381. int  nc;        /* number of colors to use */
  382. {
  383.     int  y;
  384.     register BYTE  *dp;
  385.     register int  x;
  386.  
  387.     setcolrgam(gamv);
  388.     dp = tarData+xmax*ymax;;
  389.     for (y = ymax-1; y >= 0; y--) {
  390.         if (freadcolrs(inl, xmax, stdin) < 0)
  391.             quiterr("error reading Radiance input");
  392.         if (bradj)
  393.             shiftcolrs(inl, xmax, bradj);
  394.         colrs_gambs(inl, xmax);
  395.         x = xmax;
  396.         if (nc < 256)
  397.             while (x--)
  398.                 *--dp = ((long)normbright(inl[x])*nc+128)>>8;
  399.         else
  400.             while (x--)
  401.                 *--dp = normbright(inl[x]);
  402.     }
  403.     for (x = 0; x < nc; x++)
  404.         clrtab[x][RED] = clrtab[x][GRN] =
  405.             clrtab[x][BLU] = ((long)x*256+nc/2)/nc;
  406. }
  407.  
  408.  
  409. writetarga(h, d, fp)        /* write out targa data */
  410. struct hdStruct     *h;
  411. BYTE  *d;
  412. FILE  *fp;
  413. {
  414.     register int  i, j;
  415.  
  416.     for (i = 0; i < h->mapLength; i++)    /* write color map */
  417.         for (j = 2; j >= 0; j--)
  418.             putc(clrtab[i][j], fp);
  419.     if (h->dataType == IM_CMAP) {        /* uncompressed */
  420.         if (fwrite((char *)d,h->x*sizeof(BYTE),h->y,fp) != h->y)
  421.             quiterr("error writing targa file");
  422.         return;
  423.     }
  424.     quiterr("unsupported output type");
  425. }
  426.  
  427.  
  428. readtarga(h, data, fp)        /* read in targa data */
  429. struct hdStruct     *h;
  430. BYTE  *data;
  431. FILE  *fp;
  432. {
  433.     register int  cnt, c;
  434.     register BYTE    *dp;
  435.  
  436.     if (h->dataType == IM_CMAP) {        /* uncompressed */
  437.         if (fread((char *)data,h->x*sizeof(BYTE),h->y,fp) != h->y)
  438.             goto readerr;
  439.         return;
  440.     }
  441.     for (dp = data; dp < data+h->x*h->y; ) {
  442.         if ((c = getc(fp)) == EOF)
  443.             goto readerr;
  444.         cnt = (c & 0x7f) + 1;
  445.         if (c & 0x80) {            /* repeated pixel */
  446.             if ((c = getc(fp)) == EOF)
  447.                 goto readerr;
  448.             while (cnt--)
  449.                 *dp++ = c;
  450.         } else                /* non-repeating pixels */
  451.             while (cnt--) {
  452.                 if ((c = getc(fp)) == EOF)
  453.                     goto readerr;
  454.                 *dp++ = c;
  455.             }
  456.     }
  457.     return;
  458. readerr:
  459.     quiterr("error reading targa file");
  460. }
  461.