u229
Applications Home|Email

 The GIF File Format - A Quick Reference For Classic ASP Programmers

Overview - The Anatomy of a GIF
6 bytes Required Header
7 bytes Required Logical Screen Descriptor
Max 768 bytes Optional Global Color Table
10 bytes Required Local Image Descriptor: Starts with byte &H2C.
n bytes Optional Graphic Control Extension: Starts with bytes &H21 and &HF9.
n bytes Optional Application Block Extension: Starts with bytes &H21 and &HFF.
Unlimited number of sub blocks allowed.
n bytes Optional Comment Block Extension: Starts with bytes &H21 and &HFE.
Unlimited number of sub blocks allowed.
n bytes Optional Plain Text Extension: Starts with bytes &H21 and &H01.
Unlimited number of sub blocks allowed.
1 byte Required Terminator: &H3B

This GIF image demonstrates the Application Extension Block and the Comment Extension Block. Save this file to disk and view it in a text editor.
Here's an example of an animated GIF:

 

All GIF images start with a header 6 bytes long:

The Gif File Header
1 G 1 byte First 3 bytes contains the GIF signature: GIF
2 I 1 byte  
3 F 1 byte  
4 8 1 byte Next 3 bytes contains the GIF Version: 87a or 89a
5 9 1 byte  
6 a 1 byte  
If AscB(MidB(GIFByteArray, 1, 1)) = 71 And AscB(MidB(GIFByteArray, 2, 1)) = 73 And AscB(MidB(GIFByteArray, 3, 1)) = 70 Then
'// We have found a GIF signature
End If

 

Directly after the GIF header comes the Logical Screen Descriptor. This is 7 bytes.

Logical Screen Descriptor
1 1 byte 2 bytes: Logical Screen Width
2 1 byte  
3 1 byte 2 bytes: Logical Screen Height
4 1 byte  
5 1 byte Packed Field
6 1 byte Background Color Index
7 1 byte Pixel Aspect Ratio
  1. Logical Screen Width: Width of image in pixels.
  2. Logical Screen Height: Height of image in pixels.
  3. Packed Field.
  4. Background Color Index: a value pointing to a color in the Global Color Table.
  5. Pixel Aspect Ratio: A factor used to calculate an approximation of the aspect ratio of the pixel in the GIF image.

Image Width:

lWidth = CLng(AscB(MidB(GIFByteArray, 7, 1)) + (AscB(MidB(GIFByteArray, 8, 1)) * 256))

Image Height:

lHeight = CLng(AscB(MidB(GIFByteArray, 9, 1)) + (AscB(MidB(GIFByteArray, 10, 1)) * 256))

Packed Field:
This byte contains the following information:
Global Color Table Flag = 1 Bit
Color Resolution = 3 Bits
Sort Flag = 1 Bit
Size of Global Color Table = 3 Bits

Here's an example of a GIF image opened in a hex editor. The highlighted byte 11 is the "packed" byte:

The bit pattern for this byte:

7 6 5 4 3 2 1 0
1 1 1 1 0 1 1 1

- Bit 7 is the Global Color Table Flag. If this is 1 there is a Global Color Table present:
If AscB(MidB(GIFByteArray, 11, 1)) And 128 Then bGlobalColorTableFlag = True
- Bit 6 - 4 contain the Color Resolution.
lColorDepth = 2 ^ ((Asc(CStr(AscB(MidB(GIFByteArray, 11, 1)))) And 7) + 1)
- Bit 3 is the Sort Flag: Indicates whether the Global Color Table is sorted or not.

- Bit 0 - 2 contain the size of the Global Color Table.
If AscB(MidB(GIFByteArray, 11, 1)) And 4 Then lngGlobalColorFactor = 4
If AscB(MidB(GIFByteArray, 11, 1)) And 2 Then lngGlobalColorFactor = lngGlobalColorFactor Or 2
If AscB(MidB(GIFByteArray, 11, 1)) And 1 Then lngGlobalColorFactor = lngGlobalColorFactor Or 1

lSizeGlobalColorTable = CLng(3 * (2 ^ (lngGlobalColorFactor + 1)))

Background Color Index:
The Background Color is the color used for those pixels on the screen that are not covered by an image.

Aspect Ratio:

Aspect Ratio = (Pixel Aspect Ratio + 15) / 64

 

A Color Table is a color palette. If the Global Color Table Flag is set, then this table will follow immediately after the Local Image Descriptor. If this flag is not set, then there should be a local color table contained with the image data itself. (See below). In this case we have a Global Color Table and it always starts at byte number 14. The byte pattern is like this:

Global Color Table
1 byte Red(0)
1 byte Green(0)
1 byte Blue(0)
1 byte Red(1)
1 byte Green(1)
1 byte Blue(1)
.... Max 768 bytes/256 color triplets

 

After the GIF header, the Logical Screen Descriptor and the Global Color Table, we find the actual image data. There might be an unlimited number of images present in a GIF. Each image frame is composed of a Local Image Descriptor, an optional Local Color Table, and the image data. One Image Descriptor must be present per image.

Local Image Descriptor
1 byte &H2C Identifies the beginning of an Image Descriptor.
2 bytes   Image Left Position
     
2 bytes   Image Top Position
     
2 bytes   Width of the image in pixels.
     
2 bytes   Height of the image in pixels.
     
1 byte   Packed field.

Packed field:
Local Color Table Flag = 1 bit
Interlace Flag = 1 bit
Sort Flag = 1 bit
Reserved = 2 bits
Size of Local Color Table = 3 bits

- Bit 7 is the Local Color Table Flag. Indicates the presence of a Local Color Table immediately following this Image Descriptor.
- Bit 6 is the Interlace Flag. Indicates if the image is interlaced.
- Bit 5 is the Sort Flag. Indicates whether the Local Color Table is sorted.
- Bit 4 - 3: Reserved.
- Bit 2 - 0: Size of Local Color Table

If the Local Color Table Flag is set, then the Local Color Table will follow immediately after this block. Then follows the image data.

A GIF89a may contain different Extension Blocks which are all optional. They may appear anywhere in the GIF file, in no specific order and there might be more than just one of each type. In fact, the number is unlimited. This means you might store the complete works of Shakespeare inside the Comment Extension in one single GIF file. All Extension Blocks start with hex value &H21. The byte following is the Extension Label identifying the type of Extension Block.

The information stored in a Graphics Control block is used to modify how the GIF image is displayed. One block is controlling one image frame.

Graphics Control Extension
1 byte &H21 Extension Block Identifier
1 byte &HF9 Extension Label
1 byte &H04 Fixed value of 4 which is the length of the following block.
1 byte   Packed field.
2 bytes   Delay Time: Hundredths of seconds to wait.
1 byte   Transparent Color Index
1 byte &H0 The block is terminated by a &H0 value.

Packed Field:
This byte contains the following information:
Reserved= 3 Bits
Disposal Method= 3 Bits
User Input Flag= 1 Bit
Transparent Color Flag = 1 Bit

- Bit 7 - 5: Reserved. Always 0.
- Bit 4 - 2: "The Disposal Method subfield contains a value indicating how the graphic is to be disposed of once it has been displayed. The currently defined values for this field are 00h (disposal method not specified), 01h (do not dispose of graphic), 02h (overwrite graphic with background color), and 04h (overwrite graphic with previous graphic)."
- Bit 1: If the User Input Flag is set then user input (key press, mouse click, and so forth) is expected before continuing to the next graphic sequence.
- Bit 0: Transparent Color Flag. If this flag is set then the Transparent Color Index byte will contain an index value for the transparent color.

 

Application Block Extension
1 byte &H21 Extension Block Identifier
1 byte &HFF Extension Label
1 byte   Fixed value of 11 which is the length of the following block.
8 bytes   Application Identifier: 8 bytes of Ascii characters.
3 bytes   Application Authentic Code: 3 bytes of Ascii characters.
1 byte n Length of the following Application Data Block.
n bytes Max 256 bytes Application Data Block. The number of sub blocks are unlimited.
1 byte &H0 The block is terminated by a &H0 value.

The Application Identifier field is meant to identify the originating owner application. The Application Authentic Code field is meant to identify the version number of this application. You could use these fields to write hidden copyright information:

      1 2 3 4 5 6 7 8 9 10 11      
&H21 &HFF 11 M Y F O O A P P 1 . 5 n Length of Application Data is n bytes. &H0

Here's an example seen with a hex editor:

