In questo capitolo vedremo come un’immagine viene salvata nel formato JPEG. Vedremo che questo processo è basato sulle procedure DCT2, IDCT2 e la compressione delle informazioni vista nella sezione precedente.

Immagini come matrici

Una foto o qualsiasi tipo di immagine che è riportata su schermo è divisa in pixel, ossia piccoli quadrati in cui viene messo uno specifico colore. Per salvare una tonalità di colore lo si “decompone” con la quantità di Rosso, Verde e Blu che serve per generarlo. Questa procedura di rappresentazione di un colore viene comunemente chiamata sintesi additiva, perché in un certo senso si sommano colori per ottenere il colore desiderato, vedi Figujmkra 1. Il livello di Rosso,

Untitled

Verde e Blu utilizzato per rappresentare un colore è codificato in un numero intero fra 0 e 255, dove 0 sta a indicare l’assenza del colore corrispondente e 255 la sua massima presenza.

Ovviamente, più pixel utilizziamo per rappresentare un’immagine più essa sarà nitida, ma il prezzo da pagare è la memoria, vedi Figura 2. Infatti, per poterla visualizzare o scambiare, dovremmo salvare il livello di Rosso, Verde e Blu di ogni pixel. Il formato JPEG si propone di ovviare questo problema, ossia salvare meno informazioni possibile per gestire in modo agile un’immagine.

Untitled

I canali di colore Rosso, Verde e Blu possono essere visti come delle matrici in cui il coefficiente corrispondente all’entrata $ij$ rappresenta il livello di Rosso, Verde e Blu in quella specifica posizione. Ma, se tutto si riconduce a una matrice anziché vederla come immagine possiamo pensare che questa matrice sia una funzione discreta come visto nella Sezione 7.3. In Figura 3 diamo un esempio di questa decomposizione fatta sull’ultima immagine di Figura 2. Dato che le immagini sono matrici possiamo pensare di utilizzare la strategia di compressione per risparmiare memoria. Nelle prossime sezioni vedremo come sfruttare al meglio la teoria sviluppata precedentemente per aver un buon compromesso fra qualità dell’immagine e risparmio di memoria.

A tal proposito considereremo solamente immagini in bianco e nero, ossia immagini in cui c’è solamente un canale di colore a cui è associato un valore fra 0 e 255, dove 0 rappresenta il nero mentre 255 è bianco, i numeri fra 1 e 254 saranno scale di grigio. Considerare questo caso non è limitativo visto che, data un’immagine a colori, può essere applicata in parallelo a ogni canale di colore.

Untitled

Compressione globale

Sfruttando tutto quello visto per le trasformazioni DCT e IDCT, possiamo pensare di sfruttare la medesima procedura per la compressione di immagini:

  1. convertire l’immagine in matrice
  2. applicare la trasformazione DCT2
  3. troncare le alte frequenze come descritto in Equazione 7.29
  4. applicare la trasformazione IDCT2 per ottenere di nuovo l’immagine

La differenza sostanziale di questa procedura rispetto a quella definita per le funzioni, sta nel fatto che la nostra matrice rappresenta di fatto un’immagine. Questo potrebbe essere un problema quando applichiamo la trasformazione IDCT2, ossia quando passiamo dallo spazio delle frequenze a quello del segnale. Infatti a priori non è garantito che i numeri che otteniamo da questa trasformazioni siano interi, e soprattutto numeri compresi fra 0 e 255. Il computer riesce a rappresentare un’immagine solamente se tutte le entrate della matrice sono numeri interi fra 0 e 255, quindi qualora gli si passa un valore con la virgola non riesce ad associarlo a un colore.

Sopperire a questo problema è abbastanza semplice. Infatti si può aggiungere un ulteriore passaggio di arrotondamento e conversione dei valori di output della IDCT2. Sia $a_{ij}$l un generico valore uscente dal processo IDCT2, per ottenere il valore che può essere interpretato come scala di colore, è sufficiente applicare Algoritmo 13.

Untitled

In riga 1 di Algoritmo 13 abbiamo supposto di avere una funzione chiamata “round” che preso un valore double, i.e., un numero con virgola, lo converte in un intero con segno. Per poi garantire che questo numero sia un valore fra 0 e 255, è sufficiente applicare le funzioni di “min” e “max” in modo opportuno, vedi riga 2 e 3 di Algoritmo 13.