Dec 202017
GIF file encoder for Turbo Pascal v5+.
File ENGIF.ZIP from The Programmer’s Corner in
Category Pascal Source Code
GIF file encoder for Turbo Pascal v5+.
File Name File Size Zip Size Zip Type
ENGIF.DOC 17792 6156 deflated
ENGIF.TPU 3056 1485 deflated
RELACE.EXE 13088 7933 deflated
RELACE.PAS 5504 1884 deflated

Download File ENGIF.ZIP Here

Contents of the ENGIF.DOC file



ENGIF is a Turbo Pascal Unit to encode graphic images stored in
CompuServe's Graphic Interchange Format (GIF). With this unit you can write
your own GIF encoder or add GIF to any application. With its companion unit
DEGIF you can write GIF utilities to re-encode existing images. "GIF" and
"Graphic Interchange Format" are trademarks of H & R Block, Inc. The GIF
standard itself is in the public domain.

This unit is fully documented but we will not release the source code
at this time. This is a shareware product with a registration fee of $25
payable to Cyborg Software Systems, Inc. 3119 Cossell Drive, Indianapolis,
IN 46224. If you are already registered for DEGIF, you need not register
ENGIF. In future releases the two units will be distributed as a single
package. This unit, the documentation and the source and executable code
for RELACE are all Copyright 1988 by Cyborg Software Systems, Inc.

You may use this material for personal non-commercial use. If you like
it we ask you to register it. If you distribute it for free you must
distribute it in its original ARC form with all files intact. If you
distribute it for a fee or if you wish to use ENGIF in any commercial
application or custom programming written for fee or under contract, you
must register it. Violation of the above terms infringes our copyright.
Registered users will receive the next update free of charge. Further
updates will cost registered users $5.

Parts of this code are very loosely based on ENCODE.INC by Bob Berry
which was a Turbo Pascal 3.0 translation of routines written in C by Steve
Wilhite. Sincere thanks and credit to them.

If all you are interested in is the RELACE utility then it is used by
simply typing....


.....where IN.GIF is a GIF file to be laced or un-laced and OUT.GIF is
overwritten and can be destroyed. This is just a simple demo. Its not a
foolproof professional program.


The best way we know to document the ENGIF unit is to give an example
program called RELACE. RELACE is a utility which will run on any IBM PC
compatible regardless of graphic cards. It uses the DEGIF unit to decode an
image to memory and then uses ENGIF to re-encode it. You are given the
option to interlace non-interlaced images or un-lace interlaced images --
hence the name RELACE. If you do not already have a copy of the DEGIF unit
and documentation, we suggest you obtain them from the same source as you
obtained ENGIF.

You should print out a copy of RELACE.PAS and follow it along its main
routine as we go.

Copyright (c) 1988 Cyborg Software Systems, Inc. page 1.

2.1 Initialization

The ENGIF unit requires that you establish a pointer to your procedure
WrtByte. WrtByte must be a far-call procedure to write one byte to the
output file. We will discuss this routine in section 3.0 below.
AddrWrtByte is a global pointer declared in the ENGIF unit but you must
initialize it. AddrGetByte and AddrPutByte are required by the DEGIF unit.

The next few lines of RELACE's main routine engage the CRT unit and
prints the copyright notice. A file name is retrieved from the command line
or the user is prompted for one. Names for the source and destination files
are retrieved from the command line or you are prompted for them. The files
are opened.

Because ENGIF "uses" DEGIF, many of DEGIF's types, variables and
routines are needed by ENGIF too. The DEGIF unit defines the following....

Type MapType=(Global,Local);

GIF files may or may not have a global color map and or a local color
map for multiple image files. DEGIF and ENGIF need the variable
CurMap:MapType to be initialized before you begin.

2.2 Procedure PutGIFSig

All valid GIF files begin with a 6 byte signature. The DEGIF unit
provides a procedure GetGIFSig to retrieve it. After calling GetGIFSig the
global string GIFSig should contain the string. As of this writing (March
1988) the only valid string is 'GIF87a'. Similarly ENGIF provides PutGIFSig
to write the signature to the output file. If you are not using GetGIFSig,
you should use the following....


2.3 Procedure PutScrDes

Following the GIF signature in a GIF file is the screen description.
The DEGIF unit provides a procedure GetScrDes to retrieve it and initialize
several global variables. PutScrDes in the ENGIF unit is used to write a
screen description. Unlike PutGIFSig, PutScrDes does not simply write back
the variables which GetScrDes read because you may wish to write different
values with ENGIF while maintaining the DEGIF variables. The PutScrDes
routine is passed the following parameters.

procedure PutScrDes(SW,SH,BC,CR,PR:word;ME:boolean);

ScreenWidth and ScreenHeight (or SW and SH) are type Word and contain
the screen width and height in pixels. All images in this file will fit in
this virtual screen space. Its up to you to scale or clip the image if it
doesn't fit the global screen size you specify.

Some GIF files are composed of multiple small images that may overlap

Copyright (c) 1988 Cyborg Software Systems, Inc. page 2.

or may not fill the screen. The standard says you should first fill in a
background before plotting the images. Some decoders don't bother. They
leave the background black. DEGIF gives you BackgrColorIndex which tells
you what color to paint the background. You should use BC to pass the index
of the background color you want.

BitsOfColorPerPrimary (or CR meaning "Color Resolution") is a Word but
the only valid values are [1..8]. I was just too lazy to declare it as a
byte or sub-range type . It is the topic of much debate among GIF
developers as to what should be put there and how useful it is. It isn't
necessary for most decoding and my experience is it is unreliable. As an
example, for EGA created images its value should be 2 because each primary
color (red, green and blue) is designated by 2 bits.

BitsPerPixel[Global] (or PR meaning "Pixel Resolution") is a Word that
does tells you the number of colors in the color map. It is also necessary
for ENGIF's compression routine to establish a minimum code size. The only
valid values are [1..8]. The number of colors in the global color map is
computed by...

NumberOfColors[Global]:= (1 shl BitsPerPixel[Global]);

This means GIF color maps always contain 2, 4, 8, 16, 32, 64, 128 or
256 entries. The image may not actually contain that many colors. It may
use fewer. I have no problem with 16 color images that contain only 10 or
12 colors. It really raises my dandruff when I download 256 color images
with 31 colors!!! Editorial over.

MapExists[Global] (or ME) is a boolean that tells you if there is a
global color map for this file.

Next, RELACE builds a virtual screen on the heap and initializes it to
the background color. It then calls DisplayScrDes. This is its own routine
which simply tells the user the information from the screen descriptor. If
you intend to modify any of the screen description, this is where you would
do it. Finally we call PutScrDes. RELACE does simply pass on the values
obtained by DEGIF but many other applications of ENGIF might make changes.

2.4 Procedure PutColorMap

The GIF standard provides for an optional global color map. Most GIF
files contain one. GetScrDes sets the boolean MapExists[Global] to true if
there is a global map. If you passed ME=true to PutScrDes then you must
have one too. The map is put in the following arrays....

RedValue,GreenValue,BlueValue: array [0..255] of byte;

These global arrays are declared in DEGIF and if you change them you
lose the old values. This probably will not be a problem. Only index
values in the range [0..NumberOfColors[Global]-1] are defined. They are
intensity values from [0..255] for the red, blue and green components of the

See the DEGIF documentation for more details on the color maps.

Copyright (c) 1988 Cyborg Software Systems, Inc. page 3.

The PutColorMap routine in ENGIF writes the values from those arrays.
It requires that CurMap and NumberOfColors[CurMap] have the proper values.

2.5 Writing blocks

Its time now to get down to actual encoding! The next thing to appear
in a GIF file is a block. There are currently only two types. Image blocks
are preceded by a comma. Extension blocks are preceded by an exclamation
point. GIF files are terminated by a semi-colon. Any characters other than
a ';' or a ',' or '!' may be ignored. ENGIF currently has no facility for
writing extension blocks so RELACE uses DEGIF's SkipExtendBlock routine.
Currently no extension blocks are defined.

2.6 Procedure PutImageDescription

After finding an image block which begins with a comma, RELACE does...


... and reads the image description using GetImageDescription. The
image description is output with...

procedure PutImageDescription(IL,IT,IW,IH,PR:word;ME,ITL:boolean);

ImageLeft and ImageTop (or IL and IT) define the coordinates of this
image relative to the screen description. A value of 0,0 is the upper left
corner of the screen.

ImageWidth and ImageHeight (or IW and IH) give the dimensions of this
image. The image may overlap previous images. It may or may not fill the
screen. It should never exceed the screen description.

BitsPerPixel[Local] (or PR for Pixel Resolution) and
NumberOfColors[Local] tell you the same things about the local map that
their global brothers tell you about the global map.

MapExists[Local] (or ME) is a boolean that tells you if a local color
map exists for this image.

Our AdjustImage routine prompts you to determine whether or not the
output file should be interlaced. It sets the variable LaceIt. Note that
the variable Interlaced tells whether or not the input image is laced and
LaceIt (passed as ITL) controls the output image. See section 3.2 for a
discussion of interlaced images.

If you have a local color map then you must call GetColorMap and
PutColorMap with CurMap:=Local.

2.7 Procedures CompressGIF(Pix) and EndCompress

The data blocks which follow are the image data index values compressed
in a variable length 12 bit-maximum modified LZW compression scheme.

Copyright (c) 1988 Cyborg Software Systems, Inc. page 4.


That's what I said when I first became a GIF developer. They just
handed me a bunch of code written in "C" by Steve Wilhite. They said just
use this code and everything will be ok. There was one problem. I don't
know "C"! Enter Bob Berry who sees C and Pascal. My first GIF decoder used
his Turbo Pascal 3.0 translation from Wilhite's "C". I plugged. It
chugged. Out came GIF! Presto!

