Letterbox & Pillarbox: The Exact Math of Black Bars

Bar size = (box − scaled) ÷ 2 — letterbox/pillarbox math, which side the bars land on, windowboxing, and how to compute or avoid them.

Published 2026-10-02

Black bars are not a style choice the player made — they’re the only honest output of fitting one aspect ratio inside another. Once the math is visible, every bar you’ve ever seen is predictable to the pixel.

The one formula

Fitting a source sw × sh into a box bw × bh uses the smaller scale factor:

s  = min(bw ÷ sw, bh ÷ sh)
W' = sw × s
H' = sh × s
bars on each side = (box − scaled) ÷ 2   — on whichever axis fell short

The smaller factor is always bound by exactly one axis. The other axis comes up short, and the shortfall — split evenly — is the bar.

Which side gets the bars?

The aspect comparison decides it, no memorizing needed:

  • Source wider than box (src aspect > box aspect): width touches, height falls short → bars top and bottom = letterboxing. Cinema 2.39:1 in a 16:9 player is the canonical case.
  • Source taller than box (src aspect < box aspect): height touches, width falls short → bars left and right = pillarboxing. 4:3 or 9:16 content on a widescreen display.
  • Same aspect: no bars at all — fit fills the box exactly.

A quick orientation check: the content is the shape it keeps; the bars fill the rest. Tall content → bars stand beside it (pillars). Wide content → bars lie above and below it (a letter slot).

Worked examples (verify them on the scaler)

Source Box Scaled Bars
4:3 TV (1440×1080) 1920×1080 1440×1080 pillarbox 240 px each side
Cinema 2.39:1 (1920×803) 1920×1080 1920×803 letterbox ~138 px each
9:16 phone video (1080×1920) 1920×1080 607×1080 pillarbox ~656 px each
16:9 clip (1920×1080) 1080×1920 story 1080×607 letterbox ~656 px each
Ultrawide 21:9 (2560×1080) 1920×1080 1920×810 letterbox 135 px each

That symmetric pair — vertical video in a widescreen player vs widescreen video in a vertical story — is the same ×0.5625 fit flipped, which is why the bars come out identical.

The half-pixel problem

(box − scaled) ÷ 2 isn’t always an integer: (1080 − 803) ÷ 2 = 138.5. Renderers split the remainder unevenly — 138 px one side, 139 the other — or round the scaled size to even first so the remainder lands whole. Video encoders do the second: an even-aligned output can’t have a fractional bar, which is one more reason codec-facing sizes round to even.

Windowboxing: bars on all four sides

Windowboxing is bars baked into the content meeting more bars at playback. Classic chain: a widescreen film letterboxed into a 4:3 broadcast master → that 4:3 master pillarboxed into a 16:9 stream. The image floats in a black frame with real pixels storing the black.

No scaling mode removes baked bars — they’re part of the image. The fix is detection + crop: find the bar region (FFmpeg’s cropdetect does it automatically: cropdetect=limit=24:round=2), crop it out, then fit normally. The tell is a 16:9 file whose “content” is actually a different aspect — compute the aspect of the non-black region, not the file.

Removing bars vs choosing them

Bars exist because fit refuses to crop or distort. The alternatives are the other two honest modes from the fit/fill/stretch guide: fill (crop the overflow — YouTube’s “zoom to fill” button) or stretch (distort — the mode that made a generation of 4:3 TVs play squashed widescreen). A fourth option exists when you control the pipeline: export the content’s native aspect and let the player letterbox — which is exactly what happens when a 2.39:1 file plays in a 16:9 window.

For deliberate letterboxing — say, burning cinema bars into a 16:9 deliverable — FFmpeg’s pad filter takes the same formula: pad=W:H:(ow-iw)/2:(oh-ih)/2:black centers the scaled image on a black canvas. CSS does it visually for free: object-fit: contain inside a fixed box is the bar formula, rendered live.

Frequently asked questions

Letterbox vs pillarbox — which is which?

Letterbox = horizontal bars, top and bottom: a wider source inside a taller/narrower box (2.39:1 cinema on a 16:9 TV). Pillarbox = vertical bars, left and right: a taller/narrower source inside a wider box (4:3 archive footage on a 16:9 screen). The names describe where the bars stand — letterbox bars lie flat like a mail slot, pillarbox bars stand like columns.

How do I compute the bar size exactly?

Scale the source by s = min(boxW÷srcW, boxH÷srcH), then the bar on the non-touching axis is (box − scaled) ÷ 2 on each side. 2.39:1 film into a 1920×1080 frame: scaled 1920×803 → (1080 − 803) ÷ 2 ≈ 138.5 px bars top and bottom. If the result is a half-pixel, one side gets one extra row — encoders and players handle this by rounding differently, so expect 138/139.

What is windowboxing?

Bars on all four sides — it happens when content was already letterboxed and then gets pillarboxed into an even wider frame (a 4:3 broadcast of a widescreen movie, played on a 16:9 TV). The picture floats in a black rectangle. There's no scaling fix because the bars are baked into the pixels — the fix is cropping the baked bars out first.

How do I add letterbox bars deliberately in FFmpeg?

Two filters: scale with aspect preservation, then pad to the container: scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:black. The (ow-iw)/2 expression is the bar formula itself — output minus input, halved, centered.

Why does my 'fit' result show bars of 0 px but still leaves a gap?

Half-pixel remainder or a rounding mismatch — the scaled height rounded down to an integer leaves a 1-px (or sub-pixel) seam some renderers show as a hairline. Rounding the scaled side up instead, or padding by one pixel and cropping after, both eliminate it. For video it never arises — even-rounded dims make the remainder whole.