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

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