Sådan fungerer JPEG-formatet

JPEG-billeder er allestedsnærværende i vores digitale liv, men bag denne kappe af bevidsthed gemmer sig algoritmer, der fjerner detaljer, som det menneskelige øje ikke kan se. Resultatet er den højeste visuelle kvalitet i den mindste filstørrelse – men hvordan fungerer det helt præcist? Lad os se, hvad vores øjne præcist ikke ser!

Sådan fungerer JPEG-formatet

Det er let at tage for givet muligheden for at sende et billede til en ven og ikke bekymre sig om, hvilken enhed, browser eller operativsystem de bruger – men det var ikke altid tilfældet. I begyndelsen af ​​1980'erne kunne computere gemme og vise digitale billeder, men der var mange konkurrerende ideer om den bedste måde at gøre dette på. Du kunne ikke bare sende et billede fra en computer til en anden og håbe, at det virkede.

For at løse dette problem blev en komité af eksperter fra hele verden samlet i 1986 under navnet "Joint Photographic Expert Group” (Joint Photographic Experts Group, JPEG), grundlagt som en del af det fælles arbejde i International Organization for Standardization (ISO) og International Electrotechnical Commission (IEC), to internationale standardiseringsorganisationer med hovedkontor i Genève (Schweiz).

En gruppe mennesker kaldet JPEG skabte JPEG-standarden for digital billedkomprimering i 1992. Enhver, der har brugt internettet, er sandsynligvis stødt på JPEG-kodede billeder. Dette er den mest almindelige måde at kode, sende og gemme billeder på. Fra websider til e-mail til sociale medier, JPEG bruges milliarder af gange om dagen - næsten hver gang vi ser eller sender et billede online. Uden JPEG'er ville nettet være mindre lyst, langsommere og sandsynligvis have færre kattebilleder!

Denne artikel handler om, hvordan man afkoder et JPEG-billede. Altså om, hvad der kræves for at konvertere komprimerede data gemt på en computer til et billede, der kommer frem på skærmen. Dette er værd at vide om, ikke kun fordi det er vigtigt for at forstå den teknologi, vi bruger til daglig, men også fordi, ved at afsløre kompressionsniveauerne, vil vi bedre kende perception og syn, samt hvilke detaljer vores øjne er mest følsom overfor.

Desuden er det meget interessant at lege med billeder på denne måde.

Sådan fungerer JPEG-formatet

Ser i en JPEG

På en computer er alt gemt som en sekvens af binære tal. Normalt er disse bits, nuller og etere, grupperet i ottere, der udgør bytes. Når du åbner et JPEG-billede på din computer, er der noget (browser, operativsystem, hvad som helst), der skal afkode bytes, og genoprette det originale billede som en liste over farver, der kan vises.

Hvis du downloader denne søde foto af en kat og åbner det i en teksteditor, vil du se en masse rodede tegn.

Sådan fungerer JPEG-formatet
Her bruger jeg Notepad++ til at inspicere indholdet af filen, fordi almindelige teksteditorer som Notepad fra Windows vil ødelægge binæren efter at have gemt den, og den passer ikke til JPEG-formatet.

At åbne et billede i en teksteditor forvirrer din computer, ligesom du forvirrer din hjerne, når du gnider dine øjne og begynder at se farvede pletter!

Disse pletter du ser er kendt som fosfener, og er ikke resultatet af udsættelse for en lysstimulus eller hallucinationer genereret af sindet. De opstår, fordi din hjerne tror, ​​at alle elektriske signaler i de optiske nerver bærer information om lys. Hjernen har brug for at gøre sådanne antagelser, fordi der ikke er nogen måde at vide, om signalet er en lyd, et syn eller noget andet. Alle nerver i kroppen sender nøjagtig de samme elektriske impulser. Når du lægger pres på dine øjne, sender du signaler, der ikke er visuelle, men aktiverer receptorer i øjet, som din hjerne tolker – i dette tilfælde forkert – som noget visuelt. Du kan bogstaveligt talt se presset!

Det er sjovt at tænke på, hvor ens computere ligner hjernen, men det er også en nyttig analogi, der illustrerer, hvor meget betydningen af ​​data – uanset om de bæres gennem kroppen af ​​nerver eller lagres i en computer – afhænger af, hvordan de fortolkes. Alle binære data er opbygget af XNUMX'er og XNUMX'ere, grundlæggende komponenter, der er i stand til at formidle enhver form for information. Din computer gætter ofte, hvordan de skal fortolkes ved hjælp af ledetråde såsom filtypenavne. Nu får vi det til at fortolke dem som tekst, for det forventer tekstredaktøren.

For at forstå, hvordan man afkoder en JPEG, skal vi se selve de originale signaler - de binære data. Dette kan gøres med en hex-editor eller direkte på webside for den originale artikel! Der er et billede, ved siden af ​​hvilket i tekstfeltet alle dets bytes (undtagen overskriften) præsenteres i decimalform. Du kan ændre dem, og scriptet vil omkode og producere et nyt billede i farten.

Sådan fungerer JPEG-formatet

Du kan lære meget bare ved at lege med denne editor. Kan du for eksempel fortælle, i hvilken rækkefølge pixels er lagret?

I dette eksempel er det mærkelige, at det at ændre nogle tal slet ikke påvirker billedet, og hvis du for eksempel erstatter tallet 17 med 0 i den første linje, så bliver billedet fuldstændig ødelagt!

Sådan fungerer JPEG-formatet

Andre ændringer, såsom at ændre 7'eren på linje 1988 til 254, ændrer farven, men kun efterfølgende pixels.

Sådan fungerer JPEG-formatet

Det mærkeligste er måske, at nogle tal ændrer ikke kun farven, men også formen på billedet. Skift 70 på linje 12 til 2, og se på den øverste række af billedet for at se, hvad jeg mener.

Sådan fungerer JPEG-formatet

Og uanset hvilket JPEG-billede du bruger, vil du altid finde de kryptiske skakmønstre, når du redigerer bytes.

Når man leger med editoren, er det svært at finde ud af, hvordan man genskaber et billede fra disse bytes, da JPEG-komprimering består af tre forskellige teknologier, der anvendes sekventielt i niveauer. Vi vil studere hver af dem separat for at afdække den mystiske adfærd, vi observerer.

Tre niveauer af JPEG-komprimering:

  1. Farveundersampling.
  2. Diskret Cosinus transformation og diskretisering.
  3. Kørselslængdekodning, delta и huffman

For at give dig en idé om skalaen af ​​komprimeringen skal du bemærke, at billedet ovenfor repræsenterer 79 tal, hvilket er omkring 819 KB. Hvis vi skulle gemme det uden komprimering, skulle vi bruge tre tal for hver pixel - for de røde, grønne og blå komponenter. Dette ville beløbe sig til 79 numre, eller ca. 917 Kb. Som et resultat af JPEG-komprimering er den endelige fil reduceret med mere end 700 gange!

Faktisk kan dette billede komprimeres meget mere. Nedenfor er to billeder side om side - billedet til højre blev komprimeret til 16 KB, det vil sige 57 gange mindre end den ukomprimerede version!

Sådan fungerer JPEG-formatet

Hvis du ser godt efter, vil du se, at disse billeder ikke er identiske. Begge er billeder med JPEG-komprimering, men det højre er meget mindre i volumen. Det ser også lidt værre ud (se på baggrundsfarve firkanterne). Derfor kaldes JPEG også tabsgivende komprimering; under komprimeringsprocessen ændrer billedet sig og mister nogle detaljer.

1. Farve delprøvetagning

Her er et billede med kun det første niveau af komprimering anvendt.

Sådan fungerer JPEG-formatet
(Interaktiv version i original artikler). Fjernelse af ét tal ødelægger alle farver. Men hvis præcis seks numre fjernes, har det ringe eller ingen effekt på billedet.

Nu er tallene lidt nemmere at tyde. Dette er næsten en simpel liste over farver, hver byte ændrer præcis en pixel, men den er allerede halvt så stor som et ukomprimeret billede (hvilket ville tage ca. 300 KB i en sådan reduceret størrelse). Gæt hvorfor?

Du kan se, at disse tal ikke repræsenterer de røde, grønne og blå standardkomponenter, for hvis vi erstatter alle tallene med nuller, får vi et grønt billede (ikke et hvidt).

