Two stacked charts of Pillow resampling filters, the upper one showing mean WebP file size against quality with NEAREST highest and BILINEAR lowest at every setting, the lower one showing mean resize time with NEAREST fastest and LANCZOS slowest

Top: mean encoded WebP size at each quality setting, one line per resampling filter, same eight images and the same 512 pixel box every time. The lines never cross. Bottom: what each filter costs to run, best of three per image. NEAREST is the trap, because it is the only one that is both the fastest and the biggest. Charts generated from the measurement run described below.

Lanczos Ships The Biggest WebP Of The Four Real Filters, And Bilinear Is 14 Percent Smaller

Every guide says use Lanczos and stop thinking about it. Lanczos is the sharpest filter here and sharpness is exactly what a lossy encoder has to spend bytes on, so the advice that sounds like quality advice is also a 14 percent bandwidth decision nobody told you they were making for you.

Published September 12, 2026 · RealAIGirls · About an 8 minute read

Share on X Share on Facebook Share on Reddit

There is a piece of advice in every image pipeline guide ever written. When you downscale, use Lanczos. It is the highest quality filter, it is what ImageMagick reaches for, it is what the Pillow docs point you at, and nobody argues about it.

Nobody measures what it does to the file you ship, either. So I did.

The Measurement

Eight source images from this gallery, the same eight used in every measurement piece here. Each one downscaled to fit a 512 pixel box using five Pillow resampling filters, NEAREST, BILINEAR, HAMMING, BICUBIC and LANCZOS, then encoded as WebP at quality 50, 60, 70, 75, 80 and 85 with method 4. That is 240 encodes. Resize time is best of three runs per image per filter.

The source is the same picture every time. The output box is the same size every time. The encoder settings are the same every time. The only variable in the whole run is which filter did the downscale.

The Result

FilterMean bytesvs LANCZOSMean resize timeSSIM vs the LANCZOS output
NEAREST30,881+12.22%0.81 ms0.99266
BILINEAR23,688-13.92%11.29 ms0.99771
HAMMING25,970-5.62%10.43 ms0.99849
BICUBIC26,303-4.41%17.07 ms0.99890
LANCZOS27,5170.00%25.69 ms1.00000

Lanczos produced the largest files of the four real filters and took the longest to run. That is not a defect and it is not a surprise once you say out loud what these filters do. Lanczos has the widest kernel and preserves the most high frequency detail. High frequency detail is precisely the thing a lossy encoder cannot compress cheaply. The sharper the input, the more bytes the output costs.

It Holds At Every Quality

A single average can hide a crossover, so here is the gap at each setting.

QualityBILINEARLANCZOSDifference
5017,28020,244-14.64%
6019,27622,426-14.05%
7021,63825,136-13.92%
7522,89126,662-14.14%
8027,46531,862-13.80%
8533,57638,773-13.40%

Six settings, a spread of 13.40 to 14.64 percent, no crossover anywhere. The lines in the chart above are parallel because the effect is structural, not a quirk of one quality target.

NEAREST Is The Only Real Trap

Everything else on that table trades something for something. NEAREST does not. It is 12.22 percent bigger than Lanczos and the least similar to it, at 0.99266, while being thirty times faster to run.

That combination has one cause. Nearest neighbour downscaling throws away every pixel it does not sample, which leaves hard aliased edges everywhere, and aliased edges are the most expensive thing you can hand a lossy encoder. You save eleven milliseconds of resize and pay for it in every byte served to every visitor forever.

If a thumbnail pipeline anywhere in your stack is using NEAREST because it was the fastest option in a dropdown, that is the single highest value change on this page.

What The SSIM Column Is And Is Not

This has to be said plainly or the table is misleading. The SSIM figures compare each filter's decoded output against the Lanczos output at the same quality. They are not measured against ground truth, because at a 512 pixel box there is no ground truth, only five defensible answers to the same question.

So 0.99771 for BILINEAR does not mean bilinear is 99.771 percent as good. It means bilinear lands very close to where Lanczos lands, and the difference is concentrated in fine detail. Whether that detail matters is a judgment about your images and your audience, and nothing in this measurement can make it for you.

What the measurement does settle is the price. The detail costs 14 percent of your bytes and 14 milliseconds per image, and now you know what you are buying.

What I Changed

BILINEAR for gallery thumbnails. At a 512 pixel box, on AI generated art that is already soft in the background, the difference from Lanczos is not visible to me at full attention and it is 14 percent of the transfer.

BICUBIC where the image has text or hard geometry. It is 4.41 percent under Lanczos, runs in two thirds the time, and holds edges much closer, 0.99890.

LANCZOS stays for anything that gets downloaded rather than browsed. If the file is the product, ship the sharpest version and let it cost what it costs.

NEAREST nowhere. There is no case for it in a downscale.

Method

Pillow, Image.resize to a 512 pixel long edge with each of the five filters, then save to WebP with method=4 at each quality. Sizes are exact byte counts of the encoded buffer. Resize time is the best of three runs, timed with perf_counter, which measures the resize alone and not the encode. SSIM is the global single window form on the luma channel, comparing each decoded WebP against the decoded Lanczos WebP at the same quality. Eight images, five filters, six qualities, 240 encodes. The source images are the same eight PNGs used in every measurement piece on this site so the runs stay comparable to each other.