Annotation of embedaddon/php/ext/gd/libgd/gd_gif_out.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>