home *** CD-ROM | disk | FTP | other *** search
- GIF library document
- --------------------
-
- Gershon Elber, August 1989
- --------------------------
-
- Version 1.0
- -----------
-
- 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.
-
-
- 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 DumpScreen(char *FileName, int ReqGraphDriver, int ReqGraphMode);
-
- 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.
- Returns ERROR if something went wrong, OK otherwise.
-
-
- 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);
- }
-