📄 gd.c
字号:
void gdImageFill(gdImagePtr im, int x, int y, int color){ int lastBorder; int old; int leftLimit, rightLimit; int i; old = gdImageGetPixel(im, x, y); if (color == gdTiled) { /* Tile fill -- got to watch out! */ int p, tileColor; int srcx, srcy; if (!im->tile) { return; } /* Refuse to flood-fill with a transparent pattern -- I can't do it without allocating another image */ if (gdImageGetTransparent(im->tile) != (-1)) { return; } srcx = x % gdImageSX(im->tile); srcy = y % gdImageSY(im->tile); p = gdImageGetPixel(im->tile, srcx, srcy); tileColor = im->tileColorMap[p]; if (old == tileColor) { /* Nothing to be done */ return; } } else { if (old == color) { /* Nothing to be done */ return; } } /* Seek left */ leftLimit = (-1); for (i = x; (i >= 0); i--) { if (gdImageGetPixel(im, i, y) != old) { break; } gdImageSetPixel(im, i, y, color); leftLimit = i; } if (leftLimit == (-1)) { return; } /* Seek right */ rightLimit = x; for (i = (x+1); (i < im->sx); i++) { if (gdImageGetPixel(im, i, y) != old) { break; } gdImageSetPixel(im, i, y, color); rightLimit = i; } /* Look at lines above and below and start paints */ /* Above */ if (y > 0) { lastBorder = 1; for (i = leftLimit; (i <= rightLimit); i++) { int c; c = gdImageGetPixel(im, i, y-1); if (lastBorder) { if (c == old) { gdImageFill(im, i, y-1, color); lastBorder = 0; } } else if (c != old) { lastBorder = 1; } } } /* Below */ if (y < ((im->sy) - 1)) { lastBorder = 1; for (i = leftLimit; (i <= rightLimit); i++) { int c; c = gdImageGetPixel(im, i, y+1); if (lastBorder) { if (c == old) { gdImageFill(im, i, y+1, color); lastBorder = 0; } } else if (c != old) { lastBorder = 1; } } }} /* 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.** Heavily modified by Mouse, 1998-02-12. * Remove LZW compression.* Added miGIF run length compression.**//* * a code_int must be able to hold 2**GIFBITS values of type int, and also -1 */typedef int code_int;static int colorstobpp(int colors);static void BumpPixel (void);static int GIFNextPixel (gdImagePtr im);static void GIFEncode (FILE *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im);static void Putword (int w, FILE *fp);static void compress (int, FILE *, gdImagePtr, int);static void output (code_int code);static void char_init (void);static void char_out (int c);/* Allows for reuse */static void init_statics(void);void gdImageGif(gdImagePtr im, FILE *out){ int interlace, transparent, BitsPerPixel; interlace = im->interlace; transparent = im->transparent; BitsPerPixel = colorstobpp(im->colorsTotal); /* Clear any old values in statics strewn through the GIF code */ init_statics(); /* All set, let's do it. */ GIFEncode( out, im->sx, im->sy, interlace, 0, transparent, BitsPerPixel, im->red, im->green, im->blue, im);}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 0static int Width, Height;static int curx, cury;static long CountDown;static int Pass = 0;static int Interlace;/* * Bump the 'curx' and 'cury' to point to the next pixel */static voidBumpPixel(void){ /* * Bump the current X position */ ++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( curx == Width ) { curx = 0; if( !Interlace ) ++cury; else { switch( Pass ) { case 0: cury += 8; if( cury >= Height ) { ++Pass; cury = 4; } break; case 1: cury += 8; if( cury >= Height ) { ++Pass; cury = 2; } break; case 2: cury += 4; if( cury >= Height ) { ++Pass; cury = 1; } break; case 3: cury += 2; break; } } }}/* * Return the next pixel from the image */static intGIFNextPixel(gdImagePtr im){ int r; if( CountDown == 0 ) return EOF; --CountDown; r = gdImageGetPixel(im, curx, cury); BumpPixel(); return r;}/* public */static voidGIFEncode(FILE *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; Interlace = GInterlace; ColorMapSize = 1 << BitsPerPixel; RWidth = Width = GWidth; RHeight = Height = GHeight; LeftOfs = TopOfs = 0; Resolution = BitsPerPixel; /* * Calculate number of bits we are expecting */ CountDown = (long)Width * (long)Height; /* * Indicate which pass we are on (if interlace) */ Pass = 0; /* * The initial code size */ if( BitsPerPixel <= 1 ) InitCodeSize = 2; else InitCodeSize = BitsPerPixel; /* * Set up the current x and y position */ curx = cury = 0; /* * Write the Magic header */ fwrite( Transparent < 0 ? "GIF87a" : "GIF89a", 1, 6, fp ); /* * Write out the screen width and height */ Putword( RWidth, fp ); Putword( 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) << 4; /* * OR in the Bits per Pixel */ B |= (BitsPerPixel - 1); /* * Write it out */ fputc( B, fp ); /* * Write out the Background colour */ fputc( Background, fp ); /* * Byte of 0's (future expansion) */ fputc( 0, fp ); /* * Write out the Global Colour Map */ for( i=0; i<ColorMapSize; ++i ) { fputc( Red[i], fp ); fputc( Green[i], fp ); fputc( Blue[i], fp ); } /* * Write out extension for transparent colour index, if necessary. */ if ( Transparent >= 0 ) { fputc( '!', fp ); fputc( 0xf9, fp ); fputc( 4, fp ); fputc( 1, fp ); fputc( 0, fp ); fputc( 0, fp ); fputc( (unsigned char) Transparent, fp ); fputc( 0, fp ); } /* * Write an Image separator */ fputc( ',', fp ); /* * Write the Image header */ Putword( LeftOfs, fp ); Putword( TopOfs, fp ); Putword( Width, fp ); Putword( Height, fp ); /* * Write out whether or not the image is interlaced */ if( Interlace ) fputc( 0x40, fp ); else fputc( 0x00, fp ); /* * Write out the initial code size */ fputc( InitCodeSize, fp ); /* * Go and actually compress the data */ compress( InitCodeSize+1, fp, im, Background ); /* * Write out a Zero-length packet (to end the series) */ fputc( 0, fp ); /* * Write the GIF file terminator */ fputc( ';', fp );}/* * Write out a word to the GIF file */static voidPutword(int w, FILE *fp){ fputc( w & 0xff, fp ); fputc( (w / 256) & 0xff, fp );}#define GIFBITS 12/*----------------------------------------------------------------------- * * miGIF Compression - mouse and ivo's GIF-compatible compression * * -run length encoding compression routines- * * Copyright (C) 1998 Hutchison Avenue Software Corporation * http://www.hasc.com * info@hasc.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." The Hutchison Avenue * Software Corporation disclaims all warranties, either express or implied, * including but not limited to implied warranties of merchantability and * fitness for a particular purpose, with respect to this code and accompanying * documentation. * * The miGIF compression routines do not, strictly speaking, generate files * conforming to the GIF spec, since the image data is not LZW-compressed * (this is the point: in order to avoid transgression of the Unisys patent * on the LZW algorithm.) However, miGIF generates data streams that any * reasonably sane LZW decompresser will decompress to what we want. * * miGIF compression uses run length encoding. It compresses horizontal runs * of pixels of the same color. This type of compression gives good results * on images with many runs, for example images with lines, text and solid * shapes on a solid-colored background. It gives little or no compression * on images with few runs, for example digital or scanned photos. * * der Mouse * mouse@rodents.montreal.qc.ca * 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B * * ivo@hasc.com * * The Graphics Interchange Format(c) is the Copyright property of * CompuServe Incorporated. GIF(sm) is a Service Mark property of * CompuServe Incorporated. * */static int rl_pixel;static int rl_basecode;static int rl_count;static int rl_table_pixel;static int rl_table_max;static int just_cleared;static int out_bits;static int out_bits_init;static int out_count;static int out_bump;static int out_bump_init;static int out_clear;static int out_clear_init;static int max_ocodes;static int code_clear;static int code_eof;static unsigned int obuf;static int obits;static FILE *ofile;static unsigned char oblock[256];static int oblen;/* Used only when debugging GIF compression code *//* #define DEBUGGING_ENVARS */#ifdef DEBUGGING_ENVARSstatic int verbose_set = 0;static int verbose;#define VERBOSE (verbose_set?verbose:set_verbose())static int set_verbose(void){ verbose = !!getenv("GIF_VERBOSE"); verbose_set = 1; return(verbose);}#else#define VERBOSE 0#endifstatic const char *binformat(unsigned int v, int nbits){ static char bufs[8][64]; static int bhand = 0; unsigned int bit; int bno; char *bp; bhand --; if (bhand < 0) bhand = (sizeof(bufs)/sizeof(bufs[0]))-1; bp = &bufs[bhand][0]; for (bno=nbits-1,bit=1U<<bno;bno>=0;bno--,bit>>=1) { *bp++ = (v & bit) ? '1' : '0'; if (((bno&3) == 0) && (bno != 0)) *bp++ = '.'; } *bp = '\0'; return(&bufs[bhand][0]);}static void write_block(void){ int i; if (VERBOSE) { printf("write_block %d:",oblen); for (i=0;i<oblen;i++) printf(" %02x",oblock[i]); printf("\n"); } fputc(oblen,ofile); fwrite(&oblock[0],1,oblen,ofile); oblen = 0;}static void block_out(unsigned char c){ if (VERBOSE) printf("block_out %s\n",binformat(c,8)); oblock[oblen++] = c; if (oblen >= 255) write_block();}static void block_flush(void){ if (VERBOSE) printf("block_flush\n"); if (oblen > 0) write_block();}static void output(int val){ if (VERBOSE) printf("output %s [%s %d %d]\n",binformat(val,out_bits),binformat(obuf,obits),obits,out_bits); obuf |= val << obits; obits += out_bits; while (obits >= 8) { block_out(obuf&0xff); obuf >>= 8; obits -= 8; } if (VERBOSE) printf("output leaving [%s %d]\n",binformat(obuf,obits),obits);}static void output_flush(void){ if (VERBOSE) printf("output_flush\n"); if (obits > 0) block_out(obuf); block_flush();}static void did_clear(void){ if (VERBOSE) printf("did_clear\n"); out_bits = out_bits_init; out_bump = out_bump_init; out_clear = out_clear_init; out_count = 0; rl_table_max = 0; just_cleared = 1;}static void output_plain(int c){ if (VERBOSE) printf("output_plain %s\n",binformat(c,out_bits)); just_cleared = 0; output(c); out_count ++; if (out_count >= out_bump) { out_bits ++; out_bump += 1 << (out_bits - 1); } if (out_count >= out_clear) { output(code_clear); did_clear(); }}#ifdef __GNUC__static unsigned int isqrt(unsigned int) __attribute__((__const__));#endifstatic unsigned int isqrt(unsigned int x){ unsigned int r; unsigned int v; if (x < 2) return(x); for (v=x,r=1;v;v>>=2,r<<=1) ; while (1) { v = ((x / r) + r) / 2; if ((v == r) || (v == r+1)) return(r); r = v; }}static unsigned int compute_triangle_count(unsigned int count, unsigned int nrepcodes){ unsigned int perrep; unsigned int cost; cost = 0; perrep = (nrepcodes * (nrepcodes+1)) / 2; while (count >= perrep) { cost += nrepcodes; count -= perrep; } if (count > 0) { unsigned int n; n = isqrt(count); while ((n*(n+1)) >= 2*count) n --; while ((n*(n+1)) < 2*count) n ++; cost += n; } return(cost);}static void max_out_clear(void){ out_clear = max_ocodes;}static void reset_out_clear(void){ out_clear = out_clear_init; if (out_count >= out_clear)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -