ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_gif.c
Revision: 2.8
Committed: Thu Jun 5 19:29:34 2003 UTC (20 years, 11 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.7: +6 -15 lines
Log Message:
Macros for setting binary file mode. Replacing MSDOS by _WIN32.

File Contents

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