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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #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
11 #include <time.h>
12
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 BYTE clrtab[256][3];
36
37 extern int samplefac;
38
39 extern int getgifpix();
40
41 COLR *scanln;
42 BYTE *pixscan;
43
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 int dither = 1; /* dither colors? */
51
52 int bradj = 0; /* brightness adjustment */
53
54 int ncolors = 0; /* number of colors requested */
55
56 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 samplefac = 0;
73
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 case 'd':
84 dither = !dither;
85 break;
86 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 case 'n':
95 samplefac = atoi(argv[++i]);
96 break;
97 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 "Usage: %s [-b][-d][-n samp][-c ncolors][-g gamv][-e +/-stops] input [output]\n",
146 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 exit(1);
165 }
166 while (++currow < y);
167 if (bradj)
168 shiftcolrs(scanln, xmax, bradj);
169 colrs_gambs(scanln, xmax);
170 if (pixscan != NULL)
171 if (samplefac)
172 neu_dith_colrs(pixscan, scanln, xmax);
173 else
174 dith_colrs(pixscan, scanln, xmax);
175 }
176
177
178 mkclrmap(nc) /* make our color map */
179 int nc;
180 {
181 register int i;
182
183 if ((samplefac ? neu_init(xmax*ymax) : new_histo(xmax*ymax)) == -1)
184 goto memerr;
185 for (i = 0; i < ymax; i++) {
186 getrow(i);
187 if (samplefac)
188 neu_colrs(scanln, xmax);
189 else
190 cnt_colrs(scanln, xmax);
191 }
192 if (samplefac)
193 neu_clrtab(nc);
194 else
195 new_clrtab(nc);
196 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 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 }
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 return((normbright(scanln[x])*ncolors)>>8);
232 if (pixscan != NULL)
233 return(pixscan[x]);
234 return(samplefac ? neu_map_pixel(scanln[x]) : map_pixel(scanln[x]));
235 }
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 }