semmixcolor and perception

Extension blocks ($21)

GIF89a added extensions to the format: blocks that hold no pixels but say how to show them, or carry extra data. They all share one structure, so a decoder can skip any it does not know.

Common structure

21 extension introducer ("!") xx label: the kind of extension [n ...n bytes] fixed block (not every extension has one) [n ...n bytes] data sub-blocks, as many as needed 00 terminator

Formally the fixed block is just the first sub-block. The specification singles it out because its length and byte meanings are set in advance.

The four standard extensions

LabelNamePurposeUsed?
F9graphic controltransparency, frame delay, disposalvery often, in every animation
FFapplication extensionprogram data, e.g. the animation loop countoften (NETSCAPE2.0)
FEcommenttext not shown in the imagesometimes
01plain texttext drawn on the imagealmost never

Labels 00-7F are meant for extensions that draw something, 80-F9 for control extensions, FA-FF for special ones. In practice no new official labels were ever added. New uses (XMP, ICC profiles) rely on the $FF application extension with their own identifier.

Skipping an unknown extension

// pos points at byte 21; returns the position after the terminator
function skipExtension(b, pos) {
  pos += 2;                                  // 21 and the label
  for (let n = b[pos++]; n !== 0; n = b[pos++]) pos += n;
  return pos;
}

This one function is enough to keep a decoder from stopping at an extension it does not understand. That is why 1990s browsers displayed GIFs with blocks added long after they were released.

In the example file

21 FE 09 73 65 6D 6D 69 78 2E 70 6C 00 comment "semmix.pl" 21 F9 04 00 00 00 00 00 graphic control

The whole file is broken down in the introduction.