ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_gif.c
Revision: 2.11
Committed: Sun Mar 28 20:33:14 2004 UTC (20 years, 1 month ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad4R0, rad3R6, rad3R6P1, rad3R8, rad3R9
Changes since 2.10: +113 -70 lines
Log Message:
Continued ANSIfication, and other fixes and clarifications.

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 schorsch 2.11 static const char RCSid[] = "$Id: ra_gif.c,v 2.10 2003/07/27 22:12:03 schorsch Exp $";
3 greg 2.1 #endif
4     /*
5     * Convert from Radiance picture file to Compuserve GIF.
6     * Currently, we don't know how to get back.
7     */
8    
9     #include <stdio.h>
10 greg 2.7 #include <time.h>
11 schorsch 2.8 #include <math.h>
12 greg 2.1
13 schorsch 2.8 #include "platform.h"
14 greg 2.1 #include "color.h"
15     #include "resolu.h"
16 schorsch 2.11 #include "clrtab.h"
17 greg 2.1
18     #define MAXCOLORS 256
19    
20     int rmap[MAXCOLORS];
21     int gmap[MAXCOLORS];
22     int bmap[MAXCOLORS];
23    
24     int currow;
25     long picstart;
26 greg 2.4 BYTE clrtab[256][3];
27 greg 2.1
28 greg 2.4 extern int samplefac;
29    
30 greg 2.1
31     COLR *scanln;
32 greg 2.2 BYTE *pixscan;
33 greg 2.1
34     int xmax, ymax; /* picture size */
35     double gamv = 2.2; /* gamma correction */
36     int greyscale = 0; /* convert to B&W? */
37 greg 2.2 int dither = 1; /* dither colors? */
38 greg 2.1 int bradj = 0; /* brightness adjustment */
39 greg 2.6 int ncolors = 0; /* number of colors requested */
40    
41 greg 2.1 char *progname;
42    
43 schorsch 2.11 typedef int ifun_t(int x, int y); /* required by the GIF code below */
44    
45     static void getrow(int y);
46     static void mkclrmap(int nc);
47     static void mkgrymap(int nc);
48     static ifun_t getgifpix;
49    
50     static void GIFEncode(FILE *fp, int GWidth, int GHeight, int GInterlace,
51     int Background, int BitsPerPixel, int Red[], int Green[], int Blue[],
52     ifun_t* GetPixel);
53 greg 2.1
54 schorsch 2.11
55     int
56     main(int argc, char *argv[])
57 greg 2.1 {
58     int bitsperpix;
59     int i;
60 schorsch 2.8 SET_DEFAULT_BINARY();
61     SET_FILE_BINARY(stdin);
62     SET_FILE_BINARY(stdout);
63 greg 2.1 progname = argv[0];
64 greg 2.4 samplefac = 0;
65 greg 2.1
66     for (i = 1; i < argc; i++)
67     if (argv[i][0] == '-')
68     switch (argv[i][1]) {
69     case 'g':
70     gamv = atof(argv[++i]);
71     break;
72     case 'b':
73     greyscale = 1;
74     break;
75 greg 2.2 case 'd':
76     dither = !dither;
77     break;
78 greg 2.1 case 'c':
79     ncolors = atoi(argv[++i]);
80     break;
81     case 'e':
82     if (argv[i+1][0] != '+' && argv[i+1][0] != '-')
83     goto userr;
84     bradj = atoi(argv[++i]);
85     break;
86 greg 2.4 case 'n':
87     samplefac = atoi(argv[++i]);
88     break;
89 greg 2.1 default:
90     goto userr;
91     }
92     else
93     break;
94    
95     if (i < argc-2)
96     goto userr;
97     if (i <= argc-1 && freopen(argv[i], "r", stdin) == NULL) {
98     fprintf(stderr, "%s: cannot open input \"%s\"\n",
99     progname, argv[i]);
100     exit(1);
101     }
102     if (i == argc-2 && freopen(argv[i+1], "w", stdout) == NULL) {
103     fprintf(stderr, "%s: cannot open output \"%s\"\n",
104     progname, argv[i+1]);
105     exit(1);
106     }
107     if (checkheader(stdin, COLRFMT, NULL) < 0 ||
108     fgetresolu(&xmax, &ymax, stdin) < 0) {
109     fprintf(stderr, "%s: bad picture format\n", progname);
110     exit(1);
111     }
112     picstart = ftell(stdin);
113     currow = -1;
114     scanln = (COLR *)malloc(xmax*sizeof(COLR));
115     if (scanln == NULL) {
116     fprintf(stderr, "%s: out of memory\n", progname);
117     exit(1);
118     }
119     /* set up gamma correction */
120     setcolrgam(gamv);
121     /* figure out the bits per pixel */
122 schorsch 2.10 if ((ncolors < 2) | (ncolors > MAXCOLORS))
123 greg 2.1 ncolors = MAXCOLORS;
124     for (bitsperpix = 1; ncolors > 1<<bitsperpix; bitsperpix++)
125     ;
126     /* compute color map */
127     if (greyscale)
128     mkgrymap(ncolors);
129     else
130     mkclrmap(ncolors);
131     /* convert image */
132     GIFEncode(stdout, xmax, ymax, 0, 0, bitsperpix,
133     rmap, gmap, bmap, getgifpix);
134     exit(0);
135     userr:
136     fprintf(stderr,
137 greg 2.5 "Usage: %s [-b][-d][-n samp][-c ncolors][-g gamv][-e +/-stops] input [output]\n",
138 greg 2.1 progname);
139     exit(1);
140     }
141    
142    
143 schorsch 2.11 static void
144     getrow( /* get the specified row from our image */
145     int y
146     )
147 greg 2.1 {
148     if (y == currow)
149     return;
150     if (y < currow) {
151     fseek(stdin, picstart, 0);
152     currow = -1;
153     }
154     do
155     if (freadcolrs(scanln, xmax, stdin) < 0) {
156     fprintf(stderr, "%s: error reading picture (y==%d)\n",
157     progname, ymax-1-y);
158 greg 2.3 exit(1);
159 greg 2.1 }
160     while (++currow < y);
161     if (bradj)
162     shiftcolrs(scanln, xmax, bradj);
163     colrs_gambs(scanln, xmax);
164 schorsch 2.9 if (pixscan != NULL) {
165 greg 2.4 if (samplefac)
166     neu_dith_colrs(pixscan, scanln, xmax);
167     else
168     dith_colrs(pixscan, scanln, xmax);
169 schorsch 2.9 }
170 greg 2.1 }
171    
172    
173 schorsch 2.11 static void
174     mkclrmap( /* make our color map */
175     int nc
176     )
177 greg 2.1 {
178     register int i;
179    
180 greg 2.4 if ((samplefac ? neu_init(xmax*ymax) : new_histo(xmax*ymax)) == -1)
181     goto memerr;
182 greg 2.1 for (i = 0; i < ymax; i++) {
183     getrow(i);
184 greg 2.4 if (samplefac)
185     neu_colrs(scanln, xmax);
186     else
187     cnt_colrs(scanln, xmax);
188 greg 2.1 }
189 greg 2.4 if (samplefac)
190     neu_clrtab(nc);
191     else
192     new_clrtab(nc);
193 greg 2.1 for (i = 0; i < nc; i++) {
194     rmap[i] = clrtab[i][RED];
195     gmap[i] = clrtab[i][GRN];
196     bmap[i] = clrtab[i][BLU];
197     }
198 greg 2.4 if (dither && (pixscan = (BYTE *)malloc(xmax)) == NULL)
199     goto memerr;
200     return;
201     memerr:
202     fprintf(stderr, "%s: out of memory\n", progname);
203     exit(1);
204 greg 2.1 }
205    
206    
207 schorsch 2.11 static void
208     mkgrymap(
209     int nc
210     )
211 greg 2.1 {
212     register int i;
213    
214     for (i = 0; i < nc; i++) {
215     rmap[i] =
216     gmap[i] =
217     bmap[i] = ((unsigned)i<<8)/nc;
218     }
219     }
220    
221    
222 schorsch 2.11 static int
223     getgifpix( /* get a single pixel from our picture */
224     int x,
225     int y
226     )
227 greg 2.1 {
228     getrow(y);
229     if (greyscale)
230 greg 2.6 return((normbright(scanln[x])*ncolors)>>8);
231 greg 2.2 if (pixscan != NULL)
232     return(pixscan[x]);
233 greg 2.4 return(samplefac ? neu_map_pixel(scanln[x]) : map_pixel(scanln[x]));
234 greg 2.1 }
235    
236    
237     /*
238     * SCARY GIF code follows . . . . sorry.
239     *
240     * Based on GIFENCOD by David Rowley <[email protected]>.A
241 schorsch 2.11 * Lempel-Ziv compression based on "compress".
242 greg 2.1 *
243     */
244    
245     /*****************************************************************************
246     *
247     * GIFENCODE.C - GIF Image compression interface
248     *
249     * GIFEncode( FName, GHeight, GWidth, GInterlace, Background,
250     * BitsPerPixel, Red, Green, Blue, GetPixel )
251     *
252     *****************************************************************************/
253    
254     #define TRUE 1
255     #define FALSE 0
256    
257     int Width, Height;
258     int curx, cury;
259     long CountDown;
260     int Pass;
261     int Interlace;
262     unsigned long cur_accum = 0;
263     int cur_bits = 0;
264    
265 schorsch 2.11 static void BumpPixel(void);
266     static int GIFNextPixel(ifun_t* getpixel);
267     static void Putword(int w, FILE *fp);
268     static void compress(int init_bits, FILE *outfile, ifun_t* ReadValue);
269    
270    
271     /* a code_int must be able to hold 2**CBITS values of type int, and also -1 */
272     typedef int code_int;
273     typedef long int count_int;
274     typedef unsigned char char_type;
275    
276     static void output(code_int code);
277     static void cl_block(void);
278     static void cl_hash(count_int hsize);
279     static void writeerr(void);
280    
281     static void char_init(void);
282     static void char_out(int c);
283     static void flush_char(void);
284     static void gammawarp(short *sbuf, float gam, int n);
285    
286    
287 greg 2.1 /*
288     * Bump the 'curx' and 'cury' to point to the next pixel
289     */
290 schorsch 2.11 static void
291     BumpPixel(void)
292 greg 2.1 {
293     curx++;
294     if( curx == Width ) {
295     curx = 0;
296     if( !Interlace ) {
297     cury++;
298     } else {
299     switch( Pass ) {
300     case 0:
301     cury += 8;
302     if( cury >= Height ) {
303     Pass++;
304     cury = 4;
305     }
306     break;
307     case 1:
308     cury += 8;
309     if( cury >= Height ) {
310     Pass++;
311     cury = 2;
312     }
313     break;
314     case 2:
315     cury += 4;
316     if( cury >= Height ) {
317     Pass++;
318     cury = 1;
319     }
320     break;
321     case 3:
322     cury += 2;
323     break;
324     }
325     }
326     }
327     }
328    
329     /*
330     * Return the next pixel from the image
331     */
332 schorsch 2.11 static int
333     GIFNextPixel(
334     ifun_t* getpixel
335     )
336 greg 2.1 {
337     int r;
338    
339     if( CountDown == 0 )
340     return EOF;
341     CountDown--;
342     r = (*getpixel)( curx, cury );
343     BumpPixel();
344     return r;
345     }
346    
347     /*
348     * public GIFEncode
349     */
350 schorsch 2.11 static void
351     GIFEncode(
352     FILE *fp,
353     int GWidth,
354     int GHeight,
355     int GInterlace,
356     int Background,
357     int BitsPerPixel,
358     int Red[],
359     int Green[],
360     int Blue[],
361     ifun_t* GetPixel
362     )
363 greg 2.1 {
364     int B;
365     int RWidth, RHeight;
366     int LeftOfs, TopOfs;
367     int Resolution;
368     int ColorMapSize;
369     int InitCodeSize;
370     int i;
371    
372 schorsch 2.11 cur_accum = 0; /* globals */
373 greg 2.1 cur_bits = 0;
374    
375     Interlace = GInterlace;
376     ColorMapSize = 1 << BitsPerPixel;
377     RWidth = Width = GWidth;
378     RHeight = Height = GHeight;
379     LeftOfs = TopOfs = 0;
380     Resolution = BitsPerPixel;
381    
382     CountDown = (long)Width * (long)Height;
383     Pass = 0;
384     if( BitsPerPixel <= 1 )
385     InitCodeSize = 2;
386     else
387     InitCodeSize = BitsPerPixel;
388     curx = cury = 0;
389     fwrite( "GIF87a", 1, 6, fp );
390     Putword( RWidth, fp );
391     Putword( RHeight, fp );
392     B = 0x80; /* Yes, there is a color map */
393     B |= (Resolution - 1) << 5;
394     B |= (BitsPerPixel - 1);
395     fputc( B, fp );
396     fputc( Background, fp );
397     fputc( 0, fp );
398     for( i=0; i<ColorMapSize; i++ ) {
399     fputc( Red[i], fp );
400     fputc( Green[i], fp );
401     fputc( Blue[i], fp );
402     }
403     fputc( ',', fp );
404     Putword( LeftOfs, fp );
405     Putword( TopOfs, fp );
406     Putword( Width, fp );
407     Putword( Height, fp );
408     if( Interlace )
409     fputc( 0x40, fp );
410     else
411     fputc( 0x00, fp );
412     fputc( InitCodeSize, fp );
413     compress( InitCodeSize+1, fp, GetPixel );
414     fputc( 0, fp );
415     fputc( ';', fp );
416     fclose( fp );
417     }
418    
419     /*
420     * Write out a word to the GIF file
421     */
422 schorsch 2.11 static void
423     Putword(
424     int w,
425     FILE *fp
426     )
427 greg 2.1 {
428     fputc( w & 0xff, fp );
429     fputc( (w/256) & 0xff, fp );
430     }
431    
432    
433     /***************************************************************************
434     *
435     * GIFCOMPR.C - GIF Image compression routines
436     *
437     * Lempel-Ziv compression based on 'compress'. GIF modifications by
438     * David Rowley ([email protected])
439     *
440     ***************************************************************************/
441    
442     #define CBITS 12
443     #define HSIZE 5003 /* 80% occupancy */
444    
445     /*
446     *
447     * GIF Image compression - modified 'compress'
448     *
449     * Based on: compress.c - File compression ala IEEE Computer, June 1984.
450     *
451     * By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
452     * Jim McKie (decvax!mcvax!jim)
453     * Steve Davies (decvax!vax135!petsd!peora!srd)
454     * Ken Turkowski (decvax!decwrl!turtlevax!ken)
455     * James A. Woods (decvax!ihnp4!ames!jaw)
456     * Joe Orost (decvax!vax135!petsd!joe)
457     *
458     */
459     #include <ctype.h>
460    
461     #define ARGVAL() (*++(*argv) || (--argc && *++argv))
462    
463     int n_bits; /* number of bits/code */
464     int maxbits = CBITS; /* user settable max # bits/code */
465     code_int maxcode; /* maximum code, given n_bits */
466     code_int maxmaxcode = (code_int)1 << CBITS; /* should NEVER generate this code */
467     # define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1)
468    
469     count_int htab [HSIZE];
470     unsigned short codetab [HSIZE];
471     #define HashTabOf(i) htab[i]
472     #define CodeTabOf(i) codetab[i]
473    
474     code_int hsize = HSIZE; /* for dynamic table sizing */
475    
476     /*
477     * To save much memory, we overlay the table used by compress() with those
478     * used by decompress(). The tab_prefix table is the same size and type
479     * as the codetab. The tab_suffix table needs 2**CBITS characters. We
480     * get this from the beginning of htab. The output stack uses the rest
481     * of htab, and contains characters. There is plenty of room for any
482     * possible stack (stack used to be 8000 characters).
483     */
484     #define tab_prefixof(i) CodeTabOf(i)
485     #define tab_suffixof(i) ((char_type *)(htab))[i]
486     #define de_stack ((char_type *)&tab_suffixof((code_int)1<<CBITS))
487    
488     code_int free_ent = 0; /* first unused entry */
489    
490     /*
491     * block compression parameters -- after all codes are used up,
492     * and compression rate changes, start over.
493     */
494     int clear_flg = 0;
495     int offset;
496     long int in_count = 1; /* length of input */
497     long int out_count = 0; /* # of codes output (for debugging) */
498    
499     /*
500     * compress stdin to stdout
501     *
502     * Algorithm: use open addressing double hashing (no chaining) on the
503     * prefix code / next character combination. We do a variant of Knuth's
504     * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
505     * secondary probe. Here, the modular division first probe is gives way
506     * to a faster exclusive-or manipulation. Also do block compression with
507     * an adaptive reset, whereby the code table is cleared when the compression
508     * ratio decreases, but after the table fills. The variable-length output
509     * codes are re-sized at this point, and a special CLEAR code is generated
510     * for the decompressor. Late addition: construct the table according to
511     * file size for noticeable speed improvement on small files. Please direct
512     * questions about this implementation to ames!jaw.
513     */
514    
515     int g_init_bits;
516     FILE *g_outfile;
517     int ClearCode;
518     int EOFCode;
519    
520 schorsch 2.11 static void
521     compress(
522     int init_bits,
523     FILE *outfile,
524     ifun_t* ReadValue
525     )
526 greg 2.1 {
527     register long fcode;
528     register code_int i = 0;
529     register int c;
530     register code_int ent;
531     register code_int disp;
532     register code_int hsize_reg;
533     register int hshift;
534    
535     /*
536     * Set up the globals: g_init_bits - initial number of bits
537     * g_outfile - pointer to output file
538     */
539     g_init_bits = init_bits;
540     g_outfile = outfile;
541     /*
542     * Set up the necessary values
543     */
544     offset = 0;
545     out_count = 0;
546     clear_flg = 0;
547     in_count = 1;
548     maxcode = MAXCODE(n_bits = g_init_bits);
549     ClearCode = (1 << (init_bits - 1));
550     EOFCode = ClearCode + 1;
551     free_ent = ClearCode + 2;
552     char_init();
553     ent = GIFNextPixel( ReadValue );
554     hshift = 0;
555     for ( fcode = (long) hsize; fcode < 65536L; fcode *= 2L )
556     hshift++;
557     hshift = 8 - hshift; /* set hash code range bound */
558     hsize_reg = hsize;
559     cl_hash( (count_int) hsize_reg); /* clear hash table */
560     output( (code_int)ClearCode );
561     while ( (c = GIFNextPixel( ReadValue )) != EOF ) {
562     in_count++;
563     fcode = (long) (((long) c << maxbits) + ent);
564 schorsch 2.11 /* i = (((code_int)c << hshift) ~ ent); */ /* xor hashing */
565 greg 2.1 i = (((code_int)c << hshift) ^ ent); /* xor hashing */
566     if ( HashTabOf (i) == fcode ) {
567     ent = CodeTabOf (i);
568     continue;
569     } else if ( (long)HashTabOf (i) < 0 ) /* empty slot */
570     goto nomatch;
571     disp = hsize_reg - i; /* secondary hash (after G. Knott) */
572     if ( i == 0 )
573     disp = 1;
574     probe:
575     if ( (i -= disp) < 0 )
576     i += hsize_reg;
577     if ( HashTabOf (i) == fcode ) {
578     ent = CodeTabOf (i);
579     continue;
580     }
581     if ( (long)HashTabOf (i) > 0 )
582     goto probe;
583     nomatch:
584     output ( (code_int) ent );
585     out_count++;
586     ent = c;
587     if ( free_ent < maxmaxcode ) {
588     CodeTabOf (i) = free_ent++; /* code -> hashtable */
589     HashTabOf (i) = fcode;
590     } else
591     cl_block();
592     }
593     /*
594     * Put out the final code.
595     */
596     output( (code_int)ent );
597     out_count++;
598     output( (code_int) EOFCode );
599     return;
600     }
601    
602     /*****************************************************************
603     * TAG( output )
604     *
605     * Output the given code.
606     * Inputs:
607     * code: A n_bits-bit integer. If == -1, then EOF. This assumes
608     * that n_bits =< (long)wordsize - 1.
609     * Outputs:
610     * Outputs code to the file.
611     * Assumptions:
612     * Chars are 8 bits long.
613     * Algorithm:
614     * Maintain a CBITS character long buffer (so that 8 codes will
615     * fit in it exactly). Use the VAX insv instruction to insert each
616     * code in turn. When the buffer fills up empty it and start over.
617     */
618    
619     unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
620     0x001F, 0x003F, 0x007F, 0x00FF,
621     0x01FF, 0x03FF, 0x07FF, 0x0FFF,
622     0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
623    
624 schorsch 2.11 static void
625     output(
626     code_int code
627     )
628 greg 2.1 {
629     cur_accum &= masks[ cur_bits ];
630     if( cur_bits > 0 )
631     cur_accum |= ((long)code << cur_bits);
632     else
633     cur_accum = code;
634     cur_bits += n_bits;
635     while( cur_bits >= 8 ) {
636     char_out( (unsigned int)(cur_accum & 0xff) );
637     cur_accum >>= 8;
638     cur_bits -= 8;
639     }
640    
641     /*
642     * If the next entry is going to be too big for the code size,
643     * then increase it, if possible.
644     */
645     if ( free_ent > maxcode || clear_flg ) {
646     if( clear_flg ) {
647     maxcode = MAXCODE (n_bits = g_init_bits);
648     clear_flg = 0;
649     } else {
650     n_bits++;
651     if ( n_bits == maxbits )
652     maxcode = maxmaxcode;
653     else
654     maxcode = MAXCODE(n_bits);
655     }
656     }
657     if( code == EOFCode ) {
658     /*
659     * At EOF, write the rest of the buffer.
660     */
661     while( cur_bits > 0 ) {
662     char_out( (unsigned int)(cur_accum & 0xff) );
663     cur_accum >>= 8;
664     cur_bits -= 8;
665     }
666     flush_char();
667     fflush( g_outfile );
668     if( ferror( g_outfile ) )
669     writeerr();
670     }
671     }
672    
673     /*
674     * Clear out the hash table
675     */
676 schorsch 2.11 static void
677     cl_block (void) /* table clear for block compress */
678 greg 2.1 {
679     cl_hash ( (count_int) hsize );
680     free_ent = ClearCode + 2;
681     clear_flg = 1;
682     output( (code_int)ClearCode );
683     }
684    
685 schorsch 2.11 static void
686     cl_hash( /* reset code table */
687     register count_int hsize
688     )
689 greg 2.1 {
690     register count_int *htab_p = htab+hsize;
691     register long i;
692     register long m1 = -1;
693    
694     i = hsize - 16;
695     do { /* might use Sys V memset(3) here */
696     *(htab_p-16) = m1;
697     *(htab_p-15) = m1;
698     *(htab_p-14) = m1;
699     *(htab_p-13) = m1;
700     *(htab_p-12) = m1;
701     *(htab_p-11) = m1;
702     *(htab_p-10) = m1;
703     *(htab_p-9) = m1;
704     *(htab_p-8) = m1;
705     *(htab_p-7) = m1;
706     *(htab_p-6) = m1;
707     *(htab_p-5) = m1;
708     *(htab_p-4) = m1;
709     *(htab_p-3) = m1;
710     *(htab_p-2) = m1;
711     *(htab_p-1) = m1;
712     htab_p -= 16;
713     } while ((i -= 16) >= 0);
714     for ( i += 16; i > 0; i-- )
715     *--htab_p = m1;
716     }
717    
718 schorsch 2.11 static void
719     writeerr(void)
720 greg 2.1 {
721     printf( "error writing output file\n" );
722     exit(1);
723     }
724    
725     /******************************************************************************
726     *
727     * GIF Specific routines
728     *
729     ******************************************************************************/
730    
731     /*
732     * Number of characters so far in this 'packet'
733     */
734     int a_count;
735    
736     /*
737     * Set up the 'byte output' routine
738     */
739 schorsch 2.11 static void
740     char_init(void)
741 greg 2.1 {
742     a_count = 0;
743     }
744    
745     /*
746     * Define the storage for the packet accumulator
747     */
748     char accum[256];
749    
750     /*
751     * Add a character to the end of the current packet, and if it is 254
752     * characters, flush the packet to disk.
753     */
754 schorsch 2.11 static void
755     char_out(
756     int c
757     )
758 greg 2.1 {
759     accum[ a_count++ ] = c;
760     if( a_count >= 254 )
761     flush_char();
762     }
763    
764     /*
765     * Flush the packet to disk, and reset the accumulator
766     */
767 schorsch 2.11 static void
768     flush_char(void)
769 greg 2.1 {
770     if( a_count > 0 ) {
771     fputc( a_count, g_outfile );
772     fwrite( accum, 1, a_count, g_outfile );
773     a_count = 0;
774     }
775     }
776    
777     static float curgamma;
778     static short gamtab[256];
779    
780 schorsch 2.11 static void
781     gammawarp(
782     short *sbuf,
783     float gam,
784     int n
785     )
786 greg 2.1 {
787     int i;
788    
789     if(gam!=curgamma) {
790     for(i=0; i<256; i++)
791     gamtab[i] = 255*pow(i/255.0,gam)+0.5;
792     curgamma = gam;
793     }
794     while(n--) {
795     *sbuf = gamtab[*sbuf];
796     sbuf++;
797     }
798     }