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