2K or 4K: The Bits-Per-Pixel Trap Behind "Bigger Is Better"

Two encodes, same bitrate setting, different resolutions. The 4K one gets half the bits per pixel. This is arithmetically forced and almost never mentioned, and it is why some people report that 4K looks worse than the 2K they rejected.

14 November 2026 · x264 encodes measured with ffprobe

The question "should I go 2K or 4K" is usually answered with a resolution argument. It is not a resolution argument. It is a budget argument, and the budget is bits per pixel.

The arithmetic nobody puts in the table

Pixels scale with the square of the linear dimension. Going from 2K (1440×2160, 3.11 Mpx) to 4K (2160×3240, 7.00 Mpx) multiplies pixel count by 2.25. If you keep the same bitrate — which is what happens when the encoder target does not change — each pixel gets 2.25× fewer bits to describe itself.

Measured on a real 1080×1620 source, re-encoded with x264:

ResolutionTargetFile size Bits/pixel
2K (1440×2160)4M91,670 B0.2358
2K8M163,512 B0.4206
2K16M311,668 B0.8016
4K (2160×3240)4M112,027 B0.1281
4K8M195,656 B0.2237
4K16M371,061 B0.4242

Read across the 8M row: 2K gets 0.4206 bits per pixel, 4K gets 0.2237. Not exactly half, because the encoder is not perfectly efficient at reallocating, but close. Read across the diagonal instead and the useful insight appears: 4K at 16M (0.4242 bpp) is essentially the same bit density as 2K at 8M (0.4206 bpp) — and costs 2.27× the file size for 2.25× the pixels.

The rule that falls out. To keep quality constant when you double the linear resolution, you must roughly quadruple the bitrate. Going 2K→4K at the same bitrate is not "the same quality at higher resolution" — it is a deliberate quality cut in exchange for pixel count.

When 4K is genuinely the right answer

Three cases, and they are narrower than the marketing implies:

  1. The output is text or UI. Glyph edges are the highest-frequency content a video can contain, and they are also the most compressible-when-clean. A 4K screen recording of a document downscaled to 1080p for delivery loses legibility that no bitrate recovers, because the loss is spatial, not a compression artifact.
  2. The viewer will crop or zoom. If the frame is a canvas for later reframing, extra pixels are working space. This is a production argument, not a delivery one — the audience never sees the 4K master.
  3. The display is actually 4K and the viewing distance is close. At normal TV distance, human acuity stops resolving detail well before 4K on most content. On a monitor at arm's length, it does not.

When 2K wins outright

The common case: a source that was never 4K. If you start from 1080p or below and target 4K, you are spending 2.25× the bits describing detail that was interpolated, not captured. In the interpolation measurements, Lanczos at 4× retained 1.3% of the source's high-frequency energy versus 21.5% at 2×. You are paying full 4K bitrate for content that carries roughly one-seventeenth the detail information of a native 2× upscale.

That is the mechanism behind "the 4K looks worse." The upscale invented softness, then the encoder was given half the bits to describe the soft result, and soft content with too few bits develops banding and block edges that were not in the 2K version.

The cascade myth: does upscaling in two steps beat one?

Every upscaling forum eventually produces this advice: do not jump 4× in one step, go 2× twice, because "the algorithm has less work to do at each stage." It sounds mechanically plausible, which is why it survives. It is also false, and the reason it survives is that almost nobody measures it.

Six paths from the same 100px source back to a 400px ground truth. HF% is high-frequency energy relative to the ground truth (the same 2-D FFT radial mask used throughout these notes). coh is a metric I added for this test: high-frequency phase coherence against the ground truth, which asks whether the high frequencies present point in the same direction as the real ones. Phase coherence of 1.0 means the detail is real; 0.0 means the filter produced energy that has nothing to do with the original content.

coh = <Re(F_up * conj(F_gt))>_hf_band
      / ( |F_up|_hf_band * |F_gt|_hf_band )

On the synthetic Siemens star, 4× from 100px:

PathPSNRSSIM HF%cohp99 grad%
single 4× lanczos11.600.36111.30.13913.7
cascade 2× + 2× lanczos11.600.36191.50.13213.9
cascade 3 steps lanczos11.600.36151.50.13613.8
nearest mid, then lanczos11.620.36769.30.07624.3
sharpen at mid, then 2×11.670.39431.60.13320.3
single 4× + unsharp at end11.660.37712.00.14116.6
overshoot to 8×, down to 4×11.600.36121.40.13813.7

Read the second row against the first. The cascade bought 0.0001 SSIM and 0.2 points of HF, and actually lost phase coherence — 0.132 versus 0.139. Two steps are indistinguishable from one step. Three steps are indistinguishable from two. The overshoot detour to 8× and back cost roughly four times the compute for a result identical to one step in every column.

The same test on a real photo crop tells the same story with a different absolute scale (400px ground truth from a 100px source): single 4× gives PSNR 27.31 / HF 21.1% / coh 0.355; cascade 2×+2× gives 27.32 / 21.3% / 0.354. At 2× instead of 4× — 200px to 400px — direct was 13.69 dB at 21.5% HF and a 300px cascade was 13.68 dB at 21.3%. There is no scale factor at which cascading helps. Interpolation is a linear operator; two linear operators of the same total scale compose to the same thing, and the only difference is rounding noise in the 8-bit intermediate.

Why the myth feels true. Cascading does change one thing: it stores an intermediate file. If that intermediate is written as JPEG between steps, the second step is now sharpening compression artifacts, and the result looks different. Different is not better — it is the same operation plus a generation of loss.

What invented detail costs the encoder

The fourth row above is the interesting one. "Round it up with nearest-neighbour, then smooth" is a real technique — it is how pixel-art upscaling keeps edges crisp. On a star pattern it produces 7× the high-frequency energy of a single Lanczos pass: 9.3% versus 1.3%.

It also produces half the phase coherence — 0.076 versus 0.139. The extra energy is not recovered detail. It is the square staircase of nearest-neighbour, low-passed just enough to look like texture. PSNR barely notices (11.62, the highest in the table) because PSNR is computed per pixel against a blurred reference and staircase artifacts are locally small. The p99 gradient, which measures edge overshoot, jumps from 13.7% to 24.3%.

Now the part that connects back to bits per pixel. Invented high-frequency energy is not free at encode time. I generated three 4K frames from the same 1080×1620 source — one direct upscale, one 2K→4K cascade, one nearest-mid — and encoded each with x264 at CRF 18, 23, 28 and at a fixed 8M target:

Pre-encode 4K frameHF vs direct CRF 18 bytesCRF 23 bytesCRF 28 bytes bpp @CRF23
direct lanczos100.0%225,718140,26791,0690.1603
cascade 2K→4K95.3%225,936139,63590,9650.1596
nearest mid→4K176.4%256,865155,52496,2230.1778

Two clean readings. First, the cascade row is within 0.2% of the direct row at every CRF setting — negative at CRF 23 and 28, which is encoder noise, not a real saving. The 0.5% loss of HF energy that the cascade introduces shows up as a 0.5% smaller file, and as 0.10 dB lower PSNR against its own pre-encode frame. Nothing was gained; a little was lost.

Second, the nearest-mid row costs +14% / +11% / +6% more bytes at CRF 18 / 23 / 28 to encode the same content, while its fidelity against its own source frame drops (PSNR 46.69 versus 47.47 at CRF 18). The encoder is spending real bits describing a staircase that was never in the photograph. This is the bits-per-pixel trap of this page's first section, arriving from an unexpected direction: it is not only resolution that eats the budget, it is any high-frequency content you manufacture before encoding. Staircase detail has the worst possible cost-to-value ratio because it is maximally expensive to encode and entirely fictional.

Practical conclusion, in one line: upscale once, at the final size, and never pre-sharpen a frame you are about to encode. If the frame needs sharpening, sharpen it as the last step of the delivery pipeline or not at all — and expect it to cost 5–15% more bytes for the halo it adds.

Reproducing the cascade comparison

# ground truth, low-res source
python3 -c "from PIL import Image; im=Image.open('gt.png'); \
  im.resize((100,100), Image.LANCZOS).save('low.png')"

# one step vs two steps, then measure HF energy + phase coherence
ffmpeg -i low.png -vf scale=400:400:flags=lanczos               one.png
ffmpeg -i low.png -vf scale=200:200:flags=lanczos -y step.png
ffmpeg -i step.png -vf scale=400:400:flags=lanczos              two.png

# bit cost of the invented detail
ffmpeg -i src.jpg -vf scale=1440:2160:flags=neighbor -y mid.png
ffmpeg -i mid.png -vf scale=2160:3240:flags=lanczos   -y nm4k.png
for f in direct.png cascade.png nm4k.png; do
  ffmpeg -i $f -c:v libx264 -crf 23 -pix_fmt yuv420p ${f%.png}.mp4
  # bpp = size_bytes * 8 / (2160*3240)
done

How to decide per file, in one pass

  1. What is the source's true resolution? Not the container's. Check the actual detail — if the source was upscaled already, its real resolution is lower than its pixel count.
  2. What is the delivery target? Match it, do not exceed it. Delivering 4K to a 1080p player costs bandwidth and returns nothing.
  3. Compute the budget. Target bits-per-pixel for archival is roughly 0.4–0.8; for delivery, 0.1–0.2 is normal. Multiply by pixel count to get your bitrate, rather than picking a bitrate and accepting whatever bpp falls out.
  4. Check the soft-content case. If the content is smooth gradients (sky, skin, walls), low bitrate produces banding before it produces blockiness. That is a different failure and needs a different fix — higher bit depth, not higher bitrate.

Reproducing it

for res in "1440:2160" "2160:3240"; do
  for br in 4M 8M 16M; do
    ffmpeg -i src.png -vf scale=$res -b:v $br -c:v libx264 out.jpg
    # bpp = filesize*8 / (w*h)
  done
done

Try the comparison on your own file

To see the bits-per-pixel effect rather than trust the table, export the same source at both sizes with the same quality setting and compare them side by side at 100%: UpgoLAB handles photo and video upscaling to both 2K and 4K in the browser, which makes the A/B cheap enough to actually run. Look for banding in the gradients and block edges in the shadows — those are where a squeezed bit budget shows up first.

The decision is not "which is bigger." It is "how many bits do I have per pixel, and did the source ever contain detail to justify them."