PNG: Portable Network Graphics for Lossless Web Images
PNG (Portable Network Graphics) is the de facto standard for lossless image compression on the web. Introduced in 1996 to replace GIF (avoiding patent issues), PNG has become ubiquitous for screenshots, logos, graphics, and any content requiring transparency and perfect fidelity. All browsers support PNG natively with 100% coverage.
PNG File Structure: Chunks & IHDR
Every PNG file is a sequence of chunks, each with a 4-byte type identifier and CRC-32 checksum:
89 50 4E 47 0D 0A 1A 0A (PNG signature — never changes)
00 00 00 0D (chunk length = 13 bytes)
49 48 44 52 (chunk type 'IHDR' — image header)
[13 bytes IHDR data]
[4 bytes CRC-32]
00 00 xx xx (IDAT chunk length)
49 44 41 54 ('IDAT' chunk type)
[deflated pixel data]
[4 bytes CRC-32]
00 00 00 00 (IEND length = 0)
49 45 4E 44 ('IEND' chunk type — marks end)
AE 42 60 82 (IEND CRC-32)
IHDR (Image Header) — 13 bytes:
| Field | Bytes | Meaning |
|---|---|---|
| Width | 4 | Image width in pixels (big-endian) |
| Height | 4 | Image height in pixels |
| Bit Depth | 1 | 1, 2, 4, 8, 16 bits per sample |
| Color Type | 1 | 0=grayscale, 2=RGB, 3=indexed (palette), 4=grayscale+alpha, 6=RGBA |
| Compression | 1 | 0 = deflate/inflate (only valid value) |
| Filter | 1 | 0 = adaptive filtering (only valid value) |
| Interlace | 1 | 0 = none, 1 = Adam7 (7-pass interlacing) |
Example IHDR for 256×256 RGBA PNG:
00 00 01 00 (width = 256)
00 00 01 00 (height = 256)
08 (8 bits per sample)
06 (color type 6 = RGBA)
00 (deflate compression)
00 (adaptive filtering)
00 (no interlace)
Color Types: Indexed, RGB, Grayscale, Alpha
PNG supports multiple color encoding modes:
| Type | Name | Channels | Bit Depths | Use Case |
|---|---|---|---|---|
| 0 | Grayscale | 1 | 1, 2, 4, 8, 16 | Monochrome, scanning |
| 2 | Truecolor (RGB) | 3 | 8, 16 | Photos, graphics (no alpha) |
| 3 | Indexed (Palette) | 1 | 1, 2, 4, 8 | Graphics with limited colors |
| 4 | Grayscale + Alpha | 2 | 8, 16 | Monochrome with transparency |
| 6 | RGBA | 4 | 8, 16 | Full color with transparency |
Indexed (Type 3) — using PLTE chunk:
IHDR: color type 3, bit depth 8
PLTE chunk (256×3 bytes):
[R0 G0 B0] [R1 G1 B1] … [R255 G255 B255]
tRNS chunk (optional, up to 256 bytes):
[Alpha0] [Alpha1] … [Alpha255]
IDAT: pixel values 0–255 as indices into palette
Typically 30–50% smaller than RGB for graphics with ≤256 colors.
RGBA (Type 6):
IHDR: color type 6, bit depth 8
IDAT scanlines: [R1 G1 B1 A1] [R2 G2 B2 A2] … per pixel
Full 24-bit RGB + 8-bit alpha channel, 4 bytes per pixel.
Scanlines & Filtering: Adaptive Prediction
PNG doesn't store raw pixel data. Instead, each scanline is filtered via one of 5 filter types to reduce entropy:
[Filter type] [filtered data for row]
Filter types:
| Type | Name | Formula | Purpose |
|---|---|---|---|
| 0 | None | output = pixel | No filtering (baseline) |
| 1 | Sub | output = pixel - LEFT | Exploit horizontal correlation |
| 2 | Up | output = pixel - UP | Exploit vertical correlation |
| 3 | Average | output = pixel - (LEFT + UP) / 2 | Average-based prediction |
| 4 | Paeth | output = pixel - PaethPredictor(LEFT, UP, UPLEFT) | Directional prediction |
Paeth predictor: selects LEFT, UP, or UPLEFT based on which is closest to their average—removes diagonal artifacts in natural images.
Example (Sub filter on horizontal line):
Raw pixels: [10] [15] [20] [30] [50]
After Sub filter: [10] [5] [5] [10] [20] (each pixel minus left neighbor)
Compressed size: ~2 bytes (repeated patterns compress better)
PNG encodes the filter type for each scanline, allowing an encoder to choose the best filter per row.
Compression: Deflate Algorithm
PNG uses zlib (deflate) on filtered scanlines:
- LZ77 sliding window: finds repeated byte sequences (up to 32 KB)
- Huffman encoding: encodes frequent symbols with fewer bits
- Compression ratio: typically 30–50% on graphics, 10–20% on photos
Compression levels (PNG encoder parameter):
- Level 1: Fast, poor compression (~25% reduction)
- Level 6: Default (good balance)
- Level 9: Slow, best compression (~40% reduction)
Interlacing: Adam7 for Progressive Display
Adam7 interlacing renders PNG progressively in 7 passes:
Pass 1: pixels at (x mod 8 == 0, y mod 8 == 0) — 12.5% of pixels
Pass 2: pixels at (x mod 8 == 4, y mod 8 == 0) — 12.5%
Pass 3: pixels at (x mod 8 == 0, y mod 8 == 4) — 12.5%
Pass 4: pixels at (x mod 8 == 4, y mod 8 == 4) — 12.5%
Pass 5: pixels at (x mod 8 == 2, y mod 8 == 0 | 4) — 25%
Pass 6: pixels at (x mod 8 == 0 | 4, y mod 8 == 2 | 6) — 12.5%
Pass 7: remaining pixels — 12.5%
Result: visible rough preview after pass 1, refined progressively. Tradeoff: ~25% larger file size vs. non-interlaced PNG.
Ancillary Chunks: Color Profiles, Metadata, Gamma
gAMA (Gamma):
gAMA chunk: 4 bytes
value = 100000 represents gamma 2.2 (standard)
Applies power law: displayed = linear ^ (1/gamma)
Corrects for monitor brightness (not widely used in modern color-managed workflows).
cHRM (Chromaticity): Defines the color primaries (red, green, blue, white point) for accurate color reproduction across displays.
iCCP (ICC Color Profile):
[null-terminated profile name] [compression type] [zlib-compressed ICC profile]
Embeds sRGB/Adobe RGB/ProPhoto RGB color space. Enables accurate color on color-managed displays.
tIME (Timestamp):
2 bytes year, 1 byte month/day/hour/minute/second
Format: YYYYMMDDhhmmss
tEXt (Text Metadata):
[null-terminated keyword] [text string]
Example: "Author\0John Doe"
Supports multiple tEXt chunks for comments, copyright, etc.
iTXt (International Text): UTF-8 text metadata with optional compression.
PNG Quality Comparison vs. Competitors
| Metric | PNG (8-bit) | JPEG (Q85) | WebP-L | AVIF-L |
|---|---|---|---|---|
| File size (photo) | 300 KB | 100 KB | 220 KB | 180 KB |
| File size (graphic) | 50 KB | 150 KB | 40 KB | 35 KB |
| Transparency | ✅ | ❌ | ✅ | ✅ |
| Interlacing | ✅ | ❌ | ❌ | ❌ |
| Animation | ❌ | ❌ | ✅ | ❌ |
| Browser support | 100% | 100% | 97% | 82% |
| Encoding speed | Fast | Medium | Medium | Slow |
PNG is ideal for graphics; JPEG for photos; WebP as modern fallback.
Practical PNG Optimization Workflow
For graphics (logos, icons):
- Use indexed color (Type 3) with up to 256 colors
- Interlace only if file is <50 KB (tradeoff not worth it for small files)
- Compress with level 9
For photos:
- Use RGBA (Type 6) without interlacing
- JPEG is typically smaller—consider WebP for web
- PNG only for lossless archival or when transparency needed
ImageMagick optimization:
convert input.jpg -quality 85 -colors 256 -depth 8 output.png
convert input.png -quality 95 -strip output-optimized.png
Python (Pillow):
from PIL import Image
img = Image.open('input.jpg')
img = img.convert('RGB')
img.save('output.png', 'PNG', optimize=True, compress_level=9)
PNG's combination of lossless compression, alpha transparency, and universal browser support makes it indispensable for web graphics and professional workflows.