home *** CD-ROM | disk | FTP | other *** search
- 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);
- }
-