ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_gif.c
Revision: 2.7
Committed: Sat Feb 22 02:07:27 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 2.6: +3 -4 lines
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

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