First commit ~0,10

This commit is contained in:
2021-09-08 21:26:43 +02:00
commit 37dffcdec3
188 changed files with 23679 additions and 0 deletions

512
G/LIB/DEV2GIF.C Normal file
View File

@ -0,0 +1,512 @@
/*****************************************************************************
* "Gif-Lib" - Yet another gif library. *
* *
* Written by: Gershon Elber IBM PC Ver 1.1, Jun. 1989 *
******************************************************************************
* Module to dump graphic devices into a GIF file. Current supported devices: *
* 1. EGA, VGA, SVGA (800x600), Hercules on the IBM PC (#define __MSDOS__). *
* 2. SGI 4D Irix using gl library (#define __SGI_GL__). *
* 3. X11 using libX.a (#define __X11__). *
******************************************************************************
* History: *
* 22 Jun 89 - Version 1.0 by Gershon Elber. *
* 12 Aug 90 - Version 1.1 by Gershon Elber (added devices). *
*****************************************************************************/
#ifdef __MSDOS__
#include <dos.h>
#include <alloc.h>
#include <graphics.h>
#endif /* __MSDOS__ */
#ifdef __SGI_GL__
#include <gl/gl.h>
#endif /* __SGI_GL__ */
#ifdef __X11__
#include <X11/Xlib.h>
#endif /* __X11__ */
#include <stdio.h>
#include "gif_lib.h"
#define PROGRAM_NAME "GIF_LIBRARY"
#define SVGA_SPECIAL 999 /* 800 by 600 Super VGA mode. */
static int GraphDriver = -1, /* Device parameters - reasonable values. */
GraphMode = -1,
ScreenColorBits = 1;
static long ScreenXMax = 100,
ScreenYMax = 100;
static unsigned int ScreenBase;
#ifdef SYSV
static char *VersionStr =
"Gif library module,\t\tGershon Elber\n\
(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
#else
static char *VersionStr =
PROGRAM_NAME
" IBMPC "
GIF_LIB_VERSION
" Gershon Elber, "
__DATE__ ", " __TIME__ "\n"
"(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
#endif /* SYSV */
#if defined(__SGI_GL__) || defined(__X11__)
GifByteType *GlblGifBuffer = NULL, *GlblGifBufferPtr = NULL;
#endif /* __SGI_GL__ || __X11__ */
#ifdef __SGI_GL__
static int QuantizeRGBBuffer(int Width, int Height, long *RGBBuffer,
GifColorType *ColorMap, GifByteType *GIFBuffer);
#endif /* __SGI_GL__ */
static void GetScanLine(GifPixelType *ScanLine, int Y);
static int HandleGifError(GifFileType *GifFile);
/******************************************************************************
* Dump the given Device, into given File as GIF format: *
* Return 0 on success, -1 if device not supported, or GIF-LIB error number. *
* Device is selected via the ReqGraphDriver. Device mode is selected via *
* ReqGraphMode1/2 as follows: *
* 1. IBM PC Hercules card: HERCMONO (one mode only) in ReqGraphMode1, *
* ReqGraphMode2/3 are ignored. *
* 2. IBM PC EGA card: EGALO/EGAHI in ReqGraphMode1, *
* ReqGraphMode2/3 are ignored. *
* 3. IBM PC EGA64 card: EGA64LO/EGA64HI in ReqGraphMode1, *
* ReqGraphMode2/3 are ignored. *
* 4. IBM PC EGAMONO card: EGAMONOHI (one mode only) in ReqGraphMode1, *
* ReqGraphMode2/3 are ignored. *
* 5. IBM PC VGA card: VGALO/VGAMED/VGAHI in ReqGraphMode1, *
* ReqGraphMode2/3 are ignored. *
* 6. IBM PC SVGA card: ReqGraphMode1/2 are both ignored. Fixed mode (800x600 *
* 16 colors) is assumed. *
* 7. SGI 4D using GL: window id to dump (as returned by winget()) in *
* ReqGraphMode1, ReqGraphMode2/3 are ignored. *
* 8. X11: Window id in ReqGraphMode1, Display id in ReqGraphMode2, Color *
* map id in ReqGraphMode3. *
******************************************************************************/
int DumpScreen2Gif(char *FileName, int ReqGraphDriver, int ReqGraphMode1,
int ReqGraphMode2,
int ReqGraphMode3)
{
int i, j, k;
GifPixelType *ScanLine;
GifFileType *GifFile;
GifColorType *ColorMap = NULL;
#ifdef __MSDOS__
static GifColorType MonoChromeColorMap[] = {
{ 0, 0, 0 },
{ 255, 255, 255 }
};
/* I have no idea what default EGA64 (4 colors) should be (I guessed...).*/
static GifColorType EGA64ColorMap[] = {
{ 0, 0, 0 }, /* 0. Black */
{ 255, 0, 0 }, /* 1. Red */
{ 0, 255, 0 }, /* 2. Green */
{ 0, 0, 255 }, /* 3. Blue */
};
static GifColorType EGAColorMap[] = {
{ 0, 0, 0 }, /* 0. Black */
{ 0, 0, 170 }, /* 1. Blue */
{ 0, 170, 0 }, /* 2. Green */
{ 0, 170, 170 }, /* 3. Cyan */
{ 170, 0, 0 }, /* 4. Red */
{ 170, 0, 170 }, /* 5. Magenta */
{ 170, 170, 0 }, /* 6. Brown */
{ 170, 170, 170 }, /* 7. LightGray */
{ 85, 85, 85 }, /* 8. DarkGray */
{ 85, 85, 255 }, /* 9. LightBlue */
{ 85, 255, 85 }, /* 10. LightGreen */
{ 85, 255, 255 }, /* 11. LightCyan */
{ 255, 85, 85 }, /* 12. LightRed */
{ 255, 85, 255 }, /* 13. LightMagenta */
{ 255, 255, 85 }, /* 14. Yellow */
{ 255, 255, 255 }, /* 15. White */
};
#endif /* __MSDOS__ */
#if defined(__SGI_GL__) || defined(__X11__)
long *RGBBuffer;
GifColorType ColorMap256[256];
#endif
#ifdef __X11__
XImage *XImg;
unsigned long XPixel;
XColor XColorTable[256]; /* Up to 256 colors in X. */
XWindowAttributes WinAttr;
#endif /* __X11__ */
switch (ReqGraphDriver) { /* Return on non supported screens. */
#ifdef __MSDOS__
case HERCMONO:
ScreenXMax = 720;
ScreenYMax = 350;
ScreenColorBits = 1;
ScreenBase = 0xb000;
ColorMap = MonoChromeColorMap;
break;
case EGA:
switch (ReqGraphMode1) {
case EGALO:
ScreenYMax = 200;
break;
case EGAHI:
ScreenYMax = 350;
break;
default:
return -1;
}
ScreenXMax = 640;
ScreenColorBits = 4;
ScreenBase = 0xa000;
ColorMap = EGAColorMap;
break;
case EGA64:
switch (ReqGraphMode1) {
case EGA64LO:
ScreenYMax = 200;
break;
case EGA64HI:
ScreenYMax = 350;
break;
default:
return -1;
}
ScreenXMax = 640;
ScreenColorBits = 2;
ScreenBase = 0xa000;
ColorMap = EGA64ColorMap;
break;
case EGAMONO:
switch (ReqGraphMode1) {
case EGAMONOHI:
ScreenYMax = 350;
break;
default:
return -1;
}
ScreenXMax = 640;
ScreenColorBits = 1;
ScreenBase = 0xa000;
ColorMap = MonoChromeColorMap;
break;
case VGA:
switch (ReqGraphMode1) {
case VGALO:
ScreenYMax = 200;
break;
case VGAMED:
ScreenYMax = 350;
break;
case VGAHI:
ScreenYMax = 480;
break;
default:
return -1;
}
ScreenXMax = 640;
ScreenColorBits = 4;
ScreenBase = 0xa000;
ColorMap = EGAColorMap;
break;
case SVGA_SPECIAL:
ScreenXMax = 800;
ScreenYMax = 600;
ScreenColorBits = 4;
ScreenBase = 0xa000;
ColorMap = EGAColorMap;
break;
#endif /* __MSDOS__ */
#ifdef __SGI_GL__
case GIF_DUMP_SGI_WINDOW:
winset(ReqGraphMode1); /* Select window as active window. */
getsize(&ScreenXMax, &ScreenYMax);
RGBBuffer = (long *) malloc(sizeof(long) * ScreenXMax * ScreenYMax);
readsource(SRC_FRONT);
if (lrectread((short) 0,
(short) 0,
(short) (ScreenXMax - 1),
(short) (ScreenYMax - 1), RGBBuffer) !=
ScreenXMax * ScreenYMax) { /* Get data. */
free(RGBBuffer);
return -1;
}
GlblGifBuffer = (GifByteType *) malloc(sizeof(GifByteType) *
ScreenXMax * ScreenYMax);
i = QuantizeRGBBuffer(ScreenXMax, ScreenYMax, RGBBuffer,
ColorMap256, GlblGifBuffer);
/* Find minimum color map size to hold all quantized colors. */
for (ScreenColorBits = 1;
(1 << ScreenColorBits) < i && ScreenColorBits < 8;
ScreenColorBits++);
/* Start to dump with top line as GIF expects it. */
GlblGifBufferPtr = GlblGifBuffer + ScreenXMax * (ScreenYMax - 1);
ColorMap = ColorMap256;
free(RGBBuffer);
break;
#endif /* __SGI_GL__ */
#ifdef __X11__
case GIF_DUMP_X_WINDOW:
XGetWindowAttributes((Display *) ReqGraphMode2,
(Window) ReqGraphMode1,
&WinAttr);
ScreenXMax = WinAttr.width;
ScreenYMax = WinAttr.height;
XImg = XGetImage((Display *) ReqGraphMode2,
(Window) ReqGraphMode1,
0, 0, ScreenXMax - 1, ScreenYMax - 1,
AllPlanes, XYPixmap);
GlblGifBuffer = (GifByteType *) malloc(sizeof(GifByteType) *
ScreenXMax * ScreenYMax);
/* Scan the image for all different colors exists. */
for (i = 0; i < 256; i++) XColorTable[i].pixel = 0;
k = FALSE;
for (i = 0; i < ScreenXMax; i++)
for (j = 0; j < ScreenYMax; j++) {
XPixel = XGetPixel(XImg, i, j);
if (XPixel > 255) {
if (!k) {
/* Make sure we state it once only.*/
fprintf(stderr, "X Color table - truncated.\n");
k = TRUE;
}
XPixel = 255;
}
XColorTable[XPixel].pixel = XPixel;
}
/* Find the RGB representation of the colors. */
XQueryColors((Display *) ReqGraphMode2,
(Colormap) ReqGraphMode3,
XColorTable,
256);
/* Count number of active colors (Note color 0 is always in) */
/* and create the Gif color map from it. */
ColorMap = ColorMap256;
ColorMap[0].Red = ColorMap[0].Green = ColorMap[0].Blue = 0;
for (i = j = 1; i < 256; i++)
if (XColorTable[i].pixel) {
ColorMap[j].Red = XColorTable[i].red / 256;
ColorMap[j].Green = XColorTable[i].green / 256;
ColorMap[j].Blue = XColorTable[i].blue / 256;
/* Save the X color index into the Gif table: */
XColorTable[i].pixel = j++;
}
/* and set the number of colors in the Gif color map. */
for (ScreenColorBits = 1;
(1 << ScreenColorBits) < j && ScreenColorBits < 8;
ScreenColorBits++);
/* Prepare the Gif image buffer as indices into the Gif color */
/* map from the X image. */
GlblGifBufferPtr = GlblGifBuffer;
for (i = 0; i < ScreenXMax; i++)
for (j = 0; j < ScreenYMax; j++)
*GlblGifBufferPtr++ =
XColorTable[XGetPixel(XImg, j, i) & 0xff].pixel;
XDestroyImage(XImg);
GlblGifBufferPtr = GlblGifBuffer;
ColorMap = ColorMap256;
break;
#endif /* __X11__ */
default:
return -1;
}
ScanLine = (GifPixelType *) malloc(sizeof(GifPixelType) * ScreenXMax);
GraphDriver = ReqGraphDriver;
GraphMode = ReqGraphMode1;
if ((GifFile = EGifOpenFileName(FileName, FALSE)) == NULL ||
EGifPutScreenDesc(GifFile, ScreenXMax, ScreenYMax, ScreenColorBits,
0, ScreenColorBits, ColorMap) == GIF_ERROR ||
EGifPutImageDesc(GifFile, 0, 0, ScreenXMax, ScreenYMax, FALSE, 1,
NULL) == GIF_ERROR) {
free((char *) ScanLine);
#if defined(__SGI_GL__) || defined(__X11__)
free((char *) GlblGifBuffer);
#endif
return HandleGifError(GifFile);
}
for (i = 0; i < ScreenYMax; i++) {
GetScanLine(ScanLine, i);
if (EGifPutLine(GifFile, ScanLine, ScreenXMax) == GIF_ERROR) {
free((char *) ScanLine);
#if defined(__SGI_GL__) || defined(__X11__)
free((char *) GlblGifBuffer);
#endif
return HandleGifError(GifFile);
}
}
if (EGifCloseFile(GifFile) == GIF_ERROR) {
free((char *) ScanLine);
#if defined(__SGI_GL__) || defined(__X11__)
free((char *) GlblGifBuffer);
#endif
return HandleGifError(GifFile);
}
free((char *) ScanLine);
#if defined(__SGI_GL__) || defined(__X11__)
free((char *) GlblGifBuffer);
#endif
return 0;
}
#ifdef __SGI_GL__
/******************************************************************************
* Quantize the given 24 bit (8 per RGB) into 256 colors. *
******************************************************************************/
static int QuantizeRGBBuffer(int Width, int Height, long *RGBBuffer,
GifColorType *ColorMap, GifByteType *GIFBuffer)
{
int i;
GifByteType *RedInput, *GreenInput, *BlueInput;
/* Convert the RGB Buffer into 3 seperated buffers: */
RedInput = (GifByteType *) malloc(sizeof(GifByteType) * Width * Height);
GreenInput = (GifByteType *) malloc(sizeof(GifByteType) * Width * Height);
BlueInput = (GifByteType *) malloc(sizeof(GifByteType) * Width * Height);
for (i = 0; i < Width * Height; i++) {
RedInput[i] = RGBBuffer[i] & 0xff;
GreenInput[i] = (RGBBuffer[i] >> 8) & 0xff;
BlueInput[i] = (RGBBuffer[i] >> 16) & 0xff;
}
for (i = 0; i < 256; i++)
ColorMap[i].Red = ColorMap[i].Green = ColorMap[i].Blue = 0;
i = 256;
QuantizeBuffer(Width, Height, &i,
RedInput, GreenInput, BlueInput,
GIFBuffer, ColorMap);
free(RedInput);
free(GreenInput);
free(BlueInput);
return i; /* Real number of colors in color table. */
}
#endif /* __SGI_GL__ */
/******************************************************************************
* Update the given scan line buffer with the pixel levels of the Y line. *
* This routine is device specific, so make sure you know was you are doing *
******************************************************************************/
static void GetScanLine(GifPixelType *ScanLine, int Y)
{
unsigned char ScreenByte;
int i, j, k;
unsigned int BufferOffset, Bit;
#ifdef __MSDOS__
union REGS InRegs, OutRegs;
#endif /* __MSDOS__ */
switch (GraphDriver) {
#ifdef __MSDOS__
case HERCMONO:
BufferOffset = 0x2000 * (Y % 4) + (Y / 4) * (ScreenXMax / 8);
/* In one scan lines we have ScreenXMax / 8 bytes: */
for (i = 0, k = 0; i < ScreenXMax / 8; i++) {
ScreenByte = (unsigned char) peekb(ScreenBase, BufferOffset++);
for (j = 0, Bit = 0x80; j < 8; j++) {
ScanLine[k++] = (ScreenByte & Bit ? 1 : 0);
Bit >>= 1;
}
}
break;
case EGA:
case EGA64:
case EGAMONO:
case VGA:
case SVGA_SPECIAL:
InRegs.x.dx = Y;
InRegs.h.bh = 0;
InRegs.h.ah = 0x0d; /* BIOS Read dot. */
for (i = 0; i < ScreenXMax; i++) {
InRegs.x.cx = i;
int86(0x10, &InRegs, &OutRegs);
ScanLine[i] = OutRegs.h.al;
}
/* Makr this line as done by putting a xored dot on the left. */
InRegs.x.dx = Y;
InRegs.h.bh = 0;
InRegs.h.ah = 0x0c; /* BIOS Write dot (xor mode). */
InRegs.h.al = 0x81; /* Xor with color 1. */
InRegs.x.cx = 0;
int86(0x10, &InRegs, &OutRegs);
InRegs.x.dx = Y;
InRegs.h.bh = 0;
InRegs.h.ah = 0x0c; /* BIOS Write dot (xor mode). */
InRegs.h.al = 0x81; /* Xor with color 1. */
InRegs.x.cx = 1;
int86(0x10, &InRegs, &OutRegs);
if (Y == ScreenYMax - 1) {/* Last row - clear all marks we made. */
for (i = 0; i < ScreenYMax; i++) {
InRegs.h.bh = 0;
InRegs.h.ah = 0x0c; /* BIOS Write dot (xor mode). */
InRegs.h.al = 0x81; /* Xor back with color 1. */
InRegs.x.dx = i;
InRegs.x.cx = 0;
int86(0x10, &InRegs, &OutRegs);
InRegs.h.bh = 0;
InRegs.h.ah = 0x0c; /* BIOS Write dot (xor mode). */
InRegs.h.al = 0x81; /* Xor back with color 1. */
InRegs.x.dx = i;
InRegs.x.cx = 1;
int86(0x10, &InRegs, &OutRegs);
}
}
break;
#endif /* __MSDOS__ */
#ifdef __SGI_GL__
case GIF_DUMP_SGI_WINDOW:
memcpy(ScanLine, GlblGifBufferPtr, ScreenXMax * sizeof(GifPixelType));
GlblGifBufferPtr -= ScreenXMax;
break;
#endif /* __SGI_GL__ */
#ifdef __X11__
case GIF_DUMP_X_WINDOW:
memcpy(ScanLine, GlblGifBufferPtr, ScreenXMax * sizeof(GifPixelType));
GlblGifBufferPtr += ScreenXMax;
break;
#endif /* __X11__ */
default:
break;
}
}
/******************************************************************************
* Handle last GIF error. Try to close the file and free all allocated memory. *
******************************************************************************/
static int HandleGifError(GifFileType *GifFile)
{
int i = GifLastError();
if (EGifCloseFile(GifFile) == GIF_ERROR) {
GifLastError();
}
return i;
}

