Annotation of parser3/src/classes/gd/gifio.C, revision 1.16

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

E-mail: