GIF (Graphics Interchange Format) is an image compression format for paletted still and animated images. It is specified in the GIF89a specification.
Consider test/data/bricks-nodither.gif
.
offset xoffset ASCII hex binary 000000 0x0000 G 0x47 0b_0100_0111 000001 0x0001 I 0x49 0b_0100_1001 000002 0x0002 F 0x46 0b_0100_0110 000003 0x0003 8 0x38 0b_0011_1000 000004 0x0004 9 0x39 0b_0011_1001 000005 0x0005 a 0x61 0b_0110_0001 000006 0x0006 . 0xA0 0b_1010_0000 000007 0x0007 . 0x00 0b_0000_0000 000008 0x0008 x 0x78 0b_0111_1000 etc 014230 0x3796 . 0xD3 0b_1101_0011 014231 0x3797 . 0x02 0b_0000_0010 014232 0x3798 . 0x06 0b_0000_0110 014233 0x3799 . 0x04 0b_0000_0100 014234 0x379A . 0x00 0b_0000_0000 014235 0x379B ; 0x3B 0b_0011_1011
Starting at the top, a magic identifier, either “GIF87a” or “GIF89a”. In theory, some decoders can only handle the 1987 flavor. In practice, support for the 1989 flavor is ubiquitous. Anyway, the magic ID is:
offset xoffset ASCII hex binary 000000 0x0000 G 0x47 0b_0100_0111 000001 0x0001 I 0x49 0b_0100_1001 000002 0x0002 F 0x46 0b_0100_0110 000003 0x0003 8 0x38 0b_0011_1000 000004 0x0004 9 0x39 0b_0011_1001 000005 0x0005 a 0x61 0b_0110_0001
The Logical Screen Descriptor is at least 7 bytes long:
offset xoffset ASCII hex binary 000006 0x0006 . 0xA0 0b_1010_0000 000007 0x0007 . 0x00 0b_0000_0000 000008 0x0008 x 0x78 0b_0111_1000 000009 0x0009 . 0x00 0b_0000_0000 000010 0x000A . 0xF7 0b_1111_0111 000011 0x000B . 0x00 0b_0000_0000 000012 0x000C . 0x00 0b_0000_0000
The image size is 0x00A0 by 0x0078 pixels, or 160 by 120. The fifth byte is flags, the sixth is the background color index, the seventh is ignored.
The high bit (0x80) and low three bits (0x07) of the flags indicate that we have a GCT (Global Color Table) and that it contains 1<<(7+1), or 256, elements. Global means that it applies to each frame in the possibly animated image unless a per-frame Local Color Table overrides it, and Color Table means a palette of up to 256 RGB (Red, Green, Blue) triples. That GCT follows immediately:
offset xoffset ASCII hex binary 000013 0x000D . 0x01 0b_0000_0001 000014 0x000E . 0x03 0b_0000_0011 000015 0x000F . 0x04 0b_0000_0100 000016 0x0010 . 0x00 0b_0000_0000 000017 0x0011 . 0x0C 0b_0000_1100 000018 0x0012 . 0x03 0b_0000_0011 etc 000250 0x00FA . 0x01 0b_0000_0001 000251 0x00FB $ 0x24 0b_0010_0100 000252 0x00FC c 0x63 0b_0110_0011 etc 000673 0x02A1 . 0x0F 0b_0000_1111 000674 0x02A2 . 0xA7 0b_1010_0111 000675 0x02A3 . 0xF6 0b_1111_0110 etc 000778 0x030A . 0x9F 0b_1001_1111 000779 0x030B . 0xB8 0b_1011_1000 000780 0x030C . 0xCD 0b_1100_1101
Thus, color 0 in the palette is the RGB triple {0x01, 0x03, 0x04}, color 1 is {0x00, 0x0C, 0x03}, etc, color 79 is {0x01, 0x24, 0x63}, etc, color 220 is {0x0F, 0xA7, 0xF6}, etc, color 255 is {0x9F, 0xB8, 0xCD}.
For this particular GIF, next comes an Extension Introducer byte (0x21) for a GCE (Graphic Control Extension) (0xF9), followed by one or more data blocks:
offset xoffset ASCII hex binary 000781 0x030D ! 0x21 0b_0010_0001 000782 0x030E . 0xF9 0b_1111_1001 000783 0x030F . 0x04 0b_0000_0100 000784 0x0310 . 0x00 0b_0000_0000 000785 0x0311 . 0x00 0b_0000_0000 000786 0x0312 . 0x00 0b_0000_0000 000787 0x0313 . 0x00 0b_0000_0000 000788 0x0314 . 0x00 0b_0000_0000
The first block has 0x04 payload bytes. After those four bytes, the second block has 0x00 payload bytes, which marks the end of the data blocks. The payload bytes are flags, animation timing and transparency information that, for this simple, opaque, single-frame image, happen to be all zero.
Image Descriptors form the bulk of a GIF image. A still image will have one Image Descriptor. An animated image will have many. Image Descriptors begin with an 0x2C byte, followed by at least nine more bytes for the {left, top, width, height} of this frame relative to the overall (potentially animated) image, plus a flags byte:
offset xoffset ASCII hex binary 000789 0x0315 , 0x2C 0b_0010_1100 000790 0x0316 . 0x00 0b_0000_0000 000791 0x0317 . 0x00 0b_0000_0000 000792 0x0318 . 0x00 0b_0000_0000 000793 0x0319 . 0x00 0b_0000_0000 000794 0x031A . 0xA0 0b_1010_0000 000795 0x031B . 0x00 0b_0000_0000 000796 0x031C x 0x78 0b_0111_1000 000797 0x031D . 0x00 0b_0000_0000 000798 0x031E . 0x00 0b_0000_0000
The frame‘s origin is {0x0000, 0x0000} and its extent is {0x00A0, 0x0078}. The flags byte indicates a non-interlaced frame and that no LCT (Local Color Table) overrides the GCT. After the (lack of) LCT comes the LZW (Lempel Ziv Welch) compression’s log2(literal_width)
, discussed further below.
offset xoffset ASCII hex binary 000799 0x031F . 0x08 0b_0000_1000
Pixel data from the bulk of an Image Descriptor. Just like the GCE format, the payload is framed as a sequence of blocks, each block starting with a single byte count of the remaining bytes in the block, and the final block containing only a 0x00 byte.
offset xoffset ASCII hex binary 000800 0x0320 . 0xFE 0b_1111_1110 000801 0x0321 . 0x00 0b_0000_0000 000802 0x0322 . 0xB9 0b_1011_1001 000803 0x0323 . 0x09 0b_0000_1001 000804 0x0324 . 0x14 0b_0001_0100 000805 0x0325 . 0x98 0b_1001_1000 etc 001053 0x041D 6 0x36 0b_0011_0110 001054 0x041E . 0x1E 0b_0001_1110 001055 0x041F . 0xFE 0b_1111_1110 001056 0x0420 J 0x4A 0b_0100_1010 001057 0x0421 . 0xA4 0b_1010_0100 etc 001308 0x051C . 0x1F 0b_0001_1111 001309 0x051D . 0x81 0b_1000_0001 001310 0x051E . 0xFE 0b_1111_1110 001311 0x051F 5 0x35 0b_0011_0101 001312 0x0520 ] 0x5D 0b_0101_1101 etc etc etc 013803 0x35EB n 0x6E 0b_0110_1110 013804 0x35EC . 0xD7 0b_1101_0111 013805 0x35ED . 0xFE 0b_1111_1110 013806 0x35EE . 0x17 0b_0001_0111 013807 0x35EF . 0xB4 0b_1011_0100 etc 014058 0x36EA . 0xDB 0b_1101_1011 014059 0x36EB g 0x67 0b_0110_0111 014060 0x36EC . 0xAD 0b_1010_1101 014061 0x36ED . 0x81 0b_1000_0001 014062 0x36EE . 0xD6 0b_1101_0110 etc 014232 0x3798 . 0x06 0b_0000_0110 014233 0x3799 . 0x04 0b_0000_0100 014234 0x379A . 0x00 0b_0000_0000
The specification allows for the block count to be 0xFF, but for whatever reason, the ImageMagick encoder and its command-line convert
tool generated slightly shorter blocks, with lengths 0xFE, 0xFE, 0xFE, ..., 0xFE, 0xAD, 0x00.
The payload wrapped by these block counts are LZW compressed, discussed below.
The final byte is 0x3B.
offset xoffset ASCII hex binary 014235 0x379B ; 0x3B 0b_0011_1011
See std/lzw/README.md
for a description of LZW: a general purpose compression algorithm. Below is a detailed decoding of the LZW data from the Wire Format Worked Example, deconstructed above.
It is not an official format, but the test/data/bricks-nodither.indexes.giflzw
file contains the extracted “Pixel Data” payload from test/data/bricks-nodither.gif
, preceded by the one byte log2(literal_width)
. Deriving a separate file, as a separate, contiguous stream, makes it easier to discuss the LZW compression format.
offset xoffset ASCII hex binary 000000 0x0000 . 0x08 0b_0000_1000 000001 0x0001 . 0x00 0b_0000_0000 000002 0x0002 . 0xB9 0b_1011_1001 000003 0x0003 . 0x09 0b_0000_1001 000004 0x0004 . 0x14 0b_0001_0100 000005 0x0005 . 0x98 0b_1001_1000 000006 0x0006 . 0xAD 0b_1010_1101 000007 0x0007 ^ 0x5E 0b_0101_1110 000008 0x0008 > 0x3E 0b_0011_1110 000009 0x0009 { 0x7B 0b_0111_1011 000010 0x000A . 0xDF 0b_1101_1111 000011 0x000B . 0xB8 0b_1011_1000 000012 0x000C } 0x7D 0b_0111_1101 000013 0x000D . 0xC9 0b_1100_1001 000014 0x000E . 0xA1 0b_1010_0001 000015 0x000F . 0xA3 0b_1010_0011 000016 0x0010 a 0x61 0b_0110_0001 000017 0x0011 . 0xC3 0b_1100_0011 000018 0x0012 0 0x30 0b_0011_0000 etc 000253 0x00FD 6 0x36 0b_0011_0110 000254 0x00FE . 0x1E 0b_0001_1110 000255 0x00FF J 0x4A 0b_0100_1010 000256 0x0100 . 0xA4 0b_1010_0100 etc 000507 0x01FB . 0x1F 0b_0001_1111 000508 0x01FC . 0x81 0b_1000_0001 000509 0x01FD 5 0x35 0b_0011_0101 000510 0x01FE ] 0x5D 0b_0101_1101 etc etc etc 012953 0x3299 n 0x6E 0b_0110_1110 012954 0x329A . 0xD7 0b_1101_0111 012955 0x329B . 0x17 0b_0001_0111 012956 0x329C . 0xB4 0b_1011_0100 etc 013207 0x3397 . 0xDB 0b_1101_1011 013208 0x3398 g 0x67 0b_0110_0111 013209 0x3399 . 0x81 0b_1000_0001 013210 0x339A . 0xD6 0b_1101_0110 etc 013380 0x3444 . 0x06 0b_0000_0110 013381 0x3445 . 0x04 0b_0000_0100
LZW consists of a sequence of code values, in the range [0, max]
inclusive. Each code decodes to either a literal value (one byte), a back-reference (multiple bytes), a ‘clear code’ (discussed below), or indicates the end of the data stream.
The first 1<<l2lw
codes are literal codes, where l2lw
is the log2(literal_width)
mentioned above. For GIF's flavor of LZW, valid l2lw
values are between 2 and 8 inclusive.
For example, if l2lw == 8
, then the first 256 codes are literal codes: the 0 code decodes one 0x00 byte, the 1 code decodes one 0x01 byte, etc. The next code (256) is the clear code and the next code after that (257) is the end code. Any code higher than that denotes a back-reference, but any code above the current max
value is invalid.
max
's initial value is the same as the end code, and it increases by 1 with each code consumed, up until max == 4095
. A clear code resets max
to its initial value, and clears the meaning of higher back-reference codes.
Codes take up a variable number of bits in the input stream, the width
, depending on max
. For example, if max
is in the range [256, 511] then the next code takes 9 bits, if max
is in the range [512, 1023] then width == 10
, and so on. For GIF, when a code spans multiple bytes, codes are formed Least Significant Bits first. For the test/data/bricks-nodither.indexes.giflzw
example, l2lw == 8
and so width
starts at 9 bits. Printing the bits on byte boundaries give:
offset xoffset ASCII hex binary 000001 0x0001 . 0x00 0b_0000_0000 000002 0x0002 . 0xB9 0b_1011_1001 000003 0x0003 . 0x09 0b_0000_1001 000004 0x0004 . 0x14 0b_0001_0100 000005 0x0005 . 0x98 0b_1001_1000 000006 0x0006 . 0xAD 0b_1010_1101 000007 0x0007 ^ 0x5E 0b_0101_1110 000008 0x0008 > 0x3E 0b_0011_1110 000009 0x0009 { 0x7B 0b_0111_1011 000010 0x000A . 0xDF 0b_1101_1111 000011 0x000B . 0xB8 0b_1011_1000 000012 0x000C } 0x7D 0b_0111_1101 000013 0x000D . 0xC9 0b_1100_1001 000014 0x000E . 0xA1 0b_1010_0001 000015 0x000F . 0xA3 0b_1010_0011 000016 0x0010 a 0x61 0b_0110_0001 000017 0x0011 . 0xC3 0b_1100_0011 000018 0x0012 0 0x30 0b_0011_0000 etc 000147 0x0093 > 0x3E 0b_0011_1110 000148 0x0094 . 0xC4 0b_1100_0100 etc 000286 0x011E _ 0x5F 0b_0101_1111 000287 0x011F . 0xEA 0b_1110_1010 000288 0x0120 . 0x9C 0b_1001_1100 000289 0x0121 . 0xFC 0b_1111_1100 000290 0x0122 . 0xD4 0b_1101_0100 000291 0x0123 . 0xA4 0b_1010_0100 etc 005407 0x151F . 0xBB 0b_1011_1011 005408 0x1520 . 0xFB 0b_1111_1011 005409 0x1521 . 0x00 0b_0000_0000 005410 0x1522 . 0xE1 0b_1110_0001 005411 0x1523 . 0xA1 0b_1010_0001 005412 0x1524 . 0xC3 0b_1100_0011 005413 0x1525 @ 0x40 0b_0100_0000 etc 013378 0x3442 . 0xD3 0b_1101_0011 013379 0x3443 . 0x02 0b_0000_0010 013380 0x3444 . 0x06 0b_0000_0110 013381 0x3445 . 0x04 0b_0000_0100
and on code boundaries give:
binary width code 0b_...._...._...._...1_0000_0000 9 0x0100 0b_...._...._...._..01_1011_100. 9 0x00DC 0b_...._...._...._.100_0000_10.. 9 0x0102 0b_...._...._...._1000_0001_0... 9 0x0102 0b_...._...._...0_1101_1001_.... 9 0x00D9 0b_...._...._..01_1110_101._.... 9 0x00F5 0b_...._...._.011_1110_01.._.... 9 0x00F9 0b_...._...._0111_1011_0..._.... 9 0x00F6 0b_...._...._...._...0_1101_1111 9 0x00DF 0b_...._...._...._..01_1011_100. 9 0x00DC 0b_...._...._...._.001_0111_11.. 9 0x005F 0b_...._...._...._0001_1100_1... 9 0x0039 0b_...._...._...0_0011_1010_.... 9 0x003A 0b_...._...._..10_0001_101._.... 9 0x010D 0b_...._...._.100_0011_01.._.... 9 0x010D 0b_...._...._0011_0000_1..._.... 9 0x0061 etc 0b_...._...._...._.100_0011_11.. 9 0x010F etc 0b_...._...._.110_1010_01.._.... 9 0x01A9 0b_...._...._1001_1100_1..._.... 9 0x0139 0b_...._...._...._..00_1111_1100 10 0x00FC (implicit width increase) 0b_...._...._...._0100_1101_01.. 10 0x0135 etc 0b_...._...._1111_1011_1011_.... 12 0x0FBB 0b_...._...._...._0001_0000_0000 12 0x0100 (code == 0x0100 means clear) 0b_...._...._...0_0001_1110_.... 9 0x001E (explicit width reset) 0b_...._...._..00_0011_101._.... 9 0x001D 0b_...._...._.100_0000_11.._.... 9 0x0103 etc 0b_...._..10_0000_0010_11.._.... 12 0x080B 0b_...._...._..00_0100_0000_01.. 12 0x0101
The implicit width
increase is because max
ticked over from 0x01FF to 0x200. Processing these codes give:
code meaning max output 0x0100 clear 0x0101 . 0x00DC literal 0x0101 0xDC 0x0102 back-ref 0x0102 0xDC 0xDC 0x0102 back-ref 0x0103 0xDC 0xDC 0x00D9 literal 0x0104 0xD9 0x00F5 literal 0x0105 0xF5 0x00F9 literal 0x0106 0xF9 0x00F6 literal 0x0107 0xF6 0x00DF literal 0x0108 0xDF 0x00DC literal 0x0109 0xDC 0x005F literal 0x010A 0x5F 0x0039 literal 0x010B 0x39 0x003A literal 0x010C 0x3A 0x010D back-ref 0x010D 0x3A 0x3A 0x010D back-ref 0x010E 0x3A 0x3A 0x0061 literal 0x010F 0x61 etc 0x010F back-ref 0x0182 0x3A 0x3A 0x61 etc 0x01A9 back-ref 0x01FE 0xFB 0xFB 0xFB 0xFB 0x0139 back-ref 0x01FF 0xFB 0xFC 0x00FC literal 0x0200 0xFC 0x0135 back-ref 0x0201 0xFA 0xFA etc 0x0FBB back-ref 0x0FFF 0xC1 0xC1 0xC1 0xC1 0xC1 0xC1 0xDF 0x0100 clear 0x0FFF . 0x001E literal 0x0101 0x1E 0x001D literal 0x0102 0x1D 0x0103 back-ref 0x0103 0x1D 0x1D etc 0x080B back-ref 0x0896 0x4F 0x4F 0x4F 0x4F 0x4F 0x0101 end 0x0897 .
The max
column here is the max
code allowed when processing that row's code. The initial clear code is redundant (as the initial value of max
is already 0x0101 here), but some encoders produce them because the specification says that “encoders should output a Clear code as the first code of each image data stream”.
Other than clear and end codes, each code produces some output: a variable length prefix and a one byte suffix. For literal codes, the prefix is empty and the suffix is the literal.
When max
is greater than the end code (e.g. greater than 0x0101), the row defines a new back-reference, and that definition persists up until the next clear code. For example, the third, fourth, fifth, etc. rows define what the 0x0102, 0x0103, 0x0104, etc. codes output. That code‘s output (prefix + suffix) is defined by the prefix being the previous row’s output and the suffix being the first byte of the current row's output.
For example, the 15th and 16th rows are:
code meaning max output 0x010D back-ref 0x010E 0x3A 0x3A 0x0061 literal 0x010F 0x61
which defines the 0x010F code to output “0x3A 0x3A 0x61”. Later on, an 0x010F code is encountered, and its output is exactly that.
A row's code can be the code that that row itself defines, in which case the prefix is the previous row and the suffix is the first byte of the previous row. Consider the opening few codes:
code meaning max output 0x0100 clear 0x0101 . 0x00DC literal 0x0101 0xDC 0x0102 back-ref 0x0102 0xDC 0xDC 0x0102 back-ref 0x0103 0xDC 0xDC 0x00D9 literal 0x0104 0xD9
The third row‘s code is 0x0102, which that row also defines. Its output is therefore the concatenation of “0xDC” and the first byte of “0xDC”, both of those strings being the previous row’s output. The fourth row executes the same 0x0102 code (and outputs “0xDC 0xDC” again) and defines the 0x0103 code. The next code is a literal 0xD9, and hence the decoded output starts with five 0xDC bytes and then an 0xD9.
It is also not an official format, but for reference, the test/data/bricks-nodither.indexes
contains the decoded test/data/bricks-nodither.indexes.giflzw
data:
offset xoffset ASCII hex binary 000000 0x0000 . 0xDC 0b_1101_1100 000001 0x0001 . 0xDC 0b_1101_1100 000002 0x0002 . 0xDC 0b_1101_1100 000003 0x0003 . 0xDC 0b_1101_1100 000004 0x0004 . 0xDC 0b_1101_1100 000005 0x0005 . 0xD9 0b_1101_1001 000006 0x0006 . 0xF5 0b_1111_0101 000007 0x0007 . 0xF9 0b_1111_1001 000008 0x0008 . 0xF6 0b_1111_0110 000009 0x0009 . 0xDF 0b_1101_1111 000010 0x000A . 0xDC 0b_1101_1100 000011 0x000B _ 0x5F 0b_0101_1111 000012 0x000C 9 0x39 0b_0011_1001 000013 0x000D : 0x3A 0b_0011_1010 000014 0x000E : 0x3A 0b_0011_1010 000015 0x000F : 0x3A 0b_0011_1010 000016 0x0010 : 0x3A 0b_0011_1010 000017 0x0011 : 0x3A 0b_0011_1010 000018 0x0012 a 0x61 0b_0110_0001 etc 019195 0x4AFB O 0x4F 0b_0100_1111 019196 0x4AFC O 0x4F 0b_0100_1111 019197 0x4AFD O 0x4F 0b_0100_1111 019198 0x4AFE O 0x4F 0b_0100_1111 019199 0x4AFF O 0x4F 0b_0100_1111
We have 19200 = 160 × 120 pixels. The top row starts with five pixels with RGB values indexed by 0xDC (or 220 in decimal, and recall that the GCT maps color 220 to {0x0F, 0xA7, 0xF6}), the bottom row ends with index 0x4F.
Indeed, opening test/data/bricks-nodither.gif
in an image editor should verify that the top left pixel‘s RGB is {0x0F, 0xA7, 0xF6}, and likewise the bottom right pixel’s RGB is {0x01, 0x24, 0x63}.
See test/data/artificial/gif-*.commentary.txt