First commit ~0,10
This commit is contained in:
477
G/DOC/GIF_LIB.DOC
Normal file
477
G/DOC/GIF_LIB.DOC
Normal file
@ -0,0 +1,477 @@
|
||||
GIF library document
|
||||
--------------------
|
||||
|
||||
Gershon Elber, May 1991
|
||||
-----------------------
|
||||
|
||||
Version 1.2
|
||||
-----------
|
||||
|
||||
The Graphics Interchange Format(c) is the Copyright property of
|
||||
CompuServe Incorporated. GIF(sm) is a Service Mark property of CompuServe
|
||||
Incorporated.
|
||||
|
||||
This library was written once I didnt find anything similar and I
|
||||
wanted one. I was inspired from the rle Utah tool kit, which I hoped to port
|
||||
to an IBM PC, but found it to be too machine specific, and its compression
|
||||
ratio too low. I compromised on the GIF format while I am not sure how long
|
||||
8 bits per pixel will be enough.
|
||||
|
||||
|
||||
This document explains the GIF library kernel on directory GIF/LIB.
|
||||
The kernel is built to the gif_libl.lib which is used in all the utilities
|
||||
on GIF/UTIL, or can be used in any application needs to read/write GIF file
|
||||
format. This document does NOT explain the GIF file format and assumes it
|
||||
is known, at list to the level of the GIF file structure.
|
||||
|
||||
When a GIF file is opened, a GIF file descriptor is maintained which
|
||||
is a pointer to GifFileType structure as follows:
|
||||
|
||||
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 */
|
||||
void *Private; /* The regular user should not mess with this one! */
|
||||
} GifFileType;
|
||||
|
||||
This structure was copied from gif_lib.h - the header file for the GIF
|
||||
library. Any application program that uses the gif_libl.lib library should
|
||||
include it. All items begin with S refer to GIF Screen, while the ones with I
|
||||
to current image (note GIF file may have more than one image). The user NEVER
|
||||
writes into this structure, but can read any of these items at any time it is
|
||||
proper (image information is invalid until first image was read/write).
|
||||
As the library needs to save its own internal data also, a Private
|
||||
pointer to internal structure is also saved there. Applications should ignore
|
||||
this item.
|
||||
The library has no static data. This means that it is fully reentrant
|
||||
and any number of GIF files (up to memory limits) can be opened for
|
||||
read/write. Instead of the static data, internal structure pointed by the
|
||||
Private pointer is used.
|
||||
The library do allocates its own memory dynamically, on opening of
|
||||
file, and releases that once closed. The user is NEVER requires to allocate
|
||||
any memory for any of the functions of this library (unless the provided
|
||||
parameters, such as image line, were prefered to be allocated dynammically by
|
||||
the user) nor to free them directly. In order to reduce disk access, the file
|
||||
buffer is increased to FILE_BUFFER_SIZE (defined in gif_lib.h). The library
|
||||
was compiled in large model as the memory allocated per file is quite big:
|
||||
about 17k for decoding (DGIF_LIB.C), and 32k for encoding (EGIF_LIB.C),
|
||||
excluding the FILE_BUFFER_SIZE.
|
||||
|
||||
We now can see what the library contains (directory GIF/LIB):
|
||||
|
||||
1. EGIF_LIB.C - Encoding routines, all prefixed with E.
|
||||
2. DGIF_LIB.C - Decoding routines, all prefixed with D.
|
||||
3. DEV2GIF.C - Routines to convert specific device buffers into GIF files.
|
||||
4. GIF_ERR.C - Error handler for the library.
|
||||
The library has fifth hashing table file in which is accessed internally
|
||||
only.
|
||||
Major part of the routines returns ERROR (see gif_lib.h) if something went
|
||||
wrong or OK otherwise. Once ERROR received, GIF_ERR.C module can be used to
|
||||
do something about it.
|
||||
|
||||
In addition a module to scan the command line arguments was added.
|
||||
This module is called GETARG.C and its headers are in GETARG.H. see header
|
||||
of GETARG.C for details on its usage.
|
||||
|
||||
|
||||
ENCODING (EGIF_LIB.C)
|
||||
---------------------
|
||||
|
||||
GifFileType *EGifOpenFileName(char *GifFileName, int GifTestExistance);
|
||||
|
||||
Open a new GIF file using the given GifFileName. If GifTestExistance
|
||||
is TRUE, and file exists, the file is not destroyed, and NULL returned.
|
||||
If any error occurs, NULL is returned and Error handler can be used
|
||||
to get the exact error (see GIF_ERR.C).
|
||||
The file is opened in binary mode, and its buffer size is set to
|
||||
FILE_BUFFER_SIZE bytes.
|
||||
|
||||
|
||||
GifFileType *EGifOpenFileHandle(int GifFileHandle);
|
||||
|
||||
Open a new GIF file using the given GifFileHandle
|
||||
If any error occurs, NULL is returned and Error handler can be used
|
||||
to get the exact error (see GIF_ERR.C)
|
||||
The file is opened in binary mode, and its buffer size is set to
|
||||
FILE_BUFFER_SIZE bytes.
|
||||
|
||||
|
||||
void EGifSetGifVersion(char *Version);
|
||||
|
||||
Sets the GIF version of all files to be open from this point (until
|
||||
another call to this routine is made. Version is a 3 characters
|
||||
string of the form "87a" or "89a". No test is made to validate this
|
||||
string.
|
||||
|
||||
|
||||
int EGifPutScreenDesc(GifFileType *GifFile,
|
||||
int GifWidth, int GifHeight, int GifColorRes, int GifBackGround,
|
||||
int GifBitsPerPixel, GifColorType *GifColorMap);
|
||||
|
||||
Update GifFile Screen parameters, in GifFile structure and in real
|
||||
file. if error occurs returns ERROR (see gif_lib.h), otherwise OK.
|
||||
This routine should be called immediately after the GIF file was
|
||||
opened.
|
||||
|
||||
|
||||
int EGifPutImageDesc(GifFileType *GifFile,
|
||||
int GifLeft, int GifTop, int Width, int GifHeight, int GifInterlace,
|
||||
int GifBitsPerPixel, GifColorType *GifColorMap);
|
||||
|
||||
Update GifFile Image parameters, in GifFile structure and in real
|
||||
file. if error occurs returns ERROR (see gif_lib.h), otherwise OK.
|
||||
This routine should be called each time a new image should be
|
||||
dumped to the file.
|
||||
|
||||
|
||||
int EGifPutLine(GifFileType *GifFile, PixelType *GifLine, int GifLineLen);
|
||||
|
||||
Dumps block of pixels out to the GIF file. The line length can be
|
||||
of any length. More than that, this routine may be interleaved with
|
||||
EGifPutPixel, until all pixels were sent.
|
||||
Returns ERROR if something went wrong, OK otherwise.
|
||||
|
||||
|
||||
int EGifPutPixel(GifFileType *GifFile, PixelType GifPixel);
|
||||
|
||||
Dumps one pixel to the GIF file. This routine may be interleaved
|
||||
with EGifPutLine, until all pixels were sent. Because of the overhead
|
||||
per each call, the usage of this routine is not recommended.
|
||||
Returns ERROR if something went wrong, OK otherwise.
|
||||
|
||||
|
||||
int EGifPutComment(GifFileType *GifFile, char *GifComment);
|
||||
|
||||
Uses extension GIF records to save a string as a comment is the file.
|
||||
The extension code is 'C' (for Comment). This is optional in GIF file.
|
||||
Returns ERROR if something went wrong, OK otherwise.
|
||||
|
||||
|
||||
int EGifPutExtension(GifFileType *GifFile, int GifExtCode, int GifExtLen,
|
||||
void *GifExtension);
|
||||
|
||||
Dumps the given extension block into the GIF file. Extension blocks
|
||||
are optional in GIF file. Extension blocks of more than 255 bytes or
|
||||
more than one block are not supported.
|
||||
Returns ERROR if something went wrong, OK otherwise.
|
||||
|
||||
|
||||
int EGifPutCode(GifFileType *GifFile, int *GifCodeSize,
|
||||
ByteType **GifCodeBlock);
|
||||
|
||||
It sometimes may be desired to write the compressed code as is
|
||||
without decoding it. For example a filter for GIF file that change
|
||||
only screen size (GifPos), does not need the exact pixel values and
|
||||
pipes out the compressed image as is, make this process much faster.
|
||||
This routine do exactly that (with EGifPutCodeNext), and can be
|
||||
used instead of EGifPutLine. This usually works with the
|
||||
DGifGetCode/DgifGetCodeNext routines, which reads the compressed
|
||||
code, while EGifPutCode/EGifPutCodeNext write it out. See GifPos.c
|
||||
for example.
|
||||
Returns ERROR if something went wrong, OK otherwise.
|
||||
|
||||
|
||||
int EGifPutCodeNext(GifFileType *GifFile, ByteType **GifCodeBlock);
|
||||
|
||||
See EGifPutCode above.
|
||||
|
||||
|
||||
int EGifCloseFile(GifFileType *GifFile);
|
||||
|
||||
Close GIF file and free all memory allocated for it. GifFile should
|
||||
not be used, once this routine was called.
|
||||
Returns ERROR if something went wrong, OK otherwise.
|
||||
|
||||
|
||||
DECODING (DGIF_LIB.C)
|
||||
---------------------
|
||||
|
||||
GifFileType *DGifOpenFileName(char *GifFileName);
|
||||
|
||||
Open a new GIF file using the given GifFileName, and read its Screen
|
||||
information.
|
||||
If any error occurs, NULL is returned and Error handler can be used
|
||||
to get the exact error (see GIF_ERR.C).
|
||||
The file is opened in binary mode, and its buffer size is set to
|
||||
FILE_BUFFER_SIZE bytes.
|
||||
|
||||
|
||||
GifFileType *DGifOpenFileHandle(int GifFileHandle);
|
||||
|
||||
Open a new GIF file using the given GifFileHandle, and read its
|
||||
Screen information.
|
||||
If any error occurs, NULL is returned and Error handler can be used
|
||||
to get the exact error (see GIF_ERR.C)
|
||||
The file is opened in binary mode, and its buffer size is set to
|
||||
FILE_BUFFER_SIZE bytes.
|
||||
|
||||
|
||||
int DGifGetScreenDesc(GifFileType *GifFile);
|
||||
|
||||
Reads the screen information into the GifFile structure. Note this
|
||||
routine is automatically called once a file is opened, and therefore
|
||||
usually not needed.
|
||||
Returns ERROR if something went wrong, OK otherwise.
|
||||
|
||||
|
||||
int DGifGetRecordType(GifFileType *GifFile, GifRecordType *GifType);
|
||||
|
||||
As the GIF file can have different records in arbitrary order, this
|
||||
routine should be called once the file was open to detect the next
|
||||
record type, and act upon it. Few types might be returned in GifType:
|
||||
1. UndefinedRecordType - something is wrong!
|
||||
2. ScreenDescRecordType - screen information. As the screen information
|
||||
is automatically read in when the file is open, this usually would
|
||||
not happen.
|
||||
3. ImageDescRecordType - next record is Image.
|
||||
4. ExtensionRecordType - next record is extension block.
|
||||
5. TerminateRecordType - last record reached, can close the file.
|
||||
The first Two types can usually be ignored.
|
||||
Returns ERROR if something went wrong, OK otherwise.
|
||||
|
||||
|
||||
int DGifGetImageDesc(GifFileType *GifFile);
|
||||
|
||||
Reads the image information into the GifFile structure.
|
||||
Returns ERROR if something went wrong, OK otherwise.
|
||||
|
||||
|
||||
int DGifGetLine(GifFileType *GifFile, PixelType *GifLine, int GifLineLen);
|
||||
|
||||
Load block of pixels from the GIF file. The line length can be
|
||||
of any length. More than that, this routine may be interleaved with
|
||||
DGifGetPixel, until all pixels were read.
|
||||
Returns ERROR if something went wrong, OK otherwise.
|
||||
|
||||
int DGifGetPixel(GifFileType *GifFile, PixelType GifPixel);
|
||||
|
||||
Loads one pixel from the GIF file. This routine may be interleaved
|
||||
with DGifGetLine, until all pixels were read. Because of the overhead
|
||||
per each call, the usage of this routine is not recommended.
|
||||
Returns ERROR if something went wrong, OK otherwise.
|
||||
|
||||
int DGifGetComment(GifFileType *GifFile, char *GifComment);
|
||||
|
||||
Load comment from the GIF file. Because DGifGetRecordType will
|
||||
only tell this records is of type extension, this routine should be
|
||||
called iff it is known %100 that is must be a comment.
|
||||
For definition of comment, see EGifPutComment.
|
||||
Returns ERROR if something went wrong, OK otherwise.
|
||||
|
||||
|
||||
int DGifGetExtension(GifFileType *GifFile, int *GifExtCode,
|
||||
ByteType **GifExtension);
|
||||
|
||||
Loads the given extension block from the GIF file. Extension blocks
|
||||
are optional in GIF file. This routine should be follows by
|
||||
DGifGetExtensionNext - see below
|
||||
Returns ERROR if something went wrong, OK otherwise.
|
||||
|
||||
|
||||
int DGifGetExtensionNext(GifFileType *GifFile, ByteType **GifExtension);
|
||||
|
||||
As extensions may contain more than one block, use this routine to
|
||||
continue after DGifGetExtension, until *GifExtension is NULL.
|
||||
Returns ERROR if something went wrong, OK otherwise.
|
||||
|
||||
|
||||
int DGifGetCode(GifFileType *GifFile, int *GifCodeSize,
|
||||
ByteType **GifCodeBlock);
|
||||
|
||||
It sometimes may be desired to read the compressed code as is
|
||||
without decoding it. This routine do exactly that (with
|
||||
DGifGetCodeNext), and can be used instead of DGifGetLine.
|
||||
This compressed code information can be written out using the
|
||||
EGifPutCode/EGifPutCodeNext sequence (see GifPos.c for example).
|
||||
Returns ERROR if something went wrong, OK otherwise.
|
||||
|
||||
|
||||
int DGifGetCodeNext(GifFileType *GifFile, ByteType **GifCodeBlock);
|
||||
|
||||
See DGifGetCode above.
|
||||
|
||||
|
||||
int DGifGetLZCodes(GifFileType *GifFile, int *GifCode);
|
||||
|
||||
This routine can be called instead of DGifGetLine/DGifGetPixel or
|
||||
DGifGetCode/DGifGetCodeNext to get the 12 bits LZ codes of the images.
|
||||
It may be used mainly for debugging purposes (see GifText.c for
|
||||
example).
|
||||
Returns ERROR if something went wrong, OK otherwise.
|
||||
|
||||
|
||||
int DGifCloseFile(GifFileType *GifFile);
|
||||
|
||||
Close GIF file and free all memory allocated for it. GifFile should
|
||||
not be used, once this routine was called.
|
||||
Returns ERROR if something went wrong, OK otherwise.
|
||||
|
||||
|
||||
|
||||
ERROR HANDLING (EGIF_LIB.C)
|
||||
---------------------------
|
||||
|
||||
void PrintGifError(void)
|
||||
|
||||
Print one line diagnostic on the last gif_lib error to stderr.
|
||||
|
||||
|
||||
int GifLastError(void)
|
||||
|
||||
Return last gif_lib error, and clear the error.
|
||||
Note it is the user responsibility to call the file closing routine,
|
||||
so the file will be closed (if was opened), and memory will be released
|
||||
(if was allocated).
|
||||
The different error types are defined in gif_lib.h.
|
||||
|
||||
|
||||
DEVICE SPECIFIC (XXX2GIF.C)
|
||||
---------------------------
|
||||
|
||||
int DumpScreen2Gif(char *FileName, int ReqGraphDriver, int ReqGraphMode1,
|
||||
int ReqGraphMode2);
|
||||
|
||||
Dumps the whole device buffer as specified by GraphDriver and
|
||||
GraphMode (as defined in TC 2.0 graphics.h) into FileName as GIF file.
|
||||
Current devices supported:
|
||||
1. Hercules.
|
||||
2. EGA, EGA64, EGAMONO (all modes - see TC graphics.h).
|
||||
3. VGA (all modes - see TC graphics.h).
|
||||
4. SVGA_SPECIAL. This mode is special and not supported by Borland
|
||||
graphics.h. ReqGraphDriver must be equal to 999, and ReqGraphMode
|
||||
is ignored. This modes assumes 800 by 600 in 16 colors.
|
||||
Returns ERROR if something went wrong, OK otherwise.
|
||||
5. SGI 4D using gl graphic library - window dump.
|
||||
6. X11 window dump.
|
||||
|
||||
|
||||
COMMAND LINE PARSING (GETARG.C)
|
||||
-------------------------------
|
||||
|
||||
int GAGetArgs(int argc, char **argv, char *CtrlStr, ...);
|
||||
|
||||
Main routine of this module. Given the argc & argv as received by
|
||||
the main procedure, the command line CtrlStr, and the addresses of
|
||||
all parameters, parse the command line, and update the parameters.
|
||||
The CtrlStr defines what types of variables should follow. Look
|
||||
at the beginning of getarg.c for exact usage.
|
||||
Returns 0 if successful, error number (as defined by getarg.h)
|
||||
otherwise.
|
||||
|
||||
|
||||
void GAPrintErrMsg(int Error);
|
||||
|
||||
If error occurred in GAGetARgs, this routine may be used to print
|
||||
one line diagnostic to stderr.
|
||||
|
||||
|
||||
void GAPrintHowTo(char *CtrlStr);
|
||||
|
||||
Given same CtrlStr as for GAGetArgs, can be used to print a
|
||||
one line 'how to use'
|
||||
|
||||
|
||||
Skeleton of GIF filter
|
||||
----------------------
|
||||
|
||||
This completes the functions, application can access. An application
|
||||
skeleton usually will look like (assuming it is a filter - read GIF file,
|
||||
modifies it, and write new GIF file) the following example, which only copy
|
||||
a GIF file from stdin to stdout. Please give a pick to the utilities on the
|
||||
util directory to get more idea once you fill comfortable with this skeleton.
|
||||
Also try to follow the coding standards of this package if you want me to
|
||||
officially add your new utility to it.
|
||||
|
||||
#include "getarg.h"
|
||||
|
||||
main(... )
|
||||
{
|
||||
GifFile *GifFileIn, *GifFileOut;
|
||||
|
||||
GAGetArgs( argc, argv, CtrlStr, ... ); /* Process command line */
|
||||
|
||||
/* Use the stdin as input (note this also read screen descriptor in: */
|
||||
if ((GifFileIn = DGifOpenFileHandle(0)) == NULL)
|
||||
QuitGifError(GifFileIn, GifFileOut);
|
||||
|
||||
/* Use the stdout as output: */
|
||||
if ((GifFileOut = EGifOpenFileHandle(1)) == NULL)
|
||||
QuitGifError(GifFileIn, GifFileOut);
|
||||
/* And dump out its screen information: */
|
||||
if (EGifPutScreenDesc(GifFileOut,
|
||||
GifFileIn -> SWidth, GifFileIn -> SHeight,
|
||||
GifFileIn -> SColorResolution, GifFileIn -> SBackGroundColor,
|
||||
GifFileIn -> SBitsPerPixel, GifFileIn -> SColorMap) == ERROR)
|
||||
QuitGifError(GifFileIn, GifFileOut);
|
||||
|
||||
/* Scan the content of the input GIF file and load the image(s) in: */
|
||||
do {
|
||||
if (DGifGetRecordType(GifFileIn, &RecordType) == ERROR)
|
||||
QuitGifError(GifFileIn, GifFileOut);
|
||||
|
||||
switch (RecordType) {
|
||||
case IMAGE_DESC_RECORD_TYPE:
|
||||
if (DGifGetImageDesc(GifFileIn) == ERROR)
|
||||
QuitGifError(GifFileIn, GifFileOut);
|
||||
/* Put image descriptor to out file: */
|
||||
if (EGifPutImageDesc(GifFileOut,
|
||||
GifFileIn -> ILeft, GifFileIn -> ITop,
|
||||
GifFileIn -> IWidth, GifFileIn -> IHeight,
|
||||
GifFileIn -> IInterlace, GifFileIn -> IBitsPerPixel,
|
||||
GifFileIn -> IColorMap) == ERROR)
|
||||
QuitGifError(GifFileIn, GifFileOut);
|
||||
|
||||
/* Now read image itself in decoded form as we dont really */
|
||||
/* care what we have there, and this is much faster. */
|
||||
if (DGifGetCode(GifFileIn, &CodeSize, &CodeBlock) == ERROR ||
|
||||
EGifPutCode(GifFileOut, CodeSize, CodeBlock) == ERROR)
|
||||
QuitGifError(GifFileIn, GifFileOut);
|
||||
while (CodeBlock != NULL) {
|
||||
if (DGifGetCodeNext(GifFileIn, &CodeBlock) == ERROR ||
|
||||
EGifPutCodeNext(GifFileOut, CodeBlock) == ERROR)
|
||||
QuitGifError(GifFileIn, GifFileOut);
|
||||
}
|
||||
break;
|
||||
case EXTENSION_RECORD_TYPE:
|
||||
/* Skip any extension blocks in file: */
|
||||
if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == ERROR)
|
||||
QuitGifError(GifFileIn, GifFileOut);
|
||||
if (EGifPutExtension(GifFileOut, ExtCode, Extension[0],
|
||||
Extension) == ERROR)
|
||||
QuitGifError(GifFileIn, GifFileOut);
|
||||
|
||||
/* No support to more than one extension blocks, so discard: */
|
||||
while (Extension != NULL) {
|
||||
if (DGifGetExtensionNext(GifFileIn, &Extension) == ERROR)
|
||||
QuitGifError(GifFileIn, GifFileOut);
|
||||
}
|
||||
break;
|
||||
case TERMINATE_RECORD_TYPE:
|
||||
break;
|
||||
default: /* Should be traps by DGifGetRecordType */
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (RecordType != TERMINATE_RECORD_TYPE);
|
||||
|
||||
if (DGifCloseFile(GifFileIn) == ERROR)
|
||||
QuitGifError(GifFileIn, GifFileOut);
|
||||
if (EGifCloseFile(GifFileOut) == ERROR)
|
||||
QuitGifError(GifFileIn, GifFileOut);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Close both input and output file (if open), and exit. *
|
||||
******************************************************************************/
|
||||
static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut)
|
||||
{
|
||||
PrintGifError();
|
||||
if (GifFileIn != NULL) DGifCloseFile(GifFileIn);
|
||||
if (GifFileOut != NULL) EGifCloseFile(GifFileOut);
|
||||
exit(1);
|
||||
}
|
Reference in New Issue
Block a user