Sådan fungerer JPEG-formatet

Dette skyldes, at disse bytes står for Y (lysstyrke),

Sådan fungerer JPEG-formatet

Cb (relativ blå),

Sådan fungerer JPEG-formatet

og Cr (relative redness) billeder.

Sådan fungerer JPEG-formatet

Hvorfor ikke bruge RGB? Det er trods alt sådan de fleste moderne skærme fungerer. Din skærm kan vise enhver farve, inklusive rød, grøn og blå med forskellige intensiteter for hver pixel. Hvid opnås ved at tænde for alle tre ved fuld lysstyrke, og sort slukker dem.

Sådan fungerer JPEG-formatet

Det minder også meget om, hvordan det menneskelige øje fungerer. Farvereceptorerne i vores øjne kaldes "kegler“, og er opdelt i tre typer, som hver især er mere følsomme over for enten røde eller grønne eller blå farver [S-type kegler er følsomme i violet-blå (S fra engelsk. Short - short-wavelength spectrum), M-type - i grøn-gul (M fra engelsk. Medium - mellembølge), og L-type - i gul-rød (L fra engelsk. Lang - langbølget) dele af spektret. Tilstedeværelsen af ​​disse tre typer kegler (og stænger følsomme i den smaragdgrønne del af spektret) giver en person farvesyn. / ca. oversættelse]. pinde, den anden type fotoreceptor i vores øjne, er i stand til at registrere ændringer i lysstyrken, men er meget mere følsom over for farve. Vores øjne har omkring 120 millioner stænger og kun 6 millioner kegler.

Derfor bemærker vores øjne ændringer i lysstyrke meget bedre end ændringer i farve. Hvis du adskiller farven fra lysstyrken, kan du fjerne lidt farve, og ingen vil bemærke noget. Chroma subsampling er processen med at repræsentere farvekomponenterne i et billede ved en lavere opløsning end luminanskomponenterne. I eksemplet ovenfor har hver pixel præcis én Y-komponent, og hver enkelt gruppe på fire pixels har præcis én Cb- og én Cr-komponent. Derfor indeholder billedet fire gange mindre farveinformation end originalen.

YCbCr-farverummet bruges ikke kun i JPEG'er. Det blev oprindeligt opfundet i 1938 til tv-udsendelser. Ikke alle har et farve-tv, så adskillelse af farve og lysstyrke gjorde det muligt for alle at få det samme signal, og tv'er uden farve brugte kun lysstyrkekomponenten.

Derfor ødelægger du fuldstændigt alle farver, hvis du fjerner ét nummer fra editoren. Komponenter gemmes i formen YYYY Cb Cr (faktisk ikke nødvendigvis i denne rækkefølge - lagerrækkefølgen er angivet i filoverskriften). Fjernelse af det første tal vil få den første værdi af Cb til at blive fortolket som Y, Cr som Cb, og generelt vil der opnås en dominoeffekt, der skifter alle farverne i billedet.

JPEG-specifikationen kræver ikke, at du bruger YCbCr. Men i de fleste filer bruges det, fordi det giver billeder i bedre kvalitet efter subsampling sammenlignet med RGB. Men du behøver ikke tage mit ord for det. Se selv i tabellen nedenfor, hvordan subsampling hver enkelt komponent ville se ud i både RGB og YCbCr.

Sådan fungerer JPEG-formatet
(Interaktiv version i original artikler).

Fjernelsen af ​​blå er ikke så mærkbar som rød eller grøn. Det er på grund af de seks millioner kegler i dine øjne, omkring 64% er følsomme over for rødt, 32% over for grønt og 2% over for blåt.

Delsamplingen af ​​Y-komponenten (nederst til venstre) ses bedst. Selv en lille ændring er mærkbar.

Konvertering af et billede fra RGB til YCbCr reducerer ikke filstørrelsen, men det gør det lettere at finde mindre mærkbare detaljer, der kan fjernes. Lossy kompression opstår i anden fase. Det er baseret på ideen om at præsentere data i en mere komprimerbar form.

2. Diskret cosinus transformation og diskretisering