The Application Identifier field reads: "GIFInfo!". The Application Authentic Code field reads: "1.0". The Application Data field reads: "Hello world!".

 

The Comment Extension Block is another optional GIF Block. It is used to store any length of Ascii strings in sub blocks of max 256 characters.

Comment Block Extension
1 byte &H21 Extension Block Identifier
1 byte &HFE Extension Label
1 byte n Length of the following Comment Block.
n bytes Max 256 bytes The Comment Block. The number of sub blocks are unlimited.
1 byte &H0 The block is terminated by a &H0 value.

Example of a Comment extension Block in a GIF file. The byte highlighted is the Extension Identifier &H21 followed by the Extension Label &HFE:

&H21 &HFE n Length of Comment Block is n bytes. &H0

 

The Plain Text Extension Block allows for displaying printable 7-bits Ascii characters over the actual image, a primitive watermark. The text is rendered in a grid system with each character put in a cell. (This feature is not supported by any major piece of software that I know of.)

Plain Text Extension
1 byte &H21 Extension Block Identifier
1 byte &H01 Extension Label
1 byte   Fixed value of 12 which is the length of the following block.
1 2 bytes StartX: Defines the start left position for the text grid.
2    
3 2 bytes StartY: Defines the start top position for the text grid.
4    
5 2 bytes Width of text grid in pixels.
6    
7 2 bytes Height of text grid in pixels.
8    
9 1 byte Width of grid cell for a single character.
10 1 byte Height of grid cell for a single character.
11 1 byte Index for the color of the characters.
12 1 byte Index for the background color of the characters.
1 byte n Length of the following sub block of text.
n bytes Max 256 bytes The Text block. Unlimited number of sub blocks allowed.
1 byte &H0 The block is terminated by a &H0.

 

Some Classic ASP code to get you started:

'------------------------------------------------------------------------------------------------------------
' Comment: Read GIF into a byte array.
'------------------------------------------------------------------------------------------------------------
Private Function LoadGIFAsBytes(sFullPath)
    On Error Resume Next

    Dim oStream

    If IsEmpty(oStream) Then Set oStream = Server.CreateObject("ADODB.Stream")

    With oStream
        .Type = 1 '// adTypeBinary
        .Open
        .LoadFromFile sFullPath
        GIFByteArray = .Read
    End With

    oStream.Close
    Set oStream = Nothing

    LoadGIFAsBytes = (LenB(GIFByteArray) > 0 And Err.Number = 0)

End Function
'------------------------------------------------------------------------------------------------------------
' Comment: Loop the GIF bytes and look for a Comment Extension Block.
'------------------------------------------------------------------------------------------------------------
Private Function ParseGIF()
    On Error Resume Next

    Dim i, k, sComment

    For i = 1 To m_lImageSize

        If AscB(MidB(GIFByteArray, i, 1)) = 33 Then
            If AscB(MidB(GIFByteArray, i + 1, 1)) = 254 Then

                For k = i To m_lImageSize
                    sComment = sComment & Chr(AscB(MidB(GIFByteArray, k, 1)))
                    If AscB(MidB(GIFByteArray, k, 1)) = 0 Then Exit Function
                Next

            End If
        End If

    Next

    ParseGIF = (Err.Number = 0)

End Function
'------------------------------------------------------------------------------------------------------------
' Comment: Save byte array to GIF.
'------------------------------------------------------------------------------------------------------------
Private Sub SaveAsGIF(ByteArray, sSavePath)
    On Error Resume Next

    Dim oStream

    If IsEmpty(oStream) Then Set oStream = Server.CreateObject("ADODB.Stream")

    With oStream

        If .State = 1 Then .State = 0 '// adStateOpen = 1: adStateClosed = 0
        .Type = 1 '// adTypeBinary
        Call .Open
        Call .Write(ByteArray)
        Call .SaveToFile(sSavePath, 2) '// adSaveCreateOverWrite
        Call .Close
    End With

    Set oStream = Nothing

End Sub

GIF LINKS:
http://en.wikipedia.org/wiki/GIF
http://www.w3.org/Graphics/GIF/spec-gif89a.txt
http://semmix.pl/color/exgraf/eeg10.htm
http://www.u229.no/stuff/GIFInfo/
http://www.u229.no/stuff/GIFText/

Therefore: For that or this for it.
© www.u229.no