semmixcolor and perception

The GIF file header

Every GIF file starts with six bytes: three signature letters and three version characters. It is the simplest block in the format and the only one without an identifying byte.

Structure

BytesLengthContents
0-23signature: 47 49 46 = "GIF"
3-53version: 38 37 61 = "87a" or 38 39 61 = "89a"

In the example file (see the introduction):

47 49 46 38 39 61 → "GIF89a"

87a or 89a

GIF89a added extension blocks (byte 21) and two new meanings for existing fields. A file with no extensions is practically identical in both versions.

Feature87a89a
images, palettes, LZW, interlacingyesyes
transparency, delay, frame disposalnoyes ($F9)
commentsnoyes ($FE)
plain textnoyes ($01)
application data, animation loopnoyes ($FF)
palette sort flag, pixel aspectreserved fieldsyes

The specification recommends writing "87a" if the file uses nothing from 89a, and "89a" otherwise. In practice nearly all software always writes "89a", and every modern decoder reads both versions the same way.

Detecting the format

A file's first bytes (its magic numbers) identify the format without looking at the file name extension:

FormatFirst bytes
GIF47 49 46 38 ("GIF8")
PNG89 50 4E 47 0D 0A 1A 0A
JPEGFF D8 FF
WebP52 49 46 46 ("RIFF"), then "WEBP" from byte 8
const isGif = (b) => b[0] === 0x47 && b[1] === 0x49 && b[2] === 0x46 && b[3] === 0x38;

The logical screen descriptor begins right after the header.