Dette kompressionsniveau definerer for det meste essensen af ​​JPEG. Efter at have konverteret farverne til YCbCr, komprimeres komponenterne individuelt, så vi kan kun koncentrere os om Y-komponenten fra nu af. Og her er, hvordan bytes af Y-komponenten ser ud efter at have anvendt dette niveau.

Sådan fungerer JPEG-formatet
(Interaktiv version i original artikler). I den interaktive version ruller et klik på en pixel editoren til den linje, der repræsenterer den. Prøv at fjerne tal fra slutningen eller tilføje et par nuller til et bestemt tal.

Ved første øjekast ligner det meget dårlig kompression. Der er 100 pixels i et billede, og der skal 000 tal til for at angive deres lysstyrke (Y-komponenter) – det er værre end ikke at komprimere noget som helst!

Bemærk dog, at de fleste af disse tal er nul. Desuden kan alle disse nuller i slutningen af ​​linjerne fjernes uden at ændre billedet. Der er omkring 26 numre tilbage, hvilket er næsten 000 gange mindre!

Dette niveau indeholder hemmeligheden bag skakmønstre. I modsætning til andre effekter, vi har set, er udseendet af disse mønstre ikke en fejl. De er byggestenene i hele billedet. Hver linje i editoren indeholder nøjagtigt 64 tal, diskrete cosinus transformation (DCT) koefficienter svarende til intensiteten af ​​64 unikke mønstre.

Disse mønstre er dannet ud fra cosinus-plottet. Sådan ser nogle af dem ud:

Sådan fungerer JPEG-formatet
8 ud af 64 odds

Nedenfor er et billede, der viser alle 64 mønstre.

Sådan fungerer JPEG-formatet
(Interaktiv version i original artikler).

Disse mønstre er af særlig betydning, da de danner grundlaget for 8x8 billederne. Hvis du ikke er bekendt med lineær algebra, betyder det, at ethvert 8x8 billede kan fås fra disse 64 mønstre. DCT er processen med at opdele billeder i 8x8 blokke og konvertere hver blok til en kombination af disse 64 koefficienter.

Det faktum, at ethvert billede kan være sammensat af 64 specifikke mønstre, virker som magi. Dette er dog det samme som at sige, at ethvert sted på Jorden kan beskrives med to tal - breddegrad og længdegrad [angiver halvkuglerne / ca. oversættelse]. Vi tænker ofte på Jordens overflade som todimensionel, så vi behøver kun to tal. Et 8x8 billede har 64 dimensioner, så vi skal bruge 64 tal.

Det er endnu ikke klart, hvordan dette hjælper os med hensyn til kompression. Hvis vi har brug for 64 tal til at repræsentere et 8x8 billede, hvorfor ville det så være bedre end blot at gemme 64 luminanskomponenter? Vi gør dette af samme grund, som vi forvandlede tre RGB-numre til tre YCbCr-numre: det giver os mulighed for at fjerne subtile detaljer.

Det er svært at se præcis, hvilke detaljer der fjernes på dette stadium, fordi JPEG anvender DCT til 8x8 blokke. Der er dog ingen, der forbyder os at anvende det på hele billedet. Sådan ser DCT ud for Y-komponenten, når den anvendes på hele billedet:

Sådan fungerer JPEG-formatet

Mere end 60 numre kan fjernes fra slutningen med stort set ingen mærkbare ændringer i billedet.

Sådan fungerer JPEG-formatet

Bemærk dog, at hvis vi nulstiller de første fem tal, vil forskellen være tydelig.

Sådan fungerer JPEG-formatet

Tallene i begyndelsen repræsenterer lavfrekvente ændringer i billedet, og vores øjne opfanger dem bedst. Tal mod slutningen indikerer højfrekvente ændringer, som er sværere at bemærke. For at "se hvad øjet ikke kan se" kan vi isolere disse højfrekvente detaljer ved at nulstille de første 5000 tal.

Sådan fungerer JPEG-formatet

Vi ser alle områder af billedet, hvor den største ændring sker fra pixel til pixel. Kattens øjne, hans knurhår, frottétæppet og skyggerne i nederste venstre hjørne skiller sig ud. Du kan gå længere ved at nulstille de første 10 numre:

Sådan fungerer JPEG-formatet

20 000:

