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