ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_gif.c
Revision: 2.10
Committed: Sun Jul 27 22:12:03 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.9: +2 -2 lines
Log Message:
Added grouping parens to reduce ambiguity warnings.

File Contents

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