Sådan fungerer JPEG-formatet

40 000:

Sådan fungerer JPEG-formatet

60 000:

Sådan fungerer JPEG-formatet

Disse højfrekvente detaljer fjernes af JPEG under komprimeringsfasen. Konvertering af farver til DCT-koefficienter er tabsfri. Tab dannes ved prøvetagningstrinnet, hvor værdier med høj frekvens eller tæt på nul fjernes. Når du sænker kvaliteten af ​​JPEG-lagring, øger programmet tærsklen for antallet af værdier, der skal fjernes, hvilket reducerer filstørrelsen, men gør billedet mere pixeleret. Så billedet i det første afsnit, som var 57 gange mindre, så således ud. Hver 8x8 blok repræsenterede et meget mindre antal DCT-koefficienter sammenlignet med den højere kvalitetsversion.

Du kan gøre noget så fedt som gradvist at streame billeder. Du kan vise et sløret billede, der bliver mere og mere detaljeret, efterhånden som flere koefficienter downloades.

Her, bare for sjov, hvad sker der, når du kun bruger 24 numre:

Sådan fungerer JPEG-formatet

Eller kun 5000:

Sådan fungerer JPEG-formatet

Meget sløret, men genkendeligt!

3. Kodning af løbslængder, delta og Huffman

Hidtil har alle stadier af kompression været tabsgivende. Den sidste fase går tværtimod uden tab. Det fjerner ikke information, men reducerer filstørrelsen markant.

Hvordan kan du komprimere noget uden at kassere information? Forestil dig, hvordan vi ville beskrive et simpelt sort 700 x 437 rektangel.

JPEG bruger 5000 numre til dette, men der kan opnås meget bedre resultater. Kan du forestille dig et kodningsskema, der beskriver et sådant billede i så få bytes som muligt?

Det minimale skema, jeg kunne finde på, bruger fire: tre for farven og en fjerde for, hvor mange pixels den farve har. Ideen om at repræsentere gentagne værdier på en sådan komprimeret måde kaldes run-length-kodning. Det er tabsfrit, fordi vi kan gendanne de kodede data i dens oprindelige form.

Størrelsen af ​​en JPEG-fil med et sort rektangel er meget større end 4 bytes - husk, at på DCT-niveau anvendes komprimering på blokke på 8x8 pixels. Derfor har vi som minimum brug for én DCT-koefficient for hver 64 pixels. Vi har brug for en, fordi i stedet for at gemme en enkelt DCT-koefficient efterfulgt af 63 nuller, giver run-længde-kodning os mulighed for at gemme et enkelt tal og angive "alle andre er nuller".

Delta-kodning er en teknik, hvorved hver byte indeholder en forskel fra en eller anden værdi snarere end en absolut værdi. Derfor ændrer redigering af bestemte bytes farven på alle andre pixels. For eksempel i stedet for at opbevare

12 13 14 14 14 13 13 14

Vi kunne starte med 12 og så bare skrive ned, hvor meget vi skal lægge til eller trække fra for at få det næste tal. Og denne sekvens i deltakodning har formen:

12 1 1 0 0 -1 0 1

De konverterede data er ikke mindre end de originale data, men det er nemmere at komprimere dem. Anvendelse af delta-kodning før run-længde-kodning kan hjælpe meget, mens det stadig er tabsfri komprimering.

Delta-kodning er en af ​​de få teknikker, der bruges uden for 8x8 blokke. Af de 64 DCT-koefficienter er én simpelthen en konstant bølgefunktion (fast farve). Det repræsenterer den gennemsnitlige lysstyrke for hver blok for luminanskomponenterne eller den gennemsnitlige blåhed for Cb-komponenterne og så videre. Den første værdi af hver DCT-blok kaldes DC-værdien, og hver DC-værdi er delta-kodet i forhold til de foregående. Derfor vil ændring af lysstyrken for den første blok påvirke alle blokke.

Det sidste mysterium forbliver: hvordan ødelægger ændring af entalstallet fuldstændigt hele billedet? Indtil videre har kompressionsniveauer ikke haft sådanne egenskaber. Svaret ligger i JPEG-headeren. De første 500 bytes indeholder metadata om billedet – bredde, højde osv., og indtil videre har vi ikke arbejdet med dem.

Uden en header er det næsten umuligt (nå, meget svært) at afkode en JPEG. Det vil se ud som om, jeg prøver at beskrive et billede for dig, og jeg begynder at finde på ord for at formidle mit indtryk. Beskrivelsen bliver nok meget kortfattet, da jeg kan finde på ord med præcis den betydning, jeg vil formidle, men for alle andre giver de ikke mening.

Det lyder fjollet, men det er præcis, hvad der sker. Hvert JPEG-billede komprimeres med koder, der er specifikke for det. Kodeordbogen er gemt i overskriften. Denne teknik kaldes "Huffman-kode", og ordbogen hedder Huffman table. I overskriften er tabellen markeret med to bytes - 255 og derefter 196. Hver farvekomponent kan have sin egen tabel.

Tabelændringer vil drastisk påvirke ethvert billede. Et godt eksempel er at ændre 15 til 1 på den 12. linje.

Sådan fungerer JPEG-formatet

Dette skyldes, at tabellerne angiver, hvordan individuelle bits skal læses. Hidtil har vi kun arbejdet med binære tal i decimalform. Men dette skjuler for os, at hvis du vil gemme tallet 1 i en byte, så vil det ligne 00000001, fordi hver byte skal have præcis otte bits, selvom der kun er brug for én af dem.

Dette er potentielt et stort spild af plads, hvis du har mange små numre. Huffman-kode er en teknik, der giver os mulighed for at slække på dette krav om, at hvert tal skal optage otte bit. Dette betyder, at hvis du ser to bytes:

234 115

Så kan det, afhængigt af Huffman-bordet, være tre tal. For at udtrække dem skal du først opdele dem i individuelle bits:

11101010 01110011

Så vender vi os til bordet for at forstå, hvordan man grupperer dem. For eksempel kan det være de første seks bit (111010) eller 58 i decimal, efterfulgt af fem bit (10011) eller 19 og til sidst de sidste fire bit (0011) eller 3.

Derfor er det meget svært at forstå bytes på dette stadium af komprimeringen. Bytene repræsenterer ikke, hvad de ser ud til. Jeg vil ikke gå ind på detaljerne i arbejdet med tabellen i denne artikel, men materialer om dette spørgsmål online er tilstrækkelig.

Et af de fede tricks, du kan lave med denne viden, er at adskille headeren fra JPEG'en og gemme den separat. Faktisk viser det sig, at kun du kan læse filen. Facebook gør dette for at reducere filer yderligere.

Hvad der ellers kan gøres, er at ændre Huffman-bordet en hel del. For andre vil det ligne et forkælet billede. Og kun du kender den magiske mulighed for at rette det.

For at opsummere: så hvad skal der til for at afkode en JPEG? Nødvendig:

  1. Udpak Huffman-tabellen/tabellerne fra overskriften og afkode bitsene.
  2. Udtræk de diskrete cosinustransformationskoefficienter for hver farve- og luminanskomponent for hver 8x8 blok ved omvendt transformation af run-længde-kodning og delta.
  3. Kombiner cosinus baseret på koefficienter for at få pixelværdier for hver 8x8 blok.
  4. Skaler farvekomponenter, hvis subsampling blev udført (denne information er i overskriften).
  5. Konverter de resulterende YCbCr-værdier for hver pixel til RGB.
  6. Bring billedet til skærmen!

Seriøst arbejde for blot at se et billede med en kat! Det, jeg dog godt kan lide ved det, er, at det viser, hvor menneskecentreret JPEG-teknologi er. Det er baseret på egenskaberne i vores opfattelse, hvilket giver os mulighed for at opnå meget bedre komprimering end konventionelle teknologier. Og nu, når du forstår, hvordan JPEG fungerer, kan du forestille dig, hvordan disse teknologier kan overføres til andre områder. For eksempel kan delta-kodning i video resultere i en betydelig reduktion af filstørrelsen, da der ofte er hele områder, der ikke ændrer sig fra ramme til ramme (f.eks. baggrunden).

Kode brugt i artiklen, er åben og indeholder instruktioner til at erstatte billederne med dine egne.

Kilde: www.habr.com

Tilføj en kommentar