How Interlaced GIF Second Pass Fills Pixel Rows

Interlaced GIFs allow images to render progressively as they download, transitioning from a blurry silhouette to a sharp image across four distinct passes. During the second pass, the decoder reads the scanlines positioned halfway between the rows rendered in the first pass, effectively halving the vertical blockiness of the preview. This article explains the exact scanline intervals targeted in the second pass and how rendering decoders handle the remaining unread pixels to construct a coherent image on screen.

The Interlacing Pattern

The GIF specification (both GIF87a and GIF89a) organizes interlaced scanlines into four distinct passes rather than reading the image sequentially from top to bottom. Each pass covers a specific set of rows across the image height:

Row Targeting in the Second Pass

In the raw data stream, the second pass does not actually contain any missing pixel rows; it strictly contains the compressed pixel data for row 4 and every subsequent 8th row (index \(4 + 8k\)).

The decoder writes this incoming data directly into its internal frame buffer at scanlines 4, 12, 20, and so on. Because rows 0, 8, 16, and 24 were already established in Pass 1, the addition of Pass 2 places a valid scanline precisely in the middle of each 8-row gap.

Filling the In-Between Rows on Display

Until all passes are complete, the rendering engine must decide how to visualize rows that have not yet been transmitted (rows 1–3 and rows 5–7). Decoders handle these missing rows using vertical pixel replication:

  1. Splitting the Blocks: After Pass 1, a viewer typically renders row 0 across rows 0 through 7, creating uniform blocks of 8 pixels in height. When Pass 2 arrives, the decoder updates the canvas.
  2. Assigning the Midpoint: The decoder paints the true data for row 4.
  3. Downward Replication: To fill the surrounding missing rows, the decoder replicates the newly received row 4 downward across rows 5, 6, and 7.
  4. Preserving Earlier Data: Rows 1, 2, and 3 continue to display the replicated data from row 0.

By replacing the original 8-pixel-tall solid blocks with two separate 4-pixel-tall blocks (one sourced from row 0, the other from row 4), the second pass doubles the perceived vertical resolution of the preview while awaiting the finer details delivered in the third and fourth passes.