⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gifsave.c

📁 完美的在线教育系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id: gifsave.c,v 1.1 2006/04/05 07:22:17 pcool Exp $ */
/**************************************************************************
 *
 *  FILE            gifsave.c
 *
 *  DESCRIPTION     Routines to create a GIF-file. See README for
 *                  a description.
 *
 *                  The functions were originally written using Borland's
 *                  C-compiler on an IBM PC -compatible computer, but they
 *                  are compiled and tested on Linux and SunOS as well.
 *
 *  WRITTEN BY      Sverre H. Huseby <sverrehu@online.no>
 *
 **************************************************************************/

#include <stdlib.h>
#include <stdio.h>
/* #include <unistd.h> */	/* (added by j.forkosh) to get STDOUT_FILENO*/
#include <string.h>		/* " */
/* --- windows-specific header info --- */
#ifndef WINDOWS			/* -DWINDOWS not supplied by user */
  #if defined(_WINDOWS) || defined(_WIN32) || defined(WIN32) \
  ||  defined(DJGPP)		/* try to recognize windows compilers */ \
  ||  defined(_USRDLL)		/* must be WINDOWS if compiling for DLL */
    #define WINDOWS		/* signal windows */
  #endif
#endif
#ifdef WINDOWS			/* " if filename=NULL passed to GIF_Create()*/
  #include <fcntl.h>		/* " OutFile=stdout used.  But Windows opens*/
  #include <io.h>		/* " stdout in char mode, and precedes every*/
				/* " 0x0A with spurious 0x0D. */
  #if defined(_O_BINARY) && !defined(O_BINARY)  /* only have _O_BINARY */
    #define O_BINARY _O_BINARY	/* make O_BINARY available, etc... */
    #define setmode  _setmode
    #define fileno   _fileno
  #endif
  #if defined(_O_BINARY) || defined(O_BINARY)  /* setmode() now available */
    #define HAVE_SETMODE	/* so we'll use setmode() */
  #endif
#endif

/* #include "gifsave.h" */	/* (j.forkosh) explcitly include header */
enum GIF_Code {
    GIF_OK = 0,
    GIF_ERRCREATE,
    GIF_ERRWRITE,
    GIF_OUTMEM
};

int  GIF_Create(const char *filename, int width, int height,
		int numcolors, int colorres);
void GIF_SetColor(int colornum, int red, int green, int blue);
void GIF_SetTransparent(int colornum);	/* (added by j.forkosh) */
int  GIF_CompressImage(int left, int top, int width, int height,
		       int (*getpixel)(int x, int y));
int  GIF_Close(void);
/* --- end-of-header gifsave.h --- */


/**************************************************************************
 *                                                                        *
 *                       P R I V A T E    D A T A                         *
 *                                                                        *
 **************************************************************************/

typedef unsigned Word;          /* at least two bytes (16 bits) */
typedef unsigned char Byte;     /* exactly one byte (8 bits) */

/* used by IO-routines */
static FILE *OutFile = NULL;    /* file to write to */
static Byte *OutBuffer = NULL;	/* (added by j.forkosh) */
static int isCloseOutFile = 0;	/* " */
int gifSize = 0;		/* " #bytes comprising gif */
int maxgifSize = 64000;		/* " max #bytes written to OutBuffer */

/* used when writing to a file bitwise */
static Byte Buffer[256];        /* there must be one more than `needed' */
static int  Index,              /* current byte in buffer */
            BitsLeft;           /* bits left to fill in current byte. These
                                 * are right-justified */

/* used by routines maintaining an LZW string table */
#define RES_CODES 2

#define HASH_FREE 0xFFFF
#define NEXT_FIRST 0xFFFF

#define MAXBITS 12
#define MAXSTR (1 << MAXBITS)

#define HASHSIZE 9973
#define HASHSTEP 2039

#define HASH(index, lastbyte) (((lastbyte << 8) ^ index) % HASHSIZE)

static Byte *StrChr = NULL;
static Word *StrNxt = NULL,
            *StrHsh = NULL,
            NumStrings;

/* used in the main routines */
typedef struct {
    Word LocalScreenWidth,
         LocalScreenHeight;
    Byte GlobalColorTableSize : 3,
         SortFlag             : 1,
         ColorResolution      : 3,
         GlobalColorTableFlag : 1;
    Byte BackgroundColorIndex;
    Byte PixelAspectRatio;
} ScreenDescriptor;

typedef struct {
    Byte Separator;
    Word LeftPosition,
         TopPosition;
    Word Width,
         Height;
    Byte LocalColorTableSize : 3,
         Reserved            : 2,
         SortFlag            : 1,
         InterlaceFlag       : 1,
         LocalColorTableFlag : 1;
} ImageDescriptor;

static int  BitsPrPrimColor,    /* bits pr primary color */
            NumColors;          /* number of colors in color table */
static int  TransparentColorIndex=(-1); /* (added by j.forkosh) */
static Byte *ColorTable = NULL;
static Word ScreenHeight,
            ScreenWidth,
            ImageHeight,
            ImageWidth,
            ImageLeft,
            ImageTop,
            RelPixX, RelPixY;   /* used by InputByte() -function */
static int  (*GetPixel)(int x, int y);



/**************************************************************************
 *                                                                        *
 *                   P R I V A T E    F U N C T I O N S                   *
 *                                                                        *
 **************************************************************************/

/*========================================================================*
 =                         Routines to do file IO                         =
 *========================================================================*/

/*-------------------------------------------------------------------------
 *
 *  NAME          Create
 *
 *  DESCRIPTION   Creates a new file, and enables referencing using the
 *                global variable OutFile. This variable is only used
 *                by these IO-functions, making it relatively simple to
 *                rewrite file IO.
 *
 *  INPUT         filename
 *                        name of file to create,
 *                        or NULL for stdout,
 *                        or if *filename='\000' then it's the address of
 *                           a memory buffer to which gif will be written
 *
 *  RETURNS       GIF_OK       - OK
 *                GIF_ERRWRITE - Error opening the file
 */
static int
Create(const char *filename)
{
    OutBuffer = NULL;				/* (added by j.forkosh) */
    isCloseOutFile = 0;				/* " */
    gifSize = 0;				/* " */
    if ( filename == NULL )			/* " */
      {	OutFile = stdout;			/* " */
	/*OutFile = fdopen(STDOUT_FILENO,"wb");*/ /* " doesn't work, */
	#ifdef WINDOWS				/* "   so instead... */
	  #ifdef HAVE_SETMODE			/* "   try to use setmode()*/
	    if ( setmode ( fileno (stdout), O_BINARY) /* to  set stdout */
	    == -1 ) ; /* handle error */	/* " to binary mode */
	  #else					/* " setmode not available */
	    #if 1				/* " */
	      freopen ("CON", "wb", stdout);	/* " freopen stdout binary */
	    #else				/* " */
	      stdout = fdopen (STDOUT_FILENO, "wb"); /*fdopen stdout binary*/
	    #endif				/* " */
	  #endif				/* " */
	#endif					/* " */
      }						/* " */
    else					/* " */
      if ( *filename != '\000' )		/* " */
	{ if ((OutFile = fopen(filename, "wb")) == NULL)
	    return GIF_ERRCREATE;
	  isCloseOutFile = 1; }			/* (added by j.forkosh) */
      else					/* " */
	OutBuffer = (Byte *)filename;		/* " */
    return GIF_OK;
}



/*-------------------------------------------------------------------------
 *
 *  NAME          Write
 *
 *  DESCRIPTION   Output bytes to the current OutFile.
 *
 *  INPUT         buf     pointer to buffer to write
 *                len     number of bytes to write
 *
 *  RETURNS       GIF_OK       - OK
 *                GIF_ERRWRITE - Error writing to the file
 */
static int
Write(const void *buf, unsigned len)
{
    if ( OutBuffer == NULL )			/* (added by j.forkosh) */
      {	if (fwrite(buf, sizeof(Byte), len, OutFile) < len)
	  return GIF_ERRWRITE; }
    else					/* (added by j.forkosh) */
      {	if ( gifSize+len <= maxgifSize )	/* " */
	  memcpy(OutBuffer+gifSize,buf,len); }	/* " */
    gifSize += len;				/* " */
    return GIF_OK;
}



