How to Reduce Image File Size: 10 Methods That Work
Make image files smaller without losing quality. Tested methods for JPEG, PNG, WebP - everything you need.
How to Reduce Image File Size: 10 Methods That Work
Make images smaller. Here's how.
Image file sizes affect everything: page speed, storage, upload times. Here's how to reduce them.
Quick Summary
| Method | Savings | Quality |
|---|---|---|
| Resize | 50-90% | Same |
| Compress | 60-80% | Minimal loss |
| Convert to WebP | 30-50% | Same |
| Remove metadata | 5-15% | None |
| All combined | 80-95% | Minimal loss |
Method 1: Resize (Biggest Savings)
Most effective. Smaller dimensions = smaller files.
from PIL import Image
def resize_to_web(input_path, output_path, max_dim=1920, quality=85):
img = Image.open(input_path)
# Resize if larger than max
if max(img.size) > max_dim:
ratio = max_dim / max(img.size)
new_size = tuple(int(d * ratio) for d in img.size)
img = img.resize(new_size, Image.Resampling.LANCZOS)
img.save(output_path, 'JPEG', quality=quality)
resize_to_web('photo.jpg', 'web.jpg')
Savings: 50-90%
Method 2: Compress JPEG
from PIL import Image
def compress_jpeg(input_path, output_path, quality=85):
img = Image.open(input_path)
img.save(output_path, 'JPEG', quality=quality, optimize=True)
compress_jpeg('photo.jpg', 'compressed.jpg', quality=80)
Savings: 60-80% at 80% quality
Method 3: Convert to WebP
Best format for web. 30-50% smaller than JPEG.
from PIL import Image
def convert_to_webp(input_path, output_path, quality=80):
img = Image.open(input_path)
if img.mode == 'RGBA':
img = img.convert('RGB')
img.save(output_path, 'WEBP', quality=quality)
convert_to_webp('photo.jpg', 'photo.webp')
Savings: 30-50% vs JPEG
Method 4: Remove Metadata
from PIL import Image
def remove_metadata(input_path, output_path):
img = Image.open(input_path)
# Don't save EXIF data
img.save(output_path, exif=[])
remove_metadata('photo.jpg', 'no_meta.jpg')
Savings: 5-15%
Method 5: Progressive JPEG
from PIL import Image
def save_progressive(input_path, output_path, quality=85):
img = Image.open(input_path)
img.save(output_path, 'JPEG', quality=quality, progressive=True)
save_progressive('photo.jpg', 'progressive.jpg')
Savings: Same size, but loads faster visually
Method 6: Batch Processing
from PIL import Image
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
def batch_optimize(input_dir, output_dir, max_dim=1920, quality=85):
output_dir = Path(output_dir)
output_dir.mkdir(exist_ok=True)
def process(f):
img = Image.open(f)
if max(img.size) > max_dim:
ratio = max_dim / max(img.size)
img = img.resize(tuple(int(d * ratio) for d in img.size), Image.Resampling.LANCZOS)
if img.mode == 'RGBA':
img = img.convert('RGB')
output_path = output_dir / f.with_suffix('.webp').name
img.save(output_path, 'WEBP', quality=quality)
return f.name
tasks = list(Path(input_dir).glob('*.jpg')) + list(Path(input_dir).glob('*.png'))
with ThreadPoolExecutor(max_workers=4) as executor:
results = list(executor.map(process, tasks))
print(f"Processed {len(results)} images")
batch_optimize('./photos', './optimized')
Method 7: Command Line
# ImageMagick
mogrify -resize 1920x1920 -quality 85 -strip -format webp *.jpg
# jpegoptim
jpegoptim --max=85 --strip-all photo.jpg
# cwebp
cwebp -q 80 -resize 1920 0 input.jpg -o output.webp
Method 8: Online Tools
Best: Imagic AI
Features:
- Free, unlimited
- Batch support
- Format conversion
- Quality control
Method 9: PNG Optimization
from PIL import Image
def optimize_png(input_path, output_path):
img = Image.open(input_path)
img.save(output_path, 'PNG', optimize=True)
optimize_png('graphic.png', 'optimized.png')
For smaller PNG: Use pngquant
pngquant quality.png --output optimized.png
Method 10: Remove Unnecessary Colors
from PIL import Image
def reduce_colors(input_path, output_path, colors=256):
img = Image.open(input_path)
# Convert to palette mode with limited colors
img = img.convert('P', palette=Image.ADAPTIVE, colors=colors)
img.save(output_path, 'PNG')
reduce_colors('photo.jpg', 'reduced.png', colors=128)
Complete Workflow
from PIL import Image
from pathlib import Path
def optimize_for_web(input_path, output_path, max_dim=1920, quality=85):
"""Complete optimization: resize + compress + WebP"""
img = Image.open(input_path)
# 1. Resize
if max(img.size) > max_dim:
ratio = max_dim / max(img.size)
img = img.resize(tuple(int(d * ratio) for d in img.size), Image.Resampling.LANCZOS)
# 2. Convert to RGB if needed
if img.mode == 'RGBA':
img = img.convert('RGB')
# 3. Save as WebP
img.save(output_path, 'WEBP', quality=quality)
# Report savings
orig_size = Path(input_path).stat().st_size
new_size = Path(output_path).stat().st_size
savings = (1 - new_size / orig_size) * 100
print(f"Saved {savings:.1f}%: {orig_size//1024}KB → {new_size//1024}KB")
# Usage
optimize_for_web('photo.jpg', 'photo.webp')
Target File Sizes
| Use | Target |
|---|---|
| Hero image | 200-400 KB |
| Content image | 50-150 KB |
| Thumbnail | 10-30 KB |
| Avatar | 5-15 KB |
FAQ
Q: Does compression reduce quality?
A: At 80-85% quality, usually no visible difference.
Q: What's the best format?
A: WebP for web. 30% smaller than JPEG.
Q: How small can I go?
A: 200KB for hero, 50-150KB for content images.
Q: Should I resize or compress?
A: Both. Resize first (biggest savings), then compress.
My Recommendation
Quick solution: Try Imagic AI
For automation: Python scripts
For best results: Resize + WebP + 85% quality
Reducing image sizes for 15+ years.