Making a 4K Thumbnail Master From a 720p Frame

A thumbnail is never viewed at its own resolution. It is viewed shrunk — which means the only thing that matters is whether detail survives the second downscale. That inverts almost every normal upscaling rule.

14 November 2026 · round-trip measurement at feed scale

Thumbnail workflows have a strange shape. You start with a 1280×720 frame, upscale to 2560×1440 or larger "for quality," and then the platform displays it at 320×180 in a feed. Any work you did at step two is judged entirely by what survives step three.

This changes the target. A thumbnail is not a print. It is not a still. It is a signal that has to read at 5% of its pixel count, and upscaling decisions that improve the file can make that signal worse.

The mechanism: downscaling is a low-pass filter

When the platform shrinks your 2560px thumbnail to 320px, it averages 8×8 blocks of your pixels into one output pixel. Any detail finer than that block is not "compressed" — it is averaged away. A one-pixel highlight, a thin outline, a sharpened edge: all of it contributes to the same grey average as the flat colour next to it.

So the question for a thumbnail master is not "how sharp is this at 100%." It is "does this still read when averaged 8:1." Those are different questions with different answers, and a sharpened file often loses the second one.

What sharpening does to a shrunk thumbnail

Unsharp mask adds an overshoot: a dark rail and a bright rail either side of each edge. At 100%, that reads as crispness. Averaged 8:1, the bright rail and the dark rail are in the same output pixel as the edge itself, so they cancel out to approximately the original value — and the apparent contrast gain disappears entirely. What remains is the part of the overshoot that spread into the flat areas, which reads as a muddy halo.

Most of the sharpening you can see at 100% does not survive the feed — but not all of it, and the exception is measurable. The overshoot at a typical radius vanishes into the average. A small-radius pass that tightens the two-pixel transition the downscale itself created survives, and is worth 2.9 dB. The numbers are two sections down.

What survives the shrink

Content that survives an 8:1 reduction has to be structurally large:

None of those are improved by upscaling. All of them are improved by composition.

So why upscale at all?

Three legitimate reasons, none of which is "quality":

  1. Platform requirement. YouTube asks for 1280×720 minimum. If your frame is 640×360, you must upscale to upload, and the question becomes which method loses least.
  2. Headroom for cropping. A 2× master lets you reframe to a different aspect ratio for different platforms without going below the minimum.
  3. Text overlay rendered after upscaling. If you upscale first and then render text at final resolution, the text is natively sharp and survives the shrink. This is the one workflow where upscaling genuinely helps — because the important content is not upscaled at all.

Reason 3 is the whole trick. Upscale the photograph, then add the text at master resolution. The face gets the upscaler's output; the words get native pixels. The words are what carries the click, and they were never resampled.

Which method, if you must

For the photographic part, the earlier measurements apply: Lanczos and bicubic retain detail better than bilinear, and at 2× they retain roughly 21% of high-frequency energy versus 1.3% at 4×. So scale as little as the platform allows — from 720p, 2× gets you to 1440p, which exceeds the 720p minimum comfortably.

On sharpening, the measurement two sections below revises this: it is not that sharpening never survives, it is that the radius has a budget. Keep it under about 0.4 feed pixels — 3px in a 2560px master — and it buys back 2.9 dB. Go past 0.5 and the halo is the only part that arrives.

Testing that claim against the feed grid

Everything above is reasoning. This section is a measurement, and it partly contradicts what the earlier paragraphs assert — so it is worth stating exactly what was tested and what came back.

The design uses the feed pixel grid as ground truth, because that is the only image the viewer ever sees. Build the scene you want the viewer to see at 320×180: a hard vertical edge between background and subject, a smooth gradient panel, a fine noise texture, and 1-pixel lines. Upscale it 8× to 2560×1440 — the "master". Apply unsharp mask at master resolution, which is what an editor does. Downscale back to 320×180 with Lanczos, which is what the platform does. Then score the result against the ground truth.

The variable that turns out to matter is not the amount of sharpening. It is the radius expressed in feed pixels. A radius of 8px in a 2560px master is 1px in the 320px feed — inside one output pixel, where averaging cancels it. A radius of 3px in the master is 0.375px in the feed, which is smaller than a feed pixel but still enough to reinforce a transition that averaging has spread over two of them.

USM radius
(feed px)
Radius
(master px)
Edge swing
at 100%
Edge contrast
at feed
Halo
(flat MAE)
PSNR vs
feed truth
none—205.0 0.67901.7130.26 dB
0.1251.0210.0 0.67901.5930.82 dB
0.2502.0219.0 0.68111.4232.56 dB
0.3753.0 235.00.67901.30 33.14 dB
0.5004.0248.0 0.67901.4832.29 dB
1.0008.0255.0 0.67702.4028.42 dB
2.00016.0255.0 0.73513.5926.22 dB

Two things in that table are worth separating, because they point in opposite directions.

The claim about edge contrast holds exactly. The feed-scale edge contrast is 0.6790 with no sharpening and 0.6790 at the best radius. No amount of work at master resolution moves it, because the edge already spans two feed pixels and averaging preserves the mean across them. The overshoot you see at 100% — the edge swing climbing from 205 to 255 — is invisible at feed scale. That part of the earlier argument is confirmed by measurement, not asserted.