/*-------------------------------------------------------------------------
 *
 *  NAME          WriteByte
 *
 *  DESCRIPTION   Output one byte to the current OutFile.
 *
 *  INPUT         b       byte to write
 *
 *  RETURNS       GIF_OK       - OK
 *                GIF_ERRWRITE - Error writing to the file
 */
static int
WriteByte(Byte b)
{
    if ( OutBuffer == NULL )			/* (added by j.forkosh) */
      {	if (putc(b, OutFile) == EOF)
	  return GIF_ERRWRITE; }
    else					/* (added by j.forkosh) */
      {	if ( gifSize < maxgifSize )		/* " */
	  OutBuffer[gifSize] = b; }		/* " */
    gifSize++;					/* " */
    return GIF_OK;
}



/*-------------------------------------------------------------------------
 *
 *  NAME          WriteWord
 *
 *  DESCRIPTION   Output one word (2 bytes with byte-swapping, like on
 *                the IBM PC) to the current OutFile.
 *
 *  INPUT         w       word to write
 *
 *  RETURNS       GIF_OK       - OK
 *                GIF_ERRWRITE - Error writing to the file
 */
static int
WriteWord(Word w)
{
    if ( OutBuffer == NULL )			/* (added by j.forkosh) */
      {	if (putc(w & 0xFF, OutFile) == EOF)
	  return GIF_ERRWRITE;
	if (putc((w >> 8), OutFile) == EOF)
	  return GIF_ERRWRITE; }
    else					/* (added by j.forkosh) */
      if ( gifSize+1 < maxgifSize )		/* " */
	{ OutBuffer[gifSize] = (Byte)(w & 0xFF);  /* " */
	  OutBuffer[gifSize+1] = (Byte)(w >> 8); }  /* " */
    gifSize += 2;				/* " */
    return GIF_OK;
}



/*-------------------------------------------------------------------------
 *
 *  NAME          Close
 *
 *  DESCRIPTION   Close current OutFile.
 */
static void
Close(void)
{
    if ( isCloseOutFile )			/* (added by j.forkosh) */
      fclose(OutFile);
    OutBuffer = NULL;				/* (added by j.forkosh) */
    isCloseOutFile = 0;				/* " */
}





/*========================================================================*
 =                                                                        =
 =                      Routines to write a bit-file                      =
 =                                                                        =
 *========================================================================*/

/*-------------------------------------------------------------------------
 *
 *  NAME          InitBitFile
 *
 *  DESCRIPTION   Initiate for using a bitfile. All output is sent to
 *                  the current OutFile using the I/O-routines above.
 */
static void
InitBitFile(void)
{
    Buffer[Index = 0] = 0;
    BitsLeft = 8;
}



/*-------------------------------------------------------------------------
 *
 *  NAME          ResetOutBitFile
 *
 *  DESCRIPTION   Tidy up after using a bitfile
 *
 *  RETURNS       0 - OK, -1 - error
 */
static int
ResetOutBitFile(void)
{
    Byte numbytes;

    /* how much is in the buffer? */
    numbytes = Index + (BitsLeft == 8 ? 0 : 1);

    /* write whatever is in the buffer to the file */
    if (numbytes) {
        if (WriteByte(numbytes) != GIF_OK)
            return -1;

        if (Write(Buffer, numbytes) != GIF_OK)
            return -1;

        Buffer[Index = 0] = 0;
        BitsLeft = 8;
    }
    return 0;
}



/*-------------------------------------------------------------------------
 *
 *  NAME          WriteBits
 *
 *  DESCRIPTION   Put the given number of bits to the outfile.
 *
 *  INPUT         bits    bits to write from (right justified)
 *                numbits number of bits to write
 *
 *  RETURNS       bits written, or -1 on error.
 *
 */
static int
WriteBits(int bits, int numbits)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -