ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_gif.c
Revision: 2.6
Committed: Mon Apr 3 15:29:43 1995 UTC (29 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.5: +3 -2 lines
Log Message:
fixed bug in -c option with -b

File Contents

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