semmixcolor and perception

Graphic control ($F9)

This short block sits before an image and says how to show it: which color is transparent, how long to wait before the next frame, and what to do with the image before the next one appears. Without it there would be no animated GIFs and no transparency.

Structure

BytesField
0-121 F9
2block size: always 04
3flags
4-5delay in hundredths of a second (little-endian)
6transparent color index
7terminator 00

The flag byte

bits 7-5 reserved (0) bits 4-2 disposal method bit 1 wait for user input bit 0 transparent color enabled
DisposalMeaning
0unspecified; decoders treat it like 1
1leave the image; the next frame is drawn over it
2restore to background: clear the frame's rectangle
3restore to what was there before the frame was drawn

Method 1 lets later frames store only the changes. Method 2 is needed when a transparent object moves across the background. Method 3 is the least used and the hardest for a decoder, because it has to remember part of the screen.

Examples

21 F9 04 00 00 00 00 00 │ └─┬─┘ │ │ │ └─ transparent index: 0 (unused, since bit 0 = 0) │ └───── delay: 0 └────────── flags 00: no transparency, disposal 0 this is what the example file has: the block changes nothing
21 F9 04 05 32 00 01 00 │ └─┬─┘ │ │ │ └─ transparent color: index 1 (white) │ └───── delay 0x0032 = 50 → 0.5 s └────────── flags 05 = 00000101: disposal 1, transparency on

Replacing the block in the example file with the second version would make the white pixels transparent.

Delay in practice

The delay counts hundredths of a second, so the shortest possible is 0.01 s. Browsers, however, treat very small values (0 and 1, i.e. 0-0.01 s) as 0.1 s, so old GIFs with zero delay do not flash too fast. Smooth GIF animation is in practice 2-6 hundredths per frame, about 17-50 frames per second.

The block applies only to the single image (or plain text) that follows it. Every animation frame has its own $F9 block (see block order).