gd.c
来自「CA仿真模型中SLEUTH模型」· C语言 代码 · 共 2,537 行 · 第 1/4 页
C
2,537 行
* fit in it exactly). Use the VAX insv instruction to insert each * code in turn. When the buffer fills up empty it and start over. */static unsigned long cur_accum = 0;static int cur_bits = 0;static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };static voidoutput(code_int code){ cur_accum &= masks[ cur_bits ]; if( cur_bits > 0 ) cur_accum |= ((long)code << cur_bits); else cur_accum = code; cur_bits += n_bits; while( cur_bits >= 8 ) { char_out( (unsigned int)(cur_accum & 0xff) ); cur_accum >>= 8; cur_bits -= 8; } /* * If the next entry is going to be too big for the code size, * then increase it, if possible. */ if ( free_ent > maxcode || clear_flg ) { if( clear_flg ) { maxcode = MAXCODE (n_bits = g_init_bits); clear_flg = 0; } else { ++n_bits; if ( n_bits == maxbits ) maxcode = maxmaxcode; else maxcode = MAXCODE(n_bits); } } if( code == EOFCode ) { /* * At EOF, write the rest of the buffer. */ while( cur_bits > 0 ) { char_out( (unsigned int)(cur_accum & 0xff) ); cur_accum >>= 8; cur_bits -= 8; } flush_char(); fflush( g_outfile ); if( ferror( g_outfile ) ) return; }}/* * Clear out the hash table */static voidcl_block (void) /* table clear for block compress */{ cl_hash ( (count_int) hsize ); free_ent = ClearCode + 2; clear_flg = 1; output( (code_int)ClearCode );}static voidcl_hash(register count_int hsize) /* reset code table */ { register count_int *htab_p = htab+hsize; register long i; register long m1 = -1; i = hsize - 16; do { /* might use Sys V memset(3) here */ *(htab_p-16) = m1; *(htab_p-15) = m1; *(htab_p-14) = m1; *(htab_p-13) = m1; *(htab_p-12) = m1; *(htab_p-11) = m1; *(htab_p-10) = m1; *(htab_p-9) = m1; *(htab_p-8) = m1; *(htab_p-7) = m1; *(htab_p-6) = m1; *(htab_p-5) = m1; *(htab_p-4) = m1; *(htab_p-3) = m1; *(htab_p-2) = m1; *(htab_p-1) = m1; htab_p -= 16; } while ((i -= 16) >= 0); for ( i += 16; i > 0; --i ) *--htab_p = m1;}/****************************************************************************** * * GIF Specific routines * ******************************************************************************//* * Number of characters so far in this 'packet' */static int a_count;/* * Set up the 'byte output' routine */static voidchar_init(void){ a_count = 0;}/* * Define the storage for the packet accumulator */static char accum[ 256 ];/* * Add a character to the end of the current packet, and if it is 254 * characters, flush the packet to disk. */static voidchar_out(int c){ accum[ a_count++ ] = c; if( a_count >= 254 ) flush_char();}/* * Flush the packet to disk, and reset the accumulator */static voidflush_char(void){ if( a_count > 0 ) { fputc( a_count, g_outfile ); fwrite( accum, 1, a_count, g_outfile ); a_count = 0; }}static void init_statics(void) { /* Some of these are properly initialized later. What I'm doing here is making sure code that depends on C's initialization of statics doesn't break when the code gets called more than once. */ Width = 0; Height = 0; curx = 0; cury = 0; CountDown = 0; Pass = 0; Interlace = 0; a_count = 0; cur_accum = 0; cur_bits = 0; g_init_bits = 0; g_outfile = 0; ClearCode = 0; EOFCode = 0; free_ent = 0; clear_flg = 0; offset = 0; in_count = 1; out_count = 0; hsize = HSIZE; n_bits = 0; maxbits = GIFBITS; maxcode = 0; maxmaxcode = (code_int)1 << GIFBITS;}/* +-------------------------------------------------------------------+ *//* | Copyright 1990, 1991, 1993, David Koblas. (koblas@netcom.com) | *//* | 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. | *//* +-------------------------------------------------------------------+ */#define MAXCOLORMAPSIZE 256#define TRUE 1#define FALSE 0#define CM_RED 0#define CM_GREEN 1#define CM_BLUE 2#define MAX_LWZ_BITS 12#define INTERLACE 0x40#define LOCALCOLORMAP 0x80#define BitSet(byte, bit) (((byte) & (bit)) == (bit))#define ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0)#define LM_to_uint(a,b) (((b)<<8)|(a))/* We may eventually want to use this information, but def it out for now */#if 0static struct { unsigned int Width; unsigned int Height; unsigned char ColorMap[3][MAXCOLORMAPSIZE]; unsigned int BitPixel; unsigned int ColorResolution; unsigned int Background; unsigned int AspectRatio;} GifScreen;#endifstatic struct { int transparent; int delayTime; int inputFlag; int disposal;} Gif89 = { -1, -1, -1, 0 };static int ReadColorMap (FILE *fd, int number, unsigned char (*buffer)[256]);static int DoExtension (FILE *fd, int label, int *Transparent);static int GetDataBlock (FILE *fd, unsigned char *buf);static int GetCode (FILE *fd, int code_size, int flag);static int LWZReadByte (FILE *fd, int flag, int input_code_size);static void ReadImage (gdImagePtr im, FILE *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int ignore);int ZeroDataBlock;gdImagePtrgdImageCreateFromGif(FILE *fd){ int imageNumber; int BitPixel; int ColorResolution; int Background; int AspectRatio; int Transparent = (-1); unsigned char buf[16]; unsigned char c; unsigned char ColorMap[3][MAXCOLORMAPSIZE]; unsigned char localColorMap[3][MAXCOLORMAPSIZE]; int imw, imh; int useGlobalColormap; int bitPixel; int imageCount = 0; char version[4]; gdImagePtr im = 0; ZeroDataBlock = FALSE; imageNumber = 1; if (! ReadOK(fd,buf,6)) { return 0; } if (strncmp((char *)buf,"GIF",3) != 0) { return 0; } strncpy(version, (char *)buf + 3, 3); version[3] = '\0'; if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) { return 0; } if (! ReadOK(fd,buf,7)) { return 0; } BitPixel = 2<<(buf[4]&0x07); ColorResolution = (int) (((buf[4]&0x70)>>3)+1); Background = buf[5]; AspectRatio = buf[6]; if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */ if (ReadColorMap(fd, BitPixel, ColorMap)) { return 0; } } for (;;) { if (! ReadOK(fd,&c,1)) { return 0; } if (c == ';') { /* GIF terminator */ int i; if (imageCount < imageNumber) { return 0; } /* Terminator before any image was declared! */ if (!im) { return 0; } /* Check for open colors at the end, so we can reduce colorsTotal and ultimately BitsPerPixel */ for (i=((im->colorsTotal-1)); (i>=0); i--) { if (im->open[i]) { im->colorsTotal--; } else { break; } } return im; } if (c == '!') { /* Extension */ if (! ReadOK(fd,&c,1)) { return 0; } DoExtension(fd, c, &Transparent); continue; } if (c != ',') { /* Not a valid start character */ continue; } ++imageCount; if (! ReadOK(fd,buf,9)) { return 0; } useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP); bitPixel = 1<<((buf[8]&0x07)+1); imw = LM_to_uint(buf[4],buf[5]); imh = LM_to_uint(buf[6],buf[7]); if (!(im = gdImageCreate(imw, imh))) { return 0; } im->interlace = BitSet(buf[8], INTERLACE); if (! useGlobalColormap) { if (ReadColorMap(fd, bitPixel, localColorMap)) { return 0; } ReadImage(im, fd, imw, imh, localColorMap, BitSet(buf[8], INTERLACE), imageCount != imageNumber); } else { ReadImage(im, fd, imw, imh, ColorMap, BitSet(buf[8], INTERLACE), imageCount != imageNumber); } if (Transparent != (-1)) { gdImageColorTransparent(im, Transparent); } }}static intReadColorMap(FILE *fd, int number, unsigned char (*buffer)[256]){ int i; unsigned char rgb[3]; for (i = 0; i < number; ++i) { if (! ReadOK(fd, rgb, sizeof(rgb))) { return TRUE; } buffer[CM_RED][i] = rgb[0] ; buffer[CM_GREEN][i] = rgb[1] ; buffer[CM_BLUE][i] = rgb[2] ; } return FALSE;}static intDoExtension(FILE *fd, int label, int *Transparent){ static unsigned char buf[256]; switch (label) { case 0xf9: /* Graphic Control Extension */ (void) GetDataBlock(fd, (unsigned char*) buf); Gif89.disposal = (buf[0] >> 2) & 0x7; Gif89.inputFlag = (buf[0] >> 1) & 0x1; Gif89.delayTime = LM_to_uint(buf[1],buf[2]); if ((buf[0] & 0x1) != 0) *Transparent = buf[3]; while (GetDataBlock(fd, (unsigned char*) buf) != 0) ; return FALSE; default: break; } while (GetDataBlock(fd, (unsigned char*) buf) != 0) ; return FALSE;}static intGetDataBlock(FILE *fd, unsigned char *buf){ unsigned char count; if (! ReadOK(fd,&count,1)) { return -1; } ZeroDataBlock = count == 0; if ((count != 0) && (! ReadOK(fd, buf, count))) { return -1; } return count;}static intGetCode(FILE *fd, int code_size, int flag){ static unsigned char buf[280]; static int curbit, lastbit, done, last_byte; int i, j, ret; unsigned char count; if (flag) { curbit = 0; lastbit = 0; done = FALSE; return 0; } if ( (curbit+code_size) >= lastbit) { if (done) { if (curbit >= lastbit) { /* Oh well */ } return -1; } buf[0] = buf[last_byte-2]; buf[1] = buf[last_byte-1]; if ((count = GetDataBlock(fd, &buf[2])) == 0) done = TRUE; last_byte = 2 + count; curbit = (curbit - lastbit) + 16; lastbit = (2+count)*8 ; } ret = 0; for (i = curbit, j = 0; j < code_size; ++i, ++j) ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j; curbit += code_size; return ret;}static intLWZReadByte(FILE *fd, int flag, int input_code_size){ static int fresh = FALSE; int code, incode; static int code_size, set_code_size; static int max_code, max_code_size; static int firstcode, oldcode; static int clear_code, end_code; static int table[2][(1<< MAX_LWZ_BITS)]; static int stack[(1<<(MAX_LWZ_BITS))*2], *sp; register int i; if (flag) { set_code_size = input_code_size; code_size = set_code_size+1; clear_code = 1 << set_code_size ; end_code = clear_code + 1; max_code_size = 2*clear_code; max_code = clear_code+2; GetCode(fd, 0, TRUE); fresh = TRUE; for (i = 0; i < clear_code; ++i) { table[0][i] = 0; table[1][i] = i; } for (; i < (1<<MAX_LWZ_BITS); ++i) table[0][i] = table[1][0] = 0; sp = stack; return 0; } else if (fresh) { fresh = FALSE; do { firstcode = oldcode = GetCode(fd, code_size, FALSE); } while (firstcode == clear_code); return firstcode; } if (sp > stack) return *--sp; while ((code = GetCode(fd, code_size, FALSE)) >= 0) { if (code == clear_code) { for (i = 0; i < clear_code; ++i) { table[0][i] = 0; table[1][i] = i; } for (; i < (1<<MAX_LWZ_BITS); ++i) table[0][i] = table[1][i] = 0; code_size = set_code_size+1; max_code_size = 2*clear_code; max_code = clear_code+2; sp = stack; firstcode = oldcode = GetCode(fd, code_size, FALSE); return firstcode; } else if (code == end_code) { int count; unsigned char buf[260]; if (ZeroDataBlock) return -2; while ((count = GetDataBlock(fd, buf)) > 0) ; if (count != 0) return -2; } incode = code; if (code >= max_code) { *sp++ = firstcode; code = oldcode; } while (code >= clear_code) { *sp++ = table[1][code]; if (code == table[0][code]) { /* Oh well */ } code = table[0][code]; } *sp++ = firstcode = table[1][code]; if ((code = max_code) <(1<<MAX_LWZ_BITS)) { table[0][code] = oldcode; table[1][code] = firstcode; ++max_code; if ((max_code >= max_code_size) && (max_code_size < (1<<MAX_LWZ_BITS))) { max_code_size *= 2; ++code_size; } } oldcode = incode; if (sp > stack) return *--sp; } return code;}static voidReadImage(gdImagePtr im, FILE *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int ignore){ unsigned char c; int v; int xpos = 0, ypos = 0, pass = 0; int i; /* Stash the color map into the image */ for (i=0; (i<gdMaxColors); i++) { im->red[i] = cmap[CM_RED][i]; im->green[i] = cmap[CM_GREEN][i]; im->blue[i] = cmap[CM_BLUE][i]; im->open[i] = 1; } /* Many (perhaps most) of these colors will remain marked open. */ im->colorsTotal = gdMaxColors; /* ** Initialize the Compression routines */ if (! ReadOK(fd,&c,1)) { return; } if (LWZReadByte(fd, TRUE, c) < 0) { return; } /* ** If this is an "uninteresting picture" ignore it. */ if (ignore) { while (LWZReadByte(fd, FALSE, c) >= 0) ; return; } while ((v = LWZReadByte(fd,FALSE,c)) >= 0 ) { /* This how we recognize which colors are actually used. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?