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