”Komprimera den här bilden” är fyra separata operationer bakom en och samma knapp. Vet du vilken av dem som kostar dig kvalitet blir inställningarna genast mycket mindre mystiska.
Steg ett: avkodning
Den komprimerade filen görs om till ett rutnät av pixlar. Webbläsare gör det i inbyggd kod, med hårdvaruacceleration där plattformen erbjuder den, och de klarar JPEG, PNG, WebP och AVIF — plus HEIC på Apples plattformar, eftersom operativsystemet redan innehåller den avkodaren.
Avkodningen är förlustfri i förhållande till filen: du får exakt de pixlar filen beskriver. Förlusten skedde redan när det som skapade filen kodade den.
Steg två: orientering
Telefonkameror lagrar sensorns råa orientering plus en separat EXIF-tagg som anger hur bilden ska roteras. Programvara som struntar i taggen ger foton som ligger på sidan. Att tillämpa den betyder att själva pixelrutnätet roteras innan något annat rör det — därefter behövs taggen inte längre, vilket är en del av förklaringen till att omkodning tar bort metadata.
Steg tre: omsampling
Går målstorleken inte att nå i full upplösning skalas bilden ned. Det är här mycket av den upplevda kvaliteten tyst vinns eller förloras. Ett enkelt boxfilter medelvärdesbildar närliggande pixlar och gör allt mjukare; ett Lanczos-filter väger in en bredare omgivning och håller kanterna skarpa.
Omsampling är genuint destruktiv — de bortkastade pixlarna kommer inte tillbaka — men den är ofta det minst destruktiva sättet att nå ett litet mål, eftersom den tar bort detaljer som kodaren annars skulle lägga hela sin budget på att misslyckas med att beskriva.
Steg fyra: kodning
Den destruktiva delen. JPEG räknar om bilden till en representation av ljusstyrka plus färg, kastar bort en del färgupplösning (ögat märker det knappt), delar upp bilden i block om 8×8, omvandlar varje block till frekvenskomponenter och kvantiserar sedan — rundar bort de högfrekventa detaljerna. Kvalitetsparametern är hur grov den avrundningen är. Allt efter den är förlustfri entropikodning, och det är därför en optimerad Huffman-tabell eller en progressiv avsökning sparar byte gratis.
Var WebAssembly kommer in
Webbläsarens inbyggda kodare är en svart låda: du kan be om ett kvalitetstal och inget mer. Inga optimerade entropitabeller, inget val mellan baseline och progressiv, ingen kontroll över omsamplingsfiltret och inget sätt att veta hur många byte en inställning ger utan att prova.
En codec kompilerad till WebAssembly ger tillbaka allt det, till priset av de byte du lägger på att ladda ner den. ToolZool kör hela kedjan så — avkodning, orientering, omsampling och kodning är alltihop Rust kompilerat till WebAssembly, i en bakgrundstråd — i stället för att lämna avkodningen till webbläsaren. Tre skäl, alla praktiska:
- Sökningen kräver många kodningar. Att träffa en exakt storlek innebär att samma bild kodas fem eller sex gånger. Att äga kodaren är det som gör det billigt och upprepbart.
- En avkodare måste kunna säga nej. En fil som påstår sig vara 60 000 × 60 000 pixlar måste nekas innan den tar minne i anspråk, och en avhuggen fil måste misslyckas i stället för att lämna tillbaka en halv bild. Webbläsarens avkodare fattar sina egna beslut där; vår anger gränserna och upprätthåller dem.
- Samma indata måste ge samma utdata. Webbläsares avkodare skiljer sig åt i färghantering och i hur de behandlar trasiga filer. En kedja som äger båda ändarna ger samma byte på varje enhet, och det är det som gör resultatet kontrollerbart.
Kostnaden är ärlig: motorn är en nedladdning. Den hämtas först när du har valt en fil, så att läsa en sida som den här kostar aldrig något för den.
Varför sökningen betyder mer än codecen
Givet en målfilstorlek är skillnaden mellan en bra kodare och en lysande några få procent. Skillnaden mellan att gissa på ett kvalitetsreglage och att söka fram rätt värde är mycket större, för en gissning som landar på 60 % av ditt utrymme kastade bort en tredjedel av den kvalitet du hade rätt till. Det är hela idén bakom att komprimera till en exakt storlek, och att klara en gräns på 50 KB visar vad sökningen ger dig i den svåraste änden av skalan.

