JPEG format images are everywhere in our digital lives, but behind this veil of awareness lie algorithms that eliminate details not perceived by the human eye. The result is the highest visual quality at the smallest file size—but how exactly does all this work? Let’s take a look at what our eyes don’t see!

It's easy to take for granted the ability to send a photo to a friend without worrying about what device, browser, or operating system they're using—but it wasn't always like this. By the early 1980s, computers could store and display digital images, but there were many competing ideas about the best way to do this. You couldn't just send an image from one computer to another and hope everything would work out.
To address this issue, a committee of experts from around the world was formed in 1986 called “” (JPEG), which was established under the joint efforts of the International Organization for Standardization (ISO) and the International Electrotechnical Commission (IEC)—two international standards organizations based in Geneva, Switzerland.
A group of people called JPEG created the JPEG image compression standard in 1992. Anyone who has used the internet has likely encountered images encoded in JPEG. It is the most common method for encoding, sending, and storing images. From web pages to emails and social media, JPEG is used billions of times a day—almost every time we view an image online or send one. Without JPEG, the web would be less vibrant, slower, and probably feature fewer cat photos!
Ta članek govori o tem, kako dekodirati JPEG sliko. Z drugimi besedami, o tem, kaj je potrebno za pretvorbo stisnjenih podatkov, shranjenih na računalniku, v sliko, ki se prikaže na zaslonu. O tem je dobro vedeti ne le zato, ker je to pomembno za razumevanje tehnologije, ki jo uporabljamo vsak dan, ampak tudi zato, ker z razkrivanjem stopenj stiskanja bolje spoznavamo zaznavanje in vid ter to, kakšnim podrobnostim so naše oči najbolj dovzetne.
Poleg tega je igranje z slikami na ta način zelo zabavno.

Pogled v notranjost JPEG
Na računalniku so vse stvari shranjene v obliki zaporedja binarnih številk. Običajno se ti biti, ničle in enice, skupine po osem, oblikujejo v byte. Ko na računalniku odprete JPEG sliko, mora nekaj (brskalnik, operacijski sistem, nekaj drugega) dekodirati bite in obnoviti izvirno sliko v obliki seznama barv, ki jih je mogoče prikazati.
Če prenesete to ljubko in jo odprete v besedilnem urejevalniku, boste videli kup nesmiselnih simbolov.

Tukaj uporabljam Notepad++ za pregledovanje vsebine datoteke, ker običajni besedilni urejevalniki, kot je Notepad v Windows, pokvarijo binarno datoteko po shranjevanju in ta ne bo več ustrezala JPEG formatu.
Ko sliko odprete v besedilnem urejevalniku, zmedete računalnik, prav tako kot zmedete svoj um, ko si podrgnite oči in začnete videti barvne madeže!
Ti madeži, ki jih vidite, so znani kot , in niso rezultat vpliva svetlobnega stimulusa ali halucinacij, ki jih povzroča um. Pojavijo se, ker vaš možgani menijo, da kakršni koli električni signali v očesnih žilah prenašajo informacije o svetlobi. Mozgu je treba postavljati takšne domneve, saj ni mogoče ugotoviti, ali je signal zvok, vizija ali kaj drugega. Vse žile v telesu prenašajo absolutno enake električne impulze. S pritiskanjem na oči pošiljate signale, ki niso vidni, a aktivirajo receptorje v očesu, kar vaš možgan interpretira – v tem primeru napačno – kot nekaj vidnega. Dobesedno lahko vidite pritisk!
Zabavno je razmišljati o tome koliko su računala slična mozgu, no također je to korisna analogija koja ilustrira koliko značenje podataka – prenesenih tijelom putem živaca ili pohranjenih na računalu – ovisi o njihovoj interpretaciji. Svi binarni podaci sastavljeni su od nula i jedinica, osnovnih komponenti koje mogu prenositi informacije bilo koje vrste. Vaše računalo često pretpostavlja kako ih interpretirati koristeći naznake, poput ekstenzija datoteka. A sada ga tjeramo da ih interpretira kao tekst, jer to očekuje uređivač teksta.
Da bismo razumjeli kako dekodirati JPEG, trebamo vidjeti izvorne signale – binarne podatke. Ovo možemo učiniti pomoću heksadecimalnog uređivača, ili direktno na !. Tamo se nalazi slika, pored koje su u tekstualnom okviru prikazani svi njezini bajtovi (osim zaglavlja), prikazani u decimalnom obliku. Možete ih mijenjati, a skripta će ih rekodirati i dati novu sliku u hodu.

Mnogi mogu saznati jednostavno igrajući se s ovim uređivačem. Na primjer, možete li reći u kojem su redoslijedu pohranjeni pikseli?
U ovom primjeru čudno je to što neka promjena brojeva uopće ne utječe na sliku, a, ako na primjer, promijenite broj 17 u 0 u prvom redu, slika će biti potpuno uništena!

Drake promjene, kao što je zamjena 7 u redu 1988 s brojem 254 mijenja boju, ali samo sljedećih piksela.

Možda najčudnije je to što neki brojevi mijenjaju ne samo boju, već i oblik slike. Promijenite 70 u redu 12 na 2 i pogledajte gornji red slike da biste vidjeli na što mislim.

I bez obzira na to koju JPEG sliku koristite, uvijek ćete nalaziti ove misteriozne šahovske sekvence prilikom uređivanja bajtova.
Igrajući se s uređivačem, teško je razumjeti kako se slika rekonstruira iz ovih bajtova, budući da JPEG kompresija sastoji od tri različite tehnologije koje se primjenjuju uzastopno. Istražit ćemo svaku od njih posebno kako bismo otkrili misteriozno ponašanje koje promatramo.
Tri razine JPEG kompresije:
- .
- .
- , in
Da bi si lahko predstavljali obseg stiskanja, bodite pozorni, da slika, prikazana zgoraj, predstavlja 79.819 števil, torej približno 79 Kb. Če bi jo shranili brez stiskanja, bi za vsak piksel potrebovali tri številke – za rdečo, zeleno in modro komponento. To bi bilo 917.700 števil, oziroma približno 917 Kb. Kot rezultat JPEG stiskanja se je končna datoteka zmanjšala za več kot 10-krat!
V resnici je to sliko mogoče še bolj stisniti. Spodaj so prikazane dve sliki ob strani – fotografija na desni je bila stisnjena na 16 Kb, torej 57-krat manj kot različica brez stiskanja!

Če se pozorno ogledate, boste opazili, da ti slike niso identične. Obe sta slike z JPEG stiskanjem, vendar je desna veliko manjša po velikosti. Prav tako izgleda nekoliko slabše (poglejte kvadrate barv ozadja). Zato se JPEG še imenuje stiskanje z izgubami; med procesom stiskanja se slika spremeni in izgubi nekatere podrobnosti.
1. Barvna subdiskretizacija
Tukaj je slika, pri kateri je bila uporabljena samo prva stopnja stiskanja.

(Interaktivna različica – v članka). Odstranitev enega števila zruši vse barve. Vendar pa, če odstranimo točno šest števil, to skoraj ne vpliva na sliko.
Sedaj so številke nekoliko lažje razvozlati. To je skoraj preprost seznam barv, pri čemer vsak bajt spremeni točno en piksel, vendar je že dvakrat manjša od nespravljene slike (ki bi imela približno 300 Kb v tako zmanjšani velikosti). Uganete zakaj?
Lahko vidimo, da te številke ne označujejo standardnih rdečih, zelenih in modrih komponent, saj če vse številke zamenjamo z ničlami, dobimo zeleno sliko (namesto bele).

To je zato, ker te bajti označujejo Y (svetlost),

Cb (relativna modrina),

in Cr (relativna rdečina) slike.

Zakaj ne uporabiti RGB? Saj tako deluje večina sodobnih zaslonov. Vaš monitor lahko prikaže katerokoli barvo, vključno z rdečo, zeleno in modro z različno intenzivnostjo za vsak piksel. Bela barva se doseže z vključitvijo vseh treh na polno svetlost, črna pa z izklopom.

To je prav tako zelo podobno delovanju človeškega očesa. Barvni receptorji naših oči se imenujejo „«, in deli se delijo v tri vrste, pri čemer je vsaka bolj občutljiva bodisi na rdečo, bodisi na zeleno, bodisi na modro barvo [S-tipo čepkov je občutljiv na vijolično-modri (S iz angleščine Short — kratkovalovni spekter), M-tipa — na zeleno-rumeni (M iz angleščine Medium — srednjevalovni), in L-tipa — na rumeno-rdeči (L iz angleščine Long — dolgovalovni) del spektra. Prisotnost teh treh vrst čepkov (in palic, občutljivih v zamudno zeleni del spektra) daje človeku barvni vid. / op. prev.] , drug tip fotoreceptorjev v naših očeh, ki lahko zaznavajo spremembe v svetlosti, vendar so veliko bolj občutljive na barvo. V naših očeh je približno 120 milijonov palic in le 6 milijonov čepkov.
Zato naše oči veliko bolje opazijo spremembe v svetlosti kot spremembe v barvi. Če ločimo barvo od svetlosti, lahko odstranimo malo barve, in nihče ne bo opazil. Barvna subdiskretizacija je postopek predstavitve barvnih komponent slike z manjšim ločljivostjo v primerjavi s komponentami svetlosti. V zgornjem primeru ima vsak piksel točno eno komponento Y, vsak posamezen sklop štirih pikslov pa ima točno eno komponento Cb in eno Cr. Tako slika vsebuje štirikrat manj barvnih informacij kot izvirnik.
Barvni prostor YCbCr se ne uporablja le v JPEG-u. Sprva je bil izumljen leta 1938 za televizijske prenose. Ne morejo si vsi privoščiti barvnega televizorja, zato je ločevanje barve in svetlosti omogočilo, da so vsi prejeli isti signal, medtem ko so televizorji brez barve uporabili samo komponento svetlosti.
Zato odstranitev enega števila iz urejevalnika popolnoma uniči vse barve. Komponente so shranjene v obliki Y Y Y Y Cb Cr (v resnici ni nujno v tem vrstnem redu — vrstni red shranjevanja je določen v glavi datoteke). Odstranitev prve številke bo povzročila, da bo prvo vrednost Cb zaznalo kot Y, Cr kot Cb, in v celoti bo nastal učinek domin, ki preklaplja vse barve slike.
Specifikacija JPEG ne obavezuje na korišćenje YCbCr. Međutim, u većini datoteka se koristi jer pruža bolju kvalitetu slike nakon subuzorkovanja u poređenju sa RGB. No, ne morate mi verovati na reč. Pogledajte sami u tabeli ispod kako će izgledati subuzorkovanje svakog pojedinačnog komponenta i u RGB i u YCbCr.

(Interaktivna različica – v članaka).
Uklanjanje plave nije toliko uočljivo kao crvene ili zelene. To je zato što od šest miliona čepića u vašim očima, oko 64% je osetljivo na crvenu, 32% na zelenu i 2% na plavu.
Subuzorkovanje Y komponente (na dnu levo) je najbolje uočljivo. Čak i mala promena je vidljiva.
Pretvaranje slike iz RGB u YCbCr ne smanjuje veličinu datoteke, ali olakšava pronalaženje manje uočljivih detalja koje je moguće ukloniti. Gubitničko kompresovanje dešava se u drugom koraku. Njena osnovna ideja je predstavljanje podataka u kompaktnijem obliku.
2. Diskretna kosinusna transformacija i diskretizacija
Ova stepen kompresije većinom definiše suštinu JPEG-a. Nakon konverzije boja u YCbCr, komponente se komprimuju zasebno, tako da se možemo fokusirati samo na Y komponentu. I tako izgledaju bajtovi Y komponente nakon primene ovog stepena.

(Interaktivna različica – v članaka). U interaktivnoj verziji, klikom na piksel, editor pomera na red koji ga označava. Pokušajte da obrišete brojeve sa kraja ili dodate nekoliko nula određenom broju.
Na prvi pogled, to izgleda kao veoma loša kompresija. U slici sa 100.000 piksela, potrebno je 102.400 brojeva da označimo njihovu osvetljenost (Y komponenta) — to je lošije od nepotpune kompresije!
Međutim, primetite da je većina ovih brojeva jednaka nuli. Štaviše, svi ovi nuli na kraju redova mogu se ukloniti bez promena slike. Ostaće oko 26.000 brojeva, što je skoro četiri puta manje!
Na ovom nivou se nalazi tajna šahovskih obrazaca. Za razliku od drugih efekata koje smo videli, pojava ovih obrazaca nije greška. Oni su građevni blokovi cele slike. U svakom redu editora nalazi se tačno 64 broja, koeficijenti diskretne kosinusne transformacije (DCT), koji odgovaraju intenzitetima 64 jedinstvena obrasca.
Ti vzorci se oblikujejo na podlagi kosinusovega grafa. Tukaj je, kako izgledajo nekateri od njih:

8 od 64 koeficientov
Spodaj je slika, ki prikazuje vseh 64 vzorcev.

(Interaktivna različica – v članaka).
Ti vzorci imajo poseben pomen, saj oblikujejo osnovo slik dimenzij 8x8. Če niste seznanjeni z linearno algebro, to pomeni, da je možno vsako sliko dimenzij 8x8 pridobiti iz teh 64 vzorcev. DCT je proces razdeljevanja slik v bloke 8x8 in pretvorbe vsakega bloka v kombinacijo teh 64 koeficientov.
To, da lahko vsako sliko ustvarimo iz 64 določenih vzorcev, se zdi magično. Vendar pa to pomeni isto, kot če bi rekli, da lahko vsak kraj na Zemlji opišemo z dvema številkama – širino in dolžino [z navedbo polovica / op. prev.]. Pogosto menimo, da je površina Zemlje dvodimenzionalna, zato potrebujemo zgolj dve številki. Slika 8x8 ima 64 dimenzij, zato potrebujemo 64 številk.
Zaenkrat ni jasno, kako nam to pomaga pri kompresiji. Če potrebujemo 64 številk za predstavitev slike 8x8, zakaj bi bil ta način boljši od preproste shranitve 64 komponent svetlosti? To počnemo iz istega razloga, zakaj smo tri številke RGB pretvorili v tri številke YCbCr: to nam omogoča, da odstranimo nevidne podrobnosti.
Težko je videti, katere podrobnosti so odstranjene v tej fazi, saj JPEG uporablja DCT na blokih 8x8. Vendar nam nihče ne prepoveduje, da ga uporabimo na celotni sliki. Tukaj je, kako izgleda DCT na komponenti Y, ko se uporablja na celotni sliki:

Od konca je mogoče odstraniti več kot 60.000 številk praktično brez opaznih sprememb na fotografiji.

Vendar pa opazite, da bo razlika očitna, če obrnemo prvih pet številk.

Številke na začetku označujejo spremembe nizkih frekvenc v sliki, in naše oči jih zaznavajo najbolje. Številke bližje koncu označujejo spremembe visokih frekvenc, ki jih je težje opaziti. Da bi 'videli tisto, kar je nevidno s prostim očesom', lahko izoliramo te podrobnosti visoke frekvence, tako da obrnemo prvih 5000 številk.

Vidimo vse dele slike, kjer se dogajajo največje spremembe od piksla do piksla. Izpostavljeni so oči mačke, njeni brki, plišasta odeja in sence v spodnjem levem kotu. Lahko gremo še dlje in obrnemo prvih 10.000 številk:

20 000:

40 000:

60 000:

