PNG Compression Is Fundamentally Lossless
This is the single most important thing to understand about PNG: compression level does not affect quality. A PNG saved at compression level 1 and a PNG saved at compression level 9 will produce exactly the same image when opened. Every single pixel will be identical, bit for bit.
PNG uses the DEFLATE algorithm (the same one behind gzip and ZIP files) to compress pixel data. When you adjust the compression "level," you are controlling how hard the encoder searches for repeating patterns and optimal encoding strategies. Higher levels mean:
- Smaller files — the encoder finds more efficient ways to represent the same data
- Slower encoding — more computation required to find those efficiencies
- Identical decompression — no matter the level, the decoded pixels are the same
This is fundamentally different from JPEG, where the quality setting directly controls how much visual data is permanently discarded. With PNG, nothing is ever discarded. The "quality" question is simply: how much CPU time are you willing to spend to squeeze out a few more bytes?
Key concept: PNG compression level = encoding effort, not quality. Level 9 does not mean "lower quality" — it means "try harder to find a smaller representation of the same data."
PNG-8 vs PNG-24 vs PNG-32
The most effective way to reduce PNG file size is choosing the right PNG subtype for your image. The difference between these types can mean a 3–5x size reduction with minimal or no visible change.
| Type | Color Depth | Colors | Transparency | Typical Size |
|---|---|---|---|---|
| PNG-8 | 8-bit (indexed palette) | Up to 256 | 1-bit (on/off) or 8-bit alpha | Smallest |
| PNG-24 | 24-bit (RGB) | 16.7 million | None | Medium |
| PNG-32 | 32-bit (RGBA) | 16.7 million | Full 8-bit alpha | Largest |
PNG-8: The secret weapon for small files
PNG-8 stores each pixel as an index into a palette of up to 256 colors. Instead of using 3 bytes per pixel (RGB) or 4 bytes (RGBA), it uses just 1 byte. This fundamental difference makes PNG-8 files 3–5x smaller than PNG-24 equivalents.
PNG-8 is ideal for:
- Logos — most logos use fewer than 20 colors
- Icons and UI elements — flat design icons typically have 5–15 colors
- Simple illustrations — diagrams, charts, infographics with flat color areas
- Screenshots of text-heavy UIs — terminal outputs, code editors, text documents
PNG-8 is not suitable for:
- Photographs — photos contain thousands of colors; reducing to 256 causes visible banding
- Smooth gradients — 256 colors cannot represent a smooth gradient without visible steps
- Images requiring semi-transparency — standard PNG-8 supports only fully transparent or fully opaque pixels (though some tools support 8-bit alpha in indexed mode)
PNG-24 vs PNG-32: Do you need the alpha channel?
The difference between PNG-24 and PNG-32 is the alpha (transparency) channel. Each pixel in PNG-32 carries an extra byte for transparency, making files 25–33% larger than PNG-24. If your image does not need transparency (no transparent or semi-transparent areas), save as PNG-24 to avoid the overhead of an unused alpha channel.
Quick win: If you have a PNG-24 image that uses only 50 distinct colors (common for UI mockups and diagrams), converting to PNG-8 can reduce file size by 70–80% with zero visible change. Tools like pngquant detect this automatically.
Metadata Stripping
PNG files can contain metadata in text chunks: tEXt, iTXt, zTXt, and other ancillary chunks. These include:
- Software tags — which program created the file (Photoshop, GIMP, etc.)
- Creation timestamp — when the image was created or last modified
- Author and copyright — embedded text fields
- ICC color profile — can be 500 bytes to 800KB+ for wide-gamut profiles
- Photoshop private data — Adobe software embeds layer data, smart object references, and edit history that can be substantial
For web delivery, all of this metadata is unnecessary overhead. Stripping it produces a smaller file with zero visual change:
# Strip all metadata with ImageMagick
magick input.png -strip output.png
# Strip with pngcrush (preserves critical chunks only)
pngcrush -rem allb input.png output.png
# Strip with optipng (also optimizes compression)
optipng -strip all input.png -out output.png
The savings from metadata stripping are typically 1–5 KB for simple images, but can be 50–800 KB for files exported from Photoshop with embedded ICC profiles and private data chunks.
Compression Level Settings
PNG compression level controls how aggressively the DEFLATE algorithm searches for patterns. Here is what each level means in practice:
| Level | Encoding Speed | File Size | Use Case |
|---|---|---|---|
| 0 | Instant | Largest (no compression) | Debugging, intermediate processing |
| 1–3 | Very fast | Large | Real-time processing, temporary files |
| 4–6 | Moderate | Medium | General purpose (most tools default to 6) |
| 7–8 | Slow | Small | Web delivery, archival |
| 9 | Slowest | Smallest | Final delivery, web assets |
The difference between level 6 (default) and level 9 (maximum) is typically 2–5% in file size. The encoding time difference is more significant — level 9 can take 5–10x longer than level 6 for large images. For web assets where you encode once and serve millions of times, level 9 is always worth the extra encoding time.
ImageMagick PNG quality parameter
ImageMagick encodes both the compression level and filter type in a single -quality parameter for PNG. The tens digit is the zlib compression level (0–9), and the units digit is the filter type (0–5):
# Maximum compression, adaptive filtering
magick input.png -strip -quality 95 PNG:output.png
# Breakdown: 9 = compression level 9, 5 = adaptive filter
# Adaptive filter tests all 5 filter types per row for optimal results
# Fast compression, no filtering
magick input.png -strip -quality 10 PNG:output.png
# Breakdown: 1 = compression level 1, 0 = no filter
Best default: Use -quality 95 for ImageMagick PNG output. The 9 means maximum compression effort, and 5 means adaptive filtering (tries all filter types per row). This produces the smallest file at the cost of slower encoding.
PNG Filter Types Explained
Before DEFLATE compression, PNG applies a per-row prediction filter that transforms pixel data to make it more compressible. The filter does not change the image — it is fully reversible. The goal is to make the data more repetitive so DEFLATE can compress it better.
| Filter | ID | Prediction Method | Best For |
|---|---|---|---|
| None | 0 | No prediction (raw bytes) | Palettized images (PNG-8), random noise |
| Sub | 1 | Pixel minus left neighbor | Horizontal gradients, horizontal patterns |
| Up | 2 | Pixel minus pixel above | Vertical gradients, vertical patterns |
| Average | 3 | Pixel minus average of left + above | Smooth areas, blended content |
| Paeth | 4 | Pixel minus Paeth predictor (nearest of left, above, upper-left) | Complex natural images |
| Adaptive | 5 | Tests all filters per row, picks best | All images (best default) |
The adaptive filter (sometimes called "mixed" or "all") tests all five filter types for each row of pixels and picks whichever produces the most compressible output. This brute-force approach almost always produces the smallest file but takes longer to encode. For final web delivery, adaptive filtering is always the right choice.
How much do filters matter?
The wrong filter choice can inflate file size by 10–30%. For example, using "None" filter on a photograph (where adjacent pixels are similar) wastes significant compression potential. Conversely, using "Sub" or "Paeth" on a palettized image with random index values can actually make the file larger than no filter at all.
This is why adaptive filtering is the safe default — it always picks the right filter for each row, even if the image contains mixed content types (like a screenshot with both text and photographs).
Color Palette Optimization
The most dramatic PNG size reduction comes from converting 24-bit (16.7 million colors) PNG to an optimized 8-bit palette (256 colors). Tools like pngquant and pngnq use sophisticated algorithms to select the best 256 colors and apply dithering to simulate the missing colors.
How pngquant works
pngquant analyzes the image to find the 256 colors that best represent the original. For pixels that fall between palette colors, it applies Floyd-Steinberg dithering — a technique that distributes the color error to neighboring pixels, creating the illusion of more colors through spatial mixing.
# Basic palette optimization (256 colors, quality 65-80)
pngquant 256 --quality=65-80 input.png -o output.png
# Maximum quality palette optimization
pngquant 256 --quality=80-100 --speed 1 input.png -o output.png
# Convert to specific number of colors
pngquant 64 input.png -o output.png # 64 colors
pngquant 16 input.png -o output.png # 16 colors (very small)
Typical palette optimization results
| Image Type | PNG-24 Size | PNG-8 (256 colors) | Savings | Visual Impact |
|---|---|---|---|---|
| Logo (12 colors) | 45 KB | 8 KB | 82% | None (lossless) |
| UI screenshot | 380 KB | 95 KB | 75% | Minimal dithering |
| Illustration (flat colors) | 210 KB | 52 KB | 75% | None to minimal |
| Infographic with gradients | 620 KB | 180 KB | 71% | Dithering in gradients |
| Photograph | 8.5 MB | 2.1 MB | 75% | Heavy dithering (use JPG instead) |
Important: Palette optimization is technically lossy — it reduces the number of available colors. However, for images that already use fewer than 256 distinct colors, the conversion is perfectly lossless. For images with slightly more colors, dithering produces results that are visually indistinguishable from the original at normal viewing distances.
PNG Optimization Tools Compared
Several specialized tools go beyond what ImageMagick offers for PNG compression. Each takes a different approach:
| Tool | Type | Approach | Typical Savings |
|---|---|---|---|
| optipng | Lossless | Tries multiple filter/compression combinations | 5–15% |
| pngcrush | Lossless | Brute-force testing of all filter/level combos | 5–15% |
| zopflipng | Lossless | Google’s Zopfli algorithm (better than DEFLATE) | 8–20% |
| pngquant | Lossy (palette) | Reduces to 256-color palette with dithering | 60–80% |
| oxipng | Lossless | Multi-threaded optipng alternative (Rust) | 5–15% |
For the best results, combine a lossy and lossless tool: first run pngquant (if palette reduction is acceptable), then run zopflipng or optipng on the result for maximum lossless compression:
# Maximum compression pipeline
pngquant 256 --quality=80-100 input.png -o temp.png
zopflipng temp.png output.png
rm temp.png
When PNG Compression Reaches Its Limits
No amount of PNG optimization can overcome the fundamental reality: lossless compression cannot compete with lossy compression for photographs. This is not a flaw in PNG — it is a mathematical certainty. Lossless algorithms must preserve every pixel, while JPEG discards information the eye cannot perceive.
| Image Type | Optimized PNG | JPEG Q85 | PNG is larger by |
|---|---|---|---|
| 12 MP smartphone photo | 14.2 MB | 1.8 MB | 7.9x |
| 24 MP DSLR photo | 28.5 MB | 4.7 MB | 6.1x |
| 1080p screenshot | 850 KB | 240 KB | 3.5x |
| Simple logo (12 colors) | 8 KB | 22 KB | JPEG is 2.8x larger |
| UI icon (flat colors) | 3 KB | 9 KB | JPEG is 3x larger |
The pattern is clear:
- Photographs and complex natural images — convert to JPEG. You will save 3–8x with no perceptible quality loss at Q85.
- Simple graphics, logos, icons, text-heavy screenshots — stay with PNG. It will be smaller than JPEG and preserve sharp edges perfectly.
- Images with transparency — stay with PNG (JPEG does not support transparency). Consider WebP as an alternative that supports both lossy compression and transparency.
The honest answer: If your PNG is a photograph and file size is your concern, the best "PNG compression" strategy is converting to JPEG. Use the converter above to go from PNG to JPG — you will typically see a 70–90% size reduction with imperceptible quality loss.
Step-by-Step PNG Compression Guide
Here is a practical decision tree for reducing PNG file size:
Step 1: Is your image a photograph?
If yes, convert to JPEG. Upload your PNG to the converter above and select JPG as the output format. This is the single most effective action for photo PNGs. A 15 MB PNG photograph becomes a 1–2 MB JPEG at Q85 with no visible difference.
If no (it is a graphic, logo, icon, or screenshot), continue to Step 2.
Step 2: How many colors does your image use?
Check with ImageMagick:
magick identify -verbose input.png | grep "Colors:"
If 256 or fewer colors: convert to PNG-8 for 70–80% savings with zero quality loss:
magick input.png -strip -colors 256 -type Palette PNG8:output.png
If more than 256 colors: decide if palette reduction with dithering is acceptable, or keep PNG-24.
Step 3: Strip metadata and maximize compression
# Maximum lossless compression with metadata stripping
magick input.png -strip -quality 95 PNG:output.png
Step 4: Consider specialized tools for further savings
# Lossless optimization (guaranteed no quality change)
optipng -o7 -strip all input.png -out output.png
# OR lossy palette reduction (dramatic savings)
pngquant 256 --quality=80-100 input.png -o output.png
Batch PNG Compression
When you need to compress an entire folder of PNG files, command-line tools are the fastest approach.
Lossless batch compression
# Linux / macOS: max compression + strip metadata
mkdir -p compressed
for f in *.png *.PNG; do
[ -f "$f" ] || continue
magick "$f" -strip -quality 95 "compressed/$f"
done
Batch palette optimization (pngquant)
# Reduce all PNGs to 256-color palette
mkdir -p optimized
for f in *.png *.PNG; do
[ -f "$f" ] || continue
pngquant 256 --quality=80-100 "$f" -o "optimized/$f"
done
Windows PowerShell
New-Item -ItemType Directory -Force -Path ".\compressed"
Get-ChildItem *.png | ForEach-Object {
magick $_.FullName -strip -quality 95 (".\compressed\" + $_.Name)
}
Batch convert PNG to JPG (maximum savings for photos)
# Convert all PNG photos to Q85 JPEG
mkdir -p jpg_output
for f in *.png *.PNG; do
[ -f "$f" ] || continue
magick "$f" -quality 85 -interlace Plane -strip "jpg_output/${f%.*}.jpg"
done