How to Resize an Image Without Losing Quality
Resizing an image always changes the data. When you scale down, the software discards pixels; when you scale up, it invents them. The right resampling filter and output format makes that change invisible at normal viewing distances.
Resampling methods
The filter the software uses when resizing determines how sharp the result looks.
| Method | Best for | Notes |
|---|---|---|
| Lanczos | Photos, downscaling | Sharpest result; slight ringing on hard edges |
| Bicubic | Photos, general use | Good quality; standard default in most tools |
| Bilinear | Fast previews | Softer; faster to compute |
| Nearest neighbor | Pixel art, icons | Preserves hard edges; wrong for photos |
For downscaling photos, Lanczos produces the sharpest output. For pixel art or icon sprites, nearest neighbor keeps the crisp edges intact.
In the browser
Drag an image into the image resizer, enter the target width or height, and download. Lock the aspect ratio before entering dimensions to avoid stretching. The tool runs client-side — the image doesn't leave your device.
ImageMagick (command line)
# Resize to 800px wide, maintain aspect ratio
convert input.jpg -resize 800x output.jpg
# Resize to exact dimensions (stretches if ratio differs)
convert input.jpg -resize 800x600! output.jpg
# Fit within a bounding box without upscaling
convert input.jpg -resize 800x600> output.jpg
# Resize with Lanczos resampling
convert input.jpg -resize 800x -filter Lanczos output.jpg
# Resize and convert to WebP at quality 85
convert input.jpg -resize 800x -quality 85 output.webp
The > flag prevents upscaling — useful when batch processing files of unknown dimensions.
sharp (Node.js)
npm install sharp
const sharp = require('sharp');
// Resize to 800px wide, maintain aspect ratio
sharp('input.jpg')
.resize(800)
.toFile('output.jpg');
// Resize to exact dimensions, crop to fill
sharp('input.jpg')
.resize(800, 600, { fit: 'cover', position: 'centre' })
.toFile('output.jpg');
// Resize with Lanczos kernel
sharp('input.jpg')
.resize(800, null, { kernel: sharp.kernel.lanczos3 })
.toFile('output.jpg');
// Resize and convert to WebP
sharp('input.jpg')
.resize(800)
.webp({ quality: 85 })
.toFile('output.webp');
fit: 'cover' crops to fill exactly. fit: 'contain' adds letterboxing. fit: 'inside' fits within the box without cropping or padding.
Python: Pillow
from PIL import Image
with Image.open('input.jpg') as img:
ratio = 800 / img.width
new_height = int(img.height * ratio)
resized = img.resize((800, new_height), Image.LANCZOS)
resized.save('output.jpg', quality=85, optimize=True)
Image.LANCZOS is the highest-quality downsampling filter in Pillow. In Pillow 10+, it's also available as Image.Resampling.LANCZOS.
The thumbnail() method preserves aspect ratio and never upscales:
from PIL import Image
with Image.open('input.jpg') as img:
img.thumbnail((800, 800), Image.LANCZOS) # fits within 800×800
img.save('output.jpg', quality=85)
Upscaling
Upscaling always loses quality — the software has to invent pixel data that didn't exist. Standard bicubic upscaling looks blurry past about 1.5× the original size.
AI upscalers (Real-ESRGAN, Topaz Gigapixel) produce sharper results at 2–4× but are slow and overkill for most web work. For websites, avoid upscaling: start with a source image large enough for your largest display size.
Retina and HiDPI displays
A retina screen has 2× the pixel density of a standard screen. An image displayed at 400 px CSS width needs an 800 px source file to look sharp. Serve both sizes with srcset:
<img
src="image-400.jpg"
srcset="image-400.jpg 1x, image-800.jpg 2x"
width="400"
alt="Description"
/>
Common output sizes
| Target | Recommended dimensions | Format |
|---|---|---|
| Web banner / OG image | 1200×630 | WebP |
| Blog post image | 800–1200px wide | WebP |
| Instagram square | 1080×1080 | JPEG |
| Twitter/X card | 1200×675 | JPEG |
| Email header | 600px wide | JPEG |
| Favicon | 32×32, 180×180 | PNG |
Key takeaways
- Lanczos resampling gives the sharpest result for downscaling photos — use it by default.
- Never upscale: source images should always be larger than the display size.
- After resizing, convert to WebP at quality 80–85 for the smallest file at good quality.
fit: 'cover'in sharp andthumbnail()in Pillow both handle aspect ratio automatically.- Serve 2× images via
srcsetfor retina screens.