Skip to content

PNG

currentMigrated from docs/images/PNG.mdx at 37c3317fd058; modified for Encode Wiki · CC BY-SA 4.0

PNG (1996) is the lossless format for screenshots, UI, diagrams, pixel art and anything that needs real transparency. It was created as a patent-free replacement for GIF, and the third edition of the spec (a W3C Recommendation since June 2025) adds animation (APNG), HDR colour signalling (cICP, mDCV, cLLI) and Exif.

PropertyValue
CompressionLossless (per-row filters plus DEFLATE)
Bit depth1, 2, 4, 8 or 16 bits per sample (palette up to 8 bits)
Colour typesGrayscale, RGB, indexed palette, with or without alpha
AlphaFull alpha channel, or per-entry alpha in palette images
AnimationAPNG, supported by all current browsers
ProgressiveAdam7 interlacing (usually makes files larger)
Royalty-freeYes
  • Use PNG for screenshots, graphics with flat colour or sharp edges, masters you will edit again, and anything that must come out pixel-exact.
  • Not for photos. A photo as PNG is several times larger than a good JPEG, and usually larger than lossless WebP or lossless JPEG XL too. Use JPEG, AVIF or WebP for delivery.
  • For smaller PNGs, you have two routes: lossless recompression (oxipng, ECT) which never changes pixels, or palette quantisation (pngquant) which does and often saves 60–80%.

oxipng is the usual choice: multithreaded, fast, and able to do limited optimisation of APNG. It rewrites files in place unless you give --out or --dir.

Terminal window
oxipng -o 4 --strip safe image.png --out image.opt.png
oxipng -o max --strip safe *.png
OptionWhat it does
-o 0…-o 6, -o maxEffort. Default is 2, which is fast and already good; higher levels have diminishing returns. max is level 6.
--strip safe (-s)Removes non-critical chunks but keeps cICP, iCCP, sRGB, pHYs and the APNG chunks. Use --strip all only if you are sure no colour or animation data matters.
--alpha (-a)Rewrites the colour of fully transparent pixels to compress better. Looks identical, but the hidden RGB values change.
-zUses Zopfli instead of libdeflate. Slower, small extra gain.
--scale16Converts 16-bit to 8-bit. Lossy; oxipng otherwise keeps 16-bit data intact.

Without --strip oxipng keeps every chunk that is still valid, including metadata.

Efficient Compression Tool (ect) optimises PNG and JPEG (and gzip/zip) in place. Level -9 is very slow; -3 is the default.

Terminal window
ect -9 -strip image.png

ect also recompresses JPEGs losslessly (-progressive makes them progressive). ZopfliPNG and OptiPNG do the same job; OptiPNG is the older tool, ZopfliPNG strips all ancillary chunks (including colour profiles) unless told to keep them.

pngquant converts RGB/RGBA to an 8-bit palette with per-colour alpha, using dithering to hide the loss. It suits icons, illustrations and screenshots; smooth gradients and photos can band or posterise.

Terminal window
pngquant --quality 65-90 --skip-if-larger --strip --output small.png input.png
  • --quality min-max picks the fewest colours that reach max; if it cannot reach min it writes nothing and exits with status 99 (98 for --skip-if-larger).
  • --speed runs 1 (slowest, best) to 11. The default is 4 and the author recommends leaving it unless you need real-time speed.
  • --nofs turns off dithering (cleaner flat areas, more banding in gradients). --floyd=0.5 reduces it.
  • --ext .png --force overwrites input files in place. There is no backup.

Run oxipng on the result for a little more.

  • Metadata and colour: PNG colour can come from sRGB, iCCP, cICP, or legacy gAMA/cHRM. oxipng’s --strip safe drops gAMA and cHRM, and --strip all drops everything non-critical, so check images that depended on them. Missing profiles change how colour-managed viewers show the image.
  • Interlacing: Adam7 costs compression and is rarely worth it. oxipng removes it by default; use -i keep or -i on if you need it.
  • Hidden RGB in transparent pixels: --alpha and ZopfliPNG’s --lossy_transparent change it. Harmless for display, wrong if the same file feeds a later edit or a texture pipeline.
  • 16-bit images: many tools silently convert to 8-bit. Keep an eye on --scale16, ImageMagick’s -depth 8 and any “web export” preset.
  • APNG: only some tools keep every frame. oxipng --strip all and optipng -snip flatten animations. For animation that is not a looping sticker, an actual video or animated WebP/AVIF is far smaller.
  • Large flat-colour screenshots may compress better as lossless WebP or JPEG XL if the destination supports them.

Every option and default for oxipng 10.2.1, OptiPNG 7.9.1, pngquant 3.0.3 and ZopfliPNG. Reading option tables explains the Default column.

Use -- before an input filename that begins with a hyphen. The hidden -Z is still accepted as an alias of --zopfli.

Complete oxipng 10.2.1 options and defaults
Parameter and aliasesType / accepted valuesDefaultMeaning and limits
--opt, -oenum 0–6/max2Preset from 0 (fastest) to 6 or max (smallest); explicit coding options override it.
--recursive, -rswitchoffOptimizes every .png and .apng file found in input directories.
--dirdirectorynot specifiedWrites outputs into this directory, creating it; recursion flattens the folder layout.
--outpathnot specified (input replaced if optimized)Writes the result to this file instead of replacing the input.
--stdoutswitchoffWrites the PNG to stdout; cannot combine with —dir, —out or —json.
--preserve, -pswitchoffKeeps the original permissions and timestamps where possible.
--dry-run, -dswitchoffReports the savings without writing any file.
-sswitchoffSame as —strip safe: removes non-essential chunks and keeps those that affect display.
--stripmode/listkeep valid chunks, except caBX/iDOTsafe, all or a comma-separated chunk list; all also turns APNG into a plain PNG.
--keepcomma-separated chunk namesnot specifiedStrips everything except the listed chunks; display keeps the appearance-affecting set.
--alpha, -aswitchoffRewrites colour values of fully transparent pixels to compress better; visually lossless.
--interlace, -ienumoff; keep with —nxoff, on (Adam7) or keep; interlacing adds 25–50% to the size.
--scale16switchoffReduces 16-bit channels to 8-bit by scaling; lossy.
--verbose, -vrepeatable switch0 occurrencesShows per-file detail; repeat for more. Cannot combine with —quiet.
--quiet, -qswitchoffSuppresses all output.
--json, -jswitchoffPrints results as JSON; cannot combine with —stdout.
--filters, -finteger list/range 0–90,1,6,7 at level 2Row filters to try: 0–4 fixed, 5 MinSum, 6 Entropy, 7 Bigrams, 8 BigEnt, 9 Brute.
--fastswitchon at levels 0–4; off at 5–6Scores filters with a quick pass, then runs one full trial on the best.
--zcinteger 0–1211 at level 2libdeflate level 0–12 for main trials; cannot combine with —zopfli.
--nbswitchoffKeeps the original bit depth.
--ncswitchoffKeeps the original colour type.
--npswitchoffDoes not convert to indexed colour or change an existing palette.
--ngswitchoffDoes not convert to or from greyscale.
--nxswitchoffDisables every reduction and makes the default interlace mode keep.
--nzswitchoffSkips IDAT recompression unless a transformation needs it; with —nx, disables all optimization.
--fixswitchoffSkips chunk checksum validation so damaged files can be processed; output checksums are valid.
--forceswitchoffWrites the output even when it is larger than the input.
--zopfli, -z, -ZswitchoffUses Zopfli instead of libdeflate for main trials; much slower, a little smaller.
--zipositive u6415Zopfli iteration count; fewer is faster. Requires —zopfli.
--ziwipositive u64not specifiedStops Zopfli after this many iterations without improvement; pair with a high —zi.
--brute-levelinteger 1–121; 5 at level 6libdeflate level for the Brute filter; 1–5 is sensible.
--brute-linesnonnegative integer3; 4 at level 4; 8 at levels 5–6Rows compressed together by the Brute filter; 2–16 is sensible.
--timeoutu64 secondsno limitTime budget in seconds, checked between trials; a running trial can overrun it.
--max-raw-sizesize with unit suffixno limitSkips images whose decompressed data exceeds this size; accepts suffixes like k or MB.
--threads, -tnonnegative integerlogical CPU countMaximum worker threads; 0 lets Rayon choose.
--sequentialswitchoff (parallel file processing)Processes files one at a time, in order.
--help, -hactionnot requestedShows help.
--version, -Vactionnot requestedPrints the version.
--actionnot requestedEnds option parsing so later arguments are input paths.

Presets: -o 0 uses filters 0,5 with libdeflate level 5; -o 1 uses 0,7 and level 10; -o 2 (default) uses 0,1,6,7 and level 11 with fast evaluation; -o 3 adds filters 8,9; -o 4 uses level 12; -o 5 and -o 6 disable fast evaluation, -o 6 uses every filter. Explicit --filters, --zc, --brute-* and --fast options override the preset regardless of order.

--strip safe / --keep display keep cICP, iCCP, sRGB, pHYs, acTL, fcTL and fdAT, and drop other ancillary chunks such as gAMA, cHRM, sBIT, mDCV and cLLI. Without --strip, oxipng keeps every chunk that is still valid, but drops caBX and Apple iDOT.

OptiPNG takes the same kind of optimisation switches but uses single-hyphen options, and documented prefixes are accepted as abbreviations. Prefer the full lowercase spelling. Attached forms such as -o2, -f0,5 and -zc9 are the same options.

Complete OptiPNG 7.9.1 options, aliases, and defaults
Parameter and aliasesType / accepted valuesDefaultMeaning and limits
-ononnegative integer2Preset 0–7, higher is slower and smaller; larger values act as 7.
-out, -oupathnot specified (input can be replaced)Output file for a single input; cannot combine with -dir.
-dir, -d, -didirectorynot specifiedOutput directory; cannot combine with -out.
-backup, -b, -ba, -bac, -back, -backu, -keep, -k, -ke, -keeswitchoffKeeps a .bak copy when overwriting the input.
-clobber, -c, -cl, -clo, -clob, -clobb, -clobbeswitchoffAllows replacing an existing output file.
-fix, -fiswitchoffTries to recover malformed input; check the result.
-force, -fo, -for, -forcswitchoffWrites an output file even when no improvement is found.
-preserve, -p, -pr, -pre, -pres, -prese, -preser, -preservswitchoffKeeps file attributes such as permissions and timestamps where possible.
-quiet, -q, -qu, -qui, -quie, -silent, -sil, -sile, -silenswitchoffSuppresses normal output.
-simulate, -sim, -simu, -simul, -simula, -simulatswitchoffRuns the optimization without writing files.
-fset/ranges 0–50,5 at level 2Row filters to try: 0–4 fixed, 5 adaptive. Accepts lists and ranges such as 0,5.
-iinteger 0–1retain input interlaceOutput interlacing: 0 none, 1 Adam7.
-zcset/ranges 1–99 at level 2zlib compression levels to try, 1–9.
-zmset/ranges 1–98 at level 2zlib memory levels to try, 1–9.
-zsset/ranges 0–30–3 at level 2zlib strategies to try: 0 default, 1 filtered, 2 Huffman-only, 3 RLE.
-zwpower-of-two sizelibpng default 32 KiB; smaller for Huffman/RLEzlib window size, 256 to 32768 bytes; accepts suffixes like 4k.
-full, -fu, -fulswitchoffProduces a full IDAT report, which can slow the search.
-nbswitchoffDisables bit-depth reduction.
-ncswitchoffDisables colour-type reduction.
-npswitchoffDisables palette reduction.
-nxswitchoffDisables all three reductions.
-nzswitchoffSkips IDAT recompression unless a reduction needs it.
-snip, -sn, -sniswitchoffExtracts one image from an animated or multi-image file and drops the rest.
-strip, -st, -str, -striobjectnot enabledOnly all is accepted; individual chunks cannot be named.
-vswitchoffVerbose output; with no input files, prints the version and copyright.
-verbose, -verb, -verbo, -verbosswitchoffVerbose output only.
-version, -vers, -versi, -versioactionnot requestedPrints the version when no input files are given.
-debugswitchoffEnables internal debug features; cannot be abbreviated.
-log, -loremoved optionnot supportedRemoved; the parser rejects it. Redirect output with the shell instead.
-help, -?, -h, -he, -helactionnot requestedShows extended help.
--actionnot requestedEnds option parsing so later arguments are input paths.

The default -o2 searches -zc9 -zm8 -zs0-3 -f0,5. Higher levels search more combinations but never add visual loss. Repeated -f and -z* sets are unioned. -strip accepts only all. -snip extracts a single image from an animated or multi-image input and discards the animation. See the versioned manual.

This is the Rust frontend (3.0.3). The optional positional ncolors is the same as the hidden --colors.

Complete pngquant 3.0.3 Rust options and defaults
Parameter and aliasesType / accepted valuesDefaultMeaning and limits
--colorsinteger 2–256256 maximumMaximum palette size, 2–256; the positional ncolors argument sets the same limit.
--quality, -Qmin-max in 0–100no minimum; target 100Quality range min-max, 0–100. Below min the image is refused (exit 99). A single N means 90% of N to N.
--speed, -sinteger 1–1141 (slowest, best) to 11 (fastest); 10 compresses the PNG faster, 11 also disables dithering.
--floydoptional float1Floyd–Steinberg dithering strength 0–1; write —floyd=0.5.
--nofs, --orderedswitchoffDisables dithering; —ordered is an alias.
--posterizeinteger 0–40Drops this many low bits of colour precision, 0–4; lossy but smaller.
--stripswitchoffRemoves optional metadata chunks.
--mapPNG pathnot specifiedUses the colours of this PNG as a fixed palette.
--extsuffix-fs8.png; -or8.png without ditheringOutput filename suffix for batch runs; cannot combine with —output.
--output, -opathderived suffix; stdout for stdinSingle output file; - writes to stdout.
--force, -fswitchoffOverwrites existing output files without a backup.
--no-forceswitchoffNever overwrites existing files, even when —force is also given.
--skip-if-largerswitchoffWrites nothing when the result is not smaller than the input (exit 98).
--transbugswitchoffPuts a transparent entry last in the palette for old, buggy viewers.
--iebugignored switchoffAccepted but ignored in 3.0.3.
--verbose, -vswitchoffPrints status and quantization details.
--quiet, -qswitchoffAccepted but has no effect; output is already quiet unless —verbose is given.
--help, -hactionnot requestedShows help.
--version, -Vactionnot requestedPrints the version.
--actionnot requestedEnds option parsing so later arguments are the color count and input paths.

--quality 65-85 tries a palette that meets 85 and refuses images that cannot reach 65, with exit code 99; 98 is the --skip-if-larger refusal. When reading from stdin the original may be passed through unchanged, so check what the pipeline actually produced. --iebug is registered but ignored in this version. The old C-only spellings (-nofs, -fs) are not accepted. --nofs and --ordered both mean no error diffusion.

Pinned to Google’s source commit df1517dd8518 (30 September 2026); there is no versioned release. Long-option values are attached with =.

Complete pinned Google ZopfliPNG options and defaults
Parameter and aliasesType / accepted valuesDefaultMeaning and limits
-mrepeatable switchoff (15/5 iterations)Multiplies the iteration counts by 4; repeat for more.
-yswitchoffOverwrites existing output without asking; a smaller earlier output is still kept.
-dswitchoffDry run: prints sizes without saving.
-qswitchoffFast compression without Zopfli; for quickly trying filters and colour types.
--prefixoptional text attached with =not enabled; zopfli_ when bareBatch mode: writes prefixed copies of each input, optionally into a directory. Use —prefix=name.
--always_zopflifyswitchoffWrites the Zopfli output even when larger than the input; for benchmarking.
--verboseswitchoffPrints a detailed coding report.
--lossy_transparentswitchoffDiscards RGB values behind fully transparent pixels.
--lossy_8bitswitchoffConverts 16-bit channels to 8-bit; lossy.
--iterationsinteger attached with =15 below 200000 raw bytes; 5 otherwiseZopfli iterations for any file size; more is slower and slightly smaller. Minimum 1.
--splittingignored compatibility argumentignoredIgnored; kept for backward compatibility.
--filterscharacters attached with =automatic fast selectionStrategies to try: 0–4 fixed, m MinSum, e entropy, p input filters, b brute force. 0me is a good set.
--keepchunkscomma-separated four-letter chunk namesnone (IHDR,PLTE,tRNS,IDAT,IEND only)Extra chunks to keep, as exact four-letter names separated by commas (iCCP,gAMA). bKGD or sBIT also pins the colour type.
--keepcolortypeswitchoffKeeps the input colour type and bit depth, at some cost in compression.
--help, -hactionnot requestedShows help.

The default iteration split depends on the raw DEFLATE input size (15 below 200,000 bytes, otherwise 5). An existing output file is treated as a previous candidate and kept if smaller. ZopfliPNG returns success on some failure paths, so confirm the output exists and decodes. By default it keeps only IHDR, PLTE, tRNS, IDAT and IEND, which removes colour profiles; list the ones the image needs, such as --keepchunks=iCCP,sRGB,gAMA,cHRM,cICP; names are exact four-letter, case-sensitive and comma-separated with no spaces. It is not an APNG optimiser.