Back to index

radiance  4R0+20100331
ra_gif.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: ra_gif.c,v 2.11 2004/03/28 20:33:14 schorsch Exp $";
00003 #endif
00004 /*
00005  * Convert from Radiance picture file to Compuserve GIF.
00006  * Currently, we don't know how to get back.
00007  */
00008 
00009 #include  <stdio.h>
00010 #include  <time.h>
00011 #include  <math.h>
00012 
00013 #include  "platform.h"
00014 #include  "color.h"
00015 #include  "resolu.h"
00016 #include  "clrtab.h"
00017 
00018 #define MAXCOLORS           256
00019 
00020 int rmap[MAXCOLORS];
00021 int gmap[MAXCOLORS];
00022 int bmap[MAXCOLORS];
00023 
00024 int currow;
00025 long  picstart;
00026 BYTE  clrtab[256][3];
00027 
00028 extern int  samplefac;
00029 
00030 
00031 COLR   *scanln;
00032 BYTE   *pixscan;
00033 
00034 int  xmax, ymax;                   /* picture size */
00035 double gamv = 2.2;                 /* gamma correction */
00036 int  greyscale = 0;                /* convert to B&W? */
00037 int  dither = 1;                   /* dither colors? */
00038 int  bradj = 0;                           /* brightness adjustment */
00039 int  ncolors = 0;                  /* number of colors requested */
00040 
00041 char  *progname;
00042 
00043 typedef int ifun_t(int x, int y); /* required by the GIF code below */
00044 
00045 static void getrow(int  y);
00046 static void mkclrmap(int    nc);
00047 static void mkgrymap(int    nc);
00048 static ifun_t getgifpix;
00049 
00050 static void GIFEncode(FILE *fp, int GWidth, int GHeight, int GInterlace,
00051               int Background, int BitsPerPixel, int Red[], int Green[], int Blue[],
00052               ifun_t* GetPixel);
00053 
00054 
00055 int
00056 main(int  argc, char  *argv[])
00057 {
00058        int  bitsperpix;
00059        int  i;
00060        SET_DEFAULT_BINARY();
00061        SET_FILE_BINARY(stdin);
00062        SET_FILE_BINARY(stdout);
00063        progname = argv[0];
00064        samplefac = 0;
00065 
00066        for (i = 1; i < argc; i++)
00067               if (argv[i][0] == '-')
00068                      switch (argv[i][1]) {
00069                      case 'g':
00070                             gamv = atof(argv[++i]);
00071                             break;
00072                      case 'b':
00073                             greyscale = 1;
00074                             break;
00075                      case 'd':
00076                             dither = !dither;
00077                             break;
00078                      case 'c':
00079                             ncolors = atoi(argv[++i]);
00080                             break;
00081                      case 'e':
00082                             if (argv[i+1][0] != '+' && argv[i+1][0] != '-')
00083                                    goto userr;
00084                             bradj = atoi(argv[++i]);
00085                             break;
00086                      case 'n':
00087                             samplefac = atoi(argv[++i]);
00088                             break;
00089                      default:
00090                             goto userr;
00091                      }
00092               else
00093                      break;
00094 
00095        if (i < argc-2)
00096               goto userr;
00097        if (i <= argc-1 && freopen(argv[i], "r", stdin) == NULL) {
00098               fprintf(stderr, "%s: cannot open input \"%s\"\n",
00099                             progname, argv[i]);
00100               exit(1);
00101        }
00102        if (i == argc-2 && freopen(argv[i+1], "w", stdout) == NULL) {
00103               fprintf(stderr, "%s: cannot open output \"%s\"\n",
00104                             progname, argv[i+1]);
00105               exit(1);
00106        }
00107        if (checkheader(stdin, COLRFMT, NULL) < 0 ||
00108                      fgetresolu(&xmax, &ymax, stdin) < 0) {
00109               fprintf(stderr, "%s: bad picture format\n", progname);
00110               exit(1);
00111        }
00112        picstart = ftell(stdin);
00113        currow = -1;
00114        scanln = (COLR *)malloc(xmax*sizeof(COLR));
00115        if (scanln == NULL) {
00116               fprintf(stderr, "%s: out of memory\n", progname);
00117               exit(1);
00118        }
00119                             /* set up gamma correction */
00120        setcolrgam(gamv);
00121                             /* figure out the bits per pixel */
00122        if ((ncolors < 2) | (ncolors > MAXCOLORS))
00123               ncolors = MAXCOLORS;
00124        for (bitsperpix = 1; ncolors > 1<<bitsperpix; bitsperpix++)
00125               ;
00126                             /* compute color map */
00127        if (greyscale)
00128               mkgrymap(ncolors);
00129        else
00130               mkclrmap(ncolors);
00131                             /* convert image */
00132        GIFEncode(stdout, xmax, ymax, 0, 0, bitsperpix,
00133                      rmap, gmap, bmap, getgifpix);
00134        exit(0);
00135 userr:
00136        fprintf(stderr,
00137        "Usage: %s [-b][-d][-n samp][-c ncolors][-g gamv][-e +/-stops] input [output]\n",
00138                      progname);
00139        exit(1);
00140 }
00141 
00142 
00143 static void
00144 getrow(                     /* get the specified row from our image */
00145        int  y
00146 )
00147 {
00148        if (y == currow)
00149               return;
00150        if (y < currow) {
00151               fseek(stdin, picstart, 0);
00152               currow = -1;
00153        }
00154        do
00155               if (freadcolrs(scanln, xmax, stdin) < 0) {
00156                      fprintf(stderr, "%s: error reading picture (y==%d)\n",
00157                                    progname, ymax-1-y);
00158                      exit(1);
00159               }
00160        while (++currow < y);
00161        if (bradj)
00162               shiftcolrs(scanln, xmax, bradj);
00163        colrs_gambs(scanln, xmax);
00164        if (pixscan != NULL) {
00165               if (samplefac)
00166                      neu_dith_colrs(pixscan, scanln, xmax);
00167               else
00168                      dith_colrs(pixscan, scanln, xmax);
00169        }
00170 }
00171 
00172 
00173 static void
00174 mkclrmap(                   /* make our color map */
00175        int    nc
00176 )
00177 {
00178        register int  i;
00179 
00180        if ((samplefac ? neu_init(xmax*ymax) : new_histo(xmax*ymax)) == -1)
00181               goto memerr;
00182        for (i = 0; i < ymax; i++) {
00183               getrow(i);
00184               if (samplefac)
00185                      neu_colrs(scanln, xmax);
00186               else
00187                      cnt_colrs(scanln, xmax);
00188        }
00189        if (samplefac)
00190               neu_clrtab(nc);
00191        else
00192               new_clrtab(nc);
00193        for (i = 0; i < nc; i++) {
00194               rmap[i] = clrtab[i][RED];
00195               gmap[i] = clrtab[i][GRN];
00196               bmap[i] = clrtab[i][BLU];
00197        }
00198        if (dither && (pixscan = (BYTE *)malloc(xmax)) == NULL)
00199               goto memerr;
00200        return;
00201 memerr:
00202        fprintf(stderr, "%s: out of memory\n", progname);
00203        exit(1);
00204 }
00205 
00206 
00207 static void
00208 mkgrymap(
00209        int    nc
00210 )
00211 {
00212        register int  i;
00213 
00214        for (i = 0; i < nc; i++) {
00215               rmap[i] =
00216               gmap[i] =
00217               bmap[i] = ((unsigned)i<<8)/nc;
00218        }
00219 }
00220 
00221 
00222 static int
00223 getgifpix(                  /* get a single pixel from our picture */
00224        int  x,
00225        int  y
00226 )
00227 {
00228        getrow(y);
00229        if (greyscale)
00230               return((normbright(scanln[x])*ncolors)>>8);
00231        if (pixscan != NULL)
00232               return(pixscan[x]);
00233        return(samplefac ? neu_map_pixel(scanln[x]) : map_pixel(scanln[x]));
00234 }
00235 
00236 
00237 /*
00238  * SCARY GIF code follows . . . . sorry.
00239  *
00240  * Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>.A
00241  * Lempel-Ziv compression based on "compress".
00242  *
00243  */
00244 
00245 /*****************************************************************************
00246  *
00247  * GIFENCODE.C    - GIF Image compression interface
00248  *
00249  * GIFEncode( FName, GHeight, GWidth, GInterlace, Background,
00250  *            BitsPerPixel, Red, Green, Blue, GetPixel )
00251  *
00252  *****************************************************************************/
00253 
00254 #define TRUE 1
00255 #define FALSE 0
00256 
00257 int Width, Height;
00258 int curx, cury;
00259 long CountDown;
00260 int Pass;
00261 int Interlace;
00262 unsigned long cur_accum = 0;
00263 int cur_bits = 0;
00264 
00265 static void BumpPixel(void);
00266 static int GIFNextPixel(ifun_t* getpixel);
00267 static void Putword(int w, FILE *fp);
00268 static void compress(int init_bits, FILE *outfile, ifun_t* ReadValue);
00269 
00270 
00271 /* a code_int must be able to hold 2**CBITS values of type int, and also -1 */
00272 typedef int             code_int;
00273 typedef long int        count_int;
00274 typedef unsigned char       char_type;
00275 
00276 static void output(code_int  code);
00277 static void cl_block(void);
00278 static void cl_hash(count_int hsize);
00279 static void writeerr(void);
00280 
00281 static void char_init(void);
00282 static void char_out(int c);
00283 static void flush_char(void);
00284 static void gammawarp(short *sbuf, float gam, int n);
00285 
00286 
00287 /*
00288  * Bump the 'curx' and 'cury' to point to the next pixel
00289  */
00290 static void
00291 BumpPixel(void)
00292 {
00293     curx++;
00294     if( curx == Width ) {
00295        curx = 0;
00296        if( !Interlace ) {
00297            cury++;
00298        } else {
00299            switch( Pass ) {
00300               case 0:
00301                   cury += 8;
00302                   if( cury >= Height ) {
00303                      Pass++;
00304                      cury = 4;
00305                   } 
00306                   break;
00307               case 1:
00308                   cury += 8;
00309                       if( cury >= Height ) {
00310                          Pass++;
00311                          cury = 2;
00312                      }
00313                      break;
00314                      case 2:
00315                   cury += 4;
00316                   if( cury >= Height ) {
00317                      Pass++;
00318                      cury = 1;
00319                   }
00320                   break;
00321                      case 3:
00322                   cury += 2;
00323                   break;
00324            }
00325        }
00326     }
00327 }
00328 
00329 /*
00330  * Return the next pixel from the image
00331  */
00332 static int
00333 GIFNextPixel(
00334        ifun_t* getpixel
00335 )
00336 {
00337     int r;
00338 
00339     if( CountDown == 0 )
00340        return EOF;
00341     CountDown--;
00342     r = (*getpixel)( curx, cury );
00343     BumpPixel();
00344     return r;
00345 }
00346 
00347 /*
00348  * public GIFEncode
00349  */
00350 static void
00351 GIFEncode(
00352        FILE *fp,
00353        int GWidth,
00354        int GHeight,
00355        int GInterlace,
00356        int Background,
00357        int BitsPerPixel,
00358        int Red[],
00359        int Green[],
00360        int Blue[],
00361        ifun_t* GetPixel
00362 )
00363 {
00364     int B;
00365     int RWidth, RHeight;
00366     int LeftOfs, TopOfs;
00367     int Resolution;
00368     int ColorMapSize;
00369     int InitCodeSize;
00370     int i;
00371 
00372     cur_accum = 0; /* globals */
00373     cur_bits = 0;
00374 
00375     Interlace = GInterlace;
00376     ColorMapSize = 1 << BitsPerPixel;
00377     RWidth = Width = GWidth;
00378     RHeight = Height = GHeight;
00379     LeftOfs = TopOfs = 0;
00380     Resolution = BitsPerPixel;
00381 
00382     CountDown = (long)Width * (long)Height;
00383     Pass = 0;
00384     if( BitsPerPixel <= 1 )
00385        InitCodeSize = 2;
00386     else
00387        InitCodeSize = BitsPerPixel;
00388     curx = cury = 0;
00389     fwrite( "GIF87a", 1, 6, fp );
00390     Putword( RWidth, fp );
00391     Putword( RHeight, fp );
00392     B = 0x80;       /* Yes, there is a color map */
00393     B |= (Resolution - 1) << 5;
00394     B |= (BitsPerPixel - 1);
00395     fputc( B, fp );
00396     fputc( Background, fp );
00397     fputc( 0, fp );
00398     for( i=0; i<ColorMapSize; i++ ) {
00399        fputc( Red[i], fp );
00400        fputc( Green[i], fp );
00401        fputc( Blue[i], fp );
00402     }
00403     fputc( ',', fp );
00404     Putword( LeftOfs, fp );
00405     Putword( TopOfs, fp );
00406     Putword( Width, fp );
00407     Putword( Height, fp );
00408     if( Interlace )
00409        fputc( 0x40, fp );
00410     else
00411        fputc( 0x00, fp );
00412     fputc( InitCodeSize, fp );
00413     compress( InitCodeSize+1, fp, GetPixel );
00414     fputc( 0, fp );
00415     fputc( ';', fp );
00416     fclose( fp );
00417 }
00418 
00419 /*
00420  * Write out a word to the GIF file
00421  */
00422 static void
00423 Putword(
00424        int w,
00425        FILE *fp
00426 )
00427 {
00428     fputc( w & 0xff, fp );
00429     fputc( (w/256) & 0xff, fp );
00430 }
00431 
00432 
00433 /***************************************************************************
00434  *
00435  *  GIFCOMPR.C       - GIF Image compression routines
00436  *
00437  *  Lempel-Ziv compression based on 'compress'.  GIF modifications by
00438  *  David Rowley (mgardi@watdcsu.waterloo.edu)
00439  *
00440  ***************************************************************************/
00441 
00442 #define CBITS    12
00443 #define HSIZE  5003            /* 80% occupancy */
00444 
00445 /*
00446  *
00447  * GIF Image compression - modified 'compress'
00448  *
00449  * Based on: compress.c - File compression ala IEEE Computer, June 1984.
00450  *
00451  * By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
00452  *              Jim McKie               (decvax!mcvax!jim)
00453  *              Steve Davies            (decvax!vax135!petsd!peora!srd)
00454  *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)
00455  *              James A. Woods          (decvax!ihnp4!ames!jaw)
00456  *              Joe Orost               (decvax!vax135!petsd!joe)
00457  *
00458  */
00459 #include <ctype.h>
00460 
00461 #define ARGVAL() (*++(*argv) || (--argc && *++argv))
00462 
00463 int n_bits;                        /* number of bits/code */
00464 int maxbits = CBITS;                /* user settable max # bits/code */
00465 code_int maxcode;                  /* maximum code, given n_bits */
00466 code_int maxmaxcode = (code_int)1 << CBITS; /* should NEVER generate this code */
00467 # define MAXCODE(n_bits)        (((code_int) 1 << (n_bits)) - 1)
00468 
00469 count_int htab [HSIZE];
00470 unsigned short codetab [HSIZE];
00471 #define HashTabOf(i)       htab[i]
00472 #define CodeTabOf(i)    codetab[i]
00473 
00474 code_int hsize = HSIZE;                 /* for dynamic table sizing */
00475 
00476 /*
00477  * To save much memory, we overlay the table used by compress() with those
00478  * used by decompress().  The tab_prefix table is the same size and type
00479  * as the codetab.  The tab_suffix table needs 2**CBITS characters.  We
00480  * get this from the beginning of htab.  The output stack uses the rest
00481  * of htab, and contains characters.  There is plenty of room for any
00482  * possible stack (stack used to be 8000 characters).
00483  */
00484 #define tab_prefixof(i) CodeTabOf(i)
00485 #define tab_suffixof(i)        ((char_type *)(htab))[i]
00486 #define de_stack               ((char_type *)&tab_suffixof((code_int)1<<CBITS))
00487 
00488 code_int free_ent = 0;                  /* first unused entry */
00489 
00490 /*
00491  * block compression parameters -- after all codes are used up,
00492  * and compression rate changes, start over.
00493  */
00494 int clear_flg = 0;
00495 int offset;
00496 long int in_count = 1;            /* length of input */
00497 long int out_count = 0;           /* # of codes output (for debugging) */
00498 
00499 /*
00500  * compress stdin to stdout
00501  *
00502  * Algorithm:  use open addressing double hashing (no chaining) on the
00503  * prefix code / next character combination.  We do a variant of Knuth's
00504  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
00505  * secondary probe.  Here, the modular division first probe is gives way
00506  * to a faster exclusive-or manipulation.  Also do block compression with
00507  * an adaptive reset, whereby the code table is cleared when the compression
00508  * ratio decreases, but after the table fills.  The variable-length output
00509  * codes are re-sized at this point, and a special CLEAR code is generated
00510  * for the decompressor.  Late addition:  construct the table according to
00511  * file size for noticeable speed improvement on small files.  Please direct
00512  * questions about this implementation to ames!jaw.
00513  */
00514 
00515 int g_init_bits;
00516 FILE *g_outfile;
00517 int ClearCode;
00518 int EOFCode;
00519 
00520 static void
00521 compress(
00522        int init_bits,
00523        FILE *outfile,
00524        ifun_t* ReadValue
00525 )
00526 {
00527     register long fcode;
00528     register code_int i = 0;
00529     register int c;
00530     register code_int ent;
00531     register code_int disp;
00532     register code_int hsize_reg;
00533     register int hshift;
00534 
00535     /*
00536      * Set up the globals:  g_init_bits - initial number of bits
00537      *                      g_outfile   - pointer to output file
00538      */
00539     g_init_bits = init_bits;
00540     g_outfile = outfile;
00541     /*
00542      * Set up the necessary values
00543      */
00544     offset = 0;
00545     out_count = 0;
00546     clear_flg = 0;
00547     in_count = 1;
00548     maxcode = MAXCODE(n_bits = g_init_bits);
00549     ClearCode = (1 << (init_bits - 1));
00550     EOFCode = ClearCode + 1;
00551     free_ent = ClearCode + 2;
00552     char_init();
00553     ent = GIFNextPixel( ReadValue );
00554     hshift = 0;
00555     for ( fcode = (long) hsize;  fcode < 65536L; fcode *= 2L )
00556         hshift++;
00557     hshift = 8 - hshift;                /* set hash code range bound */
00558     hsize_reg = hsize;
00559     cl_hash( (count_int) hsize_reg);            /* clear hash table */
00560     output( (code_int)ClearCode );
00561     while ( (c = GIFNextPixel( ReadValue )) != EOF ) {
00562         in_count++;
00563         fcode = (long) (((long) c << maxbits) + ent);
00564         /* i = (((code_int)c << hshift) ~ ent); */   /* xor hashing */
00565         i = (((code_int)c << hshift) ^ ent);    /* xor hashing */
00566         if ( HashTabOf (i) == fcode ) {
00567             ent = CodeTabOf (i);
00568             continue;
00569         } else if ( (long)HashTabOf (i) < 0 )      /* empty slot */
00570             goto nomatch;
00571         disp = hsize_reg - i;           /* secondary hash (after G. Knott) */
00572         if ( i == 0 )
00573             disp = 1;
00574 probe:
00575         if ( (i -= disp) < 0 )
00576             i += hsize_reg;
00577         if ( HashTabOf (i) == fcode ) {
00578             ent = CodeTabOf (i);
00579             continue;
00580         }
00581         if ( (long)HashTabOf (i) > 0 )
00582             goto probe;
00583 nomatch:
00584         output ( (code_int) ent );
00585         out_count++;
00586         ent = c;
00587         if ( free_ent < maxmaxcode ) {
00588             CodeTabOf (i) = free_ent++; /* code -> hashtable */
00589             HashTabOf (i) = fcode;
00590         } else
00591                 cl_block();
00592     }
00593     /*
00594      * Put out the final code.
00595      */
00596     output( (code_int)ent );
00597     out_count++;
00598     output( (code_int) EOFCode );
00599     return;
00600 }
00601 
00602 /*****************************************************************
00603  * TAG( output )
00604  *
00605  * Output the given code.
00606  * Inputs:
00607  *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
00608  *              that n_bits =< (long)wordsize - 1.
00609  * Outputs:
00610  *      Outputs code to the file.
00611  * Assumptions:
00612  *      Chars are 8 bits long.
00613  * Algorithm:
00614  *      Maintain a CBITS character long buffer (so that 8 codes will
00615  * fit in it exactly).  Use the VAX insv instruction to insert each
00616  * code in turn.  When the buffer fills up empty it and start over.
00617  */
00618 
00619 unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
00620                                   0x001F, 0x003F, 0x007F, 0x00FF,
00621                                   0x01FF, 0x03FF, 0x07FF, 0x0FFF,
00622                                   0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
00623 
00624 static void
00625 output(
00626        code_int  code
00627 )
00628 {
00629     cur_accum &= masks[ cur_bits ];
00630     if( cur_bits > 0 )
00631         cur_accum |= ((long)code << cur_bits);
00632     else
00633         cur_accum = code;
00634     cur_bits += n_bits;
00635     while( cur_bits >= 8 ) {
00636         char_out( (unsigned int)(cur_accum & 0xff) );
00637         cur_accum >>= 8;
00638         cur_bits -= 8;
00639     }
00640 
00641     /*
00642      * If the next entry is going to be too big for the code size,
00643      * then increase it, if possible.
00644      */
00645    if ( free_ent > maxcode || clear_flg ) {
00646             if( clear_flg ) {
00647                 maxcode = MAXCODE (n_bits = g_init_bits);
00648                 clear_flg = 0;
00649             } else {
00650                 n_bits++;
00651                 if ( n_bits == maxbits )
00652                     maxcode = maxmaxcode;
00653                 else
00654                     maxcode = MAXCODE(n_bits);
00655             }
00656     }
00657     if( code == EOFCode ) {
00658         /*
00659          * At EOF, write the rest of the buffer.
00660          */
00661         while( cur_bits > 0 ) {
00662                 char_out( (unsigned int)(cur_accum & 0xff) );
00663                 cur_accum >>= 8;
00664                 cur_bits -= 8;
00665         }
00666         flush_char();
00667         fflush( g_outfile );
00668         if( ferror( g_outfile ) )
00669                 writeerr();
00670     }
00671 }
00672 
00673 /*
00674  * Clear out the hash table
00675  */
00676 static void
00677 cl_block (void)             /* table clear for block compress */
00678 {
00679         cl_hash ( (count_int) hsize );
00680         free_ent = ClearCode + 2;
00681         clear_flg = 1;
00682         output( (code_int)ClearCode );
00683 }
00684 
00685 static void
00686 cl_hash(          /* reset code table */
00687        register count_int hsize
00688 )
00689 {
00690         register count_int *htab_p = htab+hsize;
00691         register long i;
00692         register long m1 = -1;
00693 
00694         i = hsize - 16;
00695         do {                            /* might use Sys V memset(3) here */
00696                 *(htab_p-16) = m1;
00697                 *(htab_p-15) = m1;
00698                 *(htab_p-14) = m1;
00699                 *(htab_p-13) = m1;
00700                 *(htab_p-12) = m1;
00701                 *(htab_p-11) = m1;
00702                 *(htab_p-10) = m1;
00703                 *(htab_p-9) = m1;
00704                 *(htab_p-8) = m1;
00705                 *(htab_p-7) = m1;
00706                 *(htab_p-6) = m1;
00707                 *(htab_p-5) = m1;
00708                 *(htab_p-4) = m1;
00709                 *(htab_p-3) = m1;
00710                 *(htab_p-2) = m1;
00711                 *(htab_p-1) = m1;
00712                 htab_p -= 16;
00713         } while ((i -= 16) >= 0);
00714         for ( i += 16; i > 0; i-- )
00715                 *--htab_p = m1;
00716 }
00717 
00718 static void
00719 writeerr(void)
00720 {
00721         printf( "error writing output file\n" );
00722         exit(1);
00723 }
00724 
00725 /******************************************************************************
00726  *
00727  * GIF Specific routines
00728  *
00729  ******************************************************************************/
00730 
00731 /*
00732  * Number of characters so far in this 'packet'
00733  */
00734 int a_count;
00735 
00736 /*
00737  * Set up the 'byte output' routine
00738  */
00739 static void
00740 char_init(void)
00741 {
00742         a_count = 0;
00743 }
00744 
00745 /*
00746  * Define the storage for the packet accumulator
00747  */
00748 char accum[256];
00749 
00750 /*
00751  * Add a character to the end of the current packet, and if it is 254
00752  * characters, flush the packet to disk.
00753  */
00754 static void
00755 char_out(
00756        int c
00757 )
00758 {
00759         accum[ a_count++ ] = c;
00760         if( a_count >= 254 )
00761                 flush_char();
00762 }
00763 
00764 /*
00765  * Flush the packet to disk, and reset the accumulator
00766  */
00767 static void
00768 flush_char(void)
00769 {
00770         if( a_count > 0 ) {
00771                 fputc( a_count, g_outfile );
00772                 fwrite( accum, 1, a_count, g_outfile );
00773                 a_count = 0;
00774         }
00775 }
00776 
00777 static float curgamma;
00778 static short gamtab[256];
00779 
00780 static void
00781 gammawarp(
00782        short *sbuf,
00783        float gam,
00784        int n
00785 )
00786 {
00787     int i;
00788 
00789     if(gam!=curgamma) {
00790        for(i=0; i<256; i++) 
00791            gamtab[i] = 255*pow(i/255.0,gam)+0.5;
00792        curgamma = gam;
00793     }
00794     while(n--) {
00795        *sbuf = gamtab[*sbuf];
00796        sbuf++;
00797     }
00798 }