📄 gd_gif_out.c
字号:
#include <stdio.h>#include <math.h>#include <string.h>#include <stdlib.h>#include "gd.h"/* Code drawn from ppmtogif.c, from the pbmplus package**** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A** Lempel-Zim compression based on "compress".**** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>**** Copyright (C) 1989 by Jef Poskanzer.**** Permission to use, copy, modify, and distribute this software and its** documentation for any purpose and without fee is hereby granted, provided** that the above copyright notice appear in all copies and that both that** copyright notice and this permission notice appear in supporting** documentation. This software is provided "as is" without express or** implied warranty.**** The Graphics Interchange Format(c) is the Copyright property of** CompuServe Incorporated. GIF(sm) is a Service Mark property of** CompuServe Incorporated.*//* * a code_int must be able to hold 2**GIFBITS values of type int, and also -1 */typedef int code_int;#ifdef SIGNED_COMPARE_SLOWtypedef unsigned long int count_int;typedef unsigned short int count_short;#else /*SIGNED_COMPARE_SLOW*/typedef long int count_int;#endif /*SIGNED_COMPARE_SLOW*//* 2.0.28: threadsafe */#define maxbits GIFBITS/* should NEVER generate this code */#define maxmaxcode ((code_int)1 << GIFBITS)#define HSIZE 5003 /* 80% occupancy */#define hsize HSIZE /* Apparently invariant, left over from compress */typedef struct { int Width, Height; int curx, cury; long CountDown; int Pass; int Interlace; int n_bits; /* number of bits/code */ code_int maxcode; /* maximum code, given n_bits */ count_int htab [HSIZE]; unsigned short codetab [HSIZE]; code_int free_ent; /* first unused entry */ /* * block compression parameters -- after all codes are used up, * and compression rate changes, start over. */ int clear_flg; int offset; long int in_count; /* length of input */ long int out_count; /* # of codes output (for debugging) */ int g_init_bits; gdIOCtx * g_outfile; int ClearCode; int EOFCode; unsigned long cur_accum; int cur_bits; /* * Number of characters so far in this 'packet' */ int a_count; /* * Define the storage for the packet accumulator */ char accum[ 256 ];} GifCtx;static int gifPutWord(int w, gdIOCtx *out);static int colorstobpp(int colors);static void BumpPixel (GifCtx *ctx);static int GIFNextPixel (gdImagePtr im, GifCtx *ctx);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);static void compress (int init_bits, gdIOCtx *outfile, gdImagePtr im, GifCtx *ctx);static void output (code_int code, GifCtx *ctx);static void cl_block (GifCtx *ctx);static void cl_hash (register count_int chsize, GifCtx *ctx);static void char_init (GifCtx *ctx);static void char_out (int c, GifCtx *ctx);static void flush_char (GifCtx *ctx);void * gdImageGifPtr (gdImagePtr im, int *size){ void *rv; gdIOCtx *out = gdNewDynamicCtx (2048, NULL); gdImageGifCtx (im, out); rv = gdDPExtractData (out, size); out->gd_free (out); return rv;}void gdImageGif (gdImagePtr im, FILE * outFile){ gdIOCtx *out = gdNewFileCtx (outFile); gdImageGifCtx (im, out); out->gd_free (out);}void gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out){ gdImagePtr pim = 0, tim = im; int interlace, transparent, BitsPerPixel; interlace = im->interlace; transparent = im->transparent; if (im->trueColor) { /* Expensive, but the only way that produces an acceptable result: mix down to a palette based temporary image. */ pim = gdImageCreatePaletteFromTrueColor(im, 1, 256); if (!pim) { return; } tim = pim; } BitsPerPixel = colorstobpp(tim->colorsTotal); /* All set, let's do it. */ GIFEncode( out, tim->sx, tim->sy, tim->interlace, 0, tim->transparent, BitsPerPixel, tim->red, tim->green, tim->blue, tim); if (pim) { /* Destroy palette based temporary image. */ gdImageDestroy( pim); }}static intcolorstobpp(int colors){ int bpp = 0; if ( colors <= 2 ) bpp = 1; else if ( colors <= 4 ) bpp = 2; else if ( colors <= 8 ) bpp = 3; else if ( colors <= 16 ) bpp = 4; else if ( colors <= 32 ) bpp = 5; else if ( colors <= 64 ) bpp = 6; else if ( colors <= 128 ) bpp = 7; else if ( colors <= 256 ) bpp = 8; return bpp; }/***************************************************************************** * * GIFENCODE.C - GIF Image compression interface * * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent, * BitsPerPixel, Red, Green, Blue, gdImagePtr ) * *****************************************************************************/#define TRUE 1#define FALSE 0/* * Bump the 'curx' and 'cury' to point to the next pixel */static voidBumpPixel(GifCtx *ctx){ /* * Bump the current X position */ ++(ctx->curx); /* * If we are at the end of a scan line, set curx back to the beginning * If we are interlaced, bump the cury to the appropriate spot, * otherwise, just increment it. */ if( ctx->curx == ctx->Width ) { ctx->curx = 0; if( !ctx->Interlace ) ++(ctx->cury); else { switch( ctx->Pass ) { case 0: ctx->cury += 8; if( ctx->cury >= ctx->Height ) { ++(ctx->Pass); ctx->cury = 4; } break; case 1: ctx->cury += 8; if( ctx->cury >= ctx->Height ) { ++(ctx->Pass); ctx->cury = 2; } break; case 2: ctx->cury += 4; if( ctx->cury >= ctx->Height ) { ++(ctx->Pass); ctx->cury = 1; } break; case 3: ctx->cury += 2; break; } } }}/* * Return the next pixel from the image */static intGIFNextPixel(gdImagePtr im, GifCtx *ctx){ int r; if( ctx->CountDown == 0 ) return EOF; --(ctx->CountDown); r = gdImageGetPixel(im, ctx->curx, ctx->cury); BumpPixel(ctx); return r;}/* public */static voidGIFEncode(gdIOCtxPtr fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im){ int B; int RWidth, RHeight; int LeftOfs, TopOfs; int Resolution; int ColorMapSize; int InitCodeSize; int i; GifCtx ctx; memset(&ctx, 0, sizeof(ctx)); ctx.Interlace = GInterlace; ctx.in_count = 1; ColorMapSize = 1 << BitsPerPixel; RWidth = ctx.Width = GWidth; RHeight = ctx.Height = GHeight; LeftOfs = TopOfs = 0; Resolution = BitsPerPixel; /* * Calculate number of bits we are expecting */ ctx.CountDown = (long)ctx.Width * (long)ctx.Height; /* * Indicate which pass we are on (if interlace) */ ctx.Pass = 0; /* * The initial code size */ if( BitsPerPixel <= 1 ) InitCodeSize = 2; else InitCodeSize = BitsPerPixel; /* * Set up the current x and y position */ ctx.curx = ctx.cury = 0; /* * Write the Magic header */ gdPutBuf(Transparent < 0 ? "GIF87a" : "GIF89a", 6, fp ); /* * Write out the screen width and height */ gifPutWord( RWidth, fp ); gifPutWord( RHeight, fp ); /* * Indicate that there is a global colour map */ B = 0x80; /* Yes, there is a color map */ /* * OR in the resolution */ B |= (Resolution - 1) << 5; /* * OR in the Bits per Pixel */ B |= (BitsPerPixel - 1); /* * Write it out */ gdPutC( B, fp ); /* * Write out the Background colour */ gdPutC( Background, fp ); /* * Byte of 0's (future expansion) */ gdPutC( 0, fp ); /* * Write out the Global Colour Map */ for( i=0; i<ColorMapSize; ++i ) { gdPutC( Red[i], fp ); gdPutC( Green[i], fp ); gdPutC( Blue[i], fp ); } /* * Write out extension for transparent colour index, if necessary. */ if ( Transparent >= 0 ) { gdPutC( '!', fp ); gdPutC( 0xf9, fp ); gdPutC( 4, fp ); gdPutC( 1, fp ); gdPutC( 0, fp ); gdPutC( 0, fp ); gdPutC( (unsigned char) Transparent, fp ); gdPutC( 0, fp ); } /* * Write an Image separator */ gdPutC( ',', fp ); /* * Write the Image header */ gifPutWord( LeftOfs, fp ); gifPutWord( TopOfs, fp ); gifPutWord( ctx.Width, fp ); gifPutWord( ctx.Height, fp );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -