The Core Rule
- Photographs and complex images: JPEG (or WebP lossy)
- Logos, icons, screenshots with text, images with transparency: PNG (or WebP lossless, or SVG)
- Both + browser support: WebP for everything
- Animations: WebP animated (or MP4/WebM for longer ones — avoid GIF)
- Scalable icons and illustrations: SVG
JPEG Deep Dive
JPEG uses DCT (Discrete Cosine Transform) — it converts the image to frequency components and quantizes the high-frequency (fine detail) components more aggressively at lower quality settings.
/* Quality vs file size tradeoffs (2000×1333 photo) */
Quality 95: 1.2 MB — nearly lossless
Quality 85: 450 KB — excellent, recommended for high-detail photos
Quality 75: 250 KB — good, recommended for web
Quality 60: 140 KB — acceptable, visible softness
Quality 40: 80 KB — blocky artifacts visible
JPEG limitations: No transparency, no lossless mode, artifacts at edges of sharp lines (why logos look bad as JPEG).
PNG Deep Dive
PNG uses deflate compression (lossless). It comes in three types:
- PNG-8: 256 colors max, like GIF. Small but limited palette.
- PNG-24: Full RGB, no transparency.
- PNG-32: Full RGB + alpha channel. The common "PNG with transparency".
PNG is terrible for photographs — a 2000×1333 photo as PNG-32 is ~6 MB vs ~450 KB as JPEG 85.
WebP Deep Dive
WebP supports both lossy (VP8 codec) and lossless modes, plus transparency in both. Google developed it in 2010; all major browsers support it since 2022 (Safari 14+).
/* Typical size comparison (same visual quality) */
JPEG 85: 450 KB
WebP lossy 80: 320 KB (28% smaller than JPEG)
WebP lossless: 4.2 MB (larger than JPEG for photos — use lossy)
/* For logos/UI assets (1000×1000 icon): */
PNG-32: 85 KB
WebP lossless: 62 KB (27% smaller)
Converting Images in JavaScript
// Convert any image to WebP using canvas
async function convertToWebP(file, quality = 0.85) {
const img = await createImageBitmap(file);
const canvas = new OffscreenCanvas(img.width, img.height);
canvas.getContext("2d").drawImage(img, 0, 0);
return canvas.convertToBlob({ type: "image/webp", quality });
}
// PNG → JPEG (removes transparency — set background first)
async function pngToJpeg(file, quality = 0.85) {
const img = await createImageBitmap(file);
const canvas = new OffscreenCanvas(img.width, img.height);
const ctx = canvas.getContext("2d");
ctx.fillStyle = "#ffffff"; // white background for transparent areas
ctx.fillRect(0, 0, img.width, img.height);
ctx.drawImage(img, 0, 0);
return canvas.convertToBlob({ type: "image/jpeg", quality });
}
Conversion Caveats
- Converting JPEG → PNG does not recover lost quality — you get a lossless copy of already-degraded data.
- Converting PNG with transparency → JPEG requires filling the transparent area (usually white or black).
- Converting to WebP lossy from PNG creates a lossy version — don't replace the original PNG with it if you need the lossless master.
Convert Image Formats Instantly
Use ToolsVito's Image Converter to convert between PNG, JPEG, and WebP in your browser — your images never leave your device.