Since then I've rewritten DEGIF's ExpandGIF several times on my own and
I understand "image data index values compressed in a variable length 12 bit
maximum modified LZW compression scheme."

But you don't need to.

DEGIF's ExpandGIF calls your GetByte routine to get compressed data one
byte at a time. It does all the magic by calling your PutByte routine to
put the dots on the screen.

When the entire image is done ExpandGIF returns an integer. Anything
other than a 0 is an error.

To compress the GIF image we simply call CompressGIF repeatedly passing
the image bytes to it. When we are done we call EndCompress which clears
the compression buffer and terminates the image block. See section 3.2 for
RELACE's method of outputing interlaced images.

2.8 Terminator

When you've output all the images, you should write a GIF terminator


...and close the output file.


Routines like DisplayScreenDescription and AdjustImage are so totally
your responsibility that we really can't say much more about them because
you may want to do them differently. The WrtByte, GetByte and PutByte need
more explanation.


AddrWrtByte:[email protected];
AddrGetByte:[email protected];
AddrPutByte:[email protected];

3.1 Procedure WrtByte(I:integer);

You must provide a procedure WrtByte which outputs bytes to the output
file. This function must be a far function and is compiled with the {$F+}
directive. The simplest WrtByte is..

Copyright (c) 1988 Cyborg Software Systems, Inc. page 5.

procedure WrtByte(I: integer);
var B:byte;
B:=lo(I); write(OutFile,B)

3.2 Interlacing images

If you want your images interlaced, you must pass bytes to CompressGIF
in the proper order. You pass a byte that is the index to the color array.
That color will eventually be plotted at location x,y. The catch is what
are x and y?

On non-interlaced images you just start at XCord:=ImageLeft and
YCord:=ImageTop. You pass points along Y and increment X until you've
plotted ImageWidth of them. That is until XCord=ImageLeft+ImageWidth. Then
you reset X to ImageLeft, increment Y and plot the next line.

Interlaced images start with YCord:=ImageTop but they make 4 interlaced
passes. Pass 1 begins at ImageTop+0 and plots every 8th line. Pass 2
starts at ImageTop+4 and also plots every 8th line. Pass 3 starts at
ImageTop+2 and plots every 4th line. Pass 4 starts at ImageTop+1 and plots
every other line. These 4 passes fill the screen.

In RELACE the PutByte routine and the "repeat until" structure in the
main routine both deal with interlacing. For non-interlaced images I
invented a Pass 5 which starts at ImageTop+0 and plots every line. I simply
say ...

if Interlaced then Pass:=1 else Pass:=5;

This fully implements interlaced images.


Because ENGIF uses DEGIF you will have access to both ENGIF's variables
and routines as well as ENGIF's.

4.1 DEGIF interface

Here is the interface section of the DEGIF unit.

unit degif;

type MapType=(Global,Local);

var GIFSig:String[6]; {GIF ID string usually = 'GIF87a'}
CurMap:MapType; {Current Map in use}
BitsPerPixel, {in this image}
NumberOfColors {in this image}

Copyright (c) 1988 Cyborg Software Systems, Inc. page 6.

:array [Global..Local] of word;
BackgrColorIndex, {Background Color index}
BitsOfColorPerPrimary, {For example on EGA=2}
ImageLeft, {Left edge of image relative to virtual screen}
ImageTop, {Top edge of image relative to virtual screen}
ImageWidth, {in pixels}
ImageHeight, {in pixels}
ScreenHeight, {in pixels}
ScreenWidth:word; {in pixels}
MapExists:array [Global..Local] of boolean;
AddrGetByte, {Pointer to user supplied GetByte}
AddrPutByte:pointer; {Pointer to user supplied PutByte}
RedValue,GreenValue,BlueValue: array [0..255] of byte;
Color: array [Global..Local,0..255] of byte;

function ExpandGif: integer;

procedure GetColorMap;

procedure GetGIFSig;

procedure GetImageDescription;

procedure GetScrDes;

procedure SkipExtendBlock;

4.2 ENGIF interface

Here is ENGIF's interface....

unit engif;
uses degif;
AddrWrtByte:pointer; {Pointer to user supplied WrtByte}

procedure CompressGIF(Pix: byte);

procedure EndCompress;

procedure PutColorMap;

procedure PutGIFSig;

procedure PutImageDescription(IL,IT,IW,IH,PR:word;ME,ITL:boolean);

procedure PutScrDes(SW,SH,BC,CR,PR:word;ME:boolean);


This unit is written entirely in Turbo Pascal 4.0 and contains no
assembler or Inline code. My #1 goal was to get this available as soon as

Copyright (c) 1988 Cyborg Software Systems, Inc. page 7.

possible. My #2 goal will be to make it fast. After that I'll add
extension block support and any new extensions to the GIF87a standard.

To make it worth my trouble I need your support. Please show your
appreciation and register this product.

Copyright (c) 1988 Cyborg Software Systems, Inc. page 8.

 December 20, 2017  Add comments

Leave a Reply