How GIF Files Specify Interlaced Pixel Data
A GIF file indicates whether its pixel data is stored in an interlaced or sequential order through a single dedicated bit located within the Image Descriptor block of each frame. By inspecting the "Packed Fields" byte of this descriptor, a decoding application immediately determines whether the subsequent compressed data should be rendered line-by-line from top to bottom or reconstructed using the standard four-pass interlacing scheme.
The Image Descriptor Block
Every distinct image or frame within a GIF stream begins with an Image Descriptor. This block contains metadata essential for rendering the visual data that follows. It is structured as follows:
- Image Separator: 1 byte (always hexadecimal value
0x2C) - Image Left Position: 2 bytes
- Image Top Position: 2 bytes
- Image Width: 2 bytes
- Image Height: 2 bytes
- Packed Fields: 1 byte
The tenth byte from the start of the Image Descriptor—the Packed Fields byte—contains several multi-purpose configuration flags, including the flag governing interlacing.
The Interlace Flag
The Interlace Flag is stored at Bit 6 of the Packed Fields byte (where bits are indexed from Bit 0 as the least significant bit to Bit 7 as the most significant bit).
The layout of the Packed Fields byte in the Image Descriptor is:
- Bit 7: Local Color Table Flag
- Bit 6: Interlace Flag
- Bit 5: Sort Flag
- Bits 4–3: Reserved
- Bits 2–0: Size of the Local Color Table
To determine the interlacing state programmatically, a decoder
applies a bitwise mask of 0x40 (binary
01000000) to this byte.
- Value 0: If Bit 6 is set to
0, the image is non-interlaced. The pixel data is written sequentially in normal raster order, starting from the top-left corner and proceeding row-by-row to the bottom-right. - Value 1: If Bit 6 is set to
1, the image is interlaced. The pixel data is arranged across four separate passes to allow a low-resolution preview to render while the file downloads.
The Four Interlacing Passes
When Bit 6 is set to 1, the decoder does not map the
decompressed LZW pixel stream sequentially. Instead, it populates the
frame rows in four distinct passes:
- Pass 1: Reads every 8th row, beginning at row 0 (rows 0, 8, 16, 24, ...).
- Pass 2: Reads every 8th row, beginning at row 4 (rows 4, 12, 20, 28, ...).
- Pass 3: Reads every 4th row, beginning at row 2 (rows 2, 6, 10, 14, ...).
- Pass 4: Reads every 2nd row, beginning at row 1 (rows 1, 3, 5, 7, ...).
Because each frame in a multi-frame GIF has its own Image Descriptor, individual frames within the same file can technically alternate between interlaced and non-interlaced formats, though in practice entire animations usually maintain a consistent structure.