Formatul grafic JPEG

Ioan Iacob

Pe lângă o rată înaltă de comprimare avem nevoie si de păstrarea calitătii informatiilor originale. JPEG îmbină cele două deziderate într-un mod eficient.

În ziua de astăzi auzim tot mai des despre necesitatea transmiterii imaginilor la distantă, despre compact discuri si calitatea imaginilor stocate pe acestea, despre integrarea dintre tehnologia informatică si televiziune. Dar poate ar fi bine să spunem că în spatele acestor realităti tehnologice stau anumite specificatii legate de formatul datelor ce circulă de la emitător la receptor. Practic aici este locul în care putem aminti despre existenta acestui format grafic, foarte eficient, numit JPEG. Intrând în domeniul tehnic vom spune că este un format grafic care comprimă imaginile de tip bitmap. Denumirea provine de la grupul de experti care a încercat definirea sa - Joint Photographic Experts Group. Un dezavantaj major în acest caz este faptul că respectiv comprimarea si decomprimarea se execută destul de încet. La ora actuală, formatul JPEG este inclus în standardele internationale în vederea implementării sale la nivel hard (este vorba despre cipuri care să realizeze comprimarea si decomprimarea fără a mai fi nevoie de un soft specializat în acest sens). La ora actuală, formatul este acceptat ca atare de toate softurile care se doresc a fi ajutătoare în domeniul prelucrării imaginilor, pe majoritatea platformelor.

Comprimare cu pierderi

Să ne facem întelesi de la început, JPEG este un standard ce defineste o familie de tehnici de compresie si nu este neapărat un format fix - ca în cazul BMP sau PCX. Din obisnuintă am folosit în unele fraze sintagma „formatul JPEG". Imaginile JPEG pot fi încapsulate în multe moduri - cele mai folosite sunt JFIF si JPEG-TIFF. Subformatul JFIF este prescurtarea expresiei JPEG File Interchange Format si a fost creat de către Eric Hamilton de la C-Cube Microsystems. JPEG-TIFF se bazează, în mare parte, pe specificatiile formatului TIFF 6.0. Aici vorbim despre faptul că, indiferent de schema folosită, JPEG comprimă imaginea rezultând anumite pierderi - deci imaginea reconstruită nu va fi totdeauna identică cu originalul (acest lucru nu trebuie înteles neapărat în sensul rău după cum se va vedea în continuare).

Utilizând o schemă de compresie a imaginilor digitale diferită cu mult de cele utilizate în mod curent, JPEG nu necesită reconstruirea imaginii originale, bit cu bit. Se întâmplă de multe ori ca imaginea reconstruită, prin decodificarea informatiilor stocate în fisierul de format JPEG, să fie o reprezentare mai bună a fotografiei originale decât în cazul în care se foloseste o schemă de compresie fără pierderi.

Ca urmare a digitizării imaginilor (prin scanare, de exemplu), rezultă o schemă de culori ce foloseste câte 24 biti pe pixel - câte 8 pentru fiecare componentă RGB (red, green, blue). Un format comprimat, GIF de exemplu, foloseste o tabelă de culori având 256 de intrări. Acest lucru înseamnă că fiecare pixel va fi reprezentat pe 8 biti (nu pe 24 de biti-deci un prim pas spre comprimarea informatiei). GIF comprimă în continuare cei 8 biti pe pixel folosind algoritmul LZW dar acest lucru nu mai ajută foarte mult la comprimare. JPEG, pe de altă parte, stochează, în primul rând, informatiile privind schimbările de culoare, în special variatiile de strălucire. Atât timp cât imaginea reconstruită va păstra aceste variatii, totul va fi foarte apropiat de original.

Dacă este să analizăm formatul JPEG prin considerarea căilor traditionale de urmat în cazul algoritmilor de compresie a imaginilor digitale trebuie să spunem că tehnica folosită aici este departe de a fi comună, în schimb se apropie foarte mult de modul de lucru al televiziunii.

JPEG nu mai este foarte eficient în cazul imaginilor ce contin un număr mic de culori si un număr mic de muchii, ca în cazul animatiilor generate pe calculator, alte formate grafice fiind mult mai eficiente în această situatie. Spatiul care se poate salva folosind formatul JPEG este destul de mare. Să luăm în considerare un exemplu simplu. O imagine având dimensiunile de 727 x 525 pixeli cu 24 biti pe pixel, va ocupa (în forma necomprimată) cam 1145 Kb. Versiunea GIF va fi de aproximativ 240 Kb. Un fisier în format JPEG de înaltă calitate va ocupa 155 Kb iar în cazul JPEG de calitate standard, va fi ocupat un spatiu de 58 Kb. De fapt, JPEG-ul ce ocupă 58 Kb este de calitate mai înaltă ca GIF-ul. Secretul constă, după cum am mai spus, în faptul că se păstrează variatiile de culoare si nu culoarea în sine. În plus, în cazul JPEG-ului avem de-a face cu păstrarea informatiei despre pixel pe un singur bit.

