ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_gif.c
Revision: 2.3
Committed: Fri May 20 11:44:19 1994 UTC (29 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.2: +1 -0 lines
Log Message:
fixed bug in read error handling

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