The claim that sharpening "evaporates" does not hold, and the reason is instructive. At a radius of 0.375 feed pixels, sharpening improves fidelity to the feed truth by 2.88 dB and cuts flat-area error from 1.71 to 1.30 — a 24% reduction. The sharpening did not add contrast the viewer can see. It partially undid the blur that the downscale itself introduced, by pulling the two-pixel transition back toward its original slope. That is a real gain and it survives the resize.

Past about half a feed pixel the picture inverts. At 1.0 feed px the result is 1.84 dB worse than doing nothing, and flat-area error has risen by 40%. At 2.0 feed px the edge contrast itself finally moves — 0.7351 instead of 0.6790 — but that movement is the halo being counted as subject, not a cleaner edge. The file looks sharper at 100% while being further from what the viewer should see.

The real rule is a radius budget, not a ban. Sharpening a thumbnail master helps up to roughly 0.4 feed pixels of radius and hurts past 0.5. In a 2560px master shown at 320px that budget is 3px. In a 1440px master it is under 2px. Any unsharp mask preset that ships with a radius of 1.0 or higher — which is most of them, expressed in master pixels — is spending more than the budget on the large majority of masters.

Master resolution barely matters

The same sweep run at 2560×1440, 1280×720 and 640×360 produces, with no sharpening, feed results within 0.06 dB of each other (30.26 / 30.25 / 30.20). At the best radius the spread widens to 0.71 dB (33.14 / 33.27 / 32.56) — the middle ratio does marginally best, which is the usual hit-and-miss of resampling phase rather than a real trend. An 8× master is not a better thumbnail master than a 2× one. Once the downscale to feed size happens, the extra intermediate resolution is averaged away exactly as the fine detail was.

This does not invalidate the headroom argument in the previous section — a 2× master still buys you reframing room across aspect ratios. It does mean that "upscale higher for a better thumbnail" has no basis in the pixels that reach the viewer. Use the smallest master that satisfies the platform minimum and your crop requirements, then spend the effort on the radius budget above.

Text: after the upscale wins on sharpness, loses on fidelity

The checklist says to render text after upscaling. Rendering it at 40px into the 320px feed and then round-tripping the whole composite through an 8× upscale and back gives glyph acutance 77.5 against 82.9 for text rendered natively at feed size — 6.5% softer, from two extra resamples. Rendering the same text at 320px into the 2560px master and downscaling once gives 85.9, which is 3.6% sharper than the native truth.

So the recommendation on the page is right, but for a slightly different reason than stated. Text composited after the upscale is not merely "not resampled" — it is resampled exactly once, at a resolution high enough that the single downscale overshoots and the glyphs come out marginally crisper than if they had been drawn at feed size. Note that this is a sharpness advantage, not an accuracy one: measured as plain MSE against the feed-res render, the pre-upscale route scores 44.4 dB and the post-upscale route 29.7 dB, because the two are at different subpixel phases and MSE penalises that. Acutance is the metric that matches what the eye does with a 7px glyph.

One more thing the sweep showed: non-integer master ratios are not a problem. Masters at 1.5×, 2×, 2.5×, 4× and 8× all land within 0.23 acutance units of each other after the round trip. There is no reason to force a power-of-two master for the feed's sake.

import numpy as np
from PIL import Image, ImageFilter

gt   = Image.fromarray(scene.astype(np.uint8), "L")     # 320x180 truth
S    = 8
master = gt.resize((320*S, 180*S), Image.LANCZOS)

for r_feed in (0, 0.125, 0.25, 0.375, 0.5, 1.0, 2.0):
    img = master if r_feed == 0 else master.filter(
        ImageFilter.UnsharpMask(radius=r_feed*S, percent=100, threshold=0))
    feed = np.asarray(img.resize((320, 180), Image.LANCZOS), dtype=np.float64)
    mse  = np.mean((feed - scene) ** 2)
    print(r_feed, round(10*np.log10(255**2/mse), 2))   # peaks at 0.375

Reproducible with the scene built in eight lines: a flat background, a bright rectangle at x=150, a linear gradient ramp, gaussian noise at σ=22, and 1px rules every four rows. Results were stable to ±0.02 dB across five random seeds.

A checklist that matches how thumbnails are consumed

  1. Compose at final aspect ratio. Do not plan to crop after.
  2. Upscale the photo only as far as the platform minimum requires.
  3. Add text after upscaling, at master resolution, bold enough to survive 8:1.
  4. Shrink the result to 320px wide and look at that — not at the master.
  5. If it does not read at 320px, fix the composition. No filter will save it.

Step 4 is the only one that matters and the only one almost nobody does. The file you are proud of and the file that gets clicked are separated by one downscale, and only the second one exists as far as the audience is concerned.

Reproducing the check

# the only test that reflects delivery
master = Image.open("thumb_master.png")
preview = master.resize((320, 180), Image.LANCZOS)
preview.save("feed_preview.png")
# look at feed_preview.png, not at master

Try the whole loop

If the source frame is small, or you need headroom for multiple aspect ratios, a browser-based upscaler removes the install step: UpgoLAB upscales photos and short video in the browser to 2K and 4K. Use 2× for the photo, then compose text at the final size.

Then shrink it to 320px and look. That is the only review that counts.