Ti visoko frekventni JPEG detalji i uklanjaju se tokom kompresije. Pretvaranje boja u DCT koeficijente ne nosi gubitke. Gubici nastaju u fazi diskretizacije, gde se eliminišu visoke frekvencije ili vrednosti bliske nuli. Kada smanjite kvalitet JPEG sačuvavanja, program povećava prag broja uklonjenih vrednosti, što rezultira smanjenjem veličine fajla, ali slika postaje pikselizovanija. Zato je slika u prvom odeljku, koja je bila 57 puta manja, izgledala tako. Svaki blok od 8x8 predstavljao je mnogo manje DCT koeficijente u poređenju sa kvalitetnijom verzijom.
Možete postići sjajan efekat, kao što je postepeno strimovanje slika. Možete prikazati zamagljenu sliku koja postaje sve detaljnija kako preuzimate sve veći broj koeficijenata.
Evo, samo iz znatiželje, šta dobijamo korišćenjem samo 24,000 brojeva:

Ili samo 5000:

Veoma zamagljeno, ali izgleda kao da je prepoznatljivo!
3. Kodiranje dužina serija, delta i Huffmanovo kodiranje
Do sada su svi koraci kompresije bili sa gubicima. Poslednji korak, naprotiv, ide bez gubitaka. Ne uklanja informacije, ali značajno smanjuje veličinu fajla.
Kako se može nešto kompresovati bez odbacivanja informacija? Zamislite kako bismo opisali jednostavan crni pravougaonik dimenzija 700 x 437.
JPEG to postiže korišćenjem 5000 brojeva, ali se mogu postići mnogo bolji rezultati. Možete li zamisliti šemu kodiranja koja opisuje poput slike koristeći što manje bajtova?
Minimalna šema koju sam mogao smisliti koristi četiri: tri za označavanje boje, a četvrta – koliko piksela ima tu boju. Ideja predstavljanja ponavljajućih vrednosti na ovaj sažeti način naziva se kodiranje dužina serija. Ona nema gubitaka, jer možemo obnoviti kodirane podatke u prvobitnom obliku.
Velikost JPEG datoteke s črnim pravokotnikom je veliko večja od 4 bajtov – spomnite se, da se na ravni DCT stiskanje uporablja na blokih 8x8 pikslov. Zato potrebujemo vsaj en DCT koeficient za vsakih 64 pikslov. Potreben je, ker namesto da bi shranjevali en DCT koeficient, za katerim sledi 63 ničel, kodiranje dolžin serij omogoča, da shranimo eno število in označimo, da so »vsa ostala – ničla«.
Delta kodiranje je tehnika, pri kateri vsak bajt vsebuje razliko od neke vrednosti, ne pa absolutne velikosti. Zato urejanje določenih bajtov spremeni barvo vseh ostalih pikslov. Na primer, namesto da bi shranili
12 13 14 14 14 13 13 14
Lahko bi začeli s 12, nato pa preprosto označili, koliko je treba dodati ali odvzeti, da dobimo naslednje število. In ta zaporedje v delta kodiranju pridobi obliko:
12 1 1 0 0 -1 0 1
Pretvorjeni podatki ne postanejo manjši od izvornih, vendar jih je lažje stisniti. Uporaba delta kodiranja pred kodiranjem dolžin serij lahko močno pomaga, pri čemer ostaja stiskanje brez izgub.
Delta kodiranje je ena izmed redkih tehnik, ki se uporablja izven blokov 8x8. Od 64 DCT koeficientov, eden predstavlja zgolj konstanto valovne funkcije (enotna barva). Predstavlja povprečno svetlost vsakega bloka za komponente svetlosti, ali povprečno modrino za Cb komponente, in tako naprej. Prva vrednost vsakega DCT bloka se imenuje DC vrednost in vsaka DC vrednost poteka delta kodiranje glede na prejšnje. Zato sprememba svetlosti prvega bloka vpliva na vse bloke.
Ostaja še ena uganka: kako sprememba enega samega števila popolnoma pokvari celotno sliko? Doslej takih lastnosti pri nivojih stiskanja ni bilo. Odgovor leži v JPEG naslovu. Prvih 500 bajtov vsebuje metafiksne podatke o sliki – širino, višino itd., in dokler z njimi ne delamo.
Brez naslova skorajda ni mogoče (no, ali zelo težko) dekodirati JPEG. To bi izgledalo tako, kot da bi vam poskušal opisati sliko in začel izumljati besede, da bi prenesel svoje vtise. Opis bi bil verjetno precej stisnjen, saj lahko izumljam besede s tisto natančno vsebino, ki jo želim prenesti, vendar za vse ostale ne bi imeli smisla.
Zveni smešno, ali upravo tako to ide. Svaka JPEG slika se kompresuje sa kodovima koji su specifični za nju. Rečnik kodova se čuva u zaglavlju. Ova tehnika se naziva 'Hafmanov kod', a rečnik – Hafmanova tabela. U zaglavlju tabela je označena sa dva bajta – 255, a zatim 196. Svaki komponent boje može imati svoju tabelu.
Promene u tabelama će radikalno uticati na svaku sliku. Dobar primer je promena broja 1 u 12 na 15. liniji.

