A developer on my team once spent two hours trying to find a lossless compression tool that would cut our product image sizes by 80%. That is not possible with lossless compression β the math does not allow it. Understanding which algorithm to use for which job eliminates that kind of wasted effort. Most image size problems solve in under a minute once you know which lever to pull.
Compress images locally β choose lossy or lossless.
Set quality level, pick AVIF, WebP, or PNG. Runs in your browser. No upload.
Open Image Compressor βWhat Compression Actually Does
Compression reduces file size by representing the same data with fewer bits. There are two fundamentally different approaches, and mixing them up costs either quality or time.
Lossless Compression
Lossless compression removes redundancy without discarding any pixel data. The original image can be reconstructed exactly from the compressed file. PNG uses DEFLATE (a combination of LZ77 and Huffman coding) for this.
How it works: instead of storing β255, 255, 255, 255, 255β (five white pixels), PNG stores βrun of 5 Γ 255.β For images with large flat areas β screenshots, illustrations, text on a white background β this cuts file size dramatically. For photos with natural noise, almost every pixel is different, so there is almost no redundancy to remove. Lossless compression on a photo typically saves only 10β20%.
Lossy Compression
Lossy compression discards information the algorithm predicts you will not notice. The original cannot be reconstructed after compression β the discarded data is gone.
JPEG uses Discrete Cosine Transform (DCT): the image is split into 8Γ8 pixel blocks, each block is transformed into frequency coefficients, and the high-frequency detail coefficients (fine texture) are rounded more aggressively than low-frequency ones (broad color areas). The quality slider controls how aggressively the rounding happens.
WebP uses the same DCT-based approach for lossy mode, but with better entropy coding. AVIF uses a transform from the AV1 video codec β larger block sizes and more sophisticated frequency analysis, which is why it compresses better but encodes slower.
The Quality Setting β What the Numbers Mean
The quality slider in any image editor or CLI tool maps to internal quantization table values. There is no universal standard β a JPEG at quality 80 in Photoshop and quality 80 in ImageMagick produce different file sizes and visual results. What matters is testing the SSIM output, not the number itself.
SSIM (Structural Similarity Index) measures visual similarity between 0 and 1. TheWeb Almanac Media chapteruses SSIM above 0.95 as the threshold for βperceptually losslessβ β the human eye cannot detect the difference at that score on a normal screen.
| Quality | Typical Size Reduction | SSIM Score | Visible Artifacts? |
|---|---|---|---|
| 95 | 10β20% | β₯ 0.99 | None β overkill for web |
| 85 | 35β50% | 0.97β0.98 | None |
| 80 β | 50β65% | 0.95β0.97 | None on screen β perceptually lossless |
| 75 | 60β75% | 0.93β0.95 | Barely visible at 1:1 zoom |
| 65 | 75β85% | 0.88β0.92 | Visible in smooth gradients and skies |
| 50 or below | 85β92% | Below 0.88 | Obvious blocking in 8Γ8 patches |
Choosing the Right Algorithm for the Job
| Image Type | Recommended Format | Mode | Why |
|---|---|---|---|
| Photos, hero images | AVIF or WebP | Lossy, quality 75β80 | Natural noise tolerates lossy well |
| Screenshots, UI | WebP or AVIF | Lossy, quality 80β85 | Text edges need higher quality to stay crisp |
| Logos with transparency | WebP lossless or SVG | Lossless | Sharp edges; lossy creates halo artifacts |
| Illustrations, flat color | SVG or PNG | Lossless | Large flat areas compress well losslessly |
| Icons, small graphics | SVG | Vector | Infinitely scalable; smallest file at any size |
Automating Compression in a Build Pipeline
import sharp from 'sharp';
import { glob } from 'glob';
import path from 'path';
// Process all images in a directory
const images = await glob('public/images/**/*.{jpg,jpeg,png}');
for (const inputPath of images) {
const ext = path.extname(inputPath);
const base = inputPath.replace(ext, '');
// Generate WebP (lossy quality 80)
await sharp(inputPath)
.webp({ quality: 80 })
.toFile(base + '.webp');
// Generate AVIF (lossy quality 75, effort 4 = balanced speed)
await sharp(inputPath)
.avif({ quality: 75, effort: 4 })
.toFile(base + '.avif');
console.log('Processed:', path.basename(inputPath));
}
console.log('Done. Total images processed:', images.length);When Compression Backfires
Re-Compressing Already-Compressed Images
Re-encoding a JPEG that was already compressed at quality 80 into another JPEG at quality 80 does not produce the same result. Each encode applies lossy compression again on top of the previous lossy pass. Over multiple generations, quality degrades visibly β a process called βgeneration loss.β
Always compress from the original high-quality source file. Never re-encode an already-compressed image unless you are switching formats (JPEG β WebP), and even then, prefer to start from the original if it exists.
Logos and Text at Lossy Quality Below 85
Logos with thin lines or sharp text edges show visible halos and ringing artifacts when compressed with lossy algorithms below quality 85. JPEG's 8Γ8 block structure is particularly obvious around high-contrast edges.
Use lossless WebP or SVG for logos. If you need a raster format for compatibility reasons, quality 90+ is the minimum for text-heavy images.
AVIF Can Be Larger Than WebP for Small Images
AVIF's container overhead exceeds its compression savings below roughly 100Γ100 pixels. A 32px icon as AVIF is often larger than the same icon as WebP or even PNG. For thumbnails and small images, test both formats and use whichever is smaller.
Progressive JPEG vs Baseline JPEG
Progressive JPEGs load in multiple passes β a blurry version appears immediately, sharpening as more data arrives. Baseline JPEGs load top-to-bottom. Progressive JPEGs are typically 2β3% smaller for large images and feel faster to users because they see something immediately.
// Generate progressive JPEG with sharp
await sharp('input.jpg')
.jpeg({ quality: 80, progressive: true })
.toFile('output-progressive.jpg');My Settings for Production
For photos: WebP quality 80 with AVIF quality 75 as the primary source. For screenshots: WebP quality 85. For logos: lossless WebP or SVG. Always compress from the original source file. Never re-compress an already-compressed image.
To understand how to serve these compressed files correctly β with srcset, lazy loading, and LCP-safe priority attributes β read our image optimization workflow guide. For the specific AVIF vs WebP format decision with encoding speed benchmarks, our AVIF vs WebP comparison covers the edge cases where WebP still wins.
Compress images β choose quality level and format.
WebP, AVIF, or PNG β lossy or lossless. All processed locally in your browser.
Open Image Compressor β