ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_gif.c
Revision: 2.13
Committed: Fri Jul 19 17:37:56 2019 UTC (4 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, rad5R3, HEAD
Changes since 2.12: +2 -3 lines
Log Message:
Moved declarations and definitions for header.c from resolu.h to rtio.h

File Contents

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