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:

  1. Pass 1: Reads every 8th row, beginning at row 0 (rows 0, 8, 16, 24, ...).
  2. Pass 2: Reads every 8th row, beginning at row 4 (rows 4, 12, 20, 28, ...).
  3. Pass 3: Reads every 4th row, beginning at row 2 (rows 2, 6, 10, 14, ...).
  4. 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.