|
|
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:
1.7 ! paf 6: $Id: gifio.C,v 1.6 2001/04/17 19:00:32 paf Exp $
1.5 paf 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;
1.7 ! paf 319: fp.APPEND_AS_IS(p, 1, 0, 0);
1.4 paf 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;
1.7 ! paf 330: fp.APPEND_AS_IS(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);
1.7 ! paf 336: fp.APPEND_AS_IS(p, size, 0, 0);
1.4 paf 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: #ifdef COMPATIBLE /* But wrong! */
1.2 paf 375: # define MAXCODE(n_bits) ((code_int) 1 <<(n_bits) - 1)
1.1 paf 376: #else /*COMPATIBLE*/
1.2 paf 377: # define MAXCODE(n_bits) (((code_int) 1 <<(n_bits)) - 1)
1.1 paf 378: #endif /*COMPATIBLE*/
379:
380: #define HashTabOf(i) htab[i]
381: #define CodeTabOf(i) codetab[i]
382: /*
1.2 paf 383: * To save much memory, we overlay the table used by compress() with those
384: * used by decompress(). The tab_prefix table is the same size and type
385: * as the codetab. The tab_suffix table needs 2**GIFBITS characters. We
386: * get this from the beginning of htab. The output stack uses the rest
387: * of htab, and contains characters. There is plenty of room for any
388: * possible stack(stack used to be 8000 characters).
389: */
1.1 paf 390:
391: #define tab_prefixof(i) CodeTabOf(i)
1.2 paf 392: #define tab_suffixof(i) ((char_type*)(htab))[i]
393: #define de_stack ((char_type*)&tab_suffixof((code_int)1<<GIFBITS))
1.1 paf 394:
395: /*
1.2 paf 396: * compress stdin to stdout
397: *
398: * Algorithm: use open addressing double hashing(no chaining) on the
399: * prefix code / next character combination. We do a variant of Knuth's
400: * algorithm D(vol. 3, sec. 6.4) along with G. Knott's relatively-prime
401: * secondary probe. Here, the modular division first probe is gives way
402: * to a faster exclusive-or manipulation. Also do block compression with
403: * an adaptive reset, whereby the code table is cleared when the compression
404: * ratio decreases, but after the table fills. The variable-length output
405: * codes are re-sized at this point, and a special CLEAR code is generated
406: * for the decompressor. Late addition: construct the table according to
407: * file size for noticeable speed improvement on small files. Please direct
408: * questions about this implementation to ames!jaw.
409: */
1.1 paf 410:
1.2 paf 411: void
1.4 paf 412: gdGifEncoder::compress(int init_bits)
1.1 paf 413: {
414: register long fcode;
415: register code_int i /* = 0 */;
416: register int c;
417: register code_int ent;
418: register code_int disp;
419: register code_int hsize_reg;
420: register int hshift;
1.2 paf 421:
1.1 paf 422: /*
1.2 paf 423: * Set up the globals: g_init_bits - initial number of bits
424: * g_outfile - pointer to output file
425: */
1.1 paf 426: g_init_bits = init_bits;
1.2 paf 427:
1.1 paf 428: /*
1.2 paf 429: * Set up the necessary values
430: */
1.1 paf 431: offset = 0;
432: out_count = 0;
433: clear_flg = 0;
434: in_count = 1;
435: maxcode = MAXCODE(n_bits = g_init_bits);
1.2 paf 436:
437: ClearCode =(1 <<(init_bits - 1));
1.1 paf 438: EOFCode = ClearCode + 1;
439: free_ent = ClearCode + 2;
1.2 paf 440:
1.1 paf 441: char_init();
1.2 paf 442:
443: ent = GIFNextPixel( );
444:
1.1 paf 445: hshift = 0;
1.2 paf 446: for( fcode =(long) hsize; fcode < 65536L; fcode *= 2L )
1.1 paf 447: ++hshift;
448: hshift = 8 - hshift; /* set hash code range bound */
1.2 paf 449:
1.1 paf 450: hsize_reg = hsize;
1.2 paf 451: cl_hash((count_int) hsize_reg); /* clear hash table */
452:
453: output((code_int)ClearCode );
454:
1.1 paf 455: #ifdef SIGNED_COMPARE_SLOW
1.2 paf 456: while((c = GIFNextPixel( )) !=(unsigned) EOF ) {
1.1 paf 457: #else /*SIGNED_COMPARE_SLOW*/
1.2 paf 458: while((c = GIFNextPixel( )) != EOF ) { /* } */
1.1 paf 459: #endif /*SIGNED_COMPARE_SLOW*/
1.2 paf 460:
1.3 paf 461: ++in_count;
462:
463: fcode =(long)(((long) c << maxbits) + ent);
464: i =(((code_int)c << hshift) ^ ent); /* xor hashing */
465:
466: if( HashTabOf(i) == fcode ) {
467: ent = CodeTabOf(i);
468: continue;
469: } else if((long)HashTabOf(i) < 0 ) /* empty slot */
470: goto nomatch;
471: disp = hsize_reg - i; /* secondary hash(after G. Knott) */
472: if( i == 0 )
473: disp = 1;
1.1 paf 474: probe:
1.3 paf 475: if((i -= disp) < 0 )
476: i += hsize_reg;
477:
478: if( HashTabOf(i) == fcode ) {
479: ent = CodeTabOf(i);
480: continue;
481: }
482: if((long)HashTabOf(i) > 0 )
483: goto probe;
1.1 paf 484: nomatch:
1.3 paf 485: output((code_int) ent );
486: ++out_count;
487: ent = c;
1.1 paf 488: #ifdef SIGNED_COMPARE_SLOW
1.3 paf 489: if((unsigned) free_ent <(unsigned) maxmaxcode) {
1.1 paf 490: #else /*SIGNED_COMPARE_SLOW*/
1.3 paf 491: if( free_ent < maxmaxcode ) { /* } */
1.1 paf 492: #endif /*SIGNED_COMPARE_SLOW*/
1.3 paf 493: CodeTabOf(i) = free_ent++; /* code -> hashtable */
494: HashTabOf(i) = fcode;
495: } else
496: cl_block();
497: }
498: /*
499: * Put out the final code.
500: */
501: output((code_int)ent );
502: ++out_count;
503: output((code_int) EOFCode );
504: }
505:
506: /*****************************************************************
507: * TAG( output )
508: *
509: * Output the given code.
510: * Inputs:
511: * code: A n_bits-bit integer. If == -1, then EOF. This assumes
512: * that n_bits =<(long)wordsize - 1.
513: * Outputs:
514: * Outputs code to the file.
515: * Assumptions:
516: * Chars are 8 bits long.
517: * Algorithm:
518: * Maintain a GIFBITS character long buffer(so that 8 codes will
519: * fit in it exactly). Use the VAX insv instruction to insert each
520: * code in turn. When the buffer fills up empty it and start over.
521: */
522:
523: static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
524: 0x001F, 0x003F, 0x007F, 0x00FF,
525: 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
526: 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
527:
528: void
529: gdGifEncoder::output(code_int code)
530: {
531: cur_accum &= masks[ cur_bits ];
532:
533: if( cur_bits > 0 )
534: cur_accum |=((long)code << cur_bits);
535: else
536: cur_accum = code;
537:
538: cur_bits += n_bits;
539:
540: while( cur_bits >= 8 ) {
541: char_out((unsigned int)(cur_accum & 0xff) );
542: cur_accum >>= 8;
543: cur_bits -= 8;
1.2 paf 544: }
545:
1.3 paf 546: /*
547: * If the next entry is going to be too big for the code size,
548: * then increase it, if possible.
1.2 paf 549: */
1.3 paf 550: if( free_ent > maxcode || clear_flg ) {
1.2 paf 551:
1.3 paf 552: if( clear_flg ) {
1.2 paf 553:
1.3 paf 554: maxcode = MAXCODE(n_bits = g_init_bits);
555: clear_flg = 0;
1.2 paf 556:
1.3 paf 557: } else {
1.2 paf 558:
1.3 paf 559: ++n_bits;
560: if( n_bits == maxbits )
561: maxcode = maxmaxcode;
562: else
563: maxcode = MAXCODE(n_bits);
1.2 paf 564: }
565: }
566:
1.3 paf 567: if( code == EOFCode ) {
1.2 paf 568: /*
1.3 paf 569: * At EOF, write the rest of the buffer.
570: */
571: while( cur_bits > 0 ) {
572: char_out((unsigned int)(cur_accum & 0xff) );
573: cur_accum >>= 8;
574: cur_bits -= 8;
575: }
1.2 paf 576:
1.3 paf 577: flush_char();
1.4 paf 578: }
1.3 paf 579: }
580:
581: /*
582: * Clear out the hash table
583: */
584: void
585: gdGifEncoder::cl_block(void) /* table clear for block compress */
586: {
587:
588: cl_hash((count_int) hsize );
589: free_ent = ClearCode + 2;
590: clear_flg = 1;
591:
592: output((code_int)ClearCode );
593: }
594:
595: void
596: gdGifEncoder::cl_hash(register count_int hsize) /* reset code table */
597:
598: {
599:
600: register count_int *htab_p = htab+hsize;
601:
602: register long i;
603: register long m1 = -1;
604:
605: i = hsize - 16;
606: do { /* might use Sys V memset(3) here */
607: *(htab_p-16) = m1;
608: *(htab_p-15) = m1;
609: *(htab_p-14) = m1;
610: *(htab_p-13) = m1;
611: *(htab_p-12) = m1;
612: *(htab_p-11) = m1;
613: *(htab_p-10) = m1;
614: *(htab_p-9) = m1;
615: *(htab_p-8) = m1;
616: *(htab_p-7) = m1;
617: *(htab_p-6) = m1;
618: *(htab_p-5) = m1;
619: *(htab_p-4) = m1;
620: *(htab_p-3) = m1;
621: *(htab_p-2) = m1;
622: *(htab_p-1) = m1;
623: htab_p -= 16;
624: } while((i -= 16) >= 0);
625:
626: for( i += 16; i > 0; --i )
627: *--htab_p = m1;
628: }
629:
630: /******************************************************************************
631: *
632: * GIF Specific routines
633: *
634: ******************************************************************************/
635:
636: /*
637: * Set up the 'byte output' routine
638: */
639: void
640: gdGifEncoder::char_init(void)
641: {
642: a_count = 0;
643: }
644:
645: /*
646: * Add a character to the end of the current packet, and if it is 254
647: * characters, flush the packet to disk.
648: */
649: void
650: gdGifEncoder::char_out(int c)
651: {
652: accum[ a_count++ ] = c;
653: if( a_count >= 254 )
654: flush_char();
655: }
656:
657: /*
658: * Flush the packet to disk, and reset the accumulator
659: */
660: void
661: gdGifEncoder::flush_char(void)
662: {
663: if( a_count > 0 ) {
1.4 paf 664: Putbyte( a_count );
665: Write( accum, a_count);
1.3 paf 666: a_count = 0;
1.2 paf 667: }
1.3 paf 668: }
669:
1.4 paf 670: gdGifEncoder::gdGifEncoder(Pool& pool, gdImage& aim, String& afp) : Pooled(pool),
671: im(aim),
672: fp(afp) {
1.3 paf 673: /* Some of these are properly initialized later. What I'm doing
674: here is making sure code that depends on C's initialization
675: of statics doesn't break when the code gets called more
676: than once. */
677: Width = 0;
678: Height = 0;
679: curx = 0;
680: cury = 0;
681: CountDown = 0;
682: Pass = 0;
683: Interlace = 0;
684: a_count = 0;
685: cur_accum = 0;
686: cur_bits = 0;
687: g_init_bits = 0;
688: ClearCode = 0;
689: EOFCode = 0;
690: free_ent = 0;
691: clear_flg = 0;
692: offset = 0;
693: in_count = 1;
694: out_count = 0;
695: hsize = HSIZE;
696: n_bits = 0;
697: maxbits = GIFBITS;
698: maxcode = 0;
699: maxmaxcode =(code_int)1 << GIFBITS;
700: }
701:
702:
703: /* +-------------------------------------------------------------------+ */
704: /* | Copyright 1990, 1991, 1993, David Koblas.(koblas@netcom.com) | */
705: /* | Permission to use, copy, modify, and distribute this software | */
706: /* | and its documentation for any purpose and without fee is hereby | */
707: /* | granted, provided that the above copyright notice appear in all | */
708: /* | copies and that both that copyright notice and this permission | */
709: /* | notice appear in supporting documentation. This software is | */
710: /* | provided "as is" without express or implied warranty. | */
711: /* +-------------------------------------------------------------------+ */
712:
713:
1.1 paf 714: #define MAXCOLORMAPSIZE 256
1.2 paf 715:
1.1 paf 716: #define TRUE 1
717: #define FALSE 0
1.2 paf 718:
1.1 paf 719: #define CM_RED 0
720: #define CM_GREEN 1
721: #define CM_BLUE 2
1.2 paf 722:
1.1 paf 723: #define MAX_LWZ_BITS 12
1.2 paf 724:
1.1 paf 725: #define INTERLACE 0x40
726: #define LOCALCOLORMAP 0x80
1.2 paf 727: #define BitSet(byte, bit) (((byte) &(bit)) ==(bit))
728:
729: #define ReadOK(file,buffer,len)(fread(buffer, len, 1, file) != 0)
730:
731: #define LM_to_uint(a,b) (((b)<<8)|(a))
732:
733: /* We may eventually want to use this information, but def it out for now */
1.1 paf 734: #if 0
1.2 paf 735: struct GifScreen {
736: unsigned int Width;
737: unsigned int Height;
738: unsigned char ColorMap[3][MAXCOLORMAPSIZE];
739: unsigned int BitPixel;
740: unsigned int ColorResolution;
741: unsigned int Background;
742: unsigned int AspectRatio;
743: };
1.1 paf 744: #endif
1.2 paf 745:
746: struct Gif89 {
747: int transparent;
748: int delayTime;
749: int inputFlag;
750: int disposal;
751: };
1.1 paf 752:
1.2 paf 753: static int ReadColorMap(FILE *fd, int number, unsigned char(*buffer)[256]);
754: static int GetCode(FILE *fd, int code_size, int flag);
1.1 paf 755:
1.2 paf 756: bool gdImage::CreateFromGif(FILE *fd)
1.1 paf 757: {
1.2 paf 758: int imageNumber;
759: int BitPixel;
760: int ColorResolution;
761: int Background;
762: int AspectRatio;
763: int Transparent =(-1);
764: unsigned char buf[16];
765: unsigned char c;
766: unsigned char ColorMap[3][MAXCOLORMAPSIZE];
767: unsigned char localColorMap[3][MAXCOLORMAPSIZE];
768: int imw, imh;
769: int useGlobalColormap;
770: int bitPixel;
771: int imageCount = 0;
772: char version[4];
773: ZeroDataBlock = FALSE;
774:
775: imageNumber = 1;
776: if(! ReadOK(fd,buf,6)) {
777: return false;
778: }
779: if(strncmp((char *)buf,"GIF",3) != 0) {
780: return false;
781: }
782: strncpy(version,(char *)buf + 3, 3);
783: version[3] = '\0';
784:
785: if((strcmp(version, "87a") != 0) &&(strcmp(version, "89a") != 0)) {
786: return false;
1.1 paf 787: }
1.2 paf 788: if(! ReadOK(fd,buf,7)) {
789: return false;
1.1 paf 790: }
1.2 paf 791: BitPixel = 2<<(buf[4]&0x07);
792: ColorResolution =(int)(((buf[4]&0x70)>>3)+1);
793: Background = buf[5];
794: AspectRatio = buf[6];
795:
796: if(BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
797: if(ReadColorMap(fd, BitPixel, ColorMap)) {
798: return false;
799: }
1.1 paf 800: }
1.2 paf 801: for(;;) {
802: if(! ReadOK(fd,&c,1)) {
803: return false;
804: }
805: if(c == ';') { /* GIF terminator */
806: int i;
807: if(imageCount < imageNumber) {
808: return false;
809: }
810: /* Check for open colors at the end, so
811: we can reduce colorsTotal and ultimately
812: BitsPerPixel */
813: for(i=((colorsTotal-1));(i>=0); i--) {
814: if(open[i]) {
815: colorsTotal--;
816: } else {
817: break;
818: }
819: }
820: return true;
821: }
822:
823: if(c == '!') { /* Extension */
824: if(! ReadOK(fd,&c,1)) {
825: return false;
826: }
827: DoExtension(fd, c, &Transparent);
828: continue;
829: }
830:
831: if(c != ',') { /* Not a valid start character */
832: continue;
833: }
834:
835: ++imageCount;
836:
837: if(! ReadOK(fd,buf,9)) {
838: return false;
839: }
840:
841: useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
842:
843: bitPixel = 1<<((buf[8]&0x07)+1);
844:
845: imw = LM_to_uint(buf[4],buf[5]);
846: imh = LM_to_uint(buf[6],buf[7]);
847: Create(imw, imh);
848: interlace = BitSet(buf[8], INTERLACE);
849: if(! useGlobalColormap) {
850: if(ReadColorMap(fd, bitPixel, localColorMap)) {
851: return false;
852: }
853: ReadImage(fd, imw, imh, localColorMap,
854: BitSet(buf[8], INTERLACE),
855: imageCount != imageNumber);
856: } else {
857: ReadImage(fd, imw, imh,
858: ColorMap,
859: BitSet(buf[8], INTERLACE),
860: imageCount != imageNumber);
861: }
862: if(Transparent !=(-1)) {
863: SetColorTransparent(Transparent);
864: }
1.1 paf 865: }
866: }
867:
868: static int
1.2 paf 869: ReadColorMap(FILE *fd, int number, unsigned char(*buffer)[256])
1.1 paf 870: {
1.2 paf 871: int i;
872: unsigned char rgb[3];
873:
874:
875: for(i = 0; i < number; ++i) {
876: if(! ReadOK(fd, rgb, sizeof(rgb))) {
877: return TRUE;
878: }
879: buffer[CM_RED][i] = rgb[0] ;
880: buffer[CM_GREEN][i] = rgb[1] ;
881: buffer[CM_BLUE][i] = rgb[2] ;
882: }
883:
884:
885: return FALSE;
1.1 paf 886: }
887:
1.2 paf 888: int gdImage::DoExtension(FILE *fd, int label, int *Transparent)
1.1 paf 889: {
1.2 paf 890: static unsigned char buf[256];
891:
892: switch(label) {
893: case 0xf9: { /* Graphic Control Extension */
894: (void) GetDataBlock(fd,(unsigned char*) buf);
895: Gif89 gif89 = { -1, -1, -1, 0 }; // PAF:huh?
896: gif89.disposal =(buf[0] >> 2) & 0x7;
897: gif89.inputFlag =(buf[0] >> 1) & 0x1;
898: gif89.delayTime = LM_to_uint(buf[1],buf[2]);
899: if((buf[0] & 0x1) != 0)
900: *Transparent = buf[3];
901:
902: while(GetDataBlock(fd,(unsigned char*) buf) != 0)
903: ;
904: return FALSE;
905: }
906: default:
907: break;
908: }
909: while(GetDataBlock(fd,(unsigned char*) buf) != 0)
910: ;
911:
912: return FALSE;
1.1 paf 913: }
914:
1.2 paf 915: int
916: gdImage::GetDataBlock(FILE *fd, unsigned char *buf)
1.1 paf 917: {
1.2 paf 918: unsigned char count;
919:
920: if(! ReadOK(fd,&count,1)) {
921: return -1;
922: }
923:
924: ZeroDataBlock = count == 0;
925:
926: if((count != 0) &&(! ReadOK(fd, buf, count))) {
927: return -1;
928: }
929:
930: return count;
1.1 paf 931: }
932:
1.2 paf 933: int gdImage::GetCode(FILE *fd, int code_size, int flag)
1.1 paf 934: {
1.2 paf 935: static unsigned char buf[280];
936: static int curbit, lastbit, done, last_byte;
937: int i, j, ret;
938: unsigned char count;
939:
940: if(flag) {
941: curbit = 0;
942: lastbit = 0;
943: done = FALSE;
944: return 0;
945: }
946:
947: if((curbit+code_size) >= lastbit) {
948: if(done) {
949: if(curbit >= lastbit) {
950: /* Oh well */
951: }
952: return -1;
953: }
954: buf[0] = buf[last_byte-2];
955: buf[1] = buf[last_byte-1];
956:
957: if((count = GetDataBlock(fd, &buf[2])) == 0)
958: done = TRUE;
959:
960: last_byte = 2 + count;
961: curbit =(curbit - lastbit) + 16;
962: lastbit =(2+count)*8 ;
963: }
964:
965: ret = 0;
966: for(i = curbit, j = 0; j < code_size; ++i, ++j)
967: ret |=((buf[ i / 8 ] &(1 <<(i % 8))) != 0) << j;
968:
969: curbit += code_size;
970:
971: return ret;
1.1 paf 972: }
973:
1.2 paf 974: int gdImage::LWZReadByte(FILE *fd, int flag, int input_code_size)
1.1 paf 975: {
1.2 paf 976: static int fresh = FALSE;
977: int code, incode;
978: static int code_size, set_code_size;
979: static int max_code, max_code_size;
980: static int firstcode, oldcode;
981: static int clear_code, end_code;
982: static int table[2][(1<< MAX_LWZ_BITS)];
983: static int stack[(1<<(MAX_LWZ_BITS))*2], *sp;
984: register int i;
985:
986: if(flag) {
987: set_code_size = input_code_size;
988: code_size = set_code_size+1;
989: clear_code = 1 << set_code_size ;
990: end_code = clear_code + 1;
991: max_code_size = 2*clear_code;
992: max_code = clear_code+2;
993:
994: GetCode(fd, 0, TRUE);
995:
996: fresh = TRUE;
997:
998: for(i = 0; i < clear_code; ++i) {
999: table[0][i] = 0;
1000: table[1][i] = i;
1001: }
1002: for(; i <(1<<MAX_LWZ_BITS); ++i)
1003: table[0][i] = table[1][0] = 0;
1004:
1005: sp = stack;
1006:
1007: return 0;
1008: } else if(fresh) {
1009: fresh = FALSE;
1010: do {
1011: firstcode = oldcode =
1012: GetCode(fd, code_size, FALSE);
1013: } while(firstcode == clear_code);
1014: return firstcode;
1015: }
1016:
1017: if(sp > stack)
1018: return *--sp;
1019:
1020: while((code = GetCode(fd, code_size, FALSE)) >= 0) {
1021: if(code == clear_code) {
1022: for(i = 0; i < clear_code; ++i) {
1023: table[0][i] = 0;
1024: table[1][i] = i;
1025: }
1026: for(; i <(1<<MAX_LWZ_BITS); ++i)
1027: table[0][i] = table[1][i] = 0;
1028: code_size = set_code_size+1;
1029: max_code_size = 2*clear_code;
1030: max_code = clear_code+2;
1031: sp = stack;
1032: firstcode = oldcode =
1033: GetCode(fd, code_size, FALSE);
1034: return firstcode;
1035: } else if(code == end_code) {
1036: int count;
1037: unsigned char buf[260];
1038:
1039: if(ZeroDataBlock)
1040: return -2;
1041:
1042: while((count = GetDataBlock(fd, buf)) > 0)
1043: ;
1044:
1045: if(count != 0)
1046: return -2;
1047: }
1048:
1049: incode = code;
1050:
1051: if(code >= max_code) {
1052: *sp++ = firstcode;
1053: code = oldcode;
1054: }
1055:
1056: while(code >= clear_code) {
1057: *sp++ = table[1][code];
1058: if(code == table[0][code]) {
1059: /* Oh well */
1060: }
1061: code = table[0][code];
1062: }
1063:
1064: *sp++ = firstcode = table[1][code];
1065:
1066: if((code = max_code) <(1<<MAX_LWZ_BITS)) {
1067: table[0][code] = oldcode;
1068: table[1][code] = firstcode;
1069: ++max_code;
1070: if((max_code >= max_code_size) &&
1071: (max_code_size <(1<<MAX_LWZ_BITS))) {
1072: max_code_size *= 2;
1073: ++code_size;
1074: }
1075: }
1076:
1077: oldcode = incode;
1078:
1079: if(sp > stack)
1080: return *--sp;
1081: }
1082: return code;
1.1 paf 1083: }
1084:
1.2 paf 1085: void gdImage::ReadImage(FILE *fd, int len, int height, unsigned char(*cmap)[256], int interlace, int ignore)
1.1 paf 1086: {
1.2 paf 1087: unsigned char c;
1088: int v;
1089: int xpos = 0, ypos = 0, pass = 0;
1090: int i;
1091: /* Stash the color map into the image */
1092: for(i=0;(i<gdMaxColors); i++) {
1093: red[i] = cmap[CM_RED][i];
1094: green[i] = cmap[CM_GREEN][i];
1095: blue[i] = cmap[CM_BLUE][i];
1096: open[i] = 1;
1097: }
1098: /* Many(perhaps most) of these colors will remain marked open. */
1099: colorsTotal = gdMaxColors;
1100: /*
1101: ** Initialize the Compression routines
1102: */
1103: if(! ReadOK(fd,&c,1)) {
1104: return;
1105: }
1106: if(LWZReadByte(fd, TRUE, c) < 0) {
1107: return;
1108: }
1109:
1110: /*
1111: ** If this is an "uninteresting picture" ignore it.
1112: */
1113: if(ignore) {
1114: while(LWZReadByte(fd, FALSE, c) >= 0)
1115: ;
1116: return;
1117: }
1118:
1119: while((v = LWZReadByte(fd,FALSE,c)) >= 0 ) {
1120: /* This how we recognize which colors are actually used. */
1121: if(open[v]) {
1122: open[v] = 0;
1123: }
1124: SetPixel(xpos, ypos, v);
1125: ++xpos;
1126: if(xpos == len) {
1127: xpos = 0;
1128: if(interlace) {
1129: switch(pass) {
1130: case 0:
1131: case 1:
1132: ypos += 8; break;
1133: case 2:
1134: ypos += 4; break;
1135: case 3:
1136: ypos += 2; break;
1137: }
1138:
1139: if(ypos >= height) {
1140: ++pass;
1141: switch(pass) {
1142: case 1:
1143: ypos = 4; break;
1144: case 2:
1145: ypos = 2; break;
1146: case 3:
1147: ypos = 1; break;
1148: default:
1149: goto fini;
1150: }
1151: }
1152: } else {
1153: ++ypos;
1154: }
1155: }
1156: if(ypos >= height)
1157: break;
1158: }
1159:
1.1 paf 1160: fini:
1.2 paf 1161: if(LWZReadByte(fd,FALSE,c)>=0) {
1162: /* Ignore extra */
1163: }
1.1 paf 1164: }
1165: