Build1 distinct publisher3 min readUpdated
One developer's APNG test set inflated by up to 2.41x when adaptive per-scanline filtering was switched on. The spec's rule scores byte magnitude; DEFLATE charges for repetition.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
The mechanism is a disagreement between two cost functions. Minimum sum of absolute differences scores byte magnitude, DEFLATE pays for repetition, and on these frames the two point in opposite directions [14]. A run of identical pixels left at filter None is a run of identical bytes, which is the single thing LZ77 is best at; under Sub the same run becomes zeros, which also compresses, but the value at each boundary depends on whatever came before it, so an image made of flat regions with hard edges ends up with many small varying values instead of a few long identical runs [15]. The heuristic prefers the small varying values because that is the quantity it is scoring [14].
Its revealed preference is stark. Across the set it left between 0.0% and 0.2% of rows at filter None, on files where holding every row at None was 2.4x smaller [16]. Two rows in a thousand is not a rule that needs recalibrating; it is a rule that essentially never selects the winner, because the winner almost never has the lowest sum of absolute differences [16].
The route to that conclusion, as described in the dev.to write-up, is the transferable part. The first explanation, written into a source comment before anything was measured, was that flat art has repeating scanlines and that mixing filters per row rewrites identical rows into different bytes and destroys the long matches [7]. The worst file in the set has no repeated scanlines at all, and ranked across all 28 pairs of files, more repeated rows predicted a worse adaptive result in 6 of them, where a rule carrying no information lands near 14 [8]. That means the ordering ran the other way in 22 of the 28 pairs [9], so the data was mildly against the story rather than merely silent on it. Palette size managed 10 of 28, with the best and worst files sitting at 190 and 183 colours [10]. How often the heuristic switched filter type between adjacent rows landed on 14 of 28, exactly chance [11].
One detail deserves more attention than it usually gets. The forced-filter table came out wrong the first time: all five filters reported 1.43x, identical to the decimal [20]. Five different transforms agreeing that precisely is a measurement of the harness rather than of the images, and it is the cheapest bug signal available in work like this.
The probe runs once per animation rather than once per frame, on the reasoning that the frames of one animation are the same kind of picture, so re-confirming the winner on each of them doubles the compression work to learn nothing [18]. It also preserves the gain that is real: the single continuous-tone file still comes out at 0.83x because the probe finds it [19], and on that file every differencing filter wins [13]. The textbook advice is right about a kind of image, and seven of these eight were the other kind [13]. What eight files can establish is that the losing kind is common enough to dominate a small sample of real animations, not what share of animation payloads it represents.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
The author added adaptive per-scanline filtering to an APNG encoder because that is standard practice.
PNG lets every row pick one of five filters, the spec suggests picking the one that minimises the sum of absolute differences, and every PNG optimiser the author has read does exactly that.
Adaptive per-scanline filtering made seven of the eight test animations bigger, the worst by 2.41x; one file got smaller.
Eight animations from Wikimedia were decoded to full-canvas RGBA and re-encoded as APNG with the same frames, same zlib level and same encoder; the only difference was whether each scanline got a chosen filter or was left at filter None.
The author's first explanation, written into a source comment, was that flat art has whole repeating scanlines, filter None leaves those repeats byte-identical so LZ77 can match one row against another, and mixing filter types per row destroys the long matches; the author reports this explanation was wrong.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
One transparent but unreplicated first-party experiment
The claims rest on a single dev.to post by one developer. Internal quality is above average for the format: variables are held constant, three candidate explanations are quantified and discarded, a forced-filter matrix separates switching from differencing, filter-assignment rates are instrumented, and the author documents and fixes a harness bug that had produced a plausible fictitious table. But nothing is independently verified, no encoder, harness or dataset is linked, the tables themselves are not reproduced in the supplied text, and the corpus is eight self-selected Wikimedia animations, so the evidence cannot rise past 'credible single-source engineering report'.
Two first-party benchmarks, no third-party uptake
Observable adoption is limited to the author's own encoder work: two benchmark runs over eight animations and a code-level probe added to their private APNG encoder. There is no release, no named project or repository, no downstream user, and no report of any other implementation changing behaviour, so real-world traction is near the floor even though the measurement activity is concrete.
Framing generalises further than eight files support
The headline and dek universalise ('every PNG optimiser filters by default') from an unreplicated eight-file, single-encoder test, and no named optimiser is actually measured. That is a real overstatement. It is partly offset inside the body, where the author explicitly scopes the finding to a class of image, concedes the textbook advice wins on the continuous-tone file, retracts his own first mechanism, and publishes the harness bug — so the gap is modest rather than severe.
Low commercial stake, mild attention incentive
The supplied source sells nothing: no product, vendor, pricing, sponsor or company is present, and the author works against his own prior conclusions by retracting a documented explanation and publishing a measurement bug — behaviour that cuts against incentive-driven inflation. The residual incentive is attention on a developer-blog platform for a counterintuitive, absolutist headline, which plausibly shaped the framing more than the numbers. No affiliation or funding disclosure appears in the source, so this is scored only on what the text shows.
Moderate: methodologically candid, single-sourced
Confidence is capped by structure rather than craft: one publisher, one author, one harness, eight files, no replication and no released artefacts, and the author has already shown that this harness once emitted a wholly fictitious table. Within those limits the internally consistent numbers (2.41x worst case matching the 6 MB to 14.5 MB Cicada figure), the mechanism/experiment pairing, and the explicit continuous-tone counter-example make the core narrow claim — that SAD-minimising filter selection can badly lose to filter None on flat-art frames — reasonably trustworthy, while the universal framing is not.
build
An exact byte budget is a search problem, and 18 encodes is the wrong way to run it1 distinct publisher
build
A GAN beauty filter is a device budget allocation, not a feature toggle1 distinct publisher
build
Every viewer hits your HLS key endpoint in the same second, and almost nobody tests it1 distinct publisher
build
912MB to 108MB is mostly typing now, and that weakens the base-image excuse in review1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 23, 2026