What is an Interlaced GIF?

An interlaced GIF stores image rows in four passes rather than sequentially. A decoder can therefore show a coarse version of the complete image before enough data arrives to render every row.

How Interlaced GIFs work

GIF interlacing changes only the order in which a frame’s rows enter the LZW-compressed image data. The first pass covers the full height sparsely and later passes fill the gaps. The preview that results is a decoder behavior, not something the format prescribes: GIF89a defines the row order, and a decoder may paint rows as they arrive. Firefox’s deinterlacing filter, for example, copies each received row into the neighboring rows that have not arrived yet when progressive display is enabled. The color table, dimensions, transparency rules, and final pixels are the same as for sequential storage. Libraries differ in who undoes the reordering: giflib’s DGifSlurp places the rows of an interlaced frame at their final positions using the four pass offsets, calling the line-level reader once per row in stored order.

Key facts

  1. In what order are the rows stored? Pass 1 holds every 8th row starting with row 0, pass 2 every 8th row starting with row 4, pass 3 every 4th row starting with row 2, and pass 4 every 2nd row starting with row 1. GIF89a fixes this pattern, so a decoder has about an eighth of the rows after pass 1, a quarter after pass 2, and half after pass 3 (exactly so when the height is a multiple of 8). Short frames leave passes empty: with four rows or fewer there is no pass 2 row, and a one-row frame has only pass 1. A de-interlacer has to check each pass’s starting row against the frame height before it copies a row: a public bug report against the APNG4Android GIF decoder describes it writing past its output buffer on a two-row interlaced frame because it copied a pass 2 row first.
  2. How do I tell whether a GIF is interlaced? Per frame, not per file. The Interlace Flag is one bit in the packed byte of each Image Descriptor (giflib tests it with the mask 0x40), and every image in the data stream has its own descriptor, so frames of one animation can differ. Tools do not always surface the flag: a libvips user asked for an interlaced field in the GIF header output after gifsave gained an interlace option.
  3. Does interlacing add anything besides the preview? No. The reordered rows are still indexes into the active color table, compressed with LZW, and transparency is still the single index named in the Graphic Control Extension. Interlacing adds no colors and no partial transparency.
  4. Will my tools write interlaced GIFs without being asked? Some will, and not on every code path. Pillow’s handbook says its interlace save option is on by default unless the image is less than 16 pixels wide or high. In Pillow’s source (release 12.0.0 and the main branch as read in October 2026) only the single-frame writer applies it: passing interlace=False there switches it off, while frames written by a multi-frame save (save_all producing more than one frame) always get a cleared Interlace Flag and sequential rows. Gifsicle leaves it to the caller: --interlace turns it on, and --same-interlace keeps each input’s existing setting. Set the option explicitly when a downstream consumer expects one layout, and read the flag of the frames you wrote instead of inferring it from the default.

When Interlaced GIFs matter

Interlacing matters in two places. For delivery, it changes the order in which rows arrive, which lets a decoder show a coarse version of the whole frame early. It is a row order, not a compression setting, but the reordered rows are what LZW compresses, so the encoded size is not guaranteed to match the sequential encoding. GIF89a does not say how interlacing affects size, so compare the two outputs instead of assuming they are equal or that one is smaller. For processing, interlaced files are still being produced, since Pillow interlaces single-frame GIFs by default when it saves them, so any code that reads GIF image data row by row has to put the rows back in order before it crops, resizes, or converts a frame.

Sources

Turn media knowledge into a working pipeline

Connect uploads, processing, AI, storage, and delivery through one declarative API — with the encoding stack, scaling, and format churn handled for you.

Try Transloadit for free