837
G/LIB/DGIF_LIB.C Normal file
View File

@ -0,0 +1,837 @@
/******************************************************************************
* "Gif-Lib" - Yet another gif library. *
* *
* Written by: Gershon Elber IBM PC Ver 1.1, Aug. 1990 *
*******************************************************************************
* The kernel of the GIF Decoding process can be found here. *
*******************************************************************************
* History: *
* 16 Jun 89 - Version 1.0 by Gershon Elber. *
* 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). *
******************************************************************************/
#ifdef __MSDOS__
#include <io.h>
#include <alloc.h>
#include <stdlib.h>
#include <sys\stat.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#endif /* __MSDOS__ */
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include "gif_lib.h"
#include "gif_hash.h"
#define PROGRAM_NAME "GIF_LIBRARY"
#define COMMENT_EXT_FUNC_CODE 0xfe /* Extension function code for comment. */
#define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp. */
#define GIF_STAMP_LEN sizeof(GIF_STAMP) - 1
#define GIF_VERSION_POS 3 /* Version first character in stamp. */
#define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */
#define LZ_BITS 12
#define FILE_STATE_READ 0x01/* 1 write, 0 read - EGIF_LIB compatible.*/
#define FLUSH_OUTPUT 4096 /* Impossible code, to signal flush. */
#define FIRST_CODE 4097 /* Impossible code, to signal first. */
#define NO_SUCH_CODE 4098 /* Impossible code, to signal empty. */
#define IS_READABLE(Private) (!(Private -> FileState & FILE_STATE_READ))
typedef struct GifFilePrivateType {
int FileState,
FileHandle, /* Where all this data goes to! */
BitsPerPixel, /* Bits per pixel (Codes uses at list this + 1). */
ClearCode, /* The CLEAR LZ code. */
EOFCode, /* The EOF LZ code. */
RunningCode, /* The next code algorithm can generate. */
RunningBits,/* The number of bits required to represent RunningCode. */
MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. */
LastCode, /* The code before the current code. */
CrntCode, /* Current algorithm code. */
StackPtr, /* For character stack (see below). */
CrntShiftState; /* Number of bits in CrntShiftDWord. */
unsigned long CrntShiftDWord, /* For bytes decomposition into codes. */
PixelCount; /* Number of pixels in image. */
FILE *File; /* File as stream. */
GifByteType Buf[256]; /* Compressed input is buffered here. */
GifByteType Stack[LZ_MAX_CODE]; /* Decoded pixels are stacked here. */
GifByteType Suffix[LZ_MAX_CODE+1]; /* So we can trace the codes. */
unsigned int Prefix[LZ_MAX_CODE+1];
} GifFilePrivateType;
#ifdef SYSV
static char *VersionStr =
"Gif library module,\t\tGershon Elber\n\
(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
#else
static char *VersionStr =
PROGRAM_NAME
" IBMPC "
GIF_LIB_VERSION
" Gershon Elber, "
__DATE__ ", " __TIME__ "\n"
"(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
#endif /* SYSV */
extern int _GifError;
static int DGifGetWord(FILE *File, int *Word);
static int DGifSetupDecompress(GifFileType *GifFile);
static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
int LineLen);
static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode);
static int DGifDecompressInput(GifFilePrivateType *Private, int *Code);
static int DGifBufferedInput(FILE *File, GifByteType *Buf,
GifByteType *NextByte);
/******************************************************************************
* Open a new gif file for read, given by its name. *
* Returns GifFileType pointer dynamically allocated which serves as the gif *
* info record. _GifError is cleared if succesfull. *
******************************************************************************/
GifFileType *DGifOpenFileName(char *FileName)
{
int FileHandle;
if ((FileHandle = open(FileName, O_RDONLY
#ifdef __MSDOS__
| O_BINARY
#endif /* __MSDOS__ */
)) == -1) {
_GifError = D_GIF_ERR_OPEN_FAILED;
return NULL;
}
return DGifOpenFileHandle(FileHandle);
}
/******************************************************************************
* Update a new gif file, given its file handle. *
* Returns GifFileType pointer dynamically allocated which serves as the gif *
* info record. _GifError is cleared if succesfull. *
******************************************************************************/
GifFileType *DGifOpenFileHandle(int FileHandle)
{
char Buf[GIF_STAMP_LEN+1];
GifFileType *GifFile;
GifFilePrivateType *Private;
FILE *f;
#ifdef __MSDOS__
setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */
f = fdopen(FileHandle, "rb"); /* Make it into a stream: */
setvbuf(f, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE);/* And inc. stream buffer.*/
#else
f = fdopen(FileHandle, "r"); /* Make it into a stream: */
#endif /* __MSDOS__ */
if ((GifFile = (GifFileType *) malloc(sizeof(GifFileType))) == NULL) {
_GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
return NULL;
}
if ((Private = (GifFilePrivateType *) malloc(sizeof(GifFilePrivateType)))
== NULL) {
_GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
free((char *) GifFile);
return NULL;
}
GifFile -> Private = (VoidPtr) Private;
GifFile -> SColorMap = GifFile -> IColorMap = NULL;
Private -> FileHandle = FileHandle;
Private -> File = f;
Private -> FileState = 0; /* Make sure bit 0 = 0 (File open for read). */
/* Lets see if this is GIF file: */
if (fread(Buf, 1, GIF_STAMP_LEN, Private -> File) != GIF_STAMP_LEN) {
_GifError = D_GIF_ERR_READ_FAILED;
free((char *) Private);
free((char *) GifFile);
return NULL;
}
/* The GIF Version number is ignored at this time. Maybe we should do */
/* something more useful with it. */
Buf[GIF_STAMP_LEN] = 0;
if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
_GifError = D_GIF_ERR_NOT_GIF_FILE;
free((char *) Private);
free((char *) GifFile);
return NULL;
}
if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
free((char *) Private);
free((char *) GifFile);
return NULL;
}
_GifError = 0;
return GifFile;
}
/******************************************************************************
* This routine should be called before any other DGif calls. Note that *
* this routine is called automatically from DGif file open routines. *
******************************************************************************/
int DGifGetScreenDesc(GifFileType *GifFile)
{
int Size, i;
GifByteType Buf[3];
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
if (!IS_READABLE(Private)) {
/* This file was NOT open for reading: */
_GifError = D_GIF_ERR_NOT_READABLE;
return GIF_ERROR;
}
/* Put the screen descriptor into the file: */
if (DGifGetWord(Private -> File, &GifFile -> SWidth) == GIF_ERROR ||
DGifGetWord(Private -> File, &GifFile -> SHeight) == GIF_ERROR)
return GIF_ERROR;
if (fread(Buf, 1, 3, Private -> File) != 3) {
_GifError = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
GifFile -> SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
GifFile -> SBitsPerPixel = (Buf[0] & 0x07) + 1;
GifFile -> SBackGroundColor = Buf[1];
if (Buf[0] & 0x80) { /* Do we have global color map? */
Size = (1 << GifFile -> SBitsPerPixel);
GifFile -> SColorMap =
(GifColorType *) malloc(sizeof(GifColorType) * Size);
for (i = 0; i < Size; i++) { /* Get the global color map: */
if (fread(Buf, 1, 3, Private -> File) != 3) {
_GifError = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
GifFile -> SColorMap[i].Red = Buf[0];
GifFile -> SColorMap[i].Green = Buf[1];
GifFile -> SColorMap[i].Blue = Buf[2];
}
}
return GIF_OK;
}
/******************************************************************************
* This routine should be called before any attemp to read an image. *
******************************************************************************/
int DGifGetRecordType(GifFileType *GifFile, GifRecordType *Type)
{
GifByteType Buf;
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
if (!IS_READABLE(Private)) {
/* This file was NOT open for reading: */
_GifError = D_GIF_ERR_NOT_READABLE;
return GIF_ERROR;
}
if (fread(&Buf, 1, 1, Private -> File) != 1) {
_GifError = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
switch (Buf) {
case ',':
*Type = IMAGE_DESC_RECORD_TYPE;
break;
case '!':
*Type = EXTENSION_RECORD_TYPE;
break;
case ';':
*Type = TERMINATE_RECORD_TYPE;
break;
default:
*Type = UNDEFINED_RECORD_TYPE;
_GifError = D_GIF_ERR_WRONG_RECORD;
return GIF_ERROR;
}
return GIF_OK;
}
/******************************************************************************
* This routine should be called before any attemp to read an image. *
* Note it is assumed the Image desc. header (',') has been read. *
******************************************************************************/
int DGifGetImageDesc(GifFileType *GifFile)
{
int Size, i;
GifByteType Buf[3];
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
if (!IS_READABLE(Private)) {
/* This file was NOT open for reading: */
_GifError = D_GIF_ERR_NOT_READABLE;
return GIF_ERROR;
}
if (DGifGetWord(Private -> File, &GifFile -> ILeft) == GIF_ERROR ||
DGifGetWord(Private -> File, &GifFile -> ITop) == GIF_ERROR ||
DGifGetWord(Private -> File, &GifFile -> IWidth) == GIF_ERROR ||
DGifGetWord(Private -> File, &GifFile -> IHeight) == GIF_ERROR)
return GIF_ERROR;
if (fread(Buf, 1, 1, Private -> File) != 1) {
_GifError = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
GifFile -> IBitsPerPixel = (Buf[0] & 0x07) + 1;
GifFile -> IInterlace = (Buf[0] & 0x40);
if (Buf[0] & 0x80) { /* Does this image have local color map? */
Size = (1 << GifFile -> IBitsPerPixel);
if (GifFile -> IColorMap) free((char *) GifFile -> IColorMap);
GifFile -> IColorMap =
(GifColorType *) malloc(sizeof(GifColorType) * Size);
for (i = 0; i < Size; i++) { /* Get the image local color map: */
if (fread(Buf, 1, 3, Private -> File) != 3) {
_GifError = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
GifFile -> IColorMap[i].Red = Buf[0];
GifFile -> IColorMap[i].Green = Buf[1];
GifFile -> IColorMap[i].Blue = Buf[2];
}
}
Private -> PixelCount = (long) GifFile -> IWidth *
(long) GifFile -> IHeight;
DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */
return GIF_OK;
}
/******************************************************************************
* Get one full scanned line (Line) of length LineLen from GIF file. *
******************************************************************************/
int DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
{
GifByteType *Dummy;
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
if (!IS_READABLE(Private)) {
/* This file was NOT open for reading: */
_GifError = D_GIF_ERR_NOT_READABLE;
return GIF_ERROR;
}
if (!LineLen) LineLen = GifFile -> IWidth;
#ifdef __MSDOS__
if ((Private -> PixelCount -= LineLen) > 0xffff0000UL) {
#else
if ((Private -> PixelCount -= LineLen) > 0xffff0000) {
#endif /* __MSDOS__ */
_GifError = D_GIF_ERR_DATA_TOO_BIG;
return GIF_ERROR;
}
if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
if (Private -> PixelCount == 0) {
/* We probably would not be called any more, so lets clean */
/* everything before we return: need to flush out all rest of */
/* image until empty block (size 0) detected. We use GetCodeNext.*/
do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
return GIF_ERROR;
while (Dummy != NULL);
}
return GIF_OK;
}
else
return GIF_ERROR;
}
/******************************************************************************
* Put one pixel (Pixel) into GIF file. *
******************************************************************************/
int DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel)
{
GifByteType *Dummy;
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
if (!IS_READABLE(Private)) {
/* This file was NOT open for reading: */
_GifError = D_GIF_ERR_NOT_READABLE;
return GIF_ERROR;
}
#ifdef __MSDOS__
if (--Private -> PixelCount > 0xffff0000UL)
#else
if (--Private -> PixelCount > 0xffff0000)
#endif /* __MSDOS__ */
{
_GifError = D_GIF_ERR_DATA_TOO_BIG;
return GIF_ERROR;
}
if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) {
if (Private -> PixelCount == 0) {
/* We probably would not be called any more, so lets clean */
/* everything before we return: need to flush out all rest of */
/* image until empty block (size 0) detected. We use GetCodeNext.*/
do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
return GIF_ERROR;
while (Dummy != NULL);
}
return GIF_OK;
}
else
return GIF_ERROR;
}
/******************************************************************************
* Get an extension block (see GIF manual) from gif file. This routine only *
* returns the first data block, and DGifGetExtensionNext shouldbe called *
* after this one until NULL extension is returned. *
* The Extension should NOT be freed by the user (not dynamically allocated).*
* Note it is assumed the Extension desc. header ('!') has been read. *
******************************************************************************/
int DGifGetExtension(GifFileType *GifFile, int *ExtCode,
GifByteType **Extension)
{
GifByteType Buf;
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
if (!IS_READABLE(Private)) {
/* This file was NOT open for reading: */
_GifError = D_GIF_ERR_NOT_READABLE;
return GIF_ERROR;
}
if (fread(&Buf, 1, 1, Private -> File) != 1) {
_GifError = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
*ExtCode = Buf;
return DGifGetExtensionNext(GifFile, Extension);
}
/******************************************************************************
* Get a following extension block (see GIF manual) from gif file. This *
* routine sould be called until NULL Extension is returned. *
* The Extension should NOT be freed by the user (not dynamically allocated).*
******************************************************************************/
int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **Extension)
{
GifByteType Buf;
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
if (fread(&Buf, 1, 1, Private -> File) != 1) {
_GifError = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
if (Buf > 0) {
*Extension = Private -> Buf; /* Use private unused buffer. */
(*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
if (fread(&((*Extension)[1]), 1, Buf, Private -> File) != Buf) {
_GifError = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
}
else
*Extension = NULL;
return GIF_OK;
}
/******************************************************************************
* This routine should be called last, to close GIF file. *
******************************************************************************/
int DGifCloseFile(GifFileType *GifFile)
{
GifFilePrivateType *Private;
FILE *File;
if (GifFile == NULL) return GIF_ERROR;
Private = (GifFilePrivateType *) GifFile -> Private;
if (!IS_READABLE(Private)) {
/* This file was NOT open for reading: */
_GifError = D_GIF_ERR_NOT_READABLE;
return GIF_ERROR;
}
File = Private -> File;
if (GifFile -> IColorMap) free((char *) GifFile -> IColorMap);
if (GifFile -> SColorMap) free((char *) GifFile -> SColorMap);
if (Private) free((char *) Private);
free(GifFile);
if (fclose(File) != 0) {
_GifError = D_GIF_ERR_CLOSE_FAILED;
return GIF_ERROR;
}
return GIF_OK;
}
/******************************************************************************
* Get 2 bytes (word) from the given file: *
******************************************************************************/
static int DGifGetWord(FILE *File, int *Word)
{
unsigned char c[2];
if (fread(c, 1, 2, File) != 2) {
_GifError = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
*Word = (((unsigned int) c[1]) << 8) + c[0];
return GIF_OK;
}
/******************************************************************************
* Get the image code in compressed form. his routine can be called if the *
* information needed to be piped out as is. Obviously this is much faster *
* than decoding and encoding again. This routine should be followed by calls *
* to DGifGetCodeNext, until NULL block is returned. *
* The block should NOT be freed by the user (not dynamically allocated). *
******************************************************************************/
int DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock)
{
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
if (!IS_READABLE(Private)) {
/* This file was NOT open for reading: */
_GifError = D_GIF_ERR_NOT_READABLE;
return GIF_ERROR;
}
*CodeSize = Private -> BitsPerPixel;
return DGifGetCodeNext(GifFile, CodeBlock);
}
/******************************************************************************
* Continue to get the image code in compressed form. This routine should be *
* called until NULL block is returned. *
* The block should NOT be freed by the user (not dynamically allocated). *
******************************************************************************/
int DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
{
GifByteType Buf;
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
if (fread(&Buf, 1, 1, Private -> File) != 1) {
_GifError = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
if (Buf > 0) {
*CodeBlock = Private -> Buf; /* Use private unused buffer. */
(*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
if (fread(&((*CodeBlock)[1]), 1, Buf, Private -> File) != Buf) {
_GifError = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
}
else {
*CodeBlock = NULL;
Private -> Buf[0] = 0; /* Make sure the buffer is empty! */
Private -> PixelCount = 0; /* And local info. indicate image read. */
}
return GIF_OK;
}
/******************************************************************************
* Setup the LZ decompression for this image: *
******************************************************************************/
static int DGifSetupDecompress(GifFileType *GifFile)
{
int i, BitsPerPixel;
GifByteType CodeSize;
unsigned int *Prefix;
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
fread(&CodeSize, 1, 1, Private -> File); /* Read Code size from file. */
BitsPerPixel = CodeSize;
Private -> Buf[0] = 0; /* Input Buffer empty. */
Private -> BitsPerPixel = BitsPerPixel;
Private -> ClearCode = (1 << BitsPerPixel);
Private -> EOFCode = Private -> ClearCode + 1;
Private -> RunningCode = Private -> EOFCode + 1;
Private -> RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
Private -> MaxCode1 = 1 << Private -> RunningBits; /* Max. code + 1. */
Private -> StackPtr = 0; /* No pixels on the pixel stack. */
Private -> LastCode = NO_SUCH_CODE;
Private -> CrntShiftState = 0; /* No information in CrntShiftDWord. */
Private -> CrntShiftDWord = 0;
Prefix = Private -> Prefix;
for (i = 0; i <= LZ_MAX_CODE; i++) Prefix[i] = NO_SUCH_CODE;
return GIF_OK;
}
/******************************************************************************
* The LZ decompression routine: *
* This version decompress the given gif file into Line of length LineLen. *
* This routine can be called few times (one per scan line, for example), in *
* order the complete the whole image. *
******************************************************************************/
static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
int LineLen)
{
int i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
GifByteType *Stack, *Suffix;
unsigned int *Prefix;
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
StackPtr = Private -> StackPtr;
Prefix = Private -> Prefix;
Suffix = Private -> Suffix;
Stack = Private -> Stack;
EOFCode = Private -> EOFCode;
ClearCode = Private -> ClearCode;
LastCode = Private -> LastCode;
if (StackPtr != 0) {
/* Let pop the stack off before continueing to read the gif file: */
while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr];
}
while (i < LineLen) { /* Decode LineLen items. */
if (DGifDecompressInput(Private, &CrntCode) == GIF_ERROR)
return GIF_ERROR;
if (CrntCode == EOFCode) {
/* Note however that usually we will not be here as we will stop */
/* decoding as soon as we got all the pixel, or EOF code will */
/* not be read at all, and DGifGetLine/Pixel clean everything. */
if (i != LineLen - 1 || Private -> PixelCount != 0) {
_GifError = D_GIF_ERR_EOF_TOO_SOON;
return GIF_ERROR;
}
i++;
}
else if (CrntCode == ClearCode) {
/* We need to start over again: */
for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE;
Private -> RunningCode = Private -> EOFCode + 1;
Private -> RunningBits = Private -> BitsPerPixel + 1;
Private -> MaxCode1 = 1 << Private -> RunningBits;
LastCode = Private -> LastCode = NO_SUCH_CODE;
}
else {
/* Its regular code - if in pixel range simply add it to output */
/* stream, otherwise trace to codes linked list until the prefix */
/* is in pixel range: */
if (CrntCode < ClearCode) {
/* This is simple - its pixel scalar, so add it to output: */
Line[i++] = CrntCode;
}
else {
/* Its a code to needed to be traced: trace the linked list */
/* until the prefix is a pixel, while pushing the suffix */
/* pixels on our stack. If we done, pop the stack in reverse */
/* (thats what stack is good for!) order to output. */
if (Prefix[CrntCode] == NO_SUCH_CODE) {
/* Only allowed if CrntCode is exactly the running code: */
/* In that case CrntCode = XXXCode, CrntCode or the */
/* prefix code is last code and the suffix char is */
/* exactly the prefix of last code! */
if (CrntCode == Private -> RunningCode - 2) {
CrntPrefix = LastCode;
Suffix[Private -> RunningCode - 2] =
Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
LastCode, ClearCode);
}
else {
_GifError = D_GIF_ERR_IMAGE_DEFECT;
return GIF_ERROR;
}
}
else
CrntPrefix = CrntCode;
/* Now (if image is O.K.) we should not get an NO_SUCH_CODE */
/* During the trace. As we might loop forever, in case of */
/* defective image, we count the number of loops we trace */
/* and stop if we got LZ_MAX_CODE. obviously we can not */
/* loop more than that. */
j = 0;
while (j++ <= LZ_MAX_CODE &&
CrntPrefix > ClearCode &&
CrntPrefix <= LZ_MAX_CODE) {
Stack[StackPtr++] = Suffix[CrntPrefix];
CrntPrefix = Prefix[CrntPrefix];
}
if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
_GifError = D_GIF_ERR_IMAGE_DEFECT;
return GIF_ERROR;
}
/* Push the last character on stack: */
Stack[StackPtr++] = CrntPrefix;
/* Now lets pop all the stack into output: */
while (StackPtr != 0 && i < LineLen)
Line[i++] = Stack[--StackPtr];
}
if (LastCode != NO_SUCH_CODE) {
Prefix[Private -> RunningCode - 2] = LastCode;
if (CrntCode == Private -> RunningCode - 2) {
/* Only allowed if CrntCode is exactly the running code: */
/* In that case CrntCode = XXXCode, CrntCode or the */
/* prefix code is last code and the suffix char is */
/* exactly the prefix of last code! */
Suffix[Private -> RunningCode - 2] =
DGifGetPrefixChar(Prefix, LastCode, ClearCode);
}
else {
Suffix[Private -> RunningCode - 2] =
DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
}
}
LastCode = CrntCode;
}
}
Private -> LastCode = LastCode;
Private -> StackPtr = StackPtr;
return GIF_OK;
}
/******************************************************************************
* Routine to trace the Prefixes linked list until we get a prefix which is *
* not code, but a pixel value (less than ClearCode). Returns that pixel value.*
* If image is defective, we might loop here forever, so we limit the loops to *
* the maximum possible if image O.k. - LZ_MAX_CODE times. *
******************************************************************************/
static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode)
{
int i = 0;
while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code];
return Code;
}
/******************************************************************************
* Interface for accessing the LZ codes directly. Set Code to the real code *
* (12bits), or to -1 if EOF code is returned. *
******************************************************************************/
int DGifGetLZCodes(GifFileType *GifFile, int *Code)
{
GifByteType *CodeBlock;
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
if (!IS_READABLE(Private)) {
/* This file was NOT open for reading: */
_GifError = D_GIF_ERR_NOT_READABLE;
return GIF_ERROR;
}
if (DGifDecompressInput(Private, Code) == GIF_ERROR)
return GIF_ERROR;
if (*Code == Private -> EOFCode) {
/* Skip rest of codes (hopefully only NULL terminating block): */
do if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR)
return GIF_ERROR;
while (CodeBlock != NULL);
*Code = -1;
}
else if (*Code == Private -> ClearCode) {
/* We need to start over again: */
Private -> RunningCode = Private -> EOFCode + 1;
Private -> RunningBits = Private -> BitsPerPixel + 1;
Private -> MaxCode1 = 1 << Private -> RunningBits;
}
return GIF_OK;
}
/******************************************************************************
* The LZ decompression input routine: *
* This routine is responsable for the decompression of the bit stream from *
* 8 bits (bytes) packets, into the real codes. *
* Returns GIF_OK if read succesfully. *
******************************************************************************/
static int DGifDecompressInput(GifFilePrivateType *Private, int *Code)
{
GifByteType NextByte;
static unsigned int CodeMasks[] = {
0x0000, 0x0001, 0x0003, 0x0007,
0x000f, 0x001f, 0x003f, 0x007f,
0x00ff, 0x01ff, 0x03ff, 0x07ff,
0x0fff
};
while (Private -> CrntShiftState < Private -> RunningBits) {
/* Needs to get more bytes from input stream for next code: */
if (DGifBufferedInput(Private -> File, Private -> Buf, &NextByte)
== GIF_ERROR) {
return GIF_ERROR;
}
Private -> CrntShiftDWord |=
((unsigned long) NextByte) << Private -> CrntShiftState;
Private -> CrntShiftState += 8;
}
*Code = Private -> CrntShiftDWord & CodeMasks[Private -> RunningBits];
Private -> CrntShiftDWord >>= Private -> RunningBits;
Private -> CrntShiftState -= Private -> RunningBits;
/* If code cannt fit into RunningBits bits, must raise its size. Note */
/* however that codes above 4095 are used for special signaling. */
if (++Private -> RunningCode > Private -> MaxCode1 &&
Private -> RunningBits < LZ_BITS) {
Private -> MaxCode1 <<= 1;
Private -> RunningBits++;
}
return GIF_OK;
}
/******************************************************************************
* This routines read one gif data block at a time and buffers it internally *
* so that the decompression routine could access it. *
* The routine returns the next byte from its internal buffer (or read next *
* block in if buffer empty) and returns GIF_OK if succesful. *
******************************************************************************/
static int DGifBufferedInput(FILE *File, GifByteType *Buf,
GifByteType *NextByte)
{
if (Buf[0] == 0) {
/* Needs to read the next buffer - this one is empty: */
if (fread(Buf, 1, 1, File) != 1)
{
_GifError = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
if (fread(&Buf[1], 1, Buf[0], File) != Buf[0])
{
_GifError = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
*NextByte = Buf[1];
Buf[1] = 2; /* We use now the second place as last char read! */
Buf[0]--;
}
else {
*NextByte = Buf[Buf[1]++];
Buf[0]--;
}
return GIF_OK;
}

774
G/LIB/EGIF_LIB.C Normal file
View File

@ -0,0 +1,774 @@
/******************************************************************************
* "Gif-Lib" - Yet another gif library. *
* *
* Written by: Gershon Elber Ver 1.1, Aug. 1990 *
*******************************************************************************
* The kernel of the GIF Encoding process can be found here. *
*******************************************************************************
* History: *
* 14 Jun 89 - Version 1.0 by Gershon Elber. *
* 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). *
******************************************************************************/
#ifdef __MSDOS__
#include <io.h>
#include <alloc.h>
#include <sys\stat.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#ifdef R6000
#include <sys/mode.h>
#endif
#endif /* __MSDOS__ */
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include "gif_lib.h"
#include "gif_hash.h"
#define PROGRAM_NAME "GIF_LIBRARY"
#define COMMENT_EXT_FUNC_CODE 0xfe /* Extension function code for comment. */
#define GIF_STAMP "GIF87a" /* First chars in file - GIF stamp. */
#define ZL_MAX_CODE 4095 /* Biggest code possible in 12 bits. */
#define FILE_STATE_WRITE 0x01/* 1 write, 0 read - DGIF_LIB compatible.*/
#define FILE_STATE_SCREEN 0x02
#define FILE_STATE_IMAGE 0x04
#define FLUSH_OUTPUT 4096 /* Impossible code, to signal flush. */
#define FIRST_CODE 4097 /* Impossible code, to signal first. */
#define IS_WRITEABLE(Private) (Private -> FileState & FILE_STATE_WRITE)
/* #define DEBUG_NO_PREFIX Dump only compressed data. */
typedef struct GifFilePrivateType {
int FileState,
FileHandle, /* Where old this data goes to! */
BitsPerPixel, /* Bits per pixel (Codes uses at list this + 1). */
ClearCode, /* The CLEAR LZ code. */
EOFCode, /* The EOF LZ code. */
RunningCode, /* The next code algorithm can generate. */
RunningBits,/* The number of bits required to represent RunningCode. */
MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. */
CrntCode, /* Current algorithm code. */
CrntShiftState; /* Number of bits in CrntShiftDWord. */
unsigned long CrntShiftDWord, /* For bytes decomposition into codes. */
PixelCount;
FILE *File; /* File as stream. */
GifByteType Buf[256]; /* Compressed output is buffered here. */
GifHashTableType *HashTable;
} GifFilePrivateType;
extern int _GifError;
/* Masks given codes to BitsPerPixel, to make sure all codes are in range: */
static GifPixelType CodeMask[] = {
0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
};
#ifdef SYSV
static char *VersionStr =
"Gif library module,\t\tGershon Elber\n\
(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
#else
static char *VersionStr =
PROGRAM_NAME
" IBMPC "
GIF_LIB_VERSION
" Gershon Elber, "
__DATE__ ", " __TIME__ "\n"
"(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
#endif /* SYSV */
static char *GifVersionPrefix = GIF_STAMP;
static int EGifPutWord(int Word, FILE *File);
static int EGifSetupCompress(GifFileType *GifFile);
static int EGifCompressLine(GifFileType *GifFile, GifPixelType *Line,
int LineLen);
static int EGifCompressOutput(GifFilePrivateType *Private, int Code);
static int EGifBufferedOutput(FILE *File, GifByteType *Buf, int c);
/******************************************************************************
* Open a new gif file for write, given by its name. If TestExistance then *
* if the file exists this routines fails (returns NULL). *
* Returns GifFileType pointer dynamically allocated which serves as the gif *
* info record. _GifError is cleared if succesfull. *
******************************************************************************/
GifFileType *EGifOpenFileName(char *FileName, int TestExistance)
{
int FileHandle;
if (TestExistance)
FileHandle = open(FileName,
O_WRONLY | O_CREAT | O_EXCL
#ifdef __MSDOS__
| O_BINARY
#endif /* __MSDOS__ */
,
S_IREAD | S_IWRITE);
else
FileHandle = open(FileName,
O_WRONLY | O_CREAT | O_TRUNC
#ifdef __MSDOS__
| O_BINARY
#endif /* __MSDOS__ */
,
S_IREAD | S_IWRITE);
if (FileHandle == -1) {
_GifError = E_GIF_ERR_OPEN_FAILED;
return NULL;
}
return EGifOpenFileHandle(FileHandle);
}
/******************************************************************************
* Update a new gif file, given its file handle, which must be opened for *
* write in binary mode. *
* Returns GifFileType pointer dynamically allocated which serves as the gif *
* info record. _GifError is cleared if succesfull. *
******************************************************************************/
GifFileType *EGifOpenFileHandle(int FileHandle)
{
GifFileType *GifFile;
GifFilePrivateType *Private;
FILE *f;
#ifdef __MSDOS__
setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */
f = fdopen(FileHandle, "wb"); /* Make it into a stream: */
setvbuf(f, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE); /* And inc. stream buffer. */
#else
f = fdopen(FileHandle, "w"); /* Make it into a stream: */
#endif /* __MSDOS__ */
if ((GifFile = (GifFileType *) malloc(sizeof(GifFileType))) == NULL) {
_GifError = E_GIF_ERR_NOT_ENOUGH_MEM;
return NULL;
}
GifFile -> SWidth = GifFile -> SHeight =
GifFile -> SColorResolution = GifFile -> SBitsPerPixel =
GifFile -> SBackGroundColor =
GifFile -> ILeft = GifFile -> ITop = GifFile -> IWidth = GifFile -> IHeight =
GifFile -> IInterlace =
GifFile -> IBitsPerPixel = 0;
GifFile -> SColorMap = GifFile -> IColorMap = NULL;
#ifndef DEBUG_NO_PREFIX
if (fwrite(GifVersionPrefix, 1, strlen(GifVersionPrefix), f) !=
strlen(GifVersionPrefix)) {
_GifError = E_GIF_ERR_WRITE_FAILED;
free((char *) GifFile);
return NULL;
}
#endif /* DEBUG_NO_PREFIX */
if ((Private = (GifFilePrivateType *) malloc(sizeof(GifFilePrivateType)))
== NULL) {
_GifError = E_GIF_ERR_NOT_ENOUGH_MEM;
return NULL;
}
GifFile -> Private = (VoidPtr) Private;
Private -> FileHandle = FileHandle;
Private -> File = f;
Private -> FileState = FILE_STATE_WRITE;
if ((Private -> HashTable = _InitHashTable()) == NULL) {
_GifError = E_GIF_ERR_NOT_ENOUGH_MEM;
return NULL;
}
_GifError = 0;
return GifFile;
}
/******************************************************************************
* Routine to set current GIF version. All files open for write will be *
* using this version until next call to this routine. Version consists of *
* 3 characters as "87a" or "89a". No test is made to validate the version. *
******************************************************************************/
void EGifSetGifVersion(char *Version)
{
strncpy(&GifVersionPrefix[3], Version, 3);
}
/******************************************************************************
* This routine should be called before any other EGif calls, immediately *
* follows the GIF file openning. *
******************************************************************************/
int EGifPutScreenDesc(GifFileType *GifFile,
int Width, int Height, int ColorRes, int BackGround,
int BitsPerPixel, GifColorType *ColorMap)
{
int i, Size;
GifByteType Buf[3];
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
if (Private -> FileState & FILE_STATE_SCREEN) {
/* If already has screen descriptor - something is wrong! */
_GifError = E_GIF_ERR_HAS_SCRN_DSCR;
return GIF_ERROR;
}
if (!IS_WRITEABLE(Private)) {
/* This file was NOT open for writing: */
_GifError = E_GIF_ERR_NOT_WRITEABLE;
return GIF_ERROR;
}
GifFile -> SWidth = Width;
GifFile -> SHeight = Height;
GifFile -> SColorResolution = ColorRes;
GifFile -> SBitsPerPixel = BitsPerPixel;
GifFile -> SBackGroundColor = BackGround;
if (ColorMap) {
Size = sizeof(GifColorType) * (1 << BitsPerPixel);
GifFile -> SColorMap = (GifColorType *) malloc(Size);
memcpy(GifFile -> SColorMap, ColorMap, Size);
}
/* Put the screen descriptor into the file: */
EGifPutWord(Width, Private -> File);
EGifPutWord(Height, Private -> File);
Buf[0] = (ColorMap ? 0x80 : 0x00) |
((ColorRes - 1) << 4) |
(BitsPerPixel - 1);
Buf[1] = BackGround;
Buf[2] = 0;
#ifndef DEBUG_NO_PREFIX
fwrite(Buf, 1, 3, Private -> File);
#endif /* DEBUG_NO_PREFIX */
/* If we have Global color map - dump it also: */
#ifndef DEBUG_NO_PREFIX
if (ColorMap != NULL)
for (i = 0; i < (1 << BitsPerPixel); i++) {
/* Put the ColorMap out also: */
Buf[0] = ColorMap[i].Red;
Buf[1] = ColorMap[i].Green;
Buf[2] = ColorMap[i].Blue;
if (fwrite(Buf, 1, 3, Private -> File) != 3) {
_GifError = E_GIF_ERR_WRITE_FAILED;
return GIF_ERROR;
}
}
#endif /* DEBUG_NO_PREFIX */
/* Mark this file as has screen descriptor, and no pixel written yet: */
Private -> FileState |= FILE_STATE_SCREEN;
return GIF_OK;
}
/******************************************************************************
* This routine should be called before any attemp to dump an image - any *
* call to any of the pixel dump routines. *
******************************************************************************/
int EGifPutImageDesc(GifFileType *GifFile,
int Left, int Top, int Width, int Height, int Interlace,
int BitsPerPixel, GifColorType *ColorMap)
{
int i, Size;
GifByteType Buf[3];
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
if (Private -> FileState & FILE_STATE_IMAGE &&
#ifdef __MSDOS__
Private -> PixelCount > 0xffff0000UL) {
#else
Private -> PixelCount > 0xffff0000) {
#endif /* __MSDOS__ */
/* If already has active image descriptor - something is wrong! */
_GifError = E_GIF_ERR_HAS_IMAG_DSCR;
return GIF_ERROR;
}
if (!IS_WRITEABLE(Private)) {
/* This file was NOT open for writing: */
_GifError = E_GIF_ERR_NOT_WRITEABLE;
return GIF_ERROR;
}
GifFile -> ILeft = Left;
GifFile -> ITop = Top;
GifFile -> IWidth = Width;
GifFile -> IHeight = Height;
GifFile -> IBitsPerPixel = BitsPerPixel;
GifFile -> IInterlace = Interlace;
if (ColorMap) {
Size = sizeof(GifColorType) * (1 << BitsPerPixel);
if (GifFile -> IColorMap) free((char *) GifFile -> IColorMap);
GifFile -> IColorMap = (GifColorType *) malloc(Size);
memcpy(GifFile -> IColorMap, ColorMap, Size);
}
/* Put the image descriptor into the file: */
Buf[0] = ','; /* Image seperator character. */
#ifndef DEBUG_NO_PREFIX
fwrite(Buf, 1, 1, Private -> File);
#endif /* DEBUG_NO_PREFIX */
EGifPutWord(Left, Private -> File);
EGifPutWord(Top, Private -> File);
EGifPutWord(Width, Private -> File);
EGifPutWord(Height, Private -> File);
Buf[0] = (ColorMap ? 0x80 : 0x00) |
(Interlace ? 0x40 : 0x00) |
(BitsPerPixel - 1);
#ifndef DEBUG_NO_PREFIX
fwrite(Buf, 1, 1, Private -> File);
#endif /* DEBUG_NO_PREFIX */
/* If we have Global color map - dump it also: */
#ifndef DEBUG_NO_PREFIX
if (ColorMap != NULL)
for (i = 0; i < (1 << BitsPerPixel); i++) {
/* Put the ColorMap out also: */
Buf[0] = ColorMap[i].Red;
Buf[1] = ColorMap[i].Green;
Buf[2] = ColorMap[i].Blue;
if (fwrite(Buf, 1, 3, Private -> File) != 3) {
_GifError = E_GIF_ERR_WRITE_FAILED;
return GIF_ERROR;
}
}
#endif /* DEBUG_NO_PREFIX */
if (GifFile -> SColorMap == NULL && GifFile -> IColorMap == NULL)
{
_GifError = E_GIF_ERR_NO_COLOR_MAP;
return GIF_ERROR;
}
/* Mark this file as has screen descriptor: */
Private -> FileState |= FILE_STATE_IMAGE;
Private -> PixelCount = (long) Width * (long) Height;
EGifSetupCompress(GifFile); /* Reset compress algorithm parameters. */
return GIF_OK;
}
/******************************************************************************
* Put one full scanned line (Line) of length LineLen into GIF file. *
******************************************************************************/
int EGifPutLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
{
int i;
GifPixelType Mask;
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
if (!IS_WRITEABLE(Private)) {
/* This file was NOT open for writing: */
_GifError = E_GIF_ERR_NOT_WRITEABLE;
return GIF_ERROR;
}
if (!LineLen) LineLen = GifFile -> IWidth;
if ((Private -> PixelCount -= LineLen) < 0) {
_GifError = E_GIF_ERR_DATA_TOO_BIG;
return GIF_ERROR;
}
/* Make sure the codes are not out of bit range, as we might generate */
/* wrong code (because of overflow when we combine them) in this case: */
Mask = CodeMask[Private -> BitsPerPixel];
for (i = 0; i < LineLen; i++) Line[i] &= Mask;
return EGifCompressLine(GifFile, Line, LineLen);
}
/******************************************************************************
* Put one pixel (Pixel) into GIF file. *
******************************************************************************/
int EGifPutPixel(GifFileType *GifFile, GifPixelType Pixel)
{
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
if (!IS_WRITEABLE(Private)) {
/* This file was NOT open for writing: */
_GifError = E_GIF_ERR_NOT_WRITEABLE;
return GIF_ERROR;
}
if (--Private -> PixelCount < 0)
{
_GifError = E_GIF_ERR_DATA_TOO_BIG;
return GIF_ERROR;
}
/* Make sure the code is not out of bit range, as we might generate */
/* wrong code (because of overflow when we combine them) in this case: */
Pixel &= CodeMask[Private -> BitsPerPixel];
return EGifCompressLine(GifFile, &Pixel, 1);
}
/******************************************************************************
* Put a comment into GIF file using extension block. *
******************************************************************************/
int EGifPutComment(GifFileType *GifFile, char *Comment)
{
return EGifPutExtension(GifFile, COMMENT_EXT_FUNC_CODE, strlen(Comment),
Comment);
}
/******************************************************************************
* Put an extension block (see GIF manual) into gif file. *
******************************************************************************/
int EGifPutExtension(GifFileType *GifFile, int ExtCode, int ExtLen,
VoidPtr Extension)
{
GifByteType Buf[3];
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
if (!IS_WRITEABLE(Private)) {
/* This file was NOT open for writing: */
_GifError = E_GIF_ERR_NOT_WRITEABLE;
return GIF_ERROR;
}
Buf[0] = '!';
Buf[1] = ExtCode;
Buf[2] = ExtLen;
fwrite(Buf, 1, 3, Private -> File);
fwrite(Extension, 1, ExtLen, Private -> File);
Buf[0] = 0;
fwrite(Buf, 1, 1, Private -> File);
return GIF_OK;
}
/******************************************************************************
* Put the image code in compressed form. This routine can be called if the *
* information needed to be piped out as is. Obviously this is much faster *
* than decoding and encoding again. This routine should be followed by calls *
* to EGifPutCodeNext, until NULL block is given. *
* The block should NOT be freed by the user (not dynamically allocated). *
******************************************************************************/
int EGifPutCode(GifFileType *GifFile, int CodeSize, GifByteType *CodeBlock)
{
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
if (!IS_WRITEABLE(Private)) {
/* This file was NOT open for writing: */
_GifError = E_GIF_ERR_NOT_WRITEABLE;
return GIF_ERROR;
}
/* No need to dump code size as Compression set up does any for us: */
/*
Buf = CodeSize;
if (fwrite(&Buf, 1, 1, Private -> File) != 1) {
_GifError = E_GIF_ERR_WRITE_FAILED;
return GIF_ERROR;
}
*/
return EGifPutCodeNext(GifFile, CodeBlock);
}
/******************************************************************************
* Continue to put the image code in compressed form. This routine should be *
* called with blocks of code as read via DGifGetCode/DGifGetCodeNext. If *
* given buffer pointer is NULL, empty block is written to mark end of code. *
******************************************************************************/
int EGifPutCodeNext(GifFileType *GifFile, GifByteType *CodeBlock)
{
GifByteType Buf;
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
if (CodeBlock != NULL) {
if (fwrite(CodeBlock, 1, CodeBlock[0] + 1, Private -> File)
!= CodeBlock[0] + 1) {
_GifError = E_GIF_ERR_WRITE_FAILED;
return GIF_ERROR;
}
}
else {
Buf = 0;
if (fwrite(&Buf, 1, 1, Private -> File) != 1) {
_GifError = E_GIF_ERR_WRITE_FAILED;
return GIF_ERROR;
}
Private -> PixelCount = 0; /* And local info. indicate image read. */
}
return GIF_OK;
}
/******************************************************************************
* This routine should be called last, to close GIF file. *
******************************************************************************/
int EGifCloseFile(GifFileType *GifFile)
{
GifByteType Buf;
GifFilePrivateType *Private;
FILE *File;
if (GifFile == NULL) return GIF_ERROR;
Private = (GifFilePrivateType *) GifFile -> Private;
if (!IS_WRITEABLE(Private)) {
/* This file was NOT open for writing: */
_GifError = E_GIF_ERR_NOT_WRITEABLE;
return GIF_ERROR;
}
File = Private -> File;
Buf = ';';
fwrite(&Buf, 1, 1, Private -> File);
if (GifFile -> IColorMap) free((char *) GifFile -> IColorMap);
if (GifFile -> SColorMap) free((char *) GifFile -> SColorMap);
if (Private) {
if (Private -> HashTable) free((char *) Private -> HashTable);
free((char *) Private);
}
free(GifFile);
if (fclose(File) != 0) {
_GifError = E_GIF_ERR_CLOSE_FAILED;
return GIF_ERROR;
}
return GIF_OK;
}
/******************************************************************************
* Put 2 bytes (word) into the given file: *
******************************************************************************/
static int EGifPutWord(int Word, FILE *File)
{
char c[2];
c[0] = Word & 0xff;
c[1] = (Word >> 8) & 0xff;
#ifndef DEBUG_NO_PREFIX
if (fwrite(c, 1, 2, File) == 2)
return GIF_OK;
else
return GIF_ERROR;
#else
return GIF_OK;
#endif /* DEBUG_NO_PREFIX */
}
/******************************************************************************
* Setup the LZ compression for this image: *
******************************************************************************/
static int EGifSetupCompress(GifFileType *GifFile)
{
int BitsPerPixel;
GifByteType Buf;
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
/* Test and see what color map to use, and from it # bits per pixel: */
if (GifFile -> IColorMap)
BitsPerPixel = GifFile -> IBitsPerPixel;
else if (GifFile -> SColorMap)
BitsPerPixel = GifFile -> SBitsPerPixel;
else {
_GifError = E_GIF_ERR_NO_COLOR_MAP;
return GIF_ERROR;
}
Buf = BitsPerPixel = (BitsPerPixel < 2 ? 2 : BitsPerPixel);
fwrite(&Buf, 1, 1, Private -> File); /* Write the Code size to file. */
Private -> Buf[0] = 0; /* Nothing was output yet. */
Private -> BitsPerPixel = BitsPerPixel;
Private -> ClearCode = (1 << BitsPerPixel);
Private -> EOFCode = Private -> ClearCode + 1;
Private -> RunningCode = Private -> EOFCode + 1;
Private -> RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
Private -> MaxCode1 = 1 << Private -> RunningBits; /* Max. code + 1. */
Private -> CrntCode = FIRST_CODE; /* Signal that this is first one! */
Private -> CrntShiftState = 0; /* No information in CrntShiftDWord. */
Private -> CrntShiftDWord = 0;
/* Clear hash table and send Clear to make sure the decoder do the same. */
_ClearHashTable(Private -> HashTable);
if (EGifCompressOutput(Private, Private -> ClearCode) == GIF_ERROR) {
_GifError = E_GIF_ERR_DISK_IS_FULL;
return GIF_ERROR;
}
return GIF_OK;
}
/******************************************************************************
* The LZ compression routine: *
* This version compress the given buffer Line of length LineLen. *
* This routine can be called few times (one per scan line, for example), in *
* order the complete the whole image. *
******************************************************************************/
static int EGifCompressLine(GifFileType *GifFile, GifPixelType *Line,
int LineLen)
{
int i = 0, CrntCode, NewCode;
unsigned long NewKey;
GifPixelType Pixel;
GifHashTableType *HashTable;
GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
HashTable = Private -> HashTable;
if (Private -> CrntCode == FIRST_CODE) /* Its first time! */
CrntCode = Line[i++];
else
CrntCode = Private -> CrntCode; /* Get last code in compression. */
while (i < LineLen) { /* Decode LineLen items. */
Pixel = Line[i++]; /* Get next pixel from stream. */
/* Form a new unique key to search hash table for the code combines */
/* CrntCode as Prefix string with Pixel as postfix char. */
NewKey = (((unsigned long) CrntCode) << 8) + Pixel;
if ((NewCode = _ExistsHashTable(HashTable, NewKey)) >= 0) {
/* This Key is already there, or the string is old one, so */
/* simple take new code as our CrntCode: */
CrntCode = NewCode;
}
else {
/* Put it in hash table, output the prefix code, and make our */
/* CrntCode equal to Pixel. */
if (EGifCompressOutput(Private, CrntCode)
== GIF_ERROR) {
_GifError = E_GIF_ERR_DISK_IS_FULL;
return GIF_ERROR;
}
CrntCode = Pixel;
/* If however the HashTable if full, we send a clear first and */
/* Clear the hash table. */
if (Private -> RunningCode >= ZL_MAX_CODE) {
/* Time to do some clearance: */
if (EGifCompressOutput(Private, Private -> ClearCode)
== GIF_ERROR) {
_GifError = E_GIF_ERR_DISK_IS_FULL;
return GIF_ERROR;
}
Private -> RunningCode = Private -> EOFCode + 1;
Private -> RunningBits = Private -> BitsPerPixel + 1;
Private -> MaxCode1 = 1 << Private -> RunningBits;
_ClearHashTable(HashTable);
}
else {
/* Put this unique key with its relative Code in hash table: */
_InsertHashTable(HashTable, NewKey, Private -> RunningCode++);
}
}
}
/* Preserve the current state of the compression algorithm: */
Private -> CrntCode = CrntCode;
if (Private -> PixelCount == 0)
{
/* We are done - output last Code and flush output buffers: */
if (EGifCompressOutput(Private, CrntCode)
== GIF_ERROR) {
_GifError = E_GIF_ERR_DISK_IS_FULL;
return GIF_ERROR;
}
if (EGifCompressOutput(Private, Private -> EOFCode)
== GIF_ERROR) {
_GifError = E_GIF_ERR_DISK_IS_FULL;
return GIF_ERROR;
}
if (EGifCompressOutput(Private, FLUSH_OUTPUT) == GIF_ERROR) {
_GifError = E_GIF_ERR_DISK_IS_FULL;
return GIF_ERROR;
}
}
return GIF_OK;
}
/******************************************************************************
* The LZ compression output routine: *
* This routine is responsable for the compression of the bit stream into *
* 8 bits (bytes) packets. *
* Returns GIF_OK if written succesfully. *
******************************************************************************/
static int EGifCompressOutput(GifFilePrivateType *Private, int Code)
{
int retval = GIF_OK;
if (Code == FLUSH_OUTPUT) {
while (Private -> CrntShiftState > 0) {
/* Get Rid of what is left in DWord, and flush it. */
if (EGifBufferedOutput(Private -> File, Private -> Buf,
Private -> CrntShiftDWord & 0xff) == GIF_ERROR)
retval = GIF_ERROR;
Private -> CrntShiftDWord >>= 8;
Private -> CrntShiftState -= 8;
}
Private -> CrntShiftState = 0; /* For next time. */
if (EGifBufferedOutput(Private -> File, Private -> Buf,
FLUSH_OUTPUT) == GIF_ERROR)
retval = GIF_ERROR;
}
else {
Private -> CrntShiftDWord |= ((long) Code) << Private -> CrntShiftState;
Private -> CrntShiftState += Private -> RunningBits;
while (Private -> CrntShiftState >= 8) {
/* Dump out full bytes: */
if (EGifBufferedOutput(Private -> File, Private -> Buf,
Private -> CrntShiftDWord & 0xff) == GIF_ERROR)
retval = GIF_ERROR;
Private -> CrntShiftDWord >>= 8;
Private -> CrntShiftState -= 8;
}
}
/* If code cannt fit into RunningBits bits, must raise its size. Note */
/* however that codes above 4095 are used for special signaling. */
if (Private -> RunningCode >= Private -> MaxCode1 && Code <= 4095) {
Private -> MaxCode1 = 1 << ++Private -> RunningBits;
}
return retval;
}
/******************************************************************************
* This routines buffers the given characters until 255 characters are ready *
* to be output. If Code is equal to -1 the buffer is flushed (EOF). *
* The buffer is Dumped with first byte as its size, as GIF format requires. *
* Returns GIF_OK if written succesfully. *
******************************************************************************/
static int EGifBufferedOutput(FILE *File, GifByteType *Buf, int c)
{
if (c == FLUSH_OUTPUT) {
/* Flush everything out. */
if (Buf[0] != 0 && fwrite(Buf, 1, Buf[0]+1, File) != Buf[0] + 1)
{
_GifError = E_GIF_ERR_WRITE_FAILED;
return GIF_ERROR;
}
/* Mark end of compressed data, by an empty block (see GIF doc): */
Buf[0] = 0;
if (fwrite(Buf, 1, 1, File) != 1)
{
_GifError = E_GIF_ERR_WRITE_FAILED;
return GIF_ERROR;
}
}
else {
if (Buf[0] == 255) {
/* Dump out this buffer - it is full: */
if (fwrite(Buf, 1, Buf[0] + 1, File) != Buf[0] + 1)
{
_GifError = E_GIF_ERR_WRITE_FAILED;
return GIF_ERROR;
}
Buf[0] = 0;
}
Buf[++Buf[0]] = c;
}
return GIF_OK;
}

632
G/LIB/GETARG.C Normal file
View File

@ -0,0 +1,632 @@
/***************************************************************************
* Routines to grab the parameters from the command line : *
* All the routines except the main one, starts with GA (Get Arguments) to *
* prevent from names conflicts. *
* It is assumed in these routine that any pointer, for any type has the *
* same length (i.e. length of int pointer is equal to char pointer etc.) *
* *
* The following routines are available in this module: *
* 1. int GAGetArgs(argc, argv, CtrlStr, Variables...) *
* where argc, argv as received on entry. *
* CtrlStr is the contrl string (see below) *
* Variables are all the variables to be set according to CtrlStr. *
* Note that all the variables MUST be transfered by address. *
* return 0 on correct parsing, otherwise error number (see GetArg.h). *
* 2. GAPrintHowTo(CtrlStr) *
* Print the control string to stderr, in the correct format needed. *
* This feature is very useful in case of error during GetArgs parsing. *
* Chars equal to SPACE_CHAR are not printed (regular spaces are NOT *
* allowed, and so using SPACE_CHAR you can create space in PrintHowTo). *
* 3. GAPrintErrMsg(Error) *
* Print the error to stderr, according to Error (usually returned by *
* GAGetArgs). *
* *
* CtrlStr format: *
* The control string passed to GetArgs controls the way argv (argc) are *
* parsed. Each entry in this string must not have any spaces in it. The *
* First Entry is the name of the program which is usually ignored except *
* when GAPrintHowTo is called. All the other entries (except the last one *
* which we will come back to it later) must have the following format: *
* 1. One letter which sets the option letter. *
* 2. '!' or '%' to determines if this option is really optional ('%') or *
* it must exists ('!')... *
* 3. '-' allways. *
* 4. Alpha numeric string, usually ignored, but used by GAPrintHowTo to *
* print the meaning of this input. *
* 5. Sequences starts with '!' or '%'. Again if '!' then this sequence *
* must exists (only if its option flag is given of course), and if '%' *
* it is optional. Each sequence will continue with one or two *
* characters which defines the kind of the input: *
* a. d, x, o, u - integer is expected (decimal, hex, octal base or *
* unsigned). *
* b. D, X, O, U - long integer is expected (same as above). *
* c. f - float number is expected. *
* d. F - double number is expected. *
* e. s - string is expected. *
* f. *? - any number of '?' kind (d, x, o, u, D, X, O, U, f, F, s) *
* will match this one. If '?' is numeric, it scans until *
* none numeric input is given. If '?' is 's' then it scans *
* up to the next option or end of argv. *
* *
* If the last parameter given in the CtrlStr, is not an option (i.e. the *
* second char is not in ['!', '%'] and the third one is not '-'), all what *
* remained from argv is linked to it. *
* *
* The variables passed to GAGetArgs (starting from 4th parameter) MUST *
* match the order of the CtrlStr: *
* For each option, one integer address must be passed. This integer must *
* initialized by 0. If that option is given in the command line, it will *
* be set to one. *
* In addition, the sequences that might follow an option require the *
* following parameters to pass: *
* 1. d, x, o, u - pointer to integer (int *). *
* 2. D, X, O, U - pointer to long (long *). *
* 3. f - pointer to float (float *). *
* 4. F - pointer to double (double *). *
* 5. s - pointer to char (char *). NO allocation is needed! *
* 6. *? - TWO variables are passed for each wild request. the first *
* one is (address of) integer, and it will return number of *
* parameters actually matched this sequence, and the second *
* one is a pointer to pointer to ? (? **), and will return an *
* address to a block of pointers to ? kind, terminated with *
* NULL pointer. NO pre-allocation is needed. *
* note that these two variables are pretty like the argv/argc *
* pair... *
* *
* Examples: *
* *
* "Example1 i%-OneInteger!d s%-Strings!*s j%- k!-Float!f Files" *
* Will match: Example1 -i 77 -s String1 String2 String3 -k 88.2 File1 File2*
* or match: Example1 -s String1 -k 88.3 -i 999 -j *
* but not: Example1 -i 77 78 (option i expects one integer, k must be). *
* Note the option k must exists, and that the order of the options is not *
* not important. In the first examples File1 & File2 will match the Files *
* in the command line. *
* A call to GAPrintHowTo with this CtrlStr will print to stderr: *
* Example1 [-i OneIngeter] [-s Strings...] [-j] -k Float Files... *
* *
* Notes: *
* *
* 1. This module assumes that all the pointers to all kind of data types *
* have the same length and format, i.e. sizeof(int *) == sizeof(char *).*
* *
* Gershon Elber Ver 0.2 Mar 88 *
****************************************************************************
* History: *
* 11 Mar 88 - Version 1.0 by Gershon Elber. *
***************************************************************************/
#ifdef __MSDOS__
#include <stdlib.h>
#include <alloc.h>
#endif /* __MSDOS__ */
#ifdef USE_VARARGS
#include <varargs.h>
#endif /* USE_VARARGS */
#include <stdio.h>
#include <string.h>
#include "getarg.h"
#define MYMALLOC /* If no "MyAlloc" routine elsewhere define this. */
#define MAX_PARAM 100 /* maximum number of parameters allowed. */
#define CTRL_STR_MAX_LEN 1024
#define SPACE_CHAR '|' /* The character not to print using HowTo. */
#ifndef TRUE
#define TRUE -1
#define FALSE 0
#endif /* TRUE */
#define ARG_OK 0
#define ISSPACE(x) ((x) <= ' ') /* Not conventional - but works fine! */
/* The two characters '%' and '!' are used in the control string: */
#define ISCTRLCHAR(x) (((x) == '%') || ((x) == '!'))
static char *GAErrorToken;/* On error code, ErrorToken is set to point on it.*/
static int GATestAllSatis(char *CtrlStrCopy, char *CtrlStr, int *argc,
char ***argv, int *Parameters[MAX_PARAM], int *ParamCount);
static int GAUpdateParameters(int *Parameters[], int *ParamCount,
char *Option, char *CtrlStrCopy, char *CtrlStr, int *argc,
char ***argv);
static int GAGetParmeters(int *Parameters[], int *ParamCount,
char *CtrlStrCopy , char *Option, int *argc, char ***argv);
static int GAGetMultiParmeters(int *Parameters[], int *ParamCount,
char *CtrlStrCopy, int *argc, char ***argv);
static void GASetParamCount(char *CtrlStr, int Max, int *ParamCount);
static void GAByteCopy(char *Dst, char *Src, unsigned n);
static int GAOptionExists(int argc, char **argv);
#ifdef MYMALLOC
static char *MyMalloc(unsigned size);
#endif /* MYMALLOC */
/***************************************************************************
* Routine to access the command line argument and interpret them: *
* Return ARG_OK (0) is case of succesfull parsing, error code else... *
***************************************************************************/
#ifdef USE_VARARGS
int GAGetArgs(int va_alist, ...)
{
va_list ap;
int argc, i, Error = FALSE, ParamCount = 0,
*Parameters[MAX_PARAM]; /* Save here parameter addresses. */
char **argv, *CtrlStr, *Option, CtrlStrCopy[CTRL_STR_MAX_LEN];
va_start(ap);
argc = va_arg(ap, int);
argv = va_arg(ap, char **);
CtrlStr = va_arg(ap, char *);
va_end(ap);
strcpy(CtrlStrCopy, CtrlStr);
/* Using base address of parameters we access other parameters addr: */
/* Note that me (for sure!) samples data beyond the current function */
/* frame, but we accesson these set address only by demand. */
for (i = 1; i <= MAX_PARAM; i++) Parameters[i-1] = va_arg(ap, int *);
#else
int GAGetArgs(int argc, char **argv, char *CtrlStr, ...)
{
int i, Error = FALSE, ParamCount = 0,
*Parameters[MAX_PARAM]; /* Save here parameter addresses. */
char *Option, CtrlStrCopy[CTRL_STR_MAX_LEN];
strcpy(CtrlStrCopy, CtrlStr);
/* Using base address of parameters we access other parameters addr: */
/* Note that me (for sure!) samples data beyond the current function */
/* frame, but we accesson these set address only by demand. */
for (i = 1; i <= MAX_PARAM; i++) Parameters[i-1] = (int *) *(i + &CtrlStr);
#endif /* USE_VARARG */
--argc; argv++; /* Skip the program name (first in argv/c list). */
while (argc >= 0) {
if (!GAOptionExists(argc, argv)) break; /* The loop. */
argc--;
Option = *argv++;
if ((Error = GAUpdateParameters(Parameters, &ParamCount, Option,
CtrlStrCopy, CtrlStr, &argc, &argv)) != FALSE) return Error;
}
/* Check for results and update trail of command line: */
return GATestAllSatis(CtrlStrCopy, CtrlStr, &argc, &argv, Parameters,
&ParamCount);
}
/***************************************************************************
* Routine to search for unsatisfied flags - simply scan the list for !- *
* sequence. Before this scan, this routine updates the rest of the command *
* line into the last two parameters if it is requested by the CtrlStr *
* (last item in CtrlStr is NOT an option). *
* Return ARG_OK if all satisfied, CMD_ERR_AllSatis error else. *
***************************************************************************/
static int GATestAllSatis(char *CtrlStrCopy, char *CtrlStr, int *argc,
char ***argv, int *Parameters[MAX_PARAM], int *ParamCount)
{
int i;
static char *LocalToken = NULL;
/* If LocalToken is not initialized - do it now. Note that this string */
/* should be writable as well so we can not assign it directly. */
if (LocalToken == NULL) {
LocalToken = (char *) malloc(3);
strcpy(LocalToken, "-?");
}
/* Check is last item is an option. If not then copy rest of command */
/* line into it as 1. NumOfprm, 2. pointer to block of pointers. */
for (i = strlen(CtrlStr) - 1; i > 0 && !ISSPACE(CtrlStr[i]); i--);
if (!ISCTRLCHAR(CtrlStr[i + 2])) {
GASetParamCount(CtrlStr, i, ParamCount); /* Point in correct prm.. */
*Parameters[(*ParamCount)++] = *argc;
GAByteCopy((char *) Parameters[(*ParamCount)++], (char *) argv,
sizeof(char *));
}
i = 0;
while (++i < strlen(CtrlStrCopy))
if ((CtrlStrCopy[i] == '-') && (CtrlStrCopy[i-1] == '!')) {
GAErrorToken = LocalToken;
LocalToken[1] = CtrlStrCopy[i-2]; /* Set the corrent flag. */
return CMD_ERR_AllSatis;
}
return ARG_OK;
}
/***************************************************************************
* Routine to update the parameters according to the given Option: *
***************************************************************************/
static int GAUpdateParameters(int *Parameters[], int *ParamCount,
char *Option, char *CtrlStrCopy, char *CtrlStr, int *argc, char ***argv)
{
int i, BooleanTrue = Option[2] != '-';
if (Option[0] != '-') {
GAErrorToken = Option;
return CMD_ERR_NotAnOpt;
}
i = 0; /* Scan the CtrlStrCopy for that option: */
while (i + 2 < strlen(CtrlStrCopy)) {
if ((CtrlStrCopy[i] == Option[1]) && (ISCTRLCHAR(CtrlStrCopy[i + 1]))
&& (CtrlStrCopy[i+2] == '-')) {
/* We found that option! */
break;
}
i++;
}
if (i + 2 >= strlen(CtrlStrCopy)) {
GAErrorToken = Option;
return CMD_ERR_NoSuchOpt;
}
/* If we are here, then we found that option in CtrlStr - Strip it off: */
CtrlStrCopy[i] = CtrlStrCopy[i + 1] = CtrlStrCopy[i + 2] = (char) ' ';
GASetParamCount(CtrlStr, i, ParamCount);/*Set it to point in correct prm.*/
i += 3;
/* Set boolean flag for that option. */
*Parameters[(*ParamCount)++] = BooleanTrue;
if (ISSPACE(CtrlStrCopy[i]))
return ARG_OK; /* Only a boolean flag is needed. */
/* Skip the text between the boolean option and data follows: */
while (!ISCTRLCHAR(CtrlStrCopy[i])) i++;
/* Get the parameters and return the appropriete return code: */
return GAGetParmeters(Parameters, ParamCount, &CtrlStrCopy[i],
Option, argc, argv);
}
/***************************************************************************
* Routine to get parameters according to the CtrlStr given from argv/c : *
***************************************************************************/
static int GAGetParmeters(int *Parameters[], int *ParamCount,
char *CtrlStrCopy , char *Option, int *argc, char ***argv)
{
int i = 0, ScanRes;
while (!(ISSPACE(CtrlStrCopy[i]))) {
switch (CtrlStrCopy[i+1]) {
case 'd': /* Get signed integers. */
ScanRes = sscanf(*((*argv)++), "%d",
(int *) Parameters[(*ParamCount)++]);
break;
case 'u': /* Get unsigned integers. */
ScanRes = sscanf(*((*argv)++), "%u",
(unsigned *) Parameters[(*ParamCount)++]);
break;
case 'x': /* Get hex integers. */
ScanRes = sscanf(*((*argv)++), "%x",
(int *) Parameters[(*ParamCount)++]);
break;
case 'o': /* Get octal integers. */
ScanRes = sscanf(*((*argv)++), "%o",
(int *) Parameters[(*ParamCount)++]);
break;
case 'D': /* Get signed long integers. */
ScanRes = sscanf(*((*argv)++), "%ld",
(long *) Parameters[(*ParamCount)++]);
break;
case 'U': /* Get unsigned long integers. */
ScanRes = sscanf(*((*argv)++), "%lu",
(unsigned long *) Parameters[(*ParamCount)++]);
break;
case 'X': /* Get hex long integers. */
ScanRes = sscanf(*((*argv)++), "%lx",
(long *) Parameters[(*ParamCount)++]);
break;
case 'O': /* Get octal long integers. */
ScanRes = sscanf(*((*argv)++), "%lo",
(long *) Parameters[(*ParamCount)++]);
break;
case 'f': /* Get float number. */
ScanRes = sscanf(*((*argv)++), "%f",
(float *) Parameters[(*ParamCount)++]);
case 'F': /* Get double float number. */
ScanRes = sscanf(*((*argv)++), "%lf",
(double *) Parameters[(*ParamCount)++]);
break;
case 's': /* It as a string. */
ScanRes = 1; /* Allways O.K. */
GAByteCopy((char *) Parameters[(*ParamCount)++],
(char *) ((*argv)++), sizeof(char *));
break;
case '*': /* Get few parameters into one: */
ScanRes = GAGetMultiParmeters(Parameters, ParamCount,
&CtrlStrCopy[i], argc, argv);
if ((ScanRes == 0) && (CtrlStrCopy[i] == '!')) {
GAErrorToken = Option;
return CMD_ERR_WildEmpty;
}
break;
default:
ScanRes = 0; /* Make optimizer warning silent. */
}
/* If reading fails and this number is a must (!) then error: */
if ((ScanRes == 0) && (CtrlStrCopy[i] == '!')) {
GAErrorToken = Option;
return CMD_ERR_NumRead;
}
if (CtrlStrCopy[i+1] != '*') {
(*argc)--; /* Everything is OK - update to next parameter: */
i += 2; /* Skip to next parameter (if any). */
}
else
i += 3; /* Skip the '*' also! */
}
return ARG_OK;
}
/***************************************************************************
* Routine to get few parameters into one pointer such that the returned *
* pointer actually points on a block of pointers to the parameters... *
* For example *F means a pointer to pointers on floats. *
* Returns number of parameters actually read. *
* This routine assumes that all pointers (on any kind of scalar) has the *
* same size (and the union below is totally ovelapped bteween dif. arrays) *
***************************************************************************/
static int GAGetMultiParmeters(int *Parameters[], int *ParamCount,
char *CtrlStrCopy, int *argc, char ***argv)
{
int i = 0, ScanRes, NumOfPrm = 0, **Pmain, **Ptemp;
union TmpArray { /* Save here the temporary data before copying it to */
int *IntArray[MAX_PARAM]; /* the returned pointer block. */
long *LngArray[MAX_PARAM];
float *FltArray[MAX_PARAM];
double *DblArray[MAX_PARAM];
char *ChrArray[MAX_PARAM];
} TmpArray;
do {
switch(CtrlStrCopy[2]) { /* CtrlStr == '!*?' or '%*?' where ? is. */
case 'd': /* Format to read the parameters: */
TmpArray.IntArray[NumOfPrm] = (int *) MyMalloc(sizeof(int));
ScanRes = sscanf(*((*argv)++), "%d",
(int *) TmpArray.IntArray[NumOfPrm++]);
break;
case 'u':
TmpArray.IntArray[NumOfPrm] = (int *) MyMalloc(sizeof(int));
ScanRes = sscanf(*((*argv)++), "%u",
(unsigned int *) TmpArray.IntArray[NumOfPrm++]);
break;
case 'o':
TmpArray.IntArray[NumOfPrm] = (int *) MyMalloc(sizeof(int));
ScanRes = sscanf(*((*argv)++), "%o",
(int *) TmpArray.IntArray[NumOfPrm++]);
break;
case 'x':
TmpArray.IntArray[NumOfPrm] = (int *) MyMalloc(sizeof(int));
ScanRes = sscanf(*((*argv)++), "%x",
(int *) TmpArray.IntArray[NumOfPrm++]);
break;
case 'D':
TmpArray.LngArray[NumOfPrm] = (long *) MyMalloc(sizeof(long));
ScanRes = sscanf(*((*argv)++), "%ld",
(long *) TmpArray.IntArray[NumOfPrm++]);
break;
case 'U':
TmpArray.LngArray[NumOfPrm] = (long *) MyMalloc(sizeof(long));
ScanRes = sscanf(*((*argv)++), "%lu",
(unsigned long *) TmpArray.IntArray[NumOfPrm++]);
break;
case 'O':
TmpArray.LngArray[NumOfPrm] = (long *) MyMalloc(sizeof(long));
ScanRes = sscanf(*((*argv)++), "%lo",
(long *) TmpArray.IntArray[NumOfPrm++]);
break;
case 'X':
TmpArray.LngArray[NumOfPrm] = (long *) MyMalloc(sizeof(long));
ScanRes = sscanf(*((*argv)++), "%lx",
(long *) TmpArray.IntArray[NumOfPrm++]);
break;
case 'f':
TmpArray.FltArray[NumOfPrm] = (float *) MyMalloc(sizeof(float));
ScanRes = sscanf(*((*argv)++), "%f",
(float *) TmpArray.LngArray[NumOfPrm++]);
break;
case 'F':
TmpArray.DblArray[NumOfPrm] =
(double *) MyMalloc(sizeof(double));
ScanRes = sscanf(*((*argv)++), "%lf",
(double *) TmpArray.LngArray[NumOfPrm++]);
break;
case 's':
while ((*argc) && ((**argv)[0] != '-')) {
TmpArray.ChrArray[NumOfPrm++] = *((*argv)++);
(*argc)--;
}
ScanRes = 0; /* Force quit from do - loop. */
NumOfPrm++; /* Updated again immediately after loop! */
(*argv)++; /* "" */
break;
default:
ScanRes = 0; /* Make optimizer warning silent. */
}
(*argc)--;
}
while (ScanRes == 1); /* Exactly one parameter was read. */
(*argv)--; NumOfPrm--; (*argc)++;
/* Now allocate the block with the exact size, and set it: */
Ptemp = Pmain = (int **) MyMalloc((unsigned) (NumOfPrm+1) * sizeof(int *));
/* And here we use the assumption that all pointers are the same: */
for (i = 0; i < NumOfPrm; i++)
*Ptemp++ = TmpArray.IntArray[i];
*Ptemp = NULL; /* Close the block with NULL pointer. */
/* That it save the number of parameters read as first parameter to */
/* return and the pointer to the block as second, and return: */
*Parameters[(*ParamCount)++] = NumOfPrm;
GAByteCopy((char *) Parameters[(*ParamCount)++], (char *) &Pmain,
sizeof(char *));
return NumOfPrm;
}
/***************************************************************************
* Routine to scan the CtrlStr, upto Max and count the number of parameters *
* to that point: *
* 1. Each option is counted as one parameter - boolean variable (int) *
* 2. Within an option, each %? or !? is counted once - pointer to something*
* 3. Within an option, %*? or !*? is counted twice - one for item count *
* and one for pointer to block pointers. *
* Note ALL variables are passed by address and so of fixed size (address). *
***************************************************************************/
static void GASetParamCount(char *CtrlStr, int Max, int *ParamCount)
{
int i;
*ParamCount = 0;
for (i = 0; i < Max; i++) if (ISCTRLCHAR(CtrlStr[i])) {
if (CtrlStr[i+1] == '*')
*ParamCount += 2;
else
(*ParamCount)++;
}
}
/***************************************************************************
* Routine to copy exactly n bytes from Src to Dst. Note system library *
* routine strncpy should do the same, but it stops on NULL char ! *
***************************************************************************/
static void GAByteCopy(char *Dst, char *Src, unsigned n)
{
while (n--) *(Dst++) = *(Src++);
}
/***************************************************************************
* Routine to check if more option (i.e. first char == '-') exists in the *
* given list argc, argv: *
***************************************************************************/
static int GAOptionExists(int argc, char **argv)
{
while (argc--)
if ((*argv++)[0] == '-') return TRUE;
return FALSE;
}
/***************************************************************************
* Routine to print some error messages, for this module: *
***************************************************************************/
void GAPrintErrMsg(int Error)
{
fprintf(stderr, "Error in command line parsing - ");
switch (Error) {
case 0:;
fprintf(stderr, "Undefined error");
break;
case CMD_ERR_NotAnOpt:
fprintf(stderr, "None option Found");
break;
case CMD_ERR_NoSuchOpt:
fprintf(stderr, "Undefined option Found");
break;
case CMD_ERR_WildEmpty:
fprintf(stderr, "Empty input for '!*?' seq.");
break;
case CMD_ERR_NumRead:
fprintf(stderr, "Failed on reading number");
break;
case CMD_ERR_AllSatis:
fprintf(stderr, "Fail to satisfy");
break;
}
fprintf(stderr, " - '%s'.\n", GAErrorToken);
}
/***************************************************************************
* Routine to print correct format of command line allowed: *
***************************************************************************/
void GAPrintHowTo(char *CtrlStr)
{
int i = 0, SpaceFlag;
fprintf(stderr, "Usage: ");
/* Print program name - first word in ctrl. str. (optional): */
while (!(ISSPACE(CtrlStr[i])) && (!ISCTRLCHAR(CtrlStr[i+1])))
fprintf(stderr, "%c", CtrlStr[i++]);
while (i < strlen(CtrlStr)) {
while ((ISSPACE(CtrlStr[i])) && (i < strlen(CtrlStr))) i++;
switch (CtrlStr[i+1]) {
case '%':
fprintf(stderr, " [-%c", CtrlStr[i++]);
i += 2; /* Skip the '%-' or '!- after the char! */
SpaceFlag = TRUE;
while (!ISCTRLCHAR(CtrlStr[i]) && (i < strlen(CtrlStr)) &&
(!ISSPACE(CtrlStr[i])))
if (SpaceFlag) {
if (CtrlStr[i++] == SPACE_CHAR)
fprintf(stderr, " ");
else
fprintf(stderr, " %c", CtrlStr[i-1]);
SpaceFlag = FALSE;
}
else if (CtrlStr[i++] == SPACE_CHAR)
fprintf(stderr, " ");
else
fprintf(stderr, "%c", CtrlStr[i-1]);
while (!ISSPACE(CtrlStr[i]) && (i < strlen(CtrlStr))) {
if (CtrlStr[i] == '*') fprintf(stderr, "...");
i++; /* Skip the rest of it. */
}
fprintf(stderr, "]");
break;
case '!':
fprintf(stderr, " -%c", CtrlStr[i++]);
i += 2; /* Skip the '%-' or '!- after the char! */
SpaceFlag = TRUE;
while (!ISCTRLCHAR(CtrlStr[i]) && (i < strlen(CtrlStr)) &&
(!ISSPACE(CtrlStr[i])))
if (SpaceFlag) {
if (CtrlStr[i++] == SPACE_CHAR)
fprintf(stderr, " ");
else
fprintf(stderr, " %c", CtrlStr[i-1]);
SpaceFlag = FALSE;
}
else if (CtrlStr[i++] == SPACE_CHAR)
fprintf(stderr, " ");
else
fprintf(stderr, "%c", CtrlStr[i-1]);
while (!ISSPACE(CtrlStr[i]) && (i < strlen(CtrlStr))) {
if (CtrlStr[i] == '*') fprintf(stderr, "...");
i++; /* Skip the rest of it. */
}
break;
default: /* Not checked, but must be last one! */
fprintf(stderr, " ");
while (!ISSPACE(CtrlStr[i]) && (i < strlen(CtrlStr)) &&
!ISCTRLCHAR(CtrlStr[i]))
fprintf(stderr, "%c", CtrlStr[i++]);
fprintf(stderr, "\n");
return;
}
}
fprintf(stderr, "\n");
}
#ifdef MYMALLOC
/***************************************************************************
* My Routine to allocate dynamic memory. All program requests must call *
* this routine (no direct call to malloc). Dies if no memory. *
***************************************************************************/
static char *MyMalloc(unsigned size)
{
char *p;
if ((p = (char *) malloc(size)) != NULL) return p;
fprintf(stderr, "Not enough memory, exit.\n");
exit(2);
return NULL; /* Makes warning silent. */
}
#endif /* MYMALLOC */

28
G/LIB/GETARG.H Normal file
View File

@ -0,0 +1,28 @@
/***************************************************************************
* Error numbers as returned by GAGetArg routine: *
* *
* Gershon Elber Mar 88 *
****************************************************************************
* History: *
* 11 Mar 88 - Version 1.0 by Gershon Elber. *
***************************************************************************/
#ifndef GET_ARG_H
#define GET_ARG_H
#define CMD_ERR_NotAnOpt 1 /* None Option found. */
#define CMD_ERR_NoSuchOpt 2 /* Undefined Option Found. */
#define CMD_ERR_WildEmpty 3 /* Empty input for !*? seq. */
#define CMD_ERR_NumRead 4 /* Failed on reading number. */
#define CMD_ERR_AllSatis 5 /* Fail to satisfy (must-'!') option. */
#ifdef USE_VARARGS
int GAGetArgs(int va_alist, ...);
#else
int GAGetArgs(int argc, char **argv, char *CtrlStr, ...);
#endif /* USE_VARARGS */
void GAPrintErrMsg(int Error);
void GAPrintHowTo(char *CtrlStr);
#endif /* GET_ARG_H */

130
G/LIB/GIF_ERR.C Normal file
View File

@ -0,0 +1,130 @@
/*****************************************************************************
* "Gif-Lib" - Yet another gif library. *
* *
* Written by: Gershon Elber IBM PC Ver 0.1, Jun. 1989 *
******************************************************************************
* Handle error reporting for the GIF library. *
******************************************************************************
* History: *
* 17 Jun 89 - Version 1.0 by Gershon Elber. *
*****************************************************************************/
#include <stdio.h>
#include "gif_lib.h"
#define PROGRAM_NAME "GIF_LIBRARY"
int _GifError = 0;
#ifdef SYSV
static char *VersionStr =
"Gif library module,\t\tGershon Elber\n\
(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
#else
static char *VersionStr =
PROGRAM_NAME
" IBMPC "
GIF_LIB_VERSION
" Gershon Elber, "
__DATE__ ", " __TIME__ "\n"
"(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
#endif /* SYSV */
/*****************************************************************************
* Return the last GIF error (0 if none) and reset the error. *
*****************************************************************************/
int GifLastError(void)
{
int i = _GifError;
_GifError = 0;
return i;
}
/*****************************************************************************
* Print the last GIF error to stderr. *
*****************************************************************************/
void PrintGifError(void)
{
char *Err;
switch(_GifError) {
case E_GIF_ERR_OPEN_FAILED:
Err = "Failed to open given file";
break;
case E_GIF_ERR_WRITE_FAILED:
Err = "Failed to Write to given file";
break;
case E_GIF_ERR_HAS_SCRN_DSCR:
Err = "Screen Descriptor already been set";
break;
case E_GIF_ERR_HAS_IMAG_DSCR:
Err = "Image Descriptor is still active";
break;
case E_GIF_ERR_NO_COLOR_MAP:
Err = "Neither Global Nor Local color map";
break;
case E_GIF_ERR_DATA_TOO_BIG:
Err = "#Pixels bigger than Width * Height";
break;
case E_GIF_ERR_NOT_ENOUGH_MEM:
Err = "Fail to allocate required memory";
break;
case E_GIF_ERR_DISK_IS_FULL:
Err = "Write failed (disk full?)";
break;
case E_GIF_ERR_CLOSE_FAILED:
Err = "Failed to close given file";
break;
case E_GIF_ERR_NOT_WRITEABLE:
Err = "Given file was not opened for write";
break;
case D_GIF_ERR_OPEN_FAILED:
Err = "Failed to open given file";
break;
case D_GIF_ERR_READ_FAILED:
Err = "Failed to Read from given file";
break;
case D_GIF_ERR_NOT_GIF_FILE:
Err = "Given file is NOT GIF file";
break;
case D_GIF_ERR_NO_SCRN_DSCR:
Err = "No Screen Descriptor detected";
break;
case D_GIF_ERR_NO_IMAG_DSCR:
Err = "No Image Descriptor detected";
break;
case D_GIF_ERR_NO_COLOR_MAP:
Err = "Neither Global Nor Local color map";
break;
case D_GIF_ERR_WRONG_RECORD:
Err = "Wrong record type detected";
break;
case D_GIF_ERR_DATA_TOO_BIG:
Err = "#Pixels bigger than Width * Height";
break;
case D_GIF_ERR_NOT_ENOUGH_MEM:
Err = "Fail to allocate required memory";
break;
case D_GIF_ERR_CLOSE_FAILED:
Err = "Failed to close given file";
break;
case D_GIF_ERR_NOT_READABLE:
Err = "Given file was not opened for read";
break;
case D_GIF_ERR_IMAGE_DEFECT:
Err = "Image is defective, decoding aborted";
break;
case D_GIF_ERR_EOF_TOO_SOON:
Err = "Image EOF detected, before image complete";
break;
default:
Err = NULL;
break;
}
if (Err != NULL)
fprintf(stderr, "\nGIF-LIB error: %s.\n", Err);
else
fprintf(stderr, "\nGIF-LIB undefined error %d.\n", _GifError);
}

155
G/LIB/GIF_HASH.C Normal file
View File

@ -0,0 +1,155 @@
/*****************************************************************************
* "Gif-Lib" - Yet another gif library. *
* *
* Written by: Gershon Elber IBM PC Ver 0.1, Jun. 1989 *
******************************************************************************
* Module to support the following operations: *
* *
* 1. InitHashTable - initialize hash table. *
* 2. ClearHashTable - clear the hash table to an empty state. *
* 2. InsertHashTable - insert one item into data structure. *
* 3. ExistsHashTable - test if item exists in data structure. *
* *
* This module is used to hash the GIF codes during encoding. *
******************************************************************************
* History: *
* 14 Jun 89 - Version 1.0 by Gershon Elber. *
*****************************************************************************/
#ifdef __MSDOS__
#include <io.h>
#include <alloc.h>
#include <sys\stat.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#endif /* __MSDOS__ */
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include "gif_lib.h"
#include "gif_hash.h"
#define PROGRAM_NAME "GIF_LIBRARY"
/* #define DEBUG_HIT_RATE Debug number of misses per hash Insert/Exists. */
#ifdef DEBUG_HIT_RATE
static long NumberOfTests = 0,
NumberOfMisses = 0;
#endif /* DEBUG_HIT_RATE */
#ifdef SYSV
static char *VersionStr =
"Gif library module,\t\tGershon Elber\n\
(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
#else
static char *VersionStr =
PROGRAM_NAME
" IBMPC "
GIF_LIB_VERSION
" Gershon Elber, "
__DATE__ ", " __TIME__ "\n"
"(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
#endif /* SYSV */
static int KeyItem(unsigned long Item);
/******************************************************************************
* Initialize HashTable - allocate the memory needed and clear it. *
******************************************************************************/
GifHashTableType *_InitHashTable(void)
{
GifHashTableType *HashTable;
if ((HashTable = (GifHashTableType *) malloc(sizeof(GifHashTableType)))
== NULL)
return NULL;
_ClearHashTable(HashTable);
return HashTable;
}
/******************************************************************************
* Routine to clear the HashTable to an empty state. *
* This part is a little machine depended. Use the commented part otherwise. *
******************************************************************************/
void _ClearHashTable(GifHashTableType *HashTable)
{
memset(HashTable -> HTable, 0xFF, HT_SIZE * sizeof(long));
}
/******************************************************************************
* Routine to insert a new Item into the HashTable. The data is assumed to be *
* new one. *
******************************************************************************/
void _InsertHashTable(GifHashTableType *HashTable, unsigned long Key, int Code)
{
int HKey = KeyItem(Key);
unsigned long *HTable = HashTable -> HTable;
#ifdef DEBUG_HIT_RATE
NumberOfTests++;
NumberOfMisses++;
#endif /* DEBUG_HIT_RATE */
while (HT_GET_KEY(HTable[HKey]) != 0xFFFFFL) {
#ifdef DEBUG_HIT_RATE
NumberOfMisses++;
#endif /* DEBUG_HIT_RATE */
HKey = (HKey + 1) & HT_KEY_MASK;
}
HTable[HKey] = HT_PUT_KEY(Key) | HT_PUT_CODE(Code);
}
/******************************************************************************
* Routine to test if given Key exists in HashTable and if so returns its code *
* Returns the Code if key was found, -1 if not. *
******************************************************************************/
int _ExistsHashTable(GifHashTableType *HashTable, unsigned long Key)
{
int HKey = KeyItem(Key);
unsigned long *HTable = HashTable -> HTable, HTKey;
#ifdef DEBUG_HIT_RATE
NumberOfTests++;
NumberOfMisses++;
#endif /* DEBUG_HIT_RATE */
while ((HTKey = HT_GET_KEY(HTable[HKey])) != 0xFFFFFL) {
#ifdef DEBUG_HIT_RATE
NumberOfMisses++;
#endif /* DEBUG_HIT_RATE */
if (Key == HTKey) return HT_GET_CODE(HTable[HKey]);
HKey = (HKey + 1) & HT_KEY_MASK;
}
return -1;
}
/******************************************************************************
* Routine to generate an HKey for the hashtable out of the given unique key. *
* The given Key is assumed to be 20 bits as follows: lower 8 bits are the *
* new postfix character, while the upper 12 bits are the prefix code. *
* Because the average hit ratio is only 2 (2 hash references per entry), *
* evaluating more complex keys (such as twin prime keys) does not worth it! *
******************************************************************************/
static int KeyItem(unsigned long Item)
{
return ((Item >> 12) ^ Item) & HT_KEY_MASK;
}
#ifdef DEBUG_HIT_RATE
/******************************************************************************
* Debugging routine to print the hit ratio - number of times the hash table *
* was tested per operation. This routine was used to test the KeyItem routine *
******************************************************************************/
void HashTablePrintHitRatio(void)
{
printf("Hash Table Hit Ratio is %ld/%ld = %ld%%.\n",
NumberOfMisses, NumberOfTests,
NumberOfMisses * 100 / NumberOfTests);
}
#endif /* DEBUG_HIT_RATE */

31
G/LIB/GIF_HASH.H Normal file
View File

@ -0,0 +1,31 @@
/******************************************************************************
* Declarations, global to other of the GIF-HASH.C module. *
* *
* Written by Gershon Elber, Jun 1989 *
*******************************************************************************
* History: *
* 14 Jun 89 - Version 1.0 by Gershon Elber. *
******************************************************************************/
#define HT_SIZE 8192 /* 12bits = 4096 or twice as big! */
#define HT_KEY_MASK 0x1FFF /* 13bits keys */
#define HT_KEY_NUM_BITS 13 /* 13bits keys */
#define HT_MAX_KEY 8191 /* 13bits - 1, maximal code possible */
#define HT_MAX_CODE 4095 /* Biggest code possible in 12 bits. */
/* The 32 bits of the long are divided into two parts for the key & code: */
/* 1. The code is 12 bits as our compression algorithm is limited to 12bits */
/* 2. The key is 12 bits Prefix code + 8 bit new char or 20 bits. */
#define HT_GET_KEY(l) (l >> 12)
#define HT_GET_CODE(l) (l & 0x0FFF)
#define HT_PUT_KEY(l) (l << 12)
#define HT_PUT_CODE(l) (l & 0x0FFF)
typedef struct GifHashTableType {
unsigned long HTable[HT_SIZE];
} GifHashTableType;
GifHashTableType *_InitHashTable(void);
void _ClearHashTable(GifHashTableType *HashTable);
void _InsertHashTable(GifHashTableType *HashTable, unsigned long Key, int Code);
int _ExistsHashTable(GifHashTableType *HashTable, unsigned long Key);

178
G/LIB/GIF_LIB.H Normal file
View File

@ -0,0 +1,178 @@
/******************************************************************************
* In order to make life a little bit easier when using the GIF file format, *
* this library was written, and which does all the dirty work... *
* *
* Written by Gershon Elber, Jun. 1989 *
*******************************************************************************
* History: *
* 14 Jun 89 - Version 1.0 by Gershon Elber. *
* 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). *
******************************************************************************/
#ifndef GIF_LIB_H
#define GIF_LIB_H
#define GIF_LIB_VERSION " Version 1.2, "
#define GIF_ERROR 0
#define GIF_OK 1
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#define GIF_FILE_BUFFER_SIZE 16384 /* Files uses bigger buffers than usual. */
typedef int GifBooleanType;
typedef unsigned char GifPixelType;
typedef unsigned char * GifRowType;
typedef unsigned char GifByteType;
#define GIF_MESSAGE(Msg) fprintf(stderr, "\n%s: %s\n", PROGRAM_NAME, Msg)
#define GIF_EXIT(Msg) { GIF_MESSAGE(Msg); exit(-3); }
#ifdef SYSV
#define VoidPtr char *
#else
#define VoidPtr void *
#endif /* SYSV */
typedef struct GifColorType {
GifByteType Red, Green, Blue;
} GifColorType;
/* Note entries prefixed with S are of Screen information, while entries */
/* prefixed with I are of the current defined Image. */
typedef struct GifFileType {
int SWidth, SHeight, /* Screen dimensions. */
SColorResolution, SBitsPerPixel, /* How many colors can we generate? */
SBackGroundColor, /* I hope you understand this one... */
ILeft, ITop, IWidth, IHeight, /* Current image dimensions. */
IInterlace, /* Sequential/Interlaced lines. */
IBitsPerPixel; /* How many colors this image has? */
GifColorType *SColorMap, *IColorMap; /* NULL if not exists. */
VoidPtr Private; /* The regular user should not mess with this one! */
} GifFileType;
typedef enum {
UNDEFINED_RECORD_TYPE,
SCREEN_DESC_RECORD_TYPE,
IMAGE_DESC_RECORD_TYPE, /* Begin with ',' */
EXTENSION_RECORD_TYPE, /* Begin with '!' */
TERMINATE_RECORD_TYPE /* Begin with ';' */
} GifRecordType;
/* DumpScreen2Gif routine constants identify type of window/screen to dump. */
/* Note all values below 1000 are reserved for the IBMPC different display */
/* devices (it has many!) and are compatible with the numbering TC2.0 */
/* (Turbo C 2.0 compiler for IBM PC) gives to these devices. */
typedef enum {
GIF_DUMP_SGI_WINDOW = 1000,
GIF_DUMP_X_WINDOW = 1001
} GifScreenDumpType;
/******************************************************************************
* O.k. here are the routines one can access in order to encode GIF file: *
* (GIF_LIB file EGIF_LIB.C). *
******************************************************************************/
GifFileType *EGifOpenFileName(char *GifFileName, int GifTestExistance);
GifFileType *EGifOpenFileHandle(int GifFileHandle);
void EGifSetGifVersion(char *Version);
int EGifPutScreenDesc(GifFileType *GifFile,
int GifWidth, int GifHeight, int GifColorRes, int GifBackGround,
int GifBitsPerPixel, GifColorType *GifColorMap);
int EGifPutImageDesc(GifFileType *GifFile,
int GifLeft, int GifTop, int Width, int GifHeight, int GifInterlace,
int GifBitsPerPixel, GifColorType *GifColorMap);
int EGifPutLine(GifFileType *GifFile, GifPixelType *GifLine, int GifLineLen);
int EGifPutPixel(GifFileType *GifFile, GifPixelType GifPixel);
int EGifPutComment(GifFileType *GifFile, char *GifComment);
int EGifPutExtension(GifFileType *GifFile, int GifExtCode, int GifExtLen,
VoidPtr GifExtension);
int EGifPutCode(GifFileType *GifFile, int GifCodeSize,
GifByteType *GifCodeBlock);
int EGifPutCodeNext(GifFileType *GifFile, GifByteType *GifCodeBlock);
int EGifCloseFile(GifFileType *GifFile);
#define E_GIF_ERR_OPEN_FAILED 1 /* And EGif possible errors. */
#define E_GIF_ERR_WRITE_FAILED 2
#define E_GIF_ERR_HAS_SCRN_DSCR 3
#define E_GIF_ERR_HAS_IMAG_DSCR 4
#define E_GIF_ERR_NO_COLOR_MAP 5
#define E_GIF_ERR_DATA_TOO_BIG 6
#define E_GIF_ERR_NOT_ENOUGH_MEM 7
#define E_GIF_ERR_DISK_IS_FULL 8
#define E_GIF_ERR_CLOSE_FAILED 9
#define E_GIF_ERR_NOT_WRITEABLE 10
/******************************************************************************
* O.k. here are the routines one can access in order to decode GIF file: *
* (GIF_LIB file DGIF_LIB.C). *
******************************************************************************/
GifFileType *DGifOpenFileName(char *GifFileName);
GifFileType *DGifOpenFileHandle(int GifFileHandle);
int DGifGetScreenDesc(GifFileType *GifFile);
int DGifGetRecordType(GifFileType *GifFile, GifRecordType *GifType);
int DGifGetImageDesc(GifFileType *GifFile);
int DGifGetLine(GifFileType *GifFile, GifPixelType *GifLine, int GifLineLen);
int DGifGetPixel(GifFileType *GifFile, GifPixelType GifPixel);
int DGifGetComment(GifFileType *GifFile, char *GifComment);
int DGifGetExtension(GifFileType *GifFile, int *GifExtCode,
GifByteType **GifExtension);
int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **GifExtension);
int DGifGetCode(GifFileType *GifFile, int *GifCodeSize,
GifByteType **GifCodeBlock);
int DGifGetCodeNext(GifFileType *GifFile, GifByteType **GifCodeBlock);
int DGifGetLZCodes(GifFileType *GifFile, int *GifCode);
int DGifCloseFile(GifFileType *GifFile);
#define D_GIF_ERR_OPEN_FAILED 101 /* And DGif possible errors. */
#define D_GIF_ERR_READ_FAILED 102
#define D_GIF_ERR_NOT_GIF_FILE 103
#define D_GIF_ERR_NO_SCRN_DSCR 104
#define D_GIF_ERR_NO_IMAG_DSCR 105
#define D_GIF_ERR_NO_COLOR_MAP 106
#define D_GIF_ERR_WRONG_RECORD 107
#define D_GIF_ERR_DATA_TOO_BIG 108
#define D_GIF_ERR_NOT_ENOUGH_MEM 109
#define D_GIF_ERR_CLOSE_FAILED 110
#define D_GIF_ERR_NOT_READABLE 111
#define D_GIF_ERR_IMAGE_DEFECT 112
#define D_GIF_ERR_EOF_TOO_SOON 113
/******************************************************************************
* O.k. here are the routines from GIF_LIB file QUANTIZE.C. *
******************************************************************************/
int QuantizeBuffer(unsigned int Width, unsigned int Height, int *ColorMapSize,
GifByteType *RedInput, GifByteType *GreenInput, GifByteType *BlueInput,
GifByteType *OutputBuffer, GifColorType *OutputColorMap);
/******************************************************************************
* O.k. here are the routines from GIF_LIB file QPRINTF.C. *
******************************************************************************/
extern int GifQuitePrint;
#ifdef USE_VARARGS
void GifQprintf();
#else
void GifQprintf(char *Format, ...);
#endif /* USE_VARARGS */
/******************************************************************************
* O.k. here are the routines from GIF_LIB file GIF_ERR.C. *
******************************************************************************/
void PrintGifError(void);
int GifLastError(void);
/******************************************************************************
* O.k. here are the routines from GIF_LIB file DEV2GIF.C. *
******************************************************************************/
int DumpScreen2Gif(char *FileName, int ReqGraphDriver, int ReqGraphMode1,
int ReqGraphMode2,
int ReqGraphMode3);
#endif /* GIF_LIB_H */

BIN
G/LIB/GIF_LIBC.LIB Normal file

Binary file not shown.

39
G/LIB/GIF_LIBC.LST Normal file
View File

@ -0,0 +1,39 @@
Publics by module
DEV2GIF size = 1630
_DumpScreen2Gif
DGIF_LIB size = 4640
_DGifCloseFile _DGifGetCode
_DGifGetCodeNext _DGifGetExtension
_DGifGetExtensionNext _DGifGetImageDesc
_DGifGetLZCodes _DGifGetLine
_DGifGetPixel _DGifGetRecordType
_DGifGetScreenDesc _DGifOpenFileHandle
_DGifOpenFileName
EGIF_LIB size = 4246
_EGifCloseFile _EGifOpenFileHandle
_EGifOpenFileName _EGifPutCode
_EGifPutCodeNext _EGifPutComment
_EGifPutExtension _EGifPutImageDesc
_EGifPutLine _EGifPutPixel
_EGifPutScreenDesc _EGifSetGifVersion
GETARG size = 4707
_GAGetArgs _GAPrintErrMsg
_GAPrintHowTo
GIF_ERR size = 1235
_GifLastError _PrintGifError
__GifError
GIF_HASH size = 496
__ClearHashTable __ExistsHashTable
__InitHashTable __InsertHashTable
QPRINTF size = 70
_GifQprintf _GifQuitePrint
QUANTIZE size = 3217
_QuantizeBuffer

BIN
G/LIB/GIF_LIBH.LIB Normal file

Binary file not shown.

39
G/LIB/GIF_LIBH.LST Normal file
View File

@ -0,0 +1,39 @@
Publics by module
DEV2GIF size = 1713
_DumpScreen2Gif
DGIF_LIB size = 5155
_DGifCloseFile _DGifGetCode
_DGifGetCodeNext _DGifGetExtension
_DGifGetExtensionNext _DGifGetImageDesc
_DGifGetLZCodes _DGifGetLine
_DGifGetPixel _DGifGetRecordType
_DGifGetScreenDesc _DGifOpenFileHandle
_DGifOpenFileName
EGIF_LIB size = 4751
_EGifCloseFile _EGifOpenFileHandle
_EGifOpenFileName _EGifPutCode
_EGifPutCodeNext _EGifPutComment
_EGifPutExtension _EGifPutImageDesc
_EGifPutLine _EGifPutPixel
_EGifPutScreenDesc _EGifSetGifVersion
GETARG size = 5054
_GAGetArgs _GAPrintErrMsg
_GAPrintHowTo
GIF_ERR size = 1260
_GifLastError _PrintGifError
__GifError
GIF_HASH size = 551
__ClearHashTable __ExistsHashTable
__InitHashTable __InsertHashTable
QPRINTF size = 84
_GifQprintf _GifQuitePrint
QUANTIZE size = 3287
_QuantizeBuffer

BIN
G/LIB/GIF_LIBL.LIB Normal file

Binary file not shown.

39
G/LIB/GIF_LIBL.LST Normal file
View File

@ -0,0 +1,39 @@
Publics by module
DEV2GIF size = 1680
_DumpScreen2Gif
DGIF_LIB size = 4766
_DGifCloseFile _DGifGetCode
_DGifGetCodeNext _DGifGetExtension
_DGifGetExtensionNext _DGifGetImageDesc
_DGifGetLZCodes _DGifGetLine
_DGifGetPixel _DGifGetRecordType
_DGifGetScreenDesc _DGifOpenFileHandle
_DGifOpenFileName
EGIF_LIB size = 4388
_EGifCloseFile _EGifOpenFileHandle
_EGifOpenFileName _EGifPutCode
_EGifPutCodeNext _EGifPutComment
_EGifPutExtension _EGifPutImageDesc
_EGifPutLine _EGifPutPixel
_EGifPutScreenDesc _EGifSetGifVersion
GETARG size = 4879
_GAGetArgs _GAPrintErrMsg
_GAPrintHowTo
GIF_ERR size = 1239
_GifLastError _PrintGifError
__GifError
GIF_HASH size = 514
__ClearHashTable __ExistsHashTable
__InitHashTable __InsertHashTable
QPRINTF size = 74
_GifQprintf _GifQuitePrint
QUANTIZE size = 3253
_QuantizeBuffer

BIN
G/LIB/GIF_LIBM.LIB Normal file

Binary file not shown.

39
G/LIB/GIF_LIBM.LST Normal file
View File

@ -0,0 +1,39 @@
Publics by module
DEV2GIF size = 1576
_DumpScreen2Gif
DGIF_LIB size = 3718
_DGifCloseFile _DGifGetCode
_DGifGetCodeNext _DGifGetExtension
_DGifGetExtensionNext _DGifGetImageDesc
_DGifGetLZCodes _DGifGetLine
_DGifGetPixel _DGifGetRecordType
_DGifGetScreenDesc _DGifOpenFileHandle
_DGifOpenFileName
EGIF_LIB size = 3357
_EGifCloseFile _EGifOpenFileHandle
_EGifOpenFileName _EGifPutCode
_EGifPutCodeNext _EGifPutComment
_EGifPutExtension _EGifPutImageDesc
_EGifPutLine _EGifPutPixel
_EGifPutScreenDesc _EGifSetGifVersion
GETARG size = 3871
_GAGetArgs _GAPrintErrMsg
_GAPrintHowTo
GIF_ERR size = 1066
_GifLastError _PrintGifError
__GifError
GIF_HASH size = 456
__ClearHashTable __ExistsHashTable
__InitHashTable __InsertHashTable
QPRINTF size = 62
_GifQprintf _GifQuitePrint
QUANTIZE size = 2876
_QuantizeBuffer

BIN
G/LIB/GIF_LIBS.LIB Normal file

Binary file not shown.

39
G/LIB/GIF_LIBS.LST Normal file
View File

@ -0,0 +1,39 @@
Publics by module
DEV2GIF size = 1526
_DumpScreen2Gif
DGIF_LIB size = 3595
_DGifCloseFile _DGifGetCode
_DGifGetCodeNext _DGifGetExtension
_DGifGetExtensionNext _DGifGetImageDesc
_DGifGetLZCodes _DGifGetLine
_DGifGetPixel _DGifGetRecordType
_DGifGetScreenDesc _DGifOpenFileHandle
_DGifOpenFileName
EGIF_LIB size = 3214
_EGifCloseFile _EGifOpenFileHandle
_EGifOpenFileName _EGifPutCode
_EGifPutCodeNext _EGifPutComment
_EGifPutExtension _EGifPutImageDesc
_EGifPutLine _EGifPutPixel
_EGifPutScreenDesc _EGifSetGifVersion
GETARG size = 3701
_GAGetArgs _GAPrintErrMsg
_GAPrintHowTo
GIF_ERR size = 1062
_GifLastError _PrintGifError
__GifError
GIF_HASH size = 438
__ClearHashTable __ExistsHashTable
__InitHashTable __InsertHashTable
QPRINTF size = 58
_GifQprintf _GifQuitePrint
QUANTIZE size = 2840
_QuantizeBuffer

63
G/LIB/MAKEFILE.TC Normal file
View File

@ -0,0 +1,63 @@
#
# This is the make file for the lib subdirectory of the GIF library
# In order to run it tcc is assumed to be available, in addition to
# tlib and obviously borland make.
#
# Usage: "make [-DMDL=model]" where model can be l (large) or c (compact) etc.
# Note the MDL is optional with large model as default.
#
# Gershon Elber, Jun 1989
#
# Works only on TC++ 1.0 make and up - swap out make before invoking command.
.SWAP
# Your C compiler
CC = d:\program\borlandc\bin\bcc
# MDL set?
!if !$d(MDL)
MDL=l
!endif
# Where all the include files are:
INC = -I.
CFLAGS = -m$(MDL) -a- -f- -G -O -r -c -d -w -v- -y- -k- -N-
DEST = ..\bin
OBJS = dev2gif.obj egif_lib.obj dgif_lib.obj gif_hash.obj \
qprintf.obj gif_err.obj getarg.obj quantize.obj
# Show me better way if you know one to prepare this line for TLIB:
POBJS = +dev2gif.obj +egif_lib.obj +dgif_lib.obj +gif_hash.obj \
+qprintf.obj +gif_err.obj +getarg.obj +quantize.obj
# The {$< } is also new to TC++ 1.0 make - remove the { } pair if your make
# choke on them (the { } signals batch mode that combines few operation at the
# same time - very nice feature!).
.c.obj:
$(CC) $(INC) $(CFLAGS) {$< }
gif_libl.lib: $(OBJS)
del gif_lib$(MDL).lib
tlib gif_lib$(MDL).lib @&&!
$(POBJS), gif_lib$(MDL).lst
!
copy gif_lib$(MDL).lib $(DEST)
dev2gif.obj: gif_lib.h
egif_lib.obj: gif_lib.h gif_hash.h
dgif_lib.obj: gif_lib.h gif_hash.h
gif_hash.obj: gif_lib.h gif_hash.h
qprintf.obj: gif_lib.h
gif_err.obj: gif_lib.h
getarg.obj: getarg.h

72
G/LIB/MAKEFILE.UNX Normal file
View File

@ -0,0 +1,72 @@
#
# This is the make file for the lib subdirectory of the GIF library
# In order to run it gcc is assumed to be available.
#
# Gershon Elber, Jun 1989
#
#
# Where all the include files are:
INCS = -I.
#
# What devices we should be able to grab into gif images. Note that if
# you enable them the associated library must be available at link time.
# Avaiable devices:
# 1. EGA, VGA, SVGA (800x600), Hercules - all on IBM PC only.
# 2. SGI 4D Irix using gl library (Add -D__SGI_GL__).
# 3. X11 using libX.a (Add -D__X11__)
DEVS = -D__SGI_GL__
#
# These are the flags for gcc, in BSD4.3 or Sun O.S. 4.0.3
#
# If your system has all function prototypes for gcc, replace all
# the -Wxxx with -Wall. I can not add -Wimplicit as my system uses old cc
# h files.
#
# CC = gcc
#
# CFLAGS = -O -c -W -Wreturn-type -Wcomment
# CFLAGS = -g -pg -c -W -Wreturn-type -Wcomment
#
# for sun 4 (gunnars@ifi.uib.no). Tested using gcc 1.39.
#
# CFLAGS = -O -c -sun4 -W -Wreturn-type -Wcomment -DUSE_VARARGS
# CFLAGS = -g -c -sun4 -W -Wreturn-type -Wcomment -DUSE_VARARGS
#
# These are the flags for cc on SGI iris4d. O.S. IRIX 3.2
#
CC = cc
#
CFLAGS = -O -c -DSYSV -DNO_VOID_PTR -DUSE_VARARGS -Olimit 1000 -Wf,-XNh5000 -Wf,-XNd5000 -G 4
# CFLAGS = -g -p -c -DSYSV -DNO_VOID_PTR -DUSE_VARARGS -Olimit 1000 -Wf,-XNh5000 -Wf,-XNd5000 -G 4
#
# These are the flags for xlc, ansi compiler for IBM R6000
#
# CC = xlc
#
# CFLAGS = -O -c -qnoro -D_POSIX_SOURCE -D_ALL_SOURCE -DR6000
# CFLAGS = -g -pg -c -qnoro -D_POSIX_SOURCE -D_ALL_SOURCE -DR6000
OBJS = dev2gif.o egif_lib.o dgif_lib.o gif_hash.o gif_err.o \
quantize.o qprintf.o getarg.o
.c.o:
$(CC) $(INCS) $(DEVS) $(CFLAGS) $<
libgif.a: $(OBJS)
rm -f libgif.a
ar rcv libgif.a *.o
-ranlib libgif.a
dev2gif.o: gif_lib.h
egif_lib.o: gif_lib.h gif_hash.h
dgif_lib.o: gif_lib.h gif_hash.h
gif_hash.o: gif_lib.h gif_hash.h
gif_err.o: gif_lib.h
quantize.o: gif_lib.h
qprintf.o: gif_lib.h
getarg.o: getarg.h

55
G/LIB/QPRINTF.C Normal file
View File

@ -0,0 +1,55 @@
/*****************************************************************************
* "Gif-Lib" - Yet another gif library. *
* *
* Written by: Gershon Elber IBM PC Ver 0.1, Jun. 1989 *
******************************************************************************
* Module to emulate a printf with a possible quite (disable mode.) *
* A global variable GifQuitePrint controls the printing of this routine *
******************************************************************************
* History: *
* 12 May 91 - Version 1.0 by Gershon Elber. *
*****************************************************************************/
#include <stdio.h>
#ifdef USE_VARARGS
#include <varargs.h>
#else
#include <stdarg.h>
#endif /* USE_VARARGS */
#include "gif_lib.h"
#ifdef __MSDOS__
int GifQuitePrint = FALSE;
#else
int GifQuitePrint = TRUE;
#endif /* __MSDOS__ */
/*****************************************************************************
* Same as fprintf to stderr but with optional print. *
*****************************************************************************/
#ifdef USE_VARARGS
void GifQprintf(int va_alist)
{
char *Format, Line[128];
va_list ArgPtr;
va_start(ArgPtr);
Format = va_arg(ArgPtr, char *);
#else
void GifQprintf(char *Format, ...)
{
char Line[128];
va_list ArgPtr;
va_start(ArgPtr, Format);
#endif /* USE_VARARGS */
if (GifQuitePrint) return;
vsprintf(Line, Format, ArgPtr);
va_end(ArgPtr);
fputs(Line, stderr);
}

335
G/LIB/QUANTIZE.C Normal file
View File

@ -0,0 +1,335 @@
/*****************************************************************************
* "Gif-Lib" - Yet another gif library. *
* *
* Written by: Gershon Elber IBM PC Ver 0.1, Jun. 1989 *
******************************************************************************
* Module to quatize high resolution image into lower one. You may want to *
* peek into the following article this code is based on: *
* "Color Image Quantization for frame buffer Display", by Paul Heckbert *
* SIGGRAPH 1982 page 297-307. *
******************************************************************************
* History: *
* 5 Jan 90 - Version 1.0 by Gershon Elber. *
*****************************************************************************/
#ifdef __MSDOS__
#include <dos.h>
#include <alloc.h>
#include <stdlib.h>
#include <graphics.h>
#endif /* __MSDOS__ */
#include <stdio.h>
#include "gif_lib.h"
#define PROGRAM_NAME "GIF_LIBRARY"
#define ABS(x) ((x) > 0 ? (x) : (-(x)))
/* The colors are stripped to 5 bits per primary color if non MSDOS system */
/* or to 4 (not enough memory...) if MSDOS as first step. */
#ifdef __MSDOS__
#define COLOR_ARRAY_SIZE 4096
#define BITS_PER_PRIM_COLOR 4
#define MAX_PRIM_COLOR 0x0f
#else
#define COLOR_ARRAY_SIZE 32768
#define BITS_PER_PRIM_COLOR 5
#define MAX_PRIM_COLOR 0x1f
#endif /* __MSDOS__ */
extern int _GifError;
#ifdef SYSV
static char *VersionStr =
"Gif library module,\t\tGershon Elber\n\
(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
#else
static char *VersionStr =
PROGRAM_NAME
" IBMPC "
GIF_LIB_VERSION
" Gershon Elber, "
__DATE__ ", " __TIME__ "\n"
"(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
#endif /* SYSV */
static int SortRGBAxis;
typedef struct QuantizedColorType {
GifByteType RGB[3];
GifByteType NewColorIndex;
long Count;
struct QuantizedColorType *Pnext;
} QuantizedColorType;
typedef struct NewColorMapType {
GifByteType RGBMin[3], RGBWidth[3];
unsigned int NumEntries;/* # of QuantizedColorType in linked list below. */
long Count; /* Total number of pixels in all the entries. */
QuantizedColorType *QuantizedColors;
} NewColorMapType;
static int SubdivColorMap(NewColorMapType *NewColorSubdiv,
unsigned int ColorMapSize,
unsigned int *NewColorMapSize);
#ifdef __MSDOS__
static int SortCmpRtn(const VoidPtr Entry1, const VoidPtr Entry2);
#else
static int SortCmpRtn(VoidPtr Entry1, VoidPtr Entry2);
#endif /* __MSDOS__ */
/******************************************************************************
* Quantize high resolution image into lower one. Input image consists of a *
* 2D array for each of the RGB colors with size Width by Height. There is no *
* Color map for the input. Output is a quantized image with 2D array of *
* indexes into the output color map. *
* Note input image can be 24 bits at the most (8 for red/green/blue) and *
* the output has 256 colors at the most (256 entries in the color map.). *
* ColorMapSize specifies size of color map up to 256 and will be updated to *
* real size before returning. *
* Also non of the parameter are allocated by this routine. *
* This function returns GIF_OK if succesfull, GIF_ERROR otherwise. *
******************************************************************************/
int QuantizeBuffer(unsigned int Width, unsigned int Height, int *ColorMapSize,
GifByteType *RedInput, GifByteType *GreenInput, GifByteType *BlueInput,
GifByteType *OutputBuffer, GifColorType *OutputColorMap)
{
unsigned int i, j, Index, NewColorMapSize, NumOfEntries, MaxRGBError[3];
long Red, Green, Blue;
NewColorMapType NewColorSubdiv[256];
QuantizedColorType *ColorArrayEntries, *QuantizedColor;
if ((ColorArrayEntries = (QuantizedColorType *)
malloc(sizeof(QuantizedColorType) * COLOR_ARRAY_SIZE)) == NULL) {
_GifError = E_GIF_ERR_NOT_ENOUGH_MEM;
return GIF_ERROR;
}
for (i = 0; i < COLOR_ARRAY_SIZE; i++) {
ColorArrayEntries[i].RGB[0]= i >> (2 * BITS_PER_PRIM_COLOR);
ColorArrayEntries[i].RGB[1] = (i >> BITS_PER_PRIM_COLOR) &
MAX_PRIM_COLOR;
ColorArrayEntries[i].RGB[2] = i & MAX_PRIM_COLOR;
ColorArrayEntries[i].Count = 0;
}
/* Sample the colors and their distribution: */
for (i = 0; i < Width * Height; i++) {
Index = ((RedInput[i] >> (8 - BITS_PER_PRIM_COLOR))
<< (2 * BITS_PER_PRIM_COLOR)) +
((GreenInput[i] >> (8 - BITS_PER_PRIM_COLOR))
<< BITS_PER_PRIM_COLOR) +
(BlueInput[i] >> (8 - BITS_PER_PRIM_COLOR));
ColorArrayEntries[Index].Count++;
}
/* Put all the colors in the first entry of the color map, and call the */
/* recursive subdivision process. */
for (i = 0; i < 256; i++) {
NewColorSubdiv[i].QuantizedColors = NULL;
NewColorSubdiv[i].Count = NewColorSubdiv[i].NumEntries = 0;
for (j = 0; j < 3; j++) {
NewColorSubdiv[i].RGBMin[j] = 0;
NewColorSubdiv[i].RGBWidth[j] = 255;
}
}
/* Find the non empty entries in the color table and chain them: */
for (i = 0; i < COLOR_ARRAY_SIZE; i++)
if (ColorArrayEntries[i].Count > 0) break;
QuantizedColor = NewColorSubdiv[0].QuantizedColors = &ColorArrayEntries[i];
NumOfEntries = 1;
while (++i < COLOR_ARRAY_SIZE)
if (ColorArrayEntries[i].Count > 0) {
QuantizedColor -> Pnext = &ColorArrayEntries[i];
QuantizedColor = &ColorArrayEntries[i];
NumOfEntries++;
}
QuantizedColor -> Pnext = NULL;
NewColorSubdiv[0].NumEntries = NumOfEntries;/* Different sampled colors. */
NewColorSubdiv[0].Count = ((long) Width) * Height; /* Pixels. */
NewColorMapSize = 1;
if (SubdivColorMap(NewColorSubdiv, *ColorMapSize, &NewColorMapSize) !=
GIF_OK) {
free((char *) ColorArrayEntries);
return GIF_ERROR;
}
if (NewColorMapSize < *ColorMapSize) {
/* And clear rest of color map: */
for (i = NewColorMapSize; i < *ColorMapSize; i++)
OutputColorMap[i].Red =
OutputColorMap[i].Green =
OutputColorMap[i].Blue = 0;
}
/* Average the colors in each entry to be the color to be used in the */
/* output color map, and plug it into the output color map itself. */
for (i = 0; i < NewColorMapSize; i++) {
if ((j = NewColorSubdiv[i].NumEntries) > 0) {
QuantizedColor = NewColorSubdiv[i].QuantizedColors;
Red = Green = Blue = 0;
while (QuantizedColor) {
QuantizedColor -> NewColorIndex = i;
Red += QuantizedColor -> RGB[0];
Green += QuantizedColor -> RGB[1];
Blue += QuantizedColor -> RGB[2];
QuantizedColor = QuantizedColor -> Pnext;
}
OutputColorMap[i].Red = (Red << (8 - BITS_PER_PRIM_COLOR)) / j;
OutputColorMap[i].Green = (Green << (8 - BITS_PER_PRIM_COLOR)) / j;
OutputColorMap[i].Blue= (Blue << (8 - BITS_PER_PRIM_COLOR)) / j;
}
else
GIF_MESSAGE("Null entry in quantized color map - thats weird.");
}
/* Finally scan the input buffer again and put the mapped index in the */
/* output buffer. */
MaxRGBError[0] = MaxRGBError[1] = MaxRGBError[2] = 0;
for (i = 0; i < Width * Height; i++) {
Index = ((RedInput[i] >> (8 - BITS_PER_PRIM_COLOR))
<< (2 * BITS_PER_PRIM_COLOR)) +
((GreenInput[i] >> (8 - BITS_PER_PRIM_COLOR))
<< BITS_PER_PRIM_COLOR) +
(BlueInput[i] >> (8 - BITS_PER_PRIM_COLOR));
Index = ColorArrayEntries[Index].NewColorIndex;
OutputBuffer[i] = Index;
if (MaxRGBError[0] < ABS(OutputColorMap[Index].Red - RedInput[i]))
MaxRGBError[0] = ABS(OutputColorMap[Index].Red - RedInput[i]);
if (MaxRGBError[1] < ABS(OutputColorMap[Index].Green - GreenInput[i]))
MaxRGBError[1] = ABS(OutputColorMap[Index].Green - GreenInput[i]);
if (MaxRGBError[2] < ABS(OutputColorMap[Index].Blue - BlueInput[i]))
MaxRGBError[2] = ABS(OutputColorMap[Index].Blue - BlueInput[i]);
}
#ifdef DEBUG
fprintf(stderr,
"Quantization L(0) errors: Red = %d, Green = %d, Blue = %d.\n",
MaxRGBError[0], MaxRGBError[1], MaxRGBError[2]);
#endif /* DEBUG */
free((char *) ColorArrayEntries);
*ColorMapSize = NewColorMapSize;
return GIF_OK;
}
/******************************************************************************
* Routine to subdivide the RGB space recursively using median cut in each *
* axes alternatingly until ColorMapSize different cubes exists. *
* The biggest cube in one dimension is subdivide unless it has only one entry.*
* Returns GIF_ERROR if failed, otherwise GIF_OK. *
******************************************************************************/
static int SubdivColorMap(NewColorMapType *NewColorSubdiv,
unsigned int ColorMapSize,
unsigned int *NewColorMapSize)
{
int MaxSize;
unsigned int i, j, Index = 0, NumEntries, MinColor, MaxColor;
long Sum, Count;
QuantizedColorType *QuantizedColor, **SortArray;
while (ColorMapSize > *NewColorMapSize) {
/* Find candidate for subdivision: */
MaxSize = -1;
for (i = 0; i < *NewColorMapSize; i++) {
for (j = 0; j < 3; j++) {
if (((int) NewColorSubdiv[i].RGBWidth[j]) > MaxSize &&
NewColorSubdiv[i].NumEntries > 1) {
MaxSize = NewColorSubdiv[i].RGBWidth[j];
Index = i;
SortRGBAxis = j;
}
}
}
if (MaxSize == -1)
return GIF_OK;
/* Split the entry Index into two along the axis SortRGBAxis: */
/* Sort all elements in that entry along the given axis and split at */
/* the median. */
if ((SortArray = (QuantizedColorType **)
malloc(sizeof(QuantizedColorType *) *
NewColorSubdiv[Index].NumEntries)) == NULL)
return GIF_ERROR;
for (j = 0, QuantizedColor = NewColorSubdiv[Index].QuantizedColors;
j < NewColorSubdiv[Index].NumEntries && QuantizedColor != NULL;
j++, QuantizedColor = QuantizedColor -> Pnext)
SortArray[j] = QuantizedColor;
qsort(SortArray, NewColorSubdiv[Index].NumEntries,
sizeof(QuantizedColorType *), SortCmpRtn);
/* Relink the sorted list into one: */
for (j = 0; j < NewColorSubdiv[Index].NumEntries - 1; j++)
SortArray[j] -> Pnext = SortArray[j + 1];
SortArray[NewColorSubdiv[Index].NumEntries - 1] -> Pnext = NULL;
NewColorSubdiv[Index].QuantizedColors = QuantizedColor = SortArray[0];
free((char *) SortArray);
/* Now simply add the Counts until we have half of the Count: */
Sum = NewColorSubdiv[Index].Count / 2 - QuantizedColor -> Count;
NumEntries = 1;
Count = QuantizedColor -> Count;
while ((Sum -= QuantizedColor -> Pnext -> Count) >= 0 &&
QuantizedColor -> Pnext != NULL &&
QuantizedColor -> Pnext -> Pnext != NULL) {
QuantizedColor = QuantizedColor -> Pnext;
NumEntries++;
Count += QuantizedColor -> Count;
}
/* Save the values of the last color of the first half, and first */
/* of the second half so we can update the Bounding Boxes later. */
/* Also as the colors are quantized and the BBoxes are full 0..255, */
/* they need to be rescaled. */
MaxColor = QuantizedColor -> RGB[SortRGBAxis];/* Max. of first half. */
MinColor = QuantizedColor -> Pnext -> RGB[SortRGBAxis];/* of second. */
MaxColor <<= (8 - BITS_PER_PRIM_COLOR);
MinColor <<= (8 - BITS_PER_PRIM_COLOR);
/* Partition right here: */
NewColorSubdiv[*NewColorMapSize].QuantizedColors =
QuantizedColor -> Pnext;
QuantizedColor -> Pnext = NULL;
NewColorSubdiv[*NewColorMapSize].Count = Count;
NewColorSubdiv[Index].Count -= Count;
NewColorSubdiv[*NewColorMapSize].NumEntries =
NewColorSubdiv[Index].NumEntries - NumEntries;
NewColorSubdiv[Index].NumEntries = NumEntries;
for (j = 0; j < 3; j++) {
NewColorSubdiv[*NewColorMapSize].RGBMin[j] =
NewColorSubdiv[Index].RGBMin[j];
NewColorSubdiv[*NewColorMapSize].RGBWidth[j] =
NewColorSubdiv[Index].RGBWidth[j];
}
NewColorSubdiv[*NewColorMapSize].RGBWidth[SortRGBAxis] =
NewColorSubdiv[*NewColorMapSize].RGBMin[SortRGBAxis] +
NewColorSubdiv[*NewColorMapSize].RGBWidth[SortRGBAxis] -
MinColor;
NewColorSubdiv[*NewColorMapSize].RGBMin[SortRGBAxis] = MinColor;
NewColorSubdiv[Index].RGBWidth[SortRGBAxis] =
MaxColor - NewColorSubdiv[Index].RGBMin[SortRGBAxis];
(*NewColorMapSize)++;
}
return GIF_OK;
}
/******************************************************************************
* Routine called by qsort to compare to entries. *
******************************************************************************/
#ifdef __MSDOS__
static int SortCmpRtn(const VoidPtr Entry1, const VoidPtr Entry2)
#else
static int SortCmpRtn(VoidPtr Entry1, VoidPtr Entry2)
#endif /* __MSDOS__ */
{
return (* ((QuantizedColorType **) Entry1)) -> RGB[SortRGBAxis] -
(* ((QuantizedColorType **) Entry2)) -> RGB[SortRGBAxis];
}