Skip to content

Releases: gmpassos/png_minifier

v1.0.0 — minify PNGs in pure Dart: many strategies, one judge

Choose a tag to compare

@gmpassos gmpassos released this 03 Oct 01:18

First release of png_minifier: fewer bytes, the same pixels by default — or a quality bound you choose. Pure Dart; output byte-identical on the VM, dart2js and dart2wasm.

Every active strategy proposes candidate encodings; candidates that break the quality target are rejected and the smallest of the rest wins. If nothing beats the input, the input is returned.

Strategies

  • Lossless: transparent-pixel cleanup; colour-type and bit-depth reduction (RGB, greyscale 1–16 bits, grey+alpha, tRNS colour keys); palettes at 1/2/4/8 bits in three orders; seven PNG filter strategies; deflate-level search.
  • Lossy (each checked against the quality before it may win): frequency palette for pixel art, median cut, k-means, bounded Floyd–Steinberg dithering, posterize, alpha snapping.

Quality, effort, presets

  • PngQuality.lossless() (default), .maxError(n), .psnr(dB), .bounded(...), or a TinyPNG-like .level(0–100), measured on premultiplied colour.
  • Effort fast | balanced | max; presets lossless, losslessMax, fast, web, pixelArt, photo, smallest.
  • Metadata: strip, keep colour chunks (default), or keep all valid chunks.

Also

  • Full PNG decoder (all colour types and bit depths, Adam7, tRNS, CRC checks) and encoder; APNG input is returned unchanged.
  • png_minifier CLI: files and directories, --preset, --quality, --effort, --strategies, --in-place, --dry-run, --json.
  • Tests on PngSuite, Kodak crops and Kenney CC0 tilemaps; golden hashes checked on the VM, Chrome (dart2js) and Chrome (dart2wasm); 99.5% line coverage. tool/benchmark.dart for your own datasets.

Benchmarks (saved bytes · largest per-channel error)

Preset PngSuite Kenney CC0 packs Kodak photos
lossless 37.8% · 0 2.7% · 0 0.2% · 0
web 47.7% · 12 2.7% · 0 23.5% · 12
photo 47.8% · 32 2.7% · 0 48.0% · 48 (PSNR ≥ 38 dB)
smallest 68.8% · 24 33.1% · 24 87.1% · 24