Which filter you pass to resize changes the result more than most people expect. Open an image and see all four on the same picture.
Nothing is uploaded. The resizing happens in your browser.
| Filter | Use it for | Watch out for |
|---|---|---|
NEAREST | Pixel art, masks, palette images, anything where invented colours are wrong | Jagged edges and dropped detail when shrinking |
BILINEAR | Quick previews, mild enlargement | Soft results, poor when shrinking a lot |
BICUBIC | General enlargement, a reasonable default | Slight halos on hard edges |
LANCZOS | Shrinking photographs, thumbnails you care about | Slowest, and can ring on very sharp edges |
from PIL import Image
im = Image.open("photo.jpg")
small = im.resize((320, 240), Image.Resampling.LANCZOS)
If you only take one thing away: when you are shrinking, the filter matters far more than when you are enlarging, because the filter decides how many original pixels contribute to each new one. NEAREST looks at exactly one and throws the rest away, which is why fine detail turns into noise.
Yes, the same maths, implemented here in JavaScript. The kernels are the ones Pillow uses, including the support widening that Pillow applies when shrinking, which is the part that makes the difference between a proper filter and a browser resize.
Checked against Pillow 12 on an 800 pixel image reduced to 200: NEAREST comes out pixel for pixel identical, and the other three differ by an average of under a tenth of one level of brightness, which is rounding.
im.thumbnail(size) already uses a good filter by default and keeps the aspect ratio, so for simple thumbnails you rarely need resize at all. It also changes the image in place rather than returning a new one.