|
|
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: based on:
1.2 paf 7: **
8: ** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A
9: ** Lempel-Zim compression based on "compress".
10: **
11: ** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>
12: **
13: ** Copyright(C) 1989 by Jef Poskanzer.
14: **
15: ** Permission to use, copy, modify, and distribute this software and its
16: ** documentation for any purpose and without fee is hereby granted, provided
17: ** that the above copyright notice appear in all copies and that both that
18: ** copyright notice and this permission notice appear in supporting
19: ** documentation. This software is provided "as is" without express or
20: ** implied warranty.
21: **
22: ** The Graphics Interchange Format(c) is the Copyright property of
23: ** CompuServe Incorporated. GIF(sm) is a Service Mark property of
24: ** CompuServe Incorporated.
1.1 paf 25: */
1.12 ! parser 26: static const char *RCSId="$Id: date.C,v 1.6 2001/09/04 10:50:19 parser Exp $";
1.1 paf 27:
28: #include "gif.h"
29:
30: static int colorstobpp(int colors);
31:
1.4 paf 32: void gdImage::Gif(String& out)
1.1 paf 33: {
1.2 paf 34: int BitsPerPixel = colorstobpp(colorsTotal);
1.1 paf 35: /* Clear any old values in statics strewn through the GIF code */
1.4 paf 36: gdGifEncoder encoder(pool(), *this, out);
1.1 paf 37: /* All set, let's do it. */
1.2 paf 38: encoder.encode(
1.4 paf 39: sx, sy, interlace, 0, transparent, BitsPerPixel,
1.2 paf 40: red, green, blue);
1.1 paf 41: }
42:
43: static int
44: colorstobpp(int colors)
45: {
46: int bpp = 0;
1.2 paf 47:
48: if( colors <= 2 )
1.1 paf 49: bpp = 1;
1.2 paf 50: else if( colors <= 4 )
1.1 paf 51: bpp = 2;
1.2 paf 52: else if( colors <= 8 )
1.1 paf 53: bpp = 3;
1.2 paf 54: else if( colors <= 16 )
1.1 paf 55: bpp = 4;
1.2 paf 56: else if( colors <= 32 )
1.1 paf 57: bpp = 5;
1.2 paf 58: else if( colors <= 64 )
1.1 paf 59: bpp = 6;
1.2 paf 60: else if( colors <= 128 )
1.1 paf 61: bpp = 7;
1.2 paf 62: else if( colors <= 256 )
1.1 paf 63: bpp = 8;
64: return bpp;
1.2 paf 65: }
1.1 paf 66:
67: /*****************************************************************************
1.2 paf 68: *
69: * GIFENCODE.C - GIF Image compression interface
70: *
71: * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent,
72: * BitsPerPixel, Red, Green, Blue, gdGifEncoder::Ptr )
73: *
74: *****************************************************************************/
1.1 paf 75:
76: #define TRUE 1
77: #define FALSE 0
78:
79: /*
1.2 paf 80: * Bump the 'curx' and 'cury' to point to the next pixel
81: */
82: void
83: gdGifEncoder::BumpPixel(void)
1.1 paf 84: {
1.2 paf 85: /*
86: * Bump the current X position
87: */
88: ++curx;
89:
90: /*
91: * If we are at the end of a scan line, set curx back to the beginning
92: * If we are interlaced, bump the cury to the appropriate spot,
93: * otherwise, just increment it.
94: */
95: if( curx == Width ) {
96: curx = 0;
97:
98: if( !Interlace )
99: ++cury;
100: else {
101: switch( Pass ) {
102:
103: case 0:
104: cury += 8;
105: if( cury >= Height ) {
106: ++Pass;
107: cury = 4;
108: }
109: break;
110:
111: case 1:
112: cury += 8;
113: if( cury >= Height ) {
114: ++Pass;
115: cury = 2;
116: }
117: break;
118:
119: case 2:
120: cury += 4;
121: if( cury >= Height ) {
122: ++Pass;
123: cury = 1;
124: }
125: break;
126:
127: case 3:
128: cury += 2;
129: break;
130: }
131: }
132: }
1.1 paf 133: }
134:
135: /*
1.2 paf 136: * Return the next pixel from the image
137: */
138: int
139: gdGifEncoder::GIFNextPixel()
1.1 paf 140: {
1.2 paf 141: int r;
142:
143: if( CountDown == 0 )
144: return EOF;
145:
146: --CountDown;
147:
148: r = im.GetPixel(curx, cury);
149:
150: BumpPixel();
151:
152: return r;
1.1 paf 153: }
154:
155: /* public */
156:
1.2 paf 157: void
1.4 paf 158: gdGifEncoder::encode(int GWidth, int GHeight,
159: int GInterlace, int Background, int Transparent, int BitsPerPixel,
160: int *Red, int *Green, int *Blue)
1.1 paf 161: {
1.2 paf 162: int B;
163: int RWidth, RHeight;
164: int LeftOfs, TopOfs;
165: int Resolution;
166: int ColorMapSize;
167: int InitCodeSize;
168: int i;
169:
170: Interlace = GInterlace;
171:
172: ColorMapSize = 1 << BitsPerPixel;
173:
174: RWidth = Width = GWidth;
175: RHeight = Height = GHeight;
176: LeftOfs = TopOfs = 0;
177:
178: Resolution = BitsPerPixel;
179:
180: /*
181: * Calculate number of bits we are expecting
182: */
183: CountDown =(long)Width *(long)Height;
184:
185: /*
186: * Indicate which pass we are on(if interlace)
187: */
188: Pass = 0;
189:
190: /*
191: * The initial code size
192: */
193: if( BitsPerPixel <= 1 )
194: InitCodeSize = 2;
195: else
196: InitCodeSize = BitsPerPixel;
197:
198: /*
199: * Set up the current x and y position
200: */
201: curx = cury = 0;
202:
203: /*
204: * Write the Magic header
205: */
1.4 paf 206: fp << (Transparent < 0 ? "GIF87a" : "GIF89a");
1.2 paf 207:
208: /*
209: * Write out the screen width and height
210: */
1.4 paf 211: Putword( RWidth);
212: Putword( RHeight);
1.2 paf 213:
214: /*
215: * Indicate that there is a global colour map
216: */
217: B = 0x80; /* Yes, there is a color map */
218:
219: /*
220: * OR in the resolution
221: */
222: B |=(Resolution - 1) << 5;
223:
224: /*
225: * OR in the Bits per Pixel
226: */
227: B |=(BitsPerPixel - 1);
228:
229: /*
230: * Write it out
231: */
1.4 paf 232: Putbyte(B);
1.2 paf 233:
234: /*
235: * Write out the Background colour
236: */
1.4 paf 237: Putbyte(Background);
1.2 paf 238:
239: /*
240: * Byte of 0's(future expansion)
241: */
1.4 paf 242: Putbyte(0);
1.2 paf 243:
244: /*
245: * Write out the Global Colour Map
246: */
247: for( i=0; i<ColorMapSize; ++i ) {
1.4 paf 248: Putbyte( Red[i]);
249: Putbyte( Green[i]);
250: Putbyte( Blue[i]);
1.2 paf 251: }
252:
253: /*
254: * Write out extension for transparent colour index, if necessary.
255: */
256: if( Transparent >= 0 ) {
1.4 paf 257: Putbyte( '!');
258: Putbyte( 0xf9);
259: Putbyte( 4);
260: Putbyte( 1);
261: Putbyte( 0);
262: Putbyte( 0);
263: Putbyte((unsigned char) Transparent);
264: Putbyte( 0);
1.1 paf 265: }
1.2 paf 266:
267: /*
268: * Write an Image separator
269: */
1.4 paf 270: Putbyte( ',');
1.2 paf 271:
272: /*
273: * Write the Image header
274: */
275:
1.4 paf 276: Putword( LeftOfs);
277: Putword( TopOfs);
278: Putword( Width);
279: Putword( Height);
1.2 paf 280:
281: /*
282: * Write out whether or not the image is interlaced
283: */
284: if( Interlace )
1.4 paf 285: Putbyte( 0x40);
1.2 paf 286: else
1.4 paf 287: Putbyte( 0x00);
1.2 paf 288:
289: /*
290: * Write out the initial code size
291: */
1.4 paf 292: Putbyte( InitCodeSize);
1.2 paf 293:
294: /*
295: * Go and actually compress the data
296: */
1.4 paf 297: compress( InitCodeSize+1 );
1.2 paf 298:
299: /*
300: * Write out a Zero-length packet(to end the series)
301: */
1.4 paf 302: Putbyte( 0);
1.2 paf 303:
304: /*
305: * Write the GIF file terminator
306: */
1.4 paf 307: Putbyte( ';');
1.1 paf 308: }
309:
310: /*
1.4 paf 311: * Write out a byte to the GIF file
312: */
313: void
314: gdGifEncoder::Putbyte(int c) {
315: char *p=(char *)malloc(1);
316: *p=c;
1.7 paf 317: fp.APPEND_AS_IS(p, 1, 0, 0);
1.4 paf 318: }
319: /*
1.2 paf 320: * Write out a word to the GIF file
321: */
1.4 paf 322: void
323: gdGifEncoder::Putword(int w)
1.1 paf 324: {
1.4 paf 325: char *p=(char *)malloc(2);
326: p[0]=w & 0xff;
327: p[1]=(w / 256) & 0xff;
1.7 paf 328: fp.APPEND_AS_IS(p, 2, 0, 0);
1.1 paf 329: }
330:
1.4 paf 331: void gdGifEncoder::Write(void *buf, size_t size) {
332: char *p=(char *)malloc(size);
333: memcpy(p, buf, size);
1.7 paf 334: fp.APPEND_AS_IS(p, size, 0, 0);
1.4 paf 335: }
1.1 paf 336:
337: /***************************************************************************
1.2 paf 338: *
339: * GIFCOMPR.C - GIF Image compression routines
340: *
341: * Lempel-Ziv compression based on 'compress'. GIF modifications by
342: * David Rowley(mgardi@watdcsu.waterloo.edu)
343: *
344: ***************************************************************************/
1.1 paf 345:
346: /*
1.2 paf 347: * General DEFINEs
348: */
1.1 paf 349:
350: #define GIFBITS 12
351:
352: #ifdef NO_UCHAR
1.2 paf 353: typedef char char_type;
1.10 parser 354: #else
1.2 paf 355: typedef unsigned char char_type;
1.10 parser 356: #endif
1.1 paf 357:
358: /*
1.2 paf 359: *
360: * GIF Image compression - modified 'compress'
361: *
362: * Based on: compress.c - File compression ala IEEE Computer, June 1984.
363: *
364: * By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
365: * Jim McKie (decvax!mcvax!jim)
366: * Steve Davies (decvax!vax135!petsd!peora!srd)
367: * Ken Turkowski (decvax!decwrl!turtlevax!ken)
368: * James A. Woods (decvax!ihnp4!ames!jaw)
369: * Joe Orost (decvax!vax135!petsd!joe)
370: *
371: */
1.1 paf 372: #ifdef COMPATIBLE /* But wrong! */
1.2 paf 373: # define MAXCODE(n_bits) ((code_int) 1 <<(n_bits) - 1)
1.10 parser 374: #else
1.2 paf 375: # define MAXCODE(n_bits) (((code_int) 1 <<(n_bits)) - 1)
1.10 parser 376: #endif
1.1 paf 377:
378: #define HashTabOf(i) htab[i]
379: #define CodeTabOf(i) codetab[i]
380: /*
1.2 paf 381: * To save much memory, we overlay the table used by compress() with those
382: * used by decompress(). The tab_prefix table is the same size and type
383: * as the codetab. The tab_suffix table needs 2**GIFBITS characters. We
384: * get this from the beginning of htab. The output stack uses the rest
385: * of htab, and contains characters. There is plenty of room for any
386: * possible stack(stack used to be 8000 characters).
387: */
1.1 paf 388:
389: #define tab_prefixof(i) CodeTabOf(i)
1.2 paf 390: #define tab_suffixof(i) ((char_type*)(htab))[i]
391: #define de_stack ((char_type*)&tab_suffixof((code_int)1<<GIFBITS))
1.1 paf 392:
393: /*
1.2 paf 394: * compress stdin to stdout
395: *
396: * Algorithm: use open addressing double hashing(no chaining) on the
397: * prefix code / next character combination. We do a variant of Knuth's
398: * algorithm D(vol. 3, sec. 6.4) along with G. Knott's relatively-prime
399: * secondary probe. Here, the modular division first probe is gives way
400: * to a faster exclusive-or manipulation. Also do block compression with
401: * an adaptive reset, whereby the code table is cleared when the compression
402: * ratio decreases, but after the table fills. The variable-length output
403: * codes are re-sized at this point, and a special CLEAR code is generated
404: * for the decompressor. Late addition: construct the table according to
405: * file size for noticeable speed improvement on small files. Please direct
406: * questions about this implementation to ames!jaw.
407: */
1.1 paf 408:
1.2 paf 409: void
1.4 paf 410: gdGifEncoder::compress(int init_bits)
1.1 paf 411: {
412: register long fcode;
413: register code_int i /* = 0 */;
414: register int c;
415: register code_int ent;
416: register code_int disp;
417: register code_int hsize_reg;
418: register int hshift;
1.2 paf 419:
1.1 paf 420: /*
1.2 paf 421: * Set up the globals: g_init_bits - initial number of bits
422: * g_outfile - pointer to output file
423: */
1.1 paf 424: g_init_bits = init_bits;
1.2 paf 425:
1.1 paf 426: /*
1.2 paf 427: * Set up the necessary values
428: */
1.1 paf 429: offset = 0;
430: out_count = 0;
431: clear_flg = 0;
432: in_count = 1;
433: maxcode = MAXCODE(n_bits = g_init_bits);
1.2 paf 434:
435: ClearCode =(1 <<(init_bits - 1));
1.1 paf 436: EOFCode = ClearCode + 1;
437: free_ent = ClearCode + 2;
1.2 paf 438:
1.1 paf 439: char_init();
1.2 paf 440:
441: ent = GIFNextPixel( );
442:
1.1 paf 443: hshift = 0;
1.2 paf 444: for( fcode =(long) hsize; fcode < 65536L; fcode *= 2L )
1.1 paf 445: ++hshift;
446: hshift = 8 - hshift; /* set hash code range bound */
1.2 paf 447:
1.1 paf 448: hsize_reg = hsize;
1.2 paf 449: cl_hash((count_int) hsize_reg); /* clear hash table */
450:
451: output((code_int)ClearCode );
452:
1.1 paf 453: #ifdef SIGNED_COMPARE_SLOW
1.2 paf 454: while((c = GIFNextPixel( )) !=(unsigned) EOF ) {
1.10 parser 455: #else
1.2 paf 456: while((c = GIFNextPixel( )) != EOF ) { /* } */
1.10 parser 457: #endif
1.2 paf 458:
1.3 paf 459: ++in_count;
460:
461: fcode =(long)(((long) c << maxbits) + ent);
462: i =(((code_int)c << hshift) ^ ent); /* xor hashing */
463:
464: if( HashTabOf(i) == fcode ) {
465: ent = CodeTabOf(i);
466: continue;
467: } else if((long)HashTabOf(i) < 0 ) /* empty slot */
468: goto nomatch;
469: disp = hsize_reg - i; /* secondary hash(after G. Knott) */
470: if( i == 0 )
471: disp = 1;
1.1 paf 472: probe:
1.3 paf 473: if((i -= disp) < 0 )
474: i += hsize_reg;
475:
476: if( HashTabOf(i) == fcode ) {
477: ent = CodeTabOf(i);
478: continue;
479: }
480: if((long)HashTabOf(i) > 0 )
481: goto probe;
1.1 paf 482: nomatch:
1.3 paf 483: output((code_int) ent );
484: ++out_count;
485: ent = c;
1.1 paf 486: #ifdef SIGNED_COMPARE_SLOW
1.3 paf 487: if((unsigned) free_ent <(unsigned) maxmaxcode) {
1.10 parser 488: #else
1.3 paf 489: if( free_ent < maxmaxcode ) { /* } */
1.10 parser 490: #endif
1.3 paf 491: CodeTabOf(i) = free_ent++; /* code -> hashtable */
492: HashTabOf(i) = fcode;
493: } else
494: cl_block();
495: }
496: /*
497: * Put out the final code.
498: */
499: output((code_int)ent );
500: ++out_count;
501: output((code_int) EOFCode );
502: }
503:
504: /*****************************************************************
505: * TAG( output )
506: *
507: * Output the given code.
508: * Inputs:
509: * code: A n_bits-bit integer. If == -1, then EOF. This assumes
510: * that n_bits =<(long)wordsize - 1.
511: * Outputs:
512: * Outputs code to the file.
513: * Assumptions:
514: * Chars are 8 bits long.
515: * Algorithm:
516: * Maintain a GIFBITS character long buffer(so that 8 codes will
517: * fit in it exactly). Use the VAX insv instruction to insert each
518: * code in turn. When the buffer fills up empty it and start over.
519: */
520:
521: static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
522: 0x001F, 0x003F, 0x007F, 0x00FF,
523: 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
524: 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
525:
526: void
527: gdGifEncoder::output(code_int code)
528: {
529: cur_accum &= masks[ cur_bits ];
530:
531: if( cur_bits > 0 )
532: cur_accum |=((long)code << cur_bits);
533: else
534: cur_accum = code;
535:
536: cur_bits += n_bits;
537:
538: while( cur_bits >= 8 ) {
539: char_out((unsigned int)(cur_accum & 0xff) );
540: cur_accum >>= 8;
541: cur_bits -= 8;
1.2 paf 542: }
543:
1.3 paf 544: /*
545: * If the next entry is going to be too big for the code size,
546: * then increase it, if possible.
1.2 paf 547: */
1.3 paf 548: if( free_ent > maxcode || clear_flg ) {
1.2 paf 549:
1.3 paf 550: if( clear_flg ) {
1.2 paf 551:
1.3 paf 552: maxcode = MAXCODE(n_bits = g_init_bits);
553: clear_flg = 0;
1.2 paf 554:
1.3 paf 555: } else {
1.2 paf 556:
1.3 paf 557: ++n_bits;
558: if( n_bits == maxbits )
559: maxcode = maxmaxcode;
560: else
561: maxcode = MAXCODE(n_bits);
1.2 paf 562: }
563: }
564:
1.3 paf 565: if( code == EOFCode ) {
1.2 paf 566: /*
1.3 paf 567: * At EOF, write the rest of the buffer.
568: */
569: while( cur_bits > 0 ) {
570: char_out((unsigned int)(cur_accum & 0xff) );
571: cur_accum >>= 8;
572: cur_bits -= 8;
573: }
1.2 paf 574:
1.3 paf 575: flush_char();
1.4 paf 576: }
1.3 paf 577: }
578:
579: /*
580: * Clear out the hash table
581: */
582: void
583: gdGifEncoder::cl_block(void) /* table clear for block compress */
584: {
585:
586: cl_hash((count_int) hsize );
587: free_ent = ClearCode + 2;
588: clear_flg = 1;
589:
590: output((code_int)ClearCode );
591: }
592:
593: void
1.9 paf 594: gdGifEncoder::cl_hash(count_int hsize) /* reset code table */
1.3 paf 595:
596: {
597:
598: register count_int *htab_p = htab+hsize;
599:
600: register long i;
601: register long m1 = -1;
602:
603: i = hsize - 16;
604: do { /* might use Sys V memset(3) here */
605: *(htab_p-16) = m1;
606: *(htab_p-15) = m1;
607: *(htab_p-14) = m1;
608: *(htab_p-13) = m1;
609: *(htab_p-12) = m1;
610: *(htab_p-11) = m1;
611: *(htab_p-10) = m1;
612: *(htab_p-9) = m1;
613: *(htab_p-8) = m1;
614: *(htab_p-7) = m1;
615: *(htab_p-6) = m1;
616: *(htab_p-5) = m1;
617: *(htab_p-4) = m1;
618: *(htab_p-3) = m1;
619: *(htab_p-2) = m1;
620: *(htab_p-1) = m1;
621: htab_p -= 16;
622: } while((i -= 16) >= 0);
623:
624: for( i += 16; i > 0; --i )
625: *--htab_p = m1;
626: }
627:
628: /******************************************************************************
629: *
630: * GIF Specific routines
631: *
632: ******************************************************************************/
633:
634: /*
635: * Set up the 'byte output' routine
636: */
637: void
638: gdGifEncoder::char_init(void)
639: {
640: a_count = 0;
641: }
642:
643: /*
644: * Add a character to the end of the current packet, and if it is 254
645: * characters, flush the packet to disk.
646: */
647: void
648: gdGifEncoder::char_out(int c)
649: {
650: accum[ a_count++ ] = c;
651: if( a_count >= 254 )
652: flush_char();
653: }
654:
655: /*
656: * Flush the packet to disk, and reset the accumulator
657: */
658: void
659: gdGifEncoder::flush_char(void)
660: {
661: if( a_count > 0 ) {
1.4 paf 662: Putbyte( a_count );
663: Write( accum, a_count);
1.3 paf 664: a_count = 0;
1.2 paf 665: }
1.3 paf 666: }
667:
1.4 paf 668: gdGifEncoder::gdGifEncoder(Pool& pool, gdImage& aim, String& afp) : Pooled(pool),
669: im(aim),
670: fp(afp) {
1.3 paf 671: /* Some of these are properly initialized later. What I'm doing
672: here is making sure code that depends on C's initialization
673: of statics doesn't break when the code gets called more
674: than once. */
675: Width = 0;
676: Height = 0;
677: curx = 0;
678: cury = 0;
679: CountDown = 0;
680: Pass = 0;
681: Interlace = 0;
682: a_count = 0;
683: cur_accum = 0;
684: cur_bits = 0;
685: g_init_bits = 0;
686: ClearCode = 0;
687: EOFCode = 0;
688: free_ent = 0;
689: clear_flg = 0;
690: offset = 0;
691: in_count = 1;
692: out_count = 0;
693: hsize = HSIZE;
694: n_bits = 0;
695: maxbits = GIFBITS;
696: maxcode = 0;
697: maxmaxcode =(code_int)1 << GIFBITS;
698: }
699:
700:
701: /* +-------------------------------------------------------------------+ */
702: /* | Copyright 1990, 1991, 1993, David Koblas.(koblas@netcom.com) | */
703: /* | Permission to use, copy, modify, and distribute this software | */
704: /* | and its documentation for any purpose and without fee is hereby | */
705: /* | granted, provided that the above copyright notice appear in all | */
706: /* | copies and that both that copyright notice and this permission | */
707: /* | notice appear in supporting documentation. This software is | */
708: /* | provided "as is" without express or implied warranty. | */
709: /* +-------------------------------------------------------------------+ */
710:
711:
1.1 paf 712: #define MAXCOLORMAPSIZE 256
1.2 paf 713:
1.1 paf 714: #define TRUE 1
715: #define FALSE 0
1.2 paf 716:
1.1 paf 717: #define CM_RED 0
718: #define CM_GREEN 1
719: #define CM_BLUE 2
1.2 paf 720:
1.1 paf 721: #define MAX_LWZ_BITS 12
1.2 paf 722:
1.1 paf 723: #define INTERLACE 0x40
724: #define LOCALCOLORMAP 0x80
1.2 paf 725: #define BitSet(byte, bit) (((byte) &(bit)) ==(bit))
726:
727: #define ReadOK(file,buffer,len)(fread(buffer, len, 1, file) != 0)
728:
729: #define LM_to_uint(a,b) (((b)<<8)|(a))
730:
731: /* We may eventually want to use this information, but def it out for now */
1.1 paf 732: #if 0
1.2 paf 733: struct GifScreen {
734: unsigned int Width;
735: unsigned int Height;
736: unsigned char ColorMap[3][MAXCOLORMAPSIZE];
737: unsigned int BitPixel;
738: unsigned int ColorResolution;
739: unsigned int Background;
740: unsigned int AspectRatio;
741: };
1.1 paf 742: #endif
1.8 paf 743:
744: /// Graphic Control Extension struct
1.11 parser 745: #ifndef DOXYGEN
1.2 paf 746: struct Gif89 {
747: int transparent;
748: int delayTime;
749: int inputFlag;
750: int disposal;
751: };
1.11 parser 752: #endif
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: