„Skompresuj ten obraz” to cztery odrębne operacje pod jednym przyciskiem. Świadomość, która z nich kosztuje jakość, sprawia, że ustawienia przestają być tajemnicze.
Krok pierwszy: dekodowanie
Skompresowany plik zostaje zamieniony z powrotem w siatkę pikseli. Przeglądarki robią to w kodzie natywnym, z akceleracją sprzętową tam, gdzie platforma ją oferuje, i obsługują JPEG, PNG, WebP oraz AVIF — a na platformach Apple również HEIC, bo system operacyjny ma już ten dekoder u siebie.
Dekodowanie jest bezstratne względem pliku: dostajesz dokładnie te piksele, które plik opisuje. Strata wydarzyła się wcześniej, kiedy plik zakodowało to, co go stworzyło.
Krok drugi: orientacja
Aparaty w telefonach zapisują surową orientację matrycy plus osobny znacznik EXIF mówiący, jak ją obrócić. Oprogramowanie, które ten znacznik ignoruje, produkuje zdjęcia położone na boku. Zastosowanie go oznacza obrócenie samej siatki pikseli, zanim dotknie jej cokolwiek innego — po czym znacznik przestaje być potrzebny, co jest jednym z powodów, dla których ponowne kodowanie usuwa metadane.
Krok trzeci: prepróbkowanie
Jeśli docelowego rozmiaru nie da się osiągnąć w pełnej rozdzielczości, obraz zostaje pomniejszony. To tutaj po cichu wygrywa się albo traci sporo postrzeganej jakości. Tani filtr blokowy uśrednia sąsiadujące piksele i wszystko zmiękcza; filtr Lanczosa waży szersze sąsiedztwo i utrzymuje ostre krawędzie.
Prepróbkowanie jest naprawdę destrukcyjne — odrzucone piksele nie wracają — ale często jest najmniej destrukcyjną drogą do małego rozmiaru docelowego, bo usuwa szczegół, na którego nieudany opis koder wydałby inaczej cały swój budżet.
Krok czwarty: kodowanie
Część stratna. JPEG przechodzi na reprezentację jasność plus kolor, odrzuca część rozdzielczości koloru (oko ledwo to zauważa), dzieli obraz na bloki 8×8, przekształca każdy w składowe częstotliwości, a potem kwantyzuje — zaokrągla, pozbywając się szczegółu o wysokiej częstotliwości. Parametr jakości to zgrubność tego zaokrąglania. Wszystko, co dzieje się później, to bezstratne kodowanie entropijne — i dlatego zoptymalizowana tablica Huffmana albo skan progresywny oszczędzają bajty za darmo.
Skąd tu WebAssembly
Wbudowany koder przeglądarki to czarna skrzynka: możesz poprosić o liczbę oznaczającą jakość i o nic więcej. Żadnych zoptymalizowanych tablic entropijnych, żadnego wyboru między trybem bazowym a progresywnym, żadnej kontroli nad filtrem prepróbkowania i żadnego sposobu, by dowiedzieć się, ile bajtów da dane ustawienie, zanim się go nie wypróbuje.
Kodek skompilowany do WebAssembly oddaje to wszystko z powrotem, kosztem bajtów, które wydajesz na jego pobranie. ToolZool prowadzi w ten sposób cały tok — dekodowanie, orientacja, prepróbkowanie i kodowanie to Rust skompilowany do WebAssembly, działający w wątku roboczym w tle — zamiast oddawać dekodowanie przeglądarce. Trzy powody, wszystkie praktyczne:
- Wyszukiwanie wymaga wielu kodowań. Trafienie w dokładny rozmiar oznacza zakodowanie tego samego obrazu pięć albo sześć razy. To posiadanie własnego kodera sprawia, że jest to tanie i powtarzalne.
- Dekoder musi umieć odmówić. Plik deklarujący 60 000 × 60 000 pikseli trzeba odrzucić, zanim cokolwiek zaalokuje, a plik ucięty musi zgłosić błąd, a nie zwrócić pół obrazu. Dekoder przeglądarki podejmuje tu własne decyzje; nasz podaje limity i ich pilnuje.
- To samo wejście musi dawać to samo wyjście. Dekodery przeglądarek różnią się obsługą koloru i traktowaniem plików niepoprawnych. Tok, który ma pod kontrolą oba końce, daje te same bajty na każdym urządzeniu — a to jest właśnie wynik, który da się sprawdzić.
Koszt jest uczciwy: ten silnik trzeba pobrać. Pobiera się dopiero wtedy, gdy wybierzesz plik, więc czytanie takiej strony jak ta nigdy za niego nie płaci.
Dlaczego wyszukiwanie znaczy więcej niż kodek
Przy zadanym docelowym rozmiarze pliku różnica między dobrym a znakomitym koderem to kilka procent. Różnica między zgadywaniem na suwaku jakości a wyszukaniem właściwej wartości jest znacznie większa, bo strzał, który ląduje na 60% twojego limitu, wyrzucił jedną trzecią jakości, do której miałeś prawo. Na tym opiera się cały pomysł kompresji do dokładnego rozmiaru, a tekst jak zmieścić się w limicie 50 KB pokazuje, co daje wyszukiwanie na najtrudniejszym końcu skali.

