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>