Fazele comprimării

Dealtfel JPEG permite multe optiuni de codificare si comprimare. Noi ne vom concentra pe JPEG standard, o versiune pe care toate implementările soft trebuie să o suporte si deci să o folosească. Decodificarea informatiilor stocate începe prin convertirea imaginii RGB într-un spatiu color de tip luminantă/crominantă, folosind formulele de calcul discutate în sectiunea următoare. De fapt aici este vorba despre o imagine bazată pe o scală a nuantelor de gri plus două canale ce stochează informatii despre variatiile de culoare. Datele imaginii se prelucrează prin împărtirea acesteia în blocuri de 8x8 pixeli. În continuare se aplică o transformare cosinus discretă (DCT - discrete cosine transform) în scopul convertirii informatiilor relative la imaginea bitmap în informatii legate de ratele de schimbare (se mai foloseste si termenul de analiză în frecventă). Cuantificarea, care este pasul următor, produce trunchierea rezultatelor codificării DCT obtinându-se informatiile într-un interval mai redus de valori. Această cuantificare este pasul care face ca algoritmul JPEG-ului să provoace o pierdere de informatie. Aplicatiile care permit înregistrarea imaginilor în format JPEG oferă utilizatorului posibilitatea de a regla rata de compresie. În final, rezultatele cuantificării sunt comprimate folosind algoritmul Huffman. Decomprimarea imaginii decurge prin parcurgerea etapelor descrise anterior în ordine inversă. În primul rând are loc decomprimarea rezultatelor cuantificate si apoi se utilizează transformarea cosinus inversă pentru reconstruirea imaginii. Bitii cei mai putini semnificativi (pierduti la cuantificare) nu pot fi regăsiti si atunci algorimul de decomprimare inserează zerouri în locul lor.

Scheme de culori

Într-o imagine color, JPEG comprimă fiecare componentă de culoare separat. Desi este posibilă comprimarea componentelor de rosu, verde si albastru într-un mod eficient totusi comprimarea JPEG lucrează mai bine atunci când se aplică informatiilor de culoare exprimate sub forma luminantă (strălucire) si crominantă. Acest lucru este mult mai folositor deoarece ochiul este mai putin senzitiv la schimbările de culoare decât la schimbările de luminozitate. Astfel canalele de crominantă pot fi codificate cu pierderi mai mari decât canalul de luminantă. Într-o imagine de tip RGB, toate cele trei canale contin informatii despre luminozitate si ca urmare toate trei vor fi codificate cu aceeasi rată.

O schemă de culori acceptată în toată lumea, cunoscută sub denumirea de CCIR 601, foloseste trei componente Y, Cb si Cr care, spus în general, se referă la luminozitate, „albăstreală" si „roseată". Componenta Y poate fi utilizată direct ca fiind versiunea alb-negru a imaginii (uneori Cb si Cr sunt numite U si V iar schema de culori este referită prin notatia YUV, totusi în sens strict tehnic YUV nu este acelasi lucru cu YCbCr). Considerând deci că fisierul initial este stocat folosind schema de culori RGB, pentru a ajunge la reprezentarea YCbCr vom putea folosi următoarele formule de calcul:

Y = 0,229R + 0,587G + 0,114B
Cb = 0,1687R - 0,3313G + 0,5B
Cr = 0,5R - 0,4187G - 0,0813B

Trebuie spus că această transformare este în principiu fără pierderi deoarece, per asamblu, tripletul YCbCr contine aceleasi informatii ca si RGB dar repartizate putin altfel (în practică se introduc anumite erori de rotunjire adică respectiv componentele Y, Cb, Cr vor fi niste valori întregi prin rotunjire si atunci la refacerea tripletului RGB valorile componentelor pot diferi putin fată de original).

La refacerea infomatiilor initiale vom avea nevoie de valorile tripletului RGB. În acest scop se pot folosi următoarele formule:

R = Y + 1,402(Cr-128) 
G = Y - 0,34414(Cb-128) - 0,71414(Cr- 128) 
B = Y + 1,772(Cb - 128)

Formatul grafic JPEG acceptă ca cele trei componente ale tripletului YCbCr să fie comprimate folosind rate de compresie diferite. O posibilitate folosită în mod curent propune utilizarea a câte unei valori Cb si Cr pentru fiecare 4 valori ale componentei Y. În acest mod, pentru fiecare dreptunghi de 2 x 2 pixeli vor exista 4 valori pentru componenta Y respectiv o valoare Cb si o valoare Cr. Folosind ideea descrisă mai înainte vom putea salva 50% din spatiul utilizat (6 valori în loc de 12) fără ca acest lucru să aibă vreo influentă asupra calitătii imaginii percepute de ochiul uman.

Tehnica esantionării anumitor componente la rate mai mici decât altele este cunoscută prin denumirea de subesantionare (termenul în limba engleză este subsampling). Parametrii folositi pentru esantionare împreună cu parametrii folositi în faza de cuantificare, determină rata de compresie. Într-un fisier JPEG standard, toti acesti parametri sunt inclusi în header si ca urmare decodificatorul poate reconstrui imaginea corect.

Codificarea DCT

Prin DCT am prescurtat denumirea din limba engleză Discrete Cosine Transform care tradusă în româneste ar putea însemna transformare cosinus discretă. Practic prin intermediul acestei transformări, un vector continând date despre intensitate este transpus într-un vector care contine date despre „cât de repede variază" intensitatea. Pentru imagini cu mai multe componente (ca de exemplu în cazul tripletului YCbCr) DCT este aplicată separat pentru blocuri de 8 x 8 pixeli pentru fiecare componentă. Pentru cazul în care se aplică subesantionarea, vor fi mai multe blocuri de date privind unele componente decât date privind alte componente. Pentru un pătrat de 2 x 2 pixeli vom avea patru blocuri de Y pentru fiecare bloc de Cb sau Cr.

Punctele imaginii în fiecare bloc sunt numerotate de la (0,0) la (7,7), cu f(x,y) am notat valoarea pixelului aflat în punctul de coordonate (x,y). DCT va produce un nou bloc de 8 x 8 continând date transformate prin folosirea formulei:

unde

C(z) = 1/1,41 dacă z=0 si C(z) = 1 dacă z este diferit de 0.

Rezultatul DCT este un set de frecvente F(u,v) care, în mare vorbind, indică în ce grad se schimbă valorile de intrare la o anumită rată de esantionare. Prin F(0,0) se notează valoarea ce indică la ce grad, valorile nu se schimbă deloc - este media celor 64 valori de intrare si este cunoscut ca fiind coeficientul DC. Restul valorilor reprezintă asa numitii coeficienti AC. De exemplu F(1,0) indică gradul de variatie (la frecventă joasă) pe directia orizontală si arată că nu există variatie pe directia verticală. Făcând interpretarea în acelasi mod, F(7,7) indică gradul în care valorile se schimbă cel mai repede în ambele directii (frecventă înaltă).

DCT este în principiu reversibilă, în acest scop folosindu-se formula:

Erorile de rotunjire nu produc diferentieri foarte mari ale valorilor calculate fată de valorile originale. Pentru blocurile de 8 x 8 pixeli, termenii rezultati ca urmare a aplicării DCT vor avea nevoie de patru biti în plus fată de valorile originale. Astfel, dacă valoarea pixelilor, adică f(x,y), are nevoie de 8 biti atunci după transformarea cosinus discretă vom avea nevoie de 12 biti pentru F(u,v). Deci, prin aplicarea DCT nu se face o comprimare.

Cuantificarea

Această fază de lucru setează precizia cu care fiecare dintre valorile rezultate în urma DCT vor fi stocate în fisier. JPEG foloseste un procedeu de cuantificare liniară care înseamnă practic că fiecare valoare rezultată în urma DCT va fi împărtită la un număr, ce reprezintă factorul de cuantificare, si apoi se va proceda la rotunjirea la o valoare întreagă a rezultatului. Practic este utilizată o matrice, continând factorii de cuantificare, ce va fi stocată în fisierul JPEG. Ca urmare, un program de codificare va putea utiliza o matrice standard de valori de cuantificare sau o matrice de valori ajustate pentru a permite o anumită rată de compresie a imaginii dorite. Un fisier care stochează componente multiple trebuie să aibă în mod corespunzător mai multe matrici; în mod obisnuit va exista câte o tabelă de valori pentru componenta Y si respectiv pentru Cb si Cr.

În mod tipic, valoarea factorului de cuantificare creste odată cu cresterea frecventei. În cazul în care avem o valoare DCT stocată pe 12 biti, prin cuantificare, coeficientul F(0,0) va fi stocat pe 8 biti iar F(7,7) va avea nevoie de aproximativ 5,3 biti. La decodificare, valorile originale sunt (aproximativ) refăcute prin înmultire cu factorul de cuantificare. De exemplu, dacă factorul este 16, valorile DCT cuprinse în intervalul 120 - 135 se vor stoca la valoarea 8 iar la decomprimare ele se vor regăsi la valoarea medie de 128, adică o aproximare a valorii originale.

Componenta DC este tratată într-un mod special: deoarece valorile DC adiacente tind să fie similare, fiecare componentă DC este stocată ca diferentă fată de componenta DC din blocul precedent. Componentele AC sunt plasate într-o ordine de tip zig-zag care pune componentele de frecventă mică pe primul loc. Componentele de frecventă înaltă vor fi de obicei zero si acest lucru va fi benefic în următorul stadiu al compresiei. Practic se utilizează modul de lucru RLE prin care un anumit număr de zerouri succesive se codifică astfel:(15,0) unde prin 15 am notat numărul componentelor de aceeasi valoare iar prin zero am indicat valoarea acestor componente.

Rezultatele cuantificării, în cazul JPEG-ului standard, sunt comprimate folosind un algoritm Huffman modificat sau eventual codificare aritmetică. Algoritmul Huffman modificat, cunoscut si sub denumirea de Cod de Lungime Variabilă sau VLC (Variable Length Code), codifică componenta DC pe 4 biti urmat de un întreg cu semn de lungime fixă. Componentele AC sunt stocate pe 8 biti si sunt urmate de un întreg cu semn de lungime variabilă. Cei mai semnificativi 4 biti reprezintă numărul de valori zero care preced această valoare iar cei mai putin semnificativi 4 biti reprezintă lungimea întregului ce urmează.

Alte posibilităti de comprimare

După cum am amintit mai la început, formatul grafic JPEG permite o multime de alte moduri de comprimare si respectiv stocare a informatiei. În continuare voi spune câteva cuvinte despre unele dintre aceste tehnici.

Modul ierarhic. În cadrul acestui mod de lucru, o imagine este stocată la câteva rezolutii, în mod crescător. Parcă nu ati înteles nimic din propozitia anterioară. Am dorit să spun că, de exemplu, o imagine de 1000 x 1000 pixeli poate fi stocată prima dată într-o versiune de rezolutie 10 x 10, apoi 100 x 100 si în final 1000 x 1000. Fiecare versiune a imaginii este stocată ca fiind o diferentă fată de versiunea precedentă, de rezolutie mai mică. În general, aplicatiile actuale nu implementează acest mod de lucru ierarhic dar o vor face probabil în viitor.

Modul de lucru fără pierderi. Există si un astfel de mod de lucru specificat pentru acei utilizatori care din diferite motive doresc (sau au nevoie) să reconstruiască imaginea bit cu bit. Această metodă face ca fiecare pixel să fie stocat ca diferentă fată de pixelii situati deasupra lui sau în stânga. În acest caz nu va mai fi folosită deloc faza transformării cosinus discrete la fel precum nu va fi folosită transformarea spatiului de culoare (din RGB în YCbCr). Acestea deoarece prin prelucrările pe care le aplică imaginii pot introduce (si chiar introduc) mici pierderi de informatie. Deci practic acest mod de lucru fără pierderi are destul de putin în comun cu formatul JPEG, exceptând numele folosit.

Modul progresiv. În situatiile în care o imagine JPEG este decomprimată pe măsură ce este receptionată de undeva (prin modem de exemplu) ar fi foarte interesant să putem afisa o versiune tot mai bună a acesteia pe măsură ce soseste.

Selectia spectrală transmite întâi componentele de frecventă mică pentru fiecare bloc de 8 x 8 iar apoi transmite componentele de frecventă înaltă. Un alt mod posibil de lucru este cel prin care se transmit prima dată cei mai semnificativi patru biti si în continuare se transmit cei mai putin semnificativi patru biti. Cele două moduri, descrise în acest alineat, pot fi combinate după cum este nevoie.

Iarăsi nici o implementare nu suportă modurile progresive de lucru deoarece toate au nevoie în primul rând de fisierul stocat pe disc si procesul de codificare-decodificare este destul de încet. Probabil că viitoarele implementări hard vor permite folosirea acestor moduri de lucru.

Pentru acei cititori care doresc informatii detaliate în legătură cu acest standard vom spune că există un grup, numit The Independent JPEG Group, ce se ocupă de dezvoltarea unor programe care realizează comprimarea si decomprimarea. Aceste surse de program sunt free (pot fi folosite atât în scop privat cât si în scop comercial) si pe deasupra sunt portabile pe platforme începând de la PC până la Cray. Pentru cei care au acces la reteaua Internet adresa este jpeg - info@uunet.uu.net. Versiuni ale bibliotecilor de programe pot fi găsite pe mai multe calculatoare din retea. Totusi serverul de comunicatii recomandat este ftp://ftp.uu.net . Directorul în care se găsesc este ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v?.tar.z

Caseta MPEG-Formatul de compresie video si audio


(C) Copyright Computer Press Agora