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