To se dešava jer se u tabelama navodi kako treba čitati pojedinačne bitove. Do sada smo radili samo sa binarnim brojevima u decimalnom obliku. Ali to nas skriva od činjenice da ako želite da sačuvate broj 1 u bajtu, on će izgledati kao 00000001, pošto u svakom bajtu mora biti tačno osam bitova, čak i ako vam je samo jedan potreban.
Potencijalno je to veliki gubitak prostora, ako imate mnogo malih brojeva. Hafmanov kod je tehnika koja nam omogućava da oslabi to pravilo da svaki broj mora zauzimati osam bitova. To znači da, ako vidite dva bajta:
234 115
U zavisnosti od Hafmanove tabele, to mogu biti tri broja. Da biste ih izdvojili, prvo morate da ih razdelite na pojedinačne bitove:
11101010 01110011
Zatim se obraćate tabeli da biste shvatili kako ih grupisati. Na primer, to mogu biti prvih šest bitova, (111010), ili 58 u decimalnom sistemu, a zatim pet bitova (10011), ili 19, i konačno poslednja četiri bita (0011), ili 3.
Zato je veoma teško razumeti bajtove u ovoj fazi kompresije. Bajtovi ne predstavljaju ono što se čini. Neću se dublje baviti radom sa tabelom u ovom članku, ali o ovom pitanju na internetu .
Jedan od zanimljivih trikova koji možete uraditi, znajući ovo – je da odvojite zaglavlje od JPEG-a i čuvate ga odvojeno. U suštini, file ćete moći da pročitate samo vi. Facebook to radi kako bi još više smanjio fajlove.
Šta još možete učiniti – malo izmeniti Hafmanovu tabelu. Drugima će to izgledati kao oštećena slika. I samo ćete vi znati magičnu verziju njenog ispravljanja.
Da sumiramo: šta je potrebno za dekodiranje JPEG-a? Potrebno je:
- Izdvojiti Hafmanovu tabelu(e) iz zaglavlja i dekodirati bitove.
- Извлечь коэффициенты дискретного косинусного преобразования для каждого компонента цвета и яркости для каждого блока 8х8, проведя обратные преобразования кодирования длин серий и дельты.
- Скомбинировать косинусы на основе коэффициентов, чтобы получить значения пикселей для каждого блока 8х8.
- Масштабировать компоненты цветов, если проводилась субдискретизация (эта информация есть в заголовке).
- Преобразовать полученные значения YCbCr для каждого пикселя в RGB.
- Вывести изображение на экран!
Сложная работа для простого просмотра фотографии с котиком! Однако, что мне нравится в этом, так это то, насколько технология JPEG ориентирована на человека. Она основана на особенностях нашего восприятия, что позволяет достигнуть гораздо лучшего сжатия, чем обычные технологии. И теперь, понимая, как работает JPEG, можно представить, как эти технологии могут быть адаптированы к другим областям. Например, дельта-кодирование в видео может привести к значительному уменьшению размера файла, поскольку там часто есть целые области, которые не меняются от кадра к кадру (например, фон).
, открыт, и содержит инструкции по замене изображений на свои собственные.
Izvor: habr.com
