|
|
1.1 paf 1: /** @file
2: Parser: image manipulations impl2.
3:
1.7 ! moko 4: Copyright (c) 2001-2017 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.7 ! moko 40: volatile const char * IDENT_GIFIO_C="$Id: gifio.C,v 1.6 2016/12/26 19:48:30 moko Exp $";
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 Transparent =(-1);
778: unsigned char buf[16];
779: unsigned char c;
780: unsigned char ColorMap[3][MAXCOLORMAPSIZE];
781: unsigned char localColorMap[3][MAXCOLORMAPSIZE];
782: int imw, imh;
783: int useGlobalColormap;
784: int bitPixel;
785: int imageCount = 0;
786: char version[4];
787: ZeroDataBlock = FALSE;
788:
789: imageNumber = 1;
790: if(! ReadOK(fd,buf,6)) {
791: return false;
792: }
793: if(strncmp((char *)buf,"GIF",3) != 0) {
794: return false;
795: }
796: strncpy(version,(char *)buf + 3, 3);
797: version[3] = '\0';
798:
799: if((strcmp(version, "87a") != 0) &&(strcmp(version, "89a") != 0)) {
800: return false;
801: }
802: if(! ReadOK(fd,buf,7)) {
803: return false;
804: }
805: BitPixel = 2<<(buf[4]&0x07);
806:
807: if(BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
808: if(ReadColorMap(fd, BitPixel, ColorMap)) {
809: return false;
810: }
811: }
812: for(;;) {
813: if(! ReadOK(fd,&c,1)) {
814: return false;
815: }
816: if(c == ';') { /* GIF terminator */
817: int i;
818: if(imageCount < imageNumber) {
819: return false;
820: }
821: /* Check for open colors at the end, so
822: we can reduce colorsTotal and ultimately
823: BitsPerPixel */
824: for(i=((colorsTotal-1));(i>=0); i--) {
825: if(open[i]) {
826: colorsTotal--;
827: } else {
828: break;
829: }
830: }
831: return true;
832: }
833:
834: if(c == '!') { /* Extension */
835: if(! ReadOK(fd,&c,1)) {
836: return false;
837: }
838: DoExtension(fd, c, &Transparent);
839: continue;
840: }
841:
842: if(c != ',') { /* Not a valid start character */
843: continue;
844: }
845:
846: ++imageCount;
847:
848: if(! ReadOK(fd,buf,9)) {
849: return false;
850: }
851:
852: useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
853:
854: bitPixel = 1<<((buf[8]&0x07)+1);
855:
856: imw = LM_to_uint(buf[4],buf[5]);
857: imh = LM_to_uint(buf[6],buf[7]);
858: Create(imw, imh);
859: interlace = BitSet(buf[8], INTERLACE);
860: if(! useGlobalColormap) {
861: if(ReadColorMap(fd, bitPixel, localColorMap)) {
862: return false;
863: }
864: ReadImage(fd, imw, imh, localColorMap,
865: BitSet(buf[8], INTERLACE),
866: imageCount != imageNumber);
867: } else {
868: ReadImage(fd, imw, imh,
869: ColorMap,
870: BitSet(buf[8], INTERLACE),
871: imageCount != imageNumber);
872: }
873: if(Transparent !=(-1)) {
874: SetColorTransparent(Transparent);
875: }
876: }
877: }
878:
879: static int
880: ReadColorMap(FILE *fd, int number, unsigned char(*buffer)[256])
881: {
882: int i;
883: unsigned char rgb[3];
884:
885:
886: for(i = 0; i < number; ++i) {
887: if(! ReadOK(fd, rgb, sizeof(rgb))) {
888: return TRUE;
889: }
890: buffer[CM_RED][i] = rgb[0] ;
891: buffer[CM_GREEN][i] = rgb[1] ;
892: buffer[CM_BLUE][i] = rgb[2] ;
893: }
894:
895:
896: return FALSE;
897: }
898:
899: int gdImage::DoExtension(FILE *fd, int label, int *Transparent)
900: {
901: static unsigned char buf[256];
902:
903: switch(label) {
904: case 0xf9: { /* Graphic Control Extension */
905: (void) GetDataBlock(fd,(unsigned char*) buf);
906: if((buf[0] & 0x1) != 0)
907: *Transparent = buf[3];
908:
909: while(GetDataBlock(fd,(unsigned char*) buf) != 0)
910: ;
911: return FALSE;
1.6 moko 912: }
1.1 paf 913: default:
914: break;
915: }
916: while(GetDataBlock(fd,(unsigned char*) buf) != 0)
917: ;
918:
919: return FALSE;
920: }
921:
922: int
923: gdImage::GetDataBlock(FILE *fd, unsigned char *buf)
924: {
925: unsigned char count;
926:
927: if(! ReadOK(fd,&count,1)) {
928: return -1;
929: }
930:
931: ZeroDataBlock = count == 0;
932:
933: if((count != 0) &&(! ReadOK(fd, buf, count))) {
934: return -1;
935: }
936:
937: return count;
938: }
939:
940: int gdImage::GetCode(FILE *fd, int code_size, int flag)
941: {
942: static unsigned char buf[280];
943: static int curbit, lastbit, done, last_byte;
944: int i, j, ret;
945: unsigned char count;
946:
947: if(flag) {
948: curbit = 0;
949: lastbit = 0;
950: done = FALSE;
951: return 0;
952: }
953:
954: if((curbit+code_size) >= lastbit) {
955: if(done) {
956: if(curbit >= lastbit) {
957: /* Oh well */
958: }
959: return -1;
960: }
961: buf[0] = buf[last_byte-2];
962: buf[1] = buf[last_byte-1];
963:
964: if((count = GetDataBlock(fd, &buf[2])) == 0)
965: done = TRUE;
966:
967: last_byte = 2 + count;
968: curbit =(curbit - lastbit) + 16;
969: lastbit =(2+count)*8 ;
970: }
971:
972: ret = 0;
973: for(i = curbit, j = 0; j < code_size; ++i, ++j)
974: ret |=((buf[ i / 8 ] &(1 <<(i % 8))) != 0) << j;
975:
976: curbit += code_size;
977:
978: return ret;
979: }
980:
981: int gdImage::LWZReadByte(FILE *fd, int flag, int input_code_size)
982: {
983: static int fresh = FALSE;
984: int code, incode;
985: static int code_size, set_code_size;
986: static int max_code, max_code_size;
987: static int firstcode, oldcode;
988: static int clear_code, end_code;
989: static int table[2][(1<< MAX_LWZ_BITS)];
990: static int stack[(1<<(MAX_LWZ_BITS))*2], *sp;
991: register int i;
992:
993: if(flag) {
994: set_code_size = input_code_size;
995: code_size = set_code_size+1;
996: clear_code = 1 << set_code_size ;
997: end_code = clear_code + 1;
998: max_code_size = 2*clear_code;
999: max_code = clear_code+2;
1000:
1001: GetCode(fd, 0, TRUE);
1002:
1003: fresh = TRUE;
1004:
1005: for(i = 0; i < clear_code; ++i) {
1006: table[0][i] = 0;
1007: table[1][i] = i;
1008: }
1009: for(; i <(1<<MAX_LWZ_BITS); ++i)
1010: table[0][i] = table[1][0] = 0;
1011:
1012: sp = stack;
1013:
1014: return 0;
1015: } else if(fresh) {
1016: fresh = FALSE;
1017: do {
1018: firstcode = oldcode =
1019: GetCode(fd, code_size, FALSE);
1020: } while(firstcode == clear_code);
1021: return firstcode;
1022: }
1023:
1024: if(sp > stack)
1025: return *--sp;
1026:
1027: while((code = GetCode(fd, code_size, FALSE)) >= 0) {
1028: if(code == clear_code) {
1029: for(i = 0; i < clear_code; ++i) {
1030: table[0][i] = 0;
1031: table[1][i] = i;
1032: }
1033: for(; i <(1<<MAX_LWZ_BITS); ++i)
1034: table[0][i] = table[1][i] = 0;
1035: code_size = set_code_size+1;
1036: max_code_size = 2*clear_code;
1037: max_code = clear_code+2;
1038: sp = stack;
1039: firstcode = oldcode =
1040: GetCode(fd, code_size, FALSE);
1041: return firstcode;
1042: } else if(code == end_code) {
1043: int count;
1044: unsigned char buf[260];
1045:
1046: if(ZeroDataBlock)
1047: return -2;
1048:
1049: while((count = GetDataBlock(fd, buf)) > 0)
1050: ;
1051:
1052: if(count != 0)
1053: return -2;
1054: }
1055:
1056: incode = code;
1057:
1058: if(code >= max_code) {
1059: *sp++ = firstcode;
1060: code = oldcode;
1061: }
1062:
1063: while(code >= clear_code) {
1064: *sp++ = table[1][code];
1065: if(code == table[0][code]) {
1066: /* Oh well */
1067: }
1068: code = table[0][code];
1069: }
1070:
1071: *sp++ = firstcode = table[1][code];
1072:
1073: if((code = max_code) <(1<<MAX_LWZ_BITS)) {
1074: table[0][code] = oldcode;
1075: table[1][code] = firstcode;
1076: ++max_code;
1077: if((max_code >= max_code_size) &&
1078: (max_code_size <(1<<MAX_LWZ_BITS))) {
1079: max_code_size *= 2;
1080: ++code_size;
1081: }
1082: }
1083:
1084: oldcode = incode;
1085:
1086: if(sp > stack)
1087: return *--sp;
1088: }
1089: return code;
1090: }
1091:
1092: void gdImage::ReadImage(FILE *fd, int len, int height, unsigned char(*cmap)[256], int interlace, int ignore)
1093: {
1094: unsigned char c;
1095: int v;
1096: int xpos = 0, ypos = 0, pass = 0;
1097: int i;
1098: /* Stash the color map into the image */
1099: for(i=0;(i<gdMaxColors); i++) {
1100: red[i] = cmap[CM_RED][i];
1101: green[i] = cmap[CM_GREEN][i];
1102: blue[i] = cmap[CM_BLUE][i];
1103: open[i] = 1;
1104: }
1105: /* Many(perhaps most) of these colors will remain marked open. */
1106: colorsTotal = gdMaxColors;
1107: /*
1108: ** Initialize the Compression routines
1109: */
1110: if(! ReadOK(fd,&c,1)) {
1111: return;
1112: }
1113: if(LWZReadByte(fd, TRUE, c) < 0) {
1114: return;
1115: }
1116:
1117: /*
1118: ** If this is an "uninteresting picture" ignore it.
1119: */
1120: if(ignore) {
1121: while(LWZReadByte(fd, FALSE, c) >= 0)
1122: ;
1123: return;
1124: }
1125:
1126: while((v = LWZReadByte(fd,FALSE,c)) >= 0 ) {
1127: /* This how we recognize which colors are actually used. */
1128: if(open[v]) {
1129: open[v] = 0;
1130: }
1131: SetPixel(xpos, ypos, v);
1132: ++xpos;
1133: if(xpos == len) {
1134: xpos = 0;
1135: if(interlace) {
1136: switch(pass) {
1137: case 0:
1138: case 1:
1139: ypos += 8; break;
1140: case 2:
1141: ypos += 4; break;
1142: case 3:
1143: ypos += 2; break;
1144: }
1145:
1146: if(ypos >= height) {
1147: ++pass;
1148: switch(pass) {
1149: case 1:
1150: ypos = 4; break;
1151: case 2:
1152: ypos = 2; break;
1153: case 3:
1154: ypos = 1; break;
1155: default:
1156: goto fini;
1157: }
1158: }
1159: } else {
1160: ++ypos;
1161: }
1162: }
1163: if(ypos >= height)
1164: break;
1165: }
1166:
1167: fini:
1168: if(LWZReadByte(fd,FALSE,c)>=0) {
1169: /* Ignore extra */
1170: }
1171: }
1172: