“Comprimeer deze afbeelding” zijn vier verschillende bewerkingen onder één knop. Weten welke ervan je kwaliteit kost, maakt de instellingen een stuk minder mysterieus.
Stap één: decoderen
Het gecomprimeerde bestand wordt terugvertaald naar een raster van pixels. Browsers doen dat in native code, met hardwareversnelling waar het platform die biedt, en ze kunnen overweg met JPEG, PNG, WebP en AVIF — plus HEIC op Apple-platforms, omdat het besturingssysteem die decoder al meelevert.
Decoderen is verliesloos ten opzichte van het bestand: je krijgt exact de pixels die het bestand beschrijft. Het verlies was er al, toen datgene wat het bestand maakte het codeerde.
Stap twee: oriëntatie
Telefooncamera’s slaan de ruwe stand van de sensor op, plus een losse EXIF-tag die zegt hoe je hem moet draaien. Software die die tag negeert, levert foto’s op hun kant af. De tag toepassen betekent dat het pixelraster zelf gedraaid wordt voordat iets anders het aanraakt — en daarna is de tag niet meer nodig, wat mede verklaart waarom hercoderen de metadata laat vervallen.
Stap drie: hersamplen
Als de doelgrootte op volle resolutie niet haalbaar is, wordt de afbeelding verkleind. Hier wordt stilletjes veel waargenomen kwaliteit gewonnen of verspeeld. Een goedkoop boxfilter middelt naburige pixels en maakt alles zachter; een Lanczos-filter weegt een bredere omgeving mee en houdt randen scherp.
Hersamplen is echt destructief — de weggegooide pixels komen niet terug — maar het is vaak de minst destructieve manier om een kleine doelgrootte te halen, omdat het detail weghaalt waar de encoder anders zijn hele budget aan zou opmaken zonder het te kunnen beschrijven.
Stap vier: coderen
Het lossy deel. JPEG zet de afbeelding om naar een representatie van helderheid plus kleur, gooit een deel van de kleurresolutie weg (het oog merkt daar amper iets van), deelt het beeld op in blokken van 8×8, zet elk blok om in frequentiecomponenten en kwantiseert dan — het detail met hoge frequentie wordt weggerond. De kwaliteitsparameter is de grofheid van die afronding. Alles daarna is verliesloze entropiecodering, en daarom leveren een geoptimaliseerde Huffman-tabel of een progressieve scan gratis bytes op.
Waar WebAssembly binnenkomt
De ingebouwde encoder van de browser is een black box: je mag om een kwaliteitsgetal vragen en verder niets. Geen geoptimaliseerde entropietabellen, geen keuze tussen baseline en progressief, geen controle over het hersamplefilter, en geen manier om te weten hoeveel bytes een instelling oplevert zonder het te proberen.
Een codec die naar WebAssembly is gecompileerd, geeft dat allemaal terug — je betaalt er de bytes van de download voor. ToolZool draait de hele pijplijn op die manier: decoderen, oriëntatie, hersamplen en coderen zijn allemaal Rust, gecompileerd naar WebAssembly, in een achtergrondworker, in plaats van het decoderen aan de browser over te laten. Drie redenen, en alle drie praktisch:
- De zoektocht vraagt om veel coderingen. Een exacte grootte halen betekent dat dezelfde afbeelding vijf of zes keer gecodeerd wordt. Doordat we de encoder zelf in handen hebben, is dat goedkoop en herhaalbaar.
- Een decoder moet nee kunnen zeggen. Een bestand dat 60.000 × 60.000 pixels claimt, moet geweigerd worden vóór het geheugen reserveert, en een afgekapt bestand moet falen in plaats van een halve afbeelding terug te geven. De decoder van de browser maakt daar zijn eigen keuzes; de onze benoemt de grenzen en handhaaft ze.
- Dezelfde invoer moet dezelfde uitvoer geven. Browserdecoders verschillen in hun kleurbehandeling en in hoe ze met kapotte bestanden omgaan. Een pijplijn die beide uiteinden bezit, levert op elk apparaat dezelfde bytes op, en dat is wat een resultaat controleerbaar maakt.
De prijs is eerlijk: die engine is een download. Hij wordt pas opgehaald zodra je een bestand kiest, dus een pagina als deze lezen kost je hem niet.
Waarom de zoektocht meer uitmaakt dan de codec
Bij een gegeven doelgrootte scheelt een goede encoder een paar procent met een uitstekende. Het verschil tussen gokken met een kwaliteitsschuif en zoeken naar de juiste waarde is veel groter, want een gok die op 60% van je ruimte uitkomt, heeft een derde van de kwaliteit weggegooid waar je recht op had. Dat is het hele idee achter comprimeren naar een exacte grootte, en een limiet van 50 KB halen laat zien wat die zoektocht je oplevert aan het lastigste eind van het bereik.

