|
|
1.1 paf 1: /** @file
1.2 paf 2: Code drawn from ppmtogif.c, from the pbmplus package
1.1 paf 3:
1.2 paf 4: **
5: ** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A
6: ** Lempel-Zim compression based on "compress".
7: **
8: ** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>
9: **
10: ** Copyright(C) 1989 by Jef Poskanzer.
11: **
12: ** Permission to use, copy, modify, and distribute this software and its
13: ** documentation for any purpose and without fee is hereby granted, provided
14: ** that the above copyright notice appear in all copies and that both that
15: ** copyright notice and this permission notice appear in supporting
16: ** documentation. This software is provided "as is" without express or
17: ** implied warranty.
18: **
19: ** The Graphics Interchange Format(c) is the Copyright property of
20: ** CompuServe Incorporated. GIF(sm) is a Service Mark property of
21: ** CompuServe Incorporated.
1.1 paf 22: */
23:
24: #include "gif.h"
25:
26: static int colorstobpp(int colors);
27:
1.4 ! paf 28: void gdImage::Gif(String& out)
1.1 paf 29: {
1.2 paf 30: int BitsPerPixel = colorstobpp(colorsTotal);
1.1 paf 31: /* Clear any old values in statics strewn through the GIF code */
1.4 ! paf 32: gdGifEncoder encoder(pool(), *this, out);
1.1 paf 33: /* All set, let's do it. */
1.2 paf 34: encoder.encode(
1.4 ! paf 35: sx, sy, interlace, 0, transparent, BitsPerPixel,
1.2 paf 36: red, green, blue);
1.1 paf 37: }
38:
39: static int
40: colorstobpp(int colors)
41: {
42: int bpp = 0;
1.2 paf 43:
44: if( colors <= 2 )
1.1 paf 45: bpp = 1;
1.2 paf 46: else if( colors <= 4 )
1.1 paf 47: bpp = 2;
1.2 paf 48: else if( colors <= 8 )
1.1 paf 49: bpp = 3;
1.2 paf 50: else if( colors <= 16 )
1.1 paf 51: bpp = 4;
1.2 paf 52: else if( colors <= 32 )
1.1 paf 53: bpp = 5;
1.2 paf 54: else if( colors <= 64 )
1.1 paf 55: bpp = 6;
1.2 paf 56: else if( colors <= 128 )
1.1 paf 57: bpp = 7;
1.2 paf 58: else if( colors <= 256 )
1.1 paf 59: bpp = 8;
60: return bpp;
1.2 paf 61: }
1.1 paf 62:
63: /*****************************************************************************
1.2 paf 64: *
65: * GIFENCODE.C - GIF Image compression interface
66: *
67: * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent,
68: * BitsPerPixel, Red, Green, Blue, gdGifEncoder::Ptr )
69: *
70: *****************************************************************************/
1.1 paf 71:
72: #define TRUE 1
73: #define FALSE 0
74:
75: /*
1.2 paf 76: * Bump the 'curx' and 'cury' to point to the next pixel
77: */
78: void
79: gdGifEncoder::BumpPixel(void)
1.1 paf 80: {
1.2 paf 81: /*
82: * Bump the current X position
83: */
84: ++curx;
85:
86: /*
87: * If we are at the end of a scan line, set curx back to the beginning
88: * If we are interlaced, bump the cury to the appropriate spot,
89: * otherwise, just increment it.
90: */
91: if( curx == Width ) {
92: curx = 0;
93:
94: if( !Interlace )
95: ++cury;
96: else {
97: switch( Pass ) {
98:
99: case 0:
100: cury += 8;
101: if( cury >= Height ) {
102: ++Pass;
103: cury = 4;
104: }
105: break;
106:
107: case 1:
108: cury += 8;
109: if( cury >= Height ) {
110: ++Pass;
111: cury = 2;
112: }
113: break;
114:
115: case 2:
116: cury += 4;
117: if( cury >= Height ) {
118: ++Pass;
119: cury = 1;
120: }
121: break;
122:
123: case 3:
124: cury += 2;
125: break;
126: }
127: }
128: }
1.1 paf 129: }
130:
131: /*
1.2 paf 132: * Return the next pixel from the image
133: */
134: int
135: gdGifEncoder::GIFNextPixel()
1.1 paf 136: {
1.2 paf 137: int r;
138:
139: if( CountDown == 0 )
140: return EOF;
141:
142: --CountDown;
143:
144: r = im.GetPixel(curx, cury);
145:
146: BumpPixel();
147:
148: return r;
1.1 paf 149: }
150:
151: /* public */
152:
1.2 paf 153: void
1.4 ! paf 154: gdGifEncoder::encode(int GWidth, int GHeight,
! 155: int GInterlace, int Background, int Transparent, int BitsPerPixel,
! 156: int *Red, int *Green, int *Blue)
1.1 paf 157: {
1.2 paf 158: int B;
159: int RWidth, RHeight;
160: int LeftOfs, TopOfs;
161: int Resolution;
162: int ColorMapSize;
163: int InitCodeSize;
164: int i;
165:
166: Interlace = GInterlace;
167:
168: ColorMapSize = 1 << BitsPerPixel;
169:
170: RWidth = Width = GWidth;
171: RHeight = Height = GHeight;
172: LeftOfs = TopOfs = 0;
173:
174: Resolution = BitsPerPixel;
175:
176: /*
177: * Calculate number of bits we are expecting
178: */
179: CountDown =(long)Width *(long)Height;
180:
181: /*
182: * Indicate which pass we are on(if interlace)
183: */
184: Pass = 0;
185:
186: /*
187: * The initial code size
188: */
189: if( BitsPerPixel <= 1 )
190: InitCodeSize = 2;
191: else
192: InitCodeSize = BitsPerPixel;
193:
194: /*
195: * Set up the current x and y position
196: */
197: curx = cury = 0;
198:
199: /*
200: * Write the Magic header
201: */
1.4 ! paf 202: fp << (Transparent < 0 ? "GIF87a" : "GIF89a");
1.2 paf 203:
204: /*
205: * Write out the screen width and height
206: */
1.4 ! paf 207: Putword( RWidth);
! 208: Putword( RHeight);
1.2 paf 209:
210: /*
211: * Indicate that there is a global colour map
212: */
213: B = 0x80; /* Yes, there is a color map */
214:
215: /*
216: * OR in the resolution
217: */
218: B |=(Resolution - 1) << 5;
219:
220: /*
221: * OR in the Bits per Pixel
222: */
223: B |=(BitsPerPixel - 1);
224:
225: /*
226: * Write it out
227: */
1.4 ! paf 228: Putbyte(B);
1.2 paf 229:
230: /*
231: * Write out the Background colour
232: */
1.4 ! paf 233: Putbyte(Background);
1.2 paf 234:
235: /*
236: * Byte of 0's(future expansion)
237: */
1.4 ! paf 238: Putbyte(0);
1.2 paf 239:
240: /*
241: * Write out the Global Colour Map
242: */
243: for( i=0; i<ColorMapSize; ++i ) {
1.4 ! paf 244: Putbyte( Red[i]);
! 245: Putbyte( Green[i]);
! 246: Putbyte( Blue[i]);
1.2 paf 247: }
248:
249: /*
250: * Write out extension for transparent colour index, if necessary.
251: */
252: if( Transparent >= 0 ) {
1.4 ! paf 253: Putbyte( '!');
! 254: Putbyte( 0xf9);
! 255: Putbyte( 4);
! 256: Putbyte( 1);
! 257: Putbyte( 0);
! 258: Putbyte( 0);
! 259: Putbyte((unsigned char) Transparent);
! 260: Putbyte( 0);
1.1 paf 261: }
1.2 paf 262:
263: /*
264: * Write an Image separator
265: */
1.4 ! paf 266: Putbyte( ',');
1.2 paf 267:
268: /*
269: * Write the Image header
270: */
271:
1.4 ! paf 272: Putword( LeftOfs);
! 273: Putword( TopOfs);
! 274: Putword( Width);
! 275: Putword( Height);
1.2 paf 276:
277: /*
278: * Write out whether or not the image is interlaced
279: */
280: if( Interlace )
1.4 ! paf 281: Putbyte( 0x40);
1.2 paf 282: else
1.4 ! paf 283: Putbyte( 0x00);
1.2 paf 284:
285: /*
286: * Write out the initial code size
287: */
1.4 ! paf 288: Putbyte( InitCodeSize);
1.2 paf 289:
290: /*
291: * Go and actually compress the data
292: */
1.4 ! paf 293: compress( InitCodeSize+1 );
1.2 paf 294:
295: /*
296: * Write out a Zero-length packet(to end the series)
297: */
1.4 ! paf 298: Putbyte( 0);
1.2 paf 299:
300: /*
301: * Write the GIF file terminator
302: */
1.4 ! paf 303: Putbyte( ';');
1.1 paf 304: }
305:
306: /*
1.4 ! paf 307: * Write out a byte to the GIF file
! 308: */
! 309: void
! 310: gdGifEncoder::Putbyte(int c) {
! 311: char *p=(char *)malloc(1);
! 312: *p=c;
! 313: fp.APPEND_CLEAN(p, 1, 0, 0);
! 314: }
! 315: /*
1.2 paf 316: * Write out a word to the GIF file
317: */
1.4 ! paf 318: void
! 319: gdGifEncoder::Putword(int w)
1.1 paf 320: {
1.4 ! paf 321: char *p=(char *)malloc(2);
! 322: p[0]=w & 0xff;
! 323: p[1]=(w / 256) & 0xff;
! 324: fp.APPEND_CLEAN(p, 2, 0, 0);
1.1 paf 325: }
326:
1.4 ! paf 327: void gdGifEncoder::Write(void *buf, size_t size) {
! 328: char *p=(char *)malloc(size);
! 329: memcpy(p, buf, size);
! 330: fp.APPEND_CLEAN(p, size, 0, 0);
! 331: }
1.1 paf 332:
333: /***************************************************************************
1.2 paf 334: *
335: * GIFCOMPR.C - GIF Image compression routines
336: *
337: * Lempel-Ziv compression based on 'compress'. GIF modifications by
338: * David Rowley(mgardi@watdcsu.waterloo.edu)
339: *
340: ***************************************************************************/
1.1 paf 341:
342: /*
1.2 paf 343: * General DEFINEs
344: */
1.1 paf 345:
346: #define GIFBITS 12
347:
348: #ifdef NO_UCHAR
1.2 paf 349: typedef char char_type;
1.1 paf 350: #else /*NO_UCHAR*/
1.2 paf 351: typedef unsigned char char_type;
1.1 paf 352: #endif /*NO_UCHAR*/
353:
354: /*
1.2 paf 355: *
356: * GIF Image compression - modified 'compress'
357: *
358: * Based on: compress.c - File compression ala IEEE Computer, June 1984.
359: *
360: * By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
361: * Jim McKie (decvax!mcvax!jim)
362: * Steve Davies (decvax!vax135!petsd!peora!srd)
363: * Ken Turkowski (decvax!decwrl!turtlevax!ken)
364: * James A. Woods (decvax!ihnp4!ames!jaw)
365: * Joe Orost (decvax!vax135!petsd!joe)
366: *
367: */
1.1 paf 368: #include <ctype.h>
369:
370: #ifdef COMPATIBLE /* But wrong! */
1.2 paf 371: # define MAXCODE(n_bits) ((code_int) 1 <<(n_bits) - 1)
1.1 paf 372: #else /*COMPATIBLE*/
1.2 paf 373: # define MAXCODE(n_bits) (((code_int) 1 <<(n_bits)) - 1)
1.1 paf 374: #endif /*COMPATIBLE*/
375:
376: #define HashTabOf(i) htab[i]
377: #define CodeTabOf(i) codetab[i]
378: /*
1.2 paf 379: * To save much memory, we overlay the table used by compress() with those
380: * used by decompress(). The tab_prefix table is the same size and type
381: * as the codetab. The tab_suffix table needs 2**GIFBITS characters. We
382: * get this from the beginning of htab. The output stack uses the rest
383: * of htab, and contains characters. There is plenty of room for any
384: * possible stack(stack used to be 8000 characters).
385: */
1.1 paf 386:
387: #define tab_prefixof(i) CodeTabOf(i)
1.2 paf 388: #define tab_suffixof(i) ((char_type*)(htab))[i]
389: #define de_stack ((char_type*)&tab_suffixof((code_int)1<<GIFBITS))
1.1 paf 390:
391: /*
1.2 paf 392: * compress stdin to stdout
393: *
394: * Algorithm: use open addressing double hashing(no chaining) on the
395: * prefix code / next character combination. We do a variant of Knuth's
396: * algorithm D(vol. 3, sec. 6.4) along with G. Knott's relatively-prime
397: * secondary probe. Here, the modular division first probe is gives way
398: * to a faster exclusive-or manipulation. Also do block compression with
399: * an adaptive reset, whereby the code table is cleared when the compression
400: * ratio decreases, but after the table fills. The variable-length output
401: * codes are re-sized at this point, and a special CLEAR code is generated
402: * for the decompressor. Late addition: construct the table according to
403: * file size for noticeable speed improvement on small files. Please direct
404: * questions about this implementation to ames!jaw.
405: */
1.1 paf 406:
1.2 paf 407: void
1.4 ! paf 408: gdGifEncoder::compress(int init_bits)
1.1 paf 409: {
410: register long fcode;
411: register code_int i /* = 0 */;
412: register int c;
413: register code_int ent;
414: register code_int disp;
415: register code_int hsize_reg;
416: register int hshift;
1.2 paf 417:
1.1 paf 418: /*
1.2 paf 419: * Set up the globals: g_init_bits - initial number of bits
420: * g_outfile - pointer to output file
421: */
1.1 paf 422: g_init_bits = init_bits;
1.2 paf 423:
1.1 paf 424: /*
1.2 paf 425: * Set up the necessary values
426: */
1.1 paf 427: offset = 0;
428: out_count = 0;
429: clear_flg = 0;
430: in_count = 1;
431: maxcode = MAXCODE(n_bits = g_init_bits);
1.2 paf 432:
433: ClearCode =(1 <<(init_bits - 1));
1.1 paf 434: EOFCode = ClearCode + 1;
435: free_ent = ClearCode + 2;
1.2 paf 436:
1.1 paf 437: char_init();
1.2 paf 438:
439: ent = GIFNextPixel( );
440:
1.1 paf 441: hshift = 0;
1.2 paf 442: for( fcode =(long) hsize; fcode < 65536L; fcode *= 2L )
1.1 paf 443: ++hshift;
444: hshift = 8 - hshift; /* set hash code range bound */
1.2 paf 445:
1.1 paf 446: hsize_reg = hsize;
1.2 paf 447: cl_hash((count_int) hsize_reg); /* clear hash table */
448:
449: output((code_int)ClearCode );
450:
1.1 paf 451: #ifdef SIGNED_COMPARE_SLOW
1.2 paf 452: while((c = GIFNextPixel( )) !=(unsigned) EOF ) {
1.1 paf 453: #else /*SIGNED_COMPARE_SLOW*/
1.2 paf 454: while((c = GIFNextPixel( )) != EOF ) { /* } */
1.1 paf 455: #endif /*SIGNED_COMPARE_SLOW*/
1.2 paf 456:
1.3 paf 457: ++in_count;
458:
459: fcode =(long)(((long) c << maxbits) + ent);
460: i =(((code_int)c << hshift) ^ ent); /* xor hashing */
461:
462: if( HashTabOf(i) == fcode ) {
463: ent = CodeTabOf(i);
464: continue;
465: } else if((long)HashTabOf(i) < 0 ) /* empty slot */
466: goto nomatch;
467: disp = hsize_reg - i; /* secondary hash(after G. Knott) */
468: if( i == 0 )
469: disp = 1;
1.1 paf 470: probe:
1.3 paf 471: if((i -= disp) < 0 )
472: i += hsize_reg;
473:
474: if( HashTabOf(i) == fcode ) {
475: ent = CodeTabOf(i);
476: continue;
477: }
478: if((long)HashTabOf(i) > 0 )
479: goto probe;
1.1 paf 480: nomatch:
1.3 paf 481: output((code_int) ent );
482: ++out_count;
483: ent = c;
1.1 paf 484: #ifdef SIGNED_COMPARE_SLOW
1.3 paf 485: if((unsigned) free_ent <(unsigned) maxmaxcode) {
1.1 paf 486: #else /*SIGNED_COMPARE_SLOW*/
1.3 paf 487: if( free_ent < maxmaxcode ) { /* } */
1.1 paf 488: #endif /*SIGNED_COMPARE_SLOW*/
1.3 paf 489: CodeTabOf(i) = free_ent++; /* code -> hashtable */
490: HashTabOf(i) = fcode;
491: } else
492: cl_block();
493: }
494: /*
495: * Put out the final code.
496: */
497: output((code_int)ent );
498: ++out_count;
499: output((code_int) EOFCode );
500: }
501:
502: /*****************************************************************
503: * TAG( output )
504: *
505: * Output the given code.
506: * Inputs:
507: * code: A n_bits-bit integer. If == -1, then EOF. This assumes
508: * that n_bits =<(long)wordsize - 1.
509: * Outputs:
510: * Outputs code to the file.
511: * Assumptions:
512: * Chars are 8 bits long.
513: * Algorithm:
514: * Maintain a GIFBITS character long buffer(so that 8 codes will
515: * fit in it exactly). Use the VAX insv instruction to insert each
516: * code in turn. When the buffer fills up empty it and start over.
517: */
518:
519: static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
520: 0x001F, 0x003F, 0x007F, 0x00FF,
521: 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
522: 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
523:
524: void
525: gdGifEncoder::output(code_int code)
526: {
527: cur_accum &= masks[ cur_bits ];
528:
529: if( cur_bits > 0 )
530: cur_accum |=((long)code << cur_bits);
531: else
532: cur_accum = code;
533:
534: cur_bits += n_bits;
535:
536: while( cur_bits >= 8 ) {
537: char_out((unsigned int)(cur_accum & 0xff) );
538: cur_accum >>= 8;
539: cur_bits -= 8;
1.2 paf 540: }
541:
1.3 paf 542: /*
543: * If the next entry is going to be too big for the code size,
544: * then increase it, if possible.
1.2 paf 545: */
1.3 paf 546: if( free_ent > maxcode || clear_flg ) {
1.2 paf 547:
1.3 paf 548: if( clear_flg ) {
1.2 paf 549:
1.3 paf 550: maxcode = MAXCODE(n_bits = g_init_bits);
551: clear_flg = 0;
1.2 paf 552:
1.3 paf 553: } else {
1.2 paf 554:
1.3 paf 555: ++n_bits;
556: if( n_bits == maxbits )
557: maxcode = maxmaxcode;
558: else
559: maxcode = MAXCODE(n_bits);
1.2 paf 560: }
561: }
562:
1.3 paf 563: if( code == EOFCode ) {
1.2 paf 564: /*
1.3 paf 565: * At EOF, write the rest of the buffer.
566: */
567: while( cur_bits > 0 ) {
568: char_out((unsigned int)(cur_accum & 0xff) );
569: cur_accum >>= 8;
570: cur_bits -= 8;
571: }
1.2 paf 572:
1.3 paf 573: flush_char();
1.4 ! paf 574: }
1.3 paf 575: }
576:
577: /*
578: * Clear out the hash table
579: */
580: void
581: gdGifEncoder::cl_block(void) /* table clear for block compress */
582: {
583:
584: cl_hash((count_int) hsize );
585: free_ent = ClearCode + 2;
586: clear_flg = 1;
587:
588: output((code_int)ClearCode );
589: }
590:
591: void
592: gdGifEncoder::cl_hash(register count_int hsize) /* reset code table */
593:
594: {
595:
596: register count_int *htab_p = htab+hsize;
597:
598: register long i;
599: register long m1 = -1;
600:
601: i = hsize - 16;
602: do { /* might use Sys V memset(3) here */
603: *(htab_p-16) = m1;
604: *(htab_p-15) = m1;
605: *(htab_p-14) = m1;
606: *(htab_p-13) = m1;
607: *(htab_p-12) = m1;
608: *(htab_p-11) = m1;
609: *(htab_p-10) = m1;
610: *(htab_p-9) = m1;
611: *(htab_p-8) = m1;
612: *(htab_p-7) = m1;
613: *(htab_p-6) = m1;
614: *(htab_p-5) = m1;
615: *(htab_p-4) = m1;
616: *(htab_p-3) = m1;
617: *(htab_p-2) = m1;
618: *(htab_p-1) = m1;
619: htab_p -= 16;
620: } while((i -= 16) >= 0);
621:
622: for( i += 16; i > 0; --i )
623: *--htab_p = m1;
624: }
625:
626: /******************************************************************************
627: *
628: * GIF Specific routines
629: *
630: ******************************************************************************/
631:
632: /*
633: * Set up the 'byte output' routine
634: */
635: void
636: gdGifEncoder::char_init(void)
637: {
638: a_count = 0;
639: }
640:
641: /*
642: * Add a character to the end of the current packet, and if it is 254
643: * characters, flush the packet to disk.
644: */
645: void
646: gdGifEncoder::char_out(int c)
647: {
648: accum[ a_count++ ] = c;
649: if( a_count >= 254 )
650: flush_char();
651: }
652:
653: /*
654: * Flush the packet to disk, and reset the accumulator
655: */
656: void
657: gdGifEncoder::flush_char(void)
658: {
659: if( a_count > 0 ) {
1.4 ! paf 660: Putbyte( a_count );
! 661: Write( accum, a_count);
1.3 paf 662: a_count = 0;
1.2 paf 663: }
1.3 paf 664: }
665:
1.4 ! paf 666: gdGifEncoder::gdGifEncoder(Pool& pool, gdImage& aim, String& afp) : Pooled(pool),
! 667: im(aim),
! 668: fp(afp) {
1.3 paf 669: /* Some of these are properly initialized later. What I'm doing
670: here is making sure code that depends on C's initialization
671: of statics doesn't break when the code gets called more
672: than once. */
673: Width = 0;
674: Height = 0;
675: curx = 0;
676: cury = 0;
677: CountDown = 0;
678: Pass = 0;
679: Interlace = 0;
680: a_count = 0;
681: cur_accum = 0;
682: cur_bits = 0;
683: g_init_bits = 0;
684: ClearCode = 0;
685: EOFCode = 0;
686: free_ent = 0;
687: clear_flg = 0;
688: offset = 0;
689: in_count = 1;
690: out_count = 0;
691: hsize = HSIZE;
692: n_bits = 0;
693: maxbits = GIFBITS;
694: maxcode = 0;
695: maxmaxcode =(code_int)1 << GIFBITS;
696: }
697:
698:
699: /* +-------------------------------------------------------------------+ */
700: /* | Copyright 1990, 1991, 1993, David Koblas.(koblas@netcom.com) | */
701: /* | Permission to use, copy, modify, and distribute this software | */
702: /* | and its documentation for any purpose and without fee is hereby | */
703: /* | granted, provided that the above copyright notice appear in all | */
704: /* | copies and that both that copyright notice and this permission | */
705: /* | notice appear in supporting documentation. This software is | */
706: /* | provided "as is" without express or implied warranty. | */
707: /* +-------------------------------------------------------------------+ */
708:
709:
1.1 paf 710: #define MAXCOLORMAPSIZE 256
1.2 paf 711:
1.1 paf 712: #define TRUE 1
713: #define FALSE 0
1.2 paf 714:
1.1 paf 715: #define CM_RED 0
716: #define CM_GREEN 1
717: #define CM_BLUE 2
1.2 paf 718:
1.1 paf 719: #define MAX_LWZ_BITS 12
1.2 paf 720:
1.1 paf 721: #define INTERLACE 0x40
722: #define LOCALCOLORMAP 0x80
1.2 paf 723: #define BitSet(byte, bit) (((byte) &(bit)) ==(bit))
724:
725: #define ReadOK(file,buffer,len)(fread(buffer, len, 1, file) != 0)
726:
727: #define LM_to_uint(a,b) (((b)<<8)|(a))
728:
729: /* We may eventually want to use this information, but def it out for now */
1.1 paf 730: #if 0
1.2 paf 731: struct GifScreen {
732: unsigned int Width;
733: unsigned int Height;
734: unsigned char ColorMap[3][MAXCOLORMAPSIZE];
735: unsigned int BitPixel;
736: unsigned int ColorResolution;
737: unsigned int Background;
738: unsigned int AspectRatio;
739: };
1.1 paf 740: #endif
1.2 paf 741:
742: struct Gif89 {
743: int transparent;
744: int delayTime;
745: int inputFlag;
746: int disposal;
747: };
1.1 paf 748:
1.2 paf 749: static int ReadColorMap(FILE *fd, int number, unsigned char(*buffer)[256]);
750: static int GetCode(FILE *fd, int code_size, int flag);
1.1 paf 751:
1.2 paf 752: bool gdImage::CreateFromGif(FILE *fd)
1.1 paf 753: {
1.2 paf 754: int imageNumber;
755: int BitPixel;
756: int ColorResolution;
757: int Background;
758: int AspectRatio;
759: int Transparent =(-1);
760: unsigned char buf[16];
761: unsigned char c;
762: unsigned char ColorMap[3][MAXCOLORMAPSIZE];
763: unsigned char localColorMap[3][MAXCOLORMAPSIZE];
764: int imw, imh;
765: int useGlobalColormap;
766: int bitPixel;
767: int imageCount = 0;
768: char version[4];
769: ZeroDataBlock = FALSE;
770:
771: imageNumber = 1;
772: if(! ReadOK(fd,buf,6)) {
773: return false;
774: }
775: if(strncmp((char *)buf,"GIF",3) != 0) {
776: return false;
777: }
778: strncpy(version,(char *)buf + 3, 3);
779: version[3] = '\0';
780:
781: if((strcmp(version, "87a") != 0) &&(strcmp(version, "89a") != 0)) {
782: return false;
1.1 paf 783: }
1.2 paf 784: if(! ReadOK(fd,buf,7)) {
785: return false;
1.1 paf 786: }
1.2 paf 787: BitPixel = 2<<(buf[4]&0x07);
788: ColorResolution =(int)(((buf[4]&0x70)>>3)+1);
789: Background = buf[5];
790: AspectRatio = buf[6];
791:
792: if(BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
793: if(ReadColorMap(fd, BitPixel, ColorMap)) {
794: return false;
795: }
1.1 paf 796: }
1.2 paf 797: for(;;) {
798: if(! ReadOK(fd,&c,1)) {
799: return false;
800: }
801: if(c == ';') { /* GIF terminator */
802: int i;
803: if(imageCount < imageNumber) {
804: return false;
805: }
806: /* Check for open colors at the end, so
807: we can reduce colorsTotal and ultimately
808: BitsPerPixel */
809: for(i=((colorsTotal-1));(i>=0); i--) {
810: if(open[i]) {
811: colorsTotal--;
812: } else {
813: break;
814: }
815: }
816: return true;
817: }
818:
819: if(c == '!') { /* Extension */
820: if(! ReadOK(fd,&c,1)) {
821: return false;
822: }
823: DoExtension(fd, c, &Transparent);
824: continue;
825: }
826:
827: if(c != ',') { /* Not a valid start character */
828: continue;
829: }
830:
831: ++imageCount;
832:
833: if(! ReadOK(fd,buf,9)) {
834: return false;
835: }
836:
837: useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
838:
839: bitPixel = 1<<((buf[8]&0x07)+1);
840:
841: imw = LM_to_uint(buf[4],buf[5]);
842: imh = LM_to_uint(buf[6],buf[7]);
843: Create(imw, imh);
844: interlace = BitSet(buf[8], INTERLACE);
845: if(! useGlobalColormap) {
846: if(ReadColorMap(fd, bitPixel, localColorMap)) {
847: return false;
848: }
849: ReadImage(fd, imw, imh, localColorMap,
850: BitSet(buf[8], INTERLACE),
851: imageCount != imageNumber);
852: } else {
853: ReadImage(fd, imw, imh,
854: ColorMap,
855: BitSet(buf[8], INTERLACE),
856: imageCount != imageNumber);
857: }
858: if(Transparent !=(-1)) {
859: SetColorTransparent(Transparent);
860: }
1.1 paf 861: }
862: }
863:
864: static int
1.2 paf 865: ReadColorMap(FILE *fd, int number, unsigned char(*buffer)[256])
1.1 paf 866: {
1.2 paf 867: int i;
868: unsigned char rgb[3];
869:
870:
871: for(i = 0; i < number; ++i) {
872: if(! ReadOK(fd, rgb, sizeof(rgb))) {
873: return TRUE;
874: }
875: buffer[CM_RED][i] = rgb[0] ;
876: buffer[CM_GREEN][i] = rgb[1] ;
877: buffer[CM_BLUE][i] = rgb[2] ;
878: }
879:
880:
881: return FALSE;
1.1 paf 882: }
883:
1.2 paf 884: int gdImage::DoExtension(FILE *fd, int label, int *Transparent)
1.1 paf 885: {
1.2 paf 886: static unsigned char buf[256];
887:
888: switch(label) {
889: case 0xf9: { /* Graphic Control Extension */
890: (void) GetDataBlock(fd,(unsigned char*) buf);
891: Gif89 gif89 = { -1, -1, -1, 0 }; // PAF:huh?
892: gif89.disposal =(buf[0] >> 2) & 0x7;
893: gif89.inputFlag =(buf[0] >> 1) & 0x1;
894: gif89.delayTime = LM_to_uint(buf[1],buf[2]);
895: if((buf[0] & 0x1) != 0)
896: *Transparent = buf[3];
897:
898: while(GetDataBlock(fd,(unsigned char*) buf) != 0)
899: ;
900: return FALSE;
901: }
902: default:
903: break;
904: }
905: while(GetDataBlock(fd,(unsigned char*) buf) != 0)
906: ;
907:
908: return FALSE;
1.1 paf 909: }
910:
1.2 paf 911: int
912: gdImage::GetDataBlock(FILE *fd, unsigned char *buf)
1.1 paf 913: {
1.2 paf 914: unsigned char count;
915:
916: if(! ReadOK(fd,&count,1)) {
917: return -1;
918: }
919:
920: ZeroDataBlock = count == 0;
921:
922: if((count != 0) &&(! ReadOK(fd, buf, count))) {
923: return -1;
924: }
925:
926: return count;
1.1 paf 927: }
928:
1.2 paf 929: int gdImage::GetCode(FILE *fd, int code_size, int flag)
1.1 paf 930: {
1.2 paf 931: static unsigned char buf[280];
932: static int curbit, lastbit, done, last_byte;
933: int i, j, ret;
934: unsigned char count;
935:
936: if(flag) {
937: curbit = 0;
938: lastbit = 0;
939: done = FALSE;
940: return 0;
941: }
942:
943: if((curbit+code_size) >= lastbit) {
944: if(done) {
945: if(curbit >= lastbit) {
946: /* Oh well */
947: }
948: return -1;
949: }
950: buf[0] = buf[last_byte-2];
951: buf[1] = buf[last_byte-1];
952:
953: if((count = GetDataBlock(fd, &buf[2])) == 0)
954: done = TRUE;
955:
956: last_byte = 2 + count;
957: curbit =(curbit - lastbit) + 16;
958: lastbit =(2+count)*8 ;
959: }
960:
961: ret = 0;
962: for(i = curbit, j = 0; j < code_size; ++i, ++j)
963: ret |=((buf[ i / 8 ] &(1 <<(i % 8))) != 0) << j;
964:
965: curbit += code_size;
966:
967: return ret;
1.1 paf 968: }
969:
1.2 paf 970: int gdImage::LWZReadByte(FILE *fd, int flag, int input_code_size)
1.1 paf 971: {
1.2 paf 972: static int fresh = FALSE;
973: int code, incode;
974: static int code_size, set_code_size;
975: static int max_code, max_code_size;
976: static int firstcode, oldcode;
977: static int clear_code, end_code;
978: static int table[2][(1<< MAX_LWZ_BITS)];
979: static int stack[(1<<(MAX_LWZ_BITS))*2], *sp;
980: register int i;
981:
982: if(flag) {
983: set_code_size = input_code_size;
984: code_size = set_code_size+1;
985: clear_code = 1 << set_code_size ;
986: end_code = clear_code + 1;
987: max_code_size = 2*clear_code;
988: max_code = clear_code+2;
989:
990: GetCode(fd, 0, TRUE);
991:
992: fresh = TRUE;
993:
994: for(i = 0; i < clear_code; ++i) {
995: table[0][i] = 0;
996: table[1][i] = i;
997: }
998: for(; i <(1<<MAX_LWZ_BITS); ++i)
999: table[0][i] = table[1][0] = 0;
1000:
1001: sp = stack;
1002:
1003: return 0;
1004: } else if(fresh) {
1005: fresh = FALSE;
1006: do {
1007: firstcode = oldcode =
1008: GetCode(fd, code_size, FALSE);
1009: } while(firstcode == clear_code);
1010: return firstcode;
1011: }
1012:
1013: if(sp > stack)
1014: return *--sp;
1015:
1016: while((code = GetCode(fd, code_size, FALSE)) >= 0) {
1017: if(code == clear_code) {
1018: for(i = 0; i < clear_code; ++i) {
1019: table[0][i] = 0;
1020: table[1][i] = i;
1021: }
1022: for(; i <(1<<MAX_LWZ_BITS); ++i)
1023: table[0][i] = table[1][i] = 0;
1024: code_size = set_code_size+1;
1025: max_code_size = 2*clear_code;
1026: max_code = clear_code+2;
1027: sp = stack;
1028: firstcode = oldcode =
1029: GetCode(fd, code_size, FALSE);
1030: return firstcode;
1031: } else if(code == end_code) {
1032: int count;
1033: unsigned char buf[260];
1034:
1035: if(ZeroDataBlock)
1036: return -2;
1037:
1038: while((count = GetDataBlock(fd, buf)) > 0)
1039: ;
1040:
1041: if(count != 0)
1042: return -2;
1043: }
1044:
1045: incode = code;
1046:
1047: if(code >= max_code) {
1048: *sp++ = firstcode;
1049: code = oldcode;
1050: }
1051:
1052: while(code >= clear_code) {
1053: *sp++ = table[1][code];
1054: if(code == table[0][code]) {
1055: /* Oh well */
1056: }
1057: code = table[0][code];
1058: }
1059:
1060: *sp++ = firstcode = table[1][code];
1061:
1062: if((code = max_code) <(1<<MAX_LWZ_BITS)) {
1063: table[0][code] = oldcode;
1064: table[1][code] = firstcode;
1065: ++max_code;
1066: if((max_code >= max_code_size) &&
1067: (max_code_size <(1<<MAX_LWZ_BITS))) {
1068: max_code_size *= 2;
1069: ++code_size;
1070: }
1071: }
1072:
1073: oldcode = incode;
1074:
1075: if(sp > stack)
1076: return *--sp;
1077: }
1078: return code;
1.1 paf 1079: }
1080:
1.2 paf 1081: void gdImage::ReadImage(FILE *fd, int len, int height, unsigned char(*cmap)[256], int interlace, int ignore)
1.1 paf 1082: {
1.2 paf 1083: unsigned char c;
1084: int v;
1085: int xpos = 0, ypos = 0, pass = 0;
1086: int i;
1087: /* Stash the color map into the image */
1088: for(i=0;(i<gdMaxColors); i++) {
1089: red[i] = cmap[CM_RED][i];
1090: green[i] = cmap[CM_GREEN][i];
1091: blue[i] = cmap[CM_BLUE][i];
1092: open[i] = 1;
1093: }
1094: /* Many(perhaps most) of these colors will remain marked open. */
1095: colorsTotal = gdMaxColors;
1096: /*
1097: ** Initialize the Compression routines
1098: */
1099: if(! ReadOK(fd,&c,1)) {
1100: return;
1101: }
1102: if(LWZReadByte(fd, TRUE, c) < 0) {
1103: return;
1104: }
1105:
1106: /*
1107: ** If this is an "uninteresting picture" ignore it.
1108: */
1109: if(ignore) {
1110: while(LWZReadByte(fd, FALSE, c) >= 0)
1111: ;
1112: return;
1113: }
1114:
1115: while((v = LWZReadByte(fd,FALSE,c)) >= 0 ) {
1116: /* This how we recognize which colors are actually used. */
1117: if(open[v]) {
1118: open[v] = 0;
1119: }
1120: SetPixel(xpos, ypos, v);
1121: ++xpos;
1122: if(xpos == len) {
1123: xpos = 0;
1124: if(interlace) {
1125: switch(pass) {
1126: case 0:
1127: case 1:
1128: ypos += 8; break;
1129: case 2:
1130: ypos += 4; break;
1131: case 3:
1132: ypos += 2; break;
1133: }
1134:
1135: if(ypos >= height) {
1136: ++pass;
1137: switch(pass) {
1138: case 1:
1139: ypos = 4; break;
1140: case 2:
1141: ypos = 2; break;
1142: case 3:
1143: ypos = 1; break;
1144: default:
1145: goto fini;
1146: }
1147: }
1148: } else {
1149: ++ypos;
1150: }
1151: }
1152: if(ypos >= height)
1153: break;
1154: }
1155:
1.1 paf 1156: fini:
1.2 paf 1157: if(LWZReadByte(fd,FALSE,c)>=0) {
1158: /* Ignore extra */
1159: }
1.1 paf 1160: }
1161: