Un algoritmo per la compressione di immagini senza perdita

Размер: px
Начинать показ со страницы:

Download "Un algoritmo per la compressione di immagini senza perdita"

Транскрипт

1 Università degli studi di Firenze Facoltà di scienze matematiche, fisiche e naturali Corso di laurea in Informatica Tesi di laurea Un algoritmo per la compressione di immagini senza perdita Candidato Stefano Brocchi Relatore Prof. Elena Barcucci Anno accademico 2004/ aprile 2006

2 Indice Introduzione 7 1 La compressione Introduzione alla compressione Il problema della compressione Entropia ed ottimalità secondo Shannon Rappresentazione e compressione di un immagine Tecniche di compressione Run length encoding Codifiche entropiche: alberi di Huffman e codifica aritmetica Lempel Ziv Welch e sue evoluzioni Prediction by partial matching Burrows Wheeler transform Formati compressi esistenti Zip, rar e 7z GIF e PNG Jpeg e sue evoluzioni Il formato file Funzionamento dell algoritmo Panoramica dell algoritmo Descrizione dei filtri utilizzati Schema di funzionamento Uso di matrici di bit Rappresentazione e codifica a formato fisso Codifica in domini finiti Codifica a formato variabile Codifica tramite alberi di Huffman Uso degli alberi di Huffman Codifica degli alberi di Huffman Codifica di strati tramite RLE ed alberi di Huffman Uso e codifica di poliomini Codifica di poliomini Codifica di strati tramite poliomini Uso e codifica dei filtri Codifica dei filtri selezionati Codifica della mappa di valori

3 INDICE Codifica delle matrici di bit compresse Codifica di strati e intestazione Codifica del file: intestazione e composizione L algoritmo di codifica Scelta dei filtri Criteri di ottimalità Scelta della riassegnazione dei valori Codifica degli strati Scelta del metodo di compressione ottimale Scelta del poliomino ottimale Gestione degli alberi di Huffman Realizzazione dell algoritmo Progettazione e descrizione delle classi Ottimizzazione dei tempi Requisiti di memoria Una funzionalità aggiuntiva: il filtro lossy Presentazione del programma e suo utilizzo Sperimentazione Presentazione del campione di immagini Criteri di scelta del campione di immagini Descrizione delle caratteristiche salienti delle immagini Risultati della sperimentazione Confronto con altri formati file esistenti Tempi impiegati Risultati della compressione lossy Conclusioni della sperimentazione Analisi dei risultati ottenuti Possibili evoluzioni dell algoritmo Conclusioni 115 Bibliografia 117 Appendice: un esempio di esecuzione dell algoritmo 118

4 Elenco delle figure 1.1 Esempio di raggruppamento dell entropia Un albero di Huffman Esempio di scalamento di tipo E Esempio di scalamento di tipo E Esempio di scalamento di tipo E Configurazione iniziale della BWT BWT: Matrice delle rotazioni cicliche ordinate Output della Burrows Wheeler transform Inversione della BWT: calcolo del vettore dei primi caratteri Calcolo del vettore dei predecessori nell inversione della BWT Ricostruzione finale del messaggio iniziale della BWT Esempio di dithering Punti utilizzati nel filtraggio PNG Fasi della compressione Fasi della decompressione Fase di filtraggio Fase di scomposizione Fase di compressione degli strati Punti utilizzati per il filtraggio Schema del meccanismo di compressione Schema del meccanismo di decompressione Esempio di ordine di visita standard Esempio di ordine di visita a zigzag Un secondo esempio di ordine di visita standard Un secondo esempio ordine di visita a zigzag Codifica tramite RLE ed Huffman con ordine di visita standard Codifica tramite RLE ed Huffman con ordine di visita a zigzag Scrittura delle dimensioni di un poliomino Lettura delle dimensioni di un poliomino Rotazione di un poliomino Codifica di un poliomino, situazione iniziale Codifica di un poliomino, scrittura punti di contatto Codifica di un poliomino, primo passo Codifica di un poliomino, secondo passo Codifica di un poliomino, terzo passo Codifica di un poliomino, quarto passo

5 ELENCO DELLE FIGURE Codifica di un poliomino, quinto passo Codifica di un poliomino, sesto passo Codifica di un poliomino, settimo passo Codifica di un poliomino, ottavo passo Codifica di un poliomino, nono passo Codifica di un poliomino, decimo passo Strato da codificare tramite poliomini, situazione iniziale Codifica di uno strato tramite poliomini, primo passo Codifica di uno strato tramite poliomini, secondo passo Codifica di uno strato tramite poliomini, terzo passo Codifica di uno strato tramite poliomini, quarto passo Codifica di uno strato tramite poliomini, quinto passo Codifica di uno strato tramite poliomini, sesto passo Esempio di numerazione delle zone di filtraggio Potatura di un albero di Huffman Schema delle classi Lenna Lenna: scomposizione per colore Lenna: particolare Lenna: particolare scomposto per colore Lenna: valori numerici rappresentanti il particolare Lenna: filtraggio del particolare Lenna: filtraggio per colore del particolare Visualizzazione per colori di Lenna dopo il filtraggio Visualizzazione per colori di Lenna dopo il filtraggio per colore Strati per il colore blu Strati per il colore verde Strati per il colore rosso

6 Elenco delle tabelle 1.1 Esempio di distribuzione di probabilità dei simboli Codifica aritmetica di ADBAECD con frequenza date Tabella di verità dello xor Corrispondenza fra matrici di bit e di byte Risultato di alcun scritture a formato fisso Codifica nel dominio finito [0, 6[ Codifica di vettori con limiti (2,3,2) Codifica a formato variabile con 0 bit di base Codifica a formato variabile con 2 bit di base Risultati della compressione Confronto dei risultati con altri formati Differenza di dimensioni relativa rispetto agli altri formati Risultati della compressione veloce Tempi di esecuzione Risultati della compressione con perdita di un bit Confronto della compressione con perdita con il formato jpeg Errori sulle previsioni dopo il filtraggio Entropia del particolare prima e dopo il filtraggio Entropia dell immagine prima e dopo il filtraggio Composizione del file compresso Composizione degli strati compressi tramite poliomini Composizione degli strati compressi tramite RLE ed Huffman

7 Introduzione Da sempre nell informatica è esistito il problema di rappresentare l informazione in modo conveniente. Allo stato di sviluppo tecnologico attuale è oramai chiaro che qualunque dato può essere rappresentato su di un calcolatore, sia esso testo, suono, immagine o qualsiasi altra forma di informazione si possa pensare. Tali dati possono essere tuttavia ingombranti e riempire rapidamente lo spazio a disposizione, o saturare velocemente un canale di comunicazione. Sebbene le capacità delle memorie e delle reti crescano esponenzialmente con il passare del tempo, altrettanto velocemente salgono le aspettative degli utenti nei confronti di quello che si può fare con un dispositivo elettronico. Con la diffusione del compact disc la musica ad alta qualità è diventata alla portata di tutti; la successiva invenzione del dvd sta causando il passaggio dall analogico al digitale per quanto riguarda il video. Allo stesso tempo la combinazione del processo di miniaturizzazione e del miglioramento della compressione di dati audio ha reso possibile la creazione di dispositivi per la memorizzazione e la riproduzione di musica sempre più piccoli. Analogamente l ampliamento delle velocità delle reti unito ad un efficiente compressione video permette di visualizzare film o videoconferenze trasmessi in tempo reale. Per questo ora più che mai la compressione di dati è uno dei problemi più studiati e più interessanti che si possa presentare nel mondo dell informatica. Questa tesi si occupa di compressione di immagini senza perdita di dati. Utilizzando un misto di tecniche già note e di idee sviluppate in questo lavoro, è stato creato un nuovo algoritmo per codificare immagini in un formato compatto in modo da ottimizzare memoria occupata e tempi di trasmissione. Già dalla sua prima versione qui presentata, l algoritmo produce un livello di compressione paragonabile, se non migliore, ad altri formati compressi di largo utilizzo. Nella prima parte di questo lavoro innanzitutto verrà introdotto il problema della compressione, sia da un punto di vista generico che nei confronti delle immagini. Saranno esposti i principali algoritmi finora sviluppati, alcuni dei quali sono stati utilizzati nel lavoro sviluppato. Infine saranno descritti alcuni dei formati compressi attualmente in uso, con brevi cenni sulle funzionalità che questi offrono. Nella seconda parte sarà descritto il formato file sviluppato. Inizialmente verrà fatta una panoramica sul funzionamento dell algoritmo, descrivendo e motivando brevemente i procedimenti utilizzati. Quindi si procederà nel dettaglio dal particolare al generale, descrivendo innanzitutto le strutture dati utilizzate e la loro gestione, mostrando come queste vengano composte per codificare oggetti complessi ed infine 7

8 INTRODUZIONE 8 definendo come tutto venga unito in un unico file compresso. La lettura di questa parte rende possibile a pieno titolo l implementazione di un ottimo decompressore per un file generato dall algoritmo proposto; volendo ricreare invece l algoritmo di compressione in modo efficiente occorre fare delle accurate scelte in fase di codifica, descritte nella prossima parte. Nella terza parte sarà descritto l algoritmo di codifica proposto. Saranno discussi i criteri usati per cercare di raggiungere l ottimalità, ed i compromessi fatti per ottenere un buon tempo di esecuzione. Verrà descritta quindi la realizzazione del programma che implementa l algoritmo, per quanto riguarda progettazione, stesura ed ottimizzazione del codice presentando infine l intera applicazione generata. Nella quarta parte verranno esposti i risultati della sperimentazione eseguita. Il programma verrà messo a confronto con altri algoritmi su di un campione di immagini vario per quanto riguarda origine, dimensioni e caratteristiche qualitative. Verrà fatta una breve analisi dei risultati ottenuti con particolare riguardo per i punti di forza o di debolezza dei vari formati. In conclusione, verranno presentate varie proposte per quanto riguarda i possibili sviluppi futuri dell algoritmo creato.

9 Capitolo 1 La compressione 1.1 Introduzione alla compressione In questa sezione si effettuerà un primo approccio alla compressione. Si vedranno prima delle osservazioni su cosa si intende per compressione e sulle ipotesi che rendono questa operazione possibile. Quindi si procederà esaminando la teoria di Shannon sulla codifica che definisce un limite ultimo alla comprimibilità e suggerisce un metodo su come avvicinarsi più possibile a tale quantità. Infine per definire il dominio dell algoritmo sviluppato si definirà come venga realizzata la rappresentazione di un immagine su di un calcolatore, e come tali dati rispecchino determinate ipotesi di regolarità necessarie alla compressione Il problema della compressione Poniamo di voler trovare un modo alternativo di codificare un generico messaggio M in modo più compatto. Consideriamo M come una sequenza di simboli appartenenti ad un insieme finito, detto alfabeto. Nel caso in cui M sia rappresentato su di un calcolatore, è chiaro che possa essere rappresentato con una serie di simboli binari, in quanto questo è il modo in cui viene fisicamente memorizzato. Spesso tuttavia è più sensato pensare ad un alfabeto più ampio: per un messaggio di testo tale alfabeto potrebbe essere a, b, c,... z; su di un calcolatore si considerano spesso simboli di un byte o di una parola (4 byte). Per comprimere il messaggio dobbiamo applicare una funzione biunivoca che associ un generico M ad un altro messaggio M tale che il risultato sia rappresentabile da una sequenza di simboli più breve dell originale. Tuttavia la condizione di invertibilità di tale funzione, indispensabile per garantire una corretta ricostruzione del messaggio in fase di decompressione, rende l esistenza di una funzione simile impossibile. Considerando infatti l insieme dei messaggi M di k simboli e l insieme dei messaggi M formati da k < k caratteri, il primo di questi ha chiaramente una cardinalità maggiore del secondo, rendendo impossibile una corrispondenza uno a uno. Dunque quello che ci dobbiamo aspettare è che solo una parte dei possibili messaggi M possa subire una diminuzione di volume grazie ad un operazione di compressione, mentre gli altri resteranno inalterati o addirittura cresceranno in dimensioni. Fortunatamente, è proprio quella piccola parte che solitamente contiene i messaggi che ci interessano. I dati da codificare infatti solitamente contengono numerose ridondanze, regolarità o altri dati in eccesso che si 9

10 CAPITOLO 1. LA COMPRESSIONE 10 possono eliminare con un buon algoritmo. Qualsiasi funzione di compressione per funzionare si deve quindi basare inevitabilmente su queste caratteristiche, e per non perdere di vista quali dati in ingresso ci aspettiamo di poter comprimere e quali no è importante tenere sempre presenti le ipotesi sulle quali ci si basa. Un altra semplice conseguenza di quanto detto è che sarebbe del tutto inutile tentare di ridurre ulteriormente un messaggio già compresso, in quanto dopo la prima applicazione della funzione di compressione le informazioni ridondanti sarebbero già state rimosse ed il messaggio compresso presenterebbe caratteristiche molto simili ad una serie di simboli del tutto casuali e quindi incomprimibili. Nel prossimo capitolo vedremo una definizione formale di quanto un qualsiasi messaggio possa essere compresso. Quanto detto è riferito alla compressione senza perdita di dati, detta anche lossless; questo significa che dopo aver applicato la funzione di decompressione su M riotteniamo esattamente M. Esiste un altro tipo di algoritmi detta lossy che disperde dei dati del messaggio ottenendo, dopo la decompressione, un messaggio M diverso ma in qualche modo simile ad M a vantaggio di un livello di compressione superiore. Tale somiglianza può essere misurata in molti modi; essendo tuttavia la compressione lossy utilizzata per dati che coinvolgono direttamente sensi umani come audio o video, uno degli approcci più interessanti è quello di cercare di misurare quanto l errore introdotto viene percepito da un osservatore umano. Facendo un e- sempio, nella compressione lossy mp3, usata per file audio, spesso vengono codificate più accuratamente le frequenze medie e viene utilizzata un approssimazione meno precisa per le frequenze molto basse o molto alte dove eventuali errori o imperfezioni nel suono vengono percepite più difficilmente. La compressione con perdita deve essere chiaramente applicata ad un tipo di dato di cui sappiamo di poter trascurare delle informazioni, e sarebbe inapplicabile a messaggi dove si rischia di perdere informazioni critiche come file di testo o programmi. Nonostante il largo utilizzo delle tecniche lossy, essendo l algoritmo da me proposto senza perdita, questa trattazione sulla compressione considererà principalmente tecniche lossless Entropia ed ottimalità secondo Shannon Approdiamo ora ad un approccio formale per il problema della compressione e dei suoi limiti. Uno dei primi ad occuparsene fu Claude Elwood Shannon, che con il suo lavoro [Sha48] pose le basi della sua teoria della codifica, tuttora un caposaldo per chiunque si interessi di compressione. Nella sua pubblicazione, Shannon aveva in realtà in mente il problema di trasmettere convenientemente dei simboli su di un canale; il problema della compressione è tuttavia del tutto analogo ed i risultati ottenuti regolano entrambi i casi. Nella sua teoria Shannon cerca una misura della quantità detta entropia. In generale, questo termine rappresenta il grado di disordine di un qualcosa; in termodinamica per esempio quantifica la dispersione di energia nell universo. Nella teoria dell informazione è misura inversa della comprimibilità di un messaggio, ed è in funzione delle probabilità di comparire dei simboli dell alfabeto considerato. Chiamando la probabilità dell i-esimo simbolo p i e la cardinalità dell insieme di simboli n, l entropia deve essere quindi funzione degli argomenti p 1... p n compresi tra zero ed uno tali che la loro somma sia uno. Si presuppone inoltre che la sequenza di simboli che forma il messaggio sia ergodica; evitando una definizione rigorosamente matematica, per i nostri scopi definiremo ergodica una

11 CAPITOLO 1. LA COMPRESSIONE 11 sequenza dove ogni sottosequenza abbastanza lunga di caratteri goda delle stesse proprietà statistiche. Shannon impone che la funzione dell entropia H debba avere le seguenti proprietà: 1. Continuità: H deve dipendere con continuità dai suoi argomenti p i 2. Se gli argomenti valgono tutti 1/n, l entropia deve essere una funzione monotona crescente in n. Questo perché se i simboli compaiono con uguale probabilità, un incremento del loro numero porta ad avere un messaggio maggiormente caotico. 3. Se dei simboli vengono raggruppati in un gruppo B, l entropia è data da H(p 1... p n ) = H(p i... p B ) + p(b)h((p j B)...) i / B j B Dove nel primo addendo del membro destro dell equazione l entropia ha come argomenti la probabilità del gruppo p B e tutti i p i tali che i / B e nel secondo addendo la funzione H è applicata a tutti i p j B tali che j B. Quest ultima regola definisce come si deve comportare la funzione se la probabilità di un simbolo è vista come probabilità di scegliere un gruppo che lo contenga moltiplicata la probabilità che, una volta che il suo gruppo è stato selezionato, venga scelto il simbolo stesso. Detta anche proprietà di raggruppamento, questa caratteristica assicura coerenza alla funzione, garantendo che il valore di H non cambi applicando viste diverse su dati uguali. Shannon dà come esempio della proprietà di raggruppamento la figura 1.1 Figura 1.1: Esempio di raggruppamento dell entropia Presupponendo che i simboli siano indipendenti l uno dall altro, l unica famiglia di funzioni che soddisfa le precedenti è rappresentata dalla formula K n log 2 p i, K > 0 i=1 Dove k è un fattore di proporzionalità che determina l unità di misura, e viene per convenzione imposto ad uno. Shannon ha dimostrato che tale quantità limita in

12 CAPITOLO 1. LA COMPRESSIONE 12 modo rigido la compressione che è possibile ottenere. Infatti, un messaggio non è mai comprimibile sotto il limite di H bit per carattere; per questo l entropia è talvolta misurata in bit per simbolo. Con l ipotesi dell indipendenza statistica fra i simboli, abbiamo realizzato quello che si dice modello di ordine uno. Se consideriamo inoltre che i caratteri siano equiprobabili otteniamo il modello di ordine zero; tale modello rispecchia l assoluta casualità ed è regolato dalla formula H = log 2 n, il valore massimo dell entropia per ogni n fissato. La formula ottenuta non è che un caso particolare della precedente, ed in generale ogni modello di un determinato ordine comprende tutti quelli di ordine minore. Possiamo ottenere modelli di ordine maggiore considerando la correlazione tra i vari simboli. Nel modello di ordine due si tiene conto del legame che ci può essere fra caratteri adiacenti, sostituendo a p i una probabilità in dipendenza dal suo contesto; la formula dell entropia sarà la seguente: n p j j=1 i=1 n p i j log 2 p i j In generale, possiamo ottenere un generico modello di ordine n considerando la probabilità di p i in dipendenza da altri n 1 caratteri che lo precedono. Al crescere dell ordine del modello, teniamo conto di maggiori informazioni, e troveremo quindi valori dell entropia decrescenti. Il vero valore dell entropia di un messaggio è dato dal modello generale ottenuto considerando il limite per di un modello di ordine n. Tale quantità è chiaramente incalcolabile; quello che si può fare è calcolare l entropia per un modello che la approssimi sufficientemente bene. In messaggi reali è in effetti difficile limitare la quantità di caratteri di un contesto che ci danno informazioni sul simbolo successivo, ma è altrettanto vero che il contributo dato dai simboli più distanti solitamente è quasi nullo e che quindi l ignorarli non provoca gravi errori. Una grande utilità della teoria di Shannon è che questa ci suggerisce il numero di bit da utilizzare per codificare un determinato simbolo. Un messaggio viene infatti compresso alla lunghezza minima di H bit per carattere utilizzando esattamente log 2 p i bit per la codifica di ogni simbolo. I principali problemi da affrontare per arrivare all ottimalità sono quindi due: 1. Nella maggior parte dei casi, la quantità log 2 p i non è un numero intero. Ci troviamo di fronte alla difficoltà di dover allocare un numero frazionario di bit per simbolo. Una prima soluzione è quella di usare un metodo che costruisca in qualche modo un insieme di caratteri tali che ogni valore log 2 p i sia un numero elevato minimizzando così l errore relativo fatto arrotondandolo all intero più vicino. Shannon per esempio suggerisce di minimizzare l errore raggruppando i simboli dell alfabeto a gruppi di n ottenendo una distribuzione di probabilità più granulare con possibilità di apparire minore per ogni ennupla di caratteri; tale algoritmo non può essere applicato tuttavia a grandi gruppi in quanto la sua complessità è esponenziale. Un altro metodo, rappresentato dalla codifica aritmetica, riesce effettivamente ad utilizzare un numero non intero di bit per simbolo, anche se al costo di una complessità computazionale piuttosto alta

13 CAPITOLO 1. LA COMPRESSIONE 13 in fase di codifica e decodifica. Le tecniche per l elaborazione di una codifica ottimale saranno discusse del dettaglio nei prossimi capitoli. 2. La quantità p i è difficile da calcolare in quanto al crescere dell ordine del modello la complessità del calcolo delle probabilità dei simboli sale in modo esponenziale. Solitamente questo problema è di più difficile risoluzione del precedente; un algoritmo capace di sfruttare anche modelli di ordine elevato per calcolare queste quantità è il PPM, che verrà descritto in seguito Rappresentazione e compressione di un immagine Prima di procedere dobbiamo soffermarci per analizzare come quanto detto si rifletta sul soggetto in questione: le immagini. Vediamo innanzitutto come queste vengano rappresentate su di un supporto digitale. Se l immagine è ottenuta tramite un segnale reale come nel caso di una macchina fotografica o uno scanner innanzitutto viene eseguito un campionamento uniforme sui dati in ingresso ed una quantizzazione dei valori ottenuti. Il numero dei campioni, così come la granularità della discretizzazione determinante il massimo numero di colori utilizzati, influenzano la qualità visiva dell immagine al momento della ricostruzione. Nel caso di immagini con un sufficiente numero di campioni e di colori, in fase di rappresentazione su di un supporto come uno schermo un osservatore percepisce un senso di continuità e la natura discontinua dell informazione è del tutto occultata. Tutti i colori visibili possono venire ottenuti mescolando in diverse proporzioni blu, rosso e verde, e dunque ogni campione in realtà è suddiviso in tre sottocampioni ognuno riferito ad uno di questi tre colori. Ogni punto rappresentato è anche detto Pixel (picture element). Il formato immagine di base, dove i campioni vengono memorizzati senza alcuna elaborazione, è il BMP. Tale formato contiene innanzitutto una breve intestazione che specifica alcune delle informazioni di base, tra cui la risoluzione orizzontale e verticale (definendo così la griglia dei campioni) ed il numero dei colori utilizzati nell immagine. Il caso di cui ci si occuperà in questo lavoro è quello dove ogni campione è formato da 24 bit, otto per ogni colore primario. Altre funzionalità del formato consentono di utilizzare solo 256 o 16 colori dei 2 24 disponibili, definendo nell intestazione un vettore di colori utilizzati detto tavolozza e mettendo al posto dei campioni un riferimento a questa lista. Esistono molte altre informazioni che possono essere considerate parte di un immagine, supportate da altri tipi di file. Per fare un paio di esempi, formati intesi per l utilizzo in internet supportano la presenza di un ulteriore valore per ogni punto rappresentante la quantità di trasparenza del pixel nel caso l immagine debba essere sovrapposta ad un altro contesto come lo sfondo di una pagina web. Altri formati utilizzati da programmi di grafica permettono di memorizzare un immagine come sovrapposizione di più immagini stratificate in modo da facilitarne la lavorazione. In questo lavoro informazioni ausiliarie come queste saranno tralasciate e saranno trattati esclusivamente i dati di base. A questo punto ci dobbiamo chiedere in che modo i dati in un immagine siano correlati fra loro. Nulla vieta che possa esistere un immagine dove ogni punto sia

14 CAPITOLO 1. LA COMPRESSIONE 14 totalmente scorrelato dagli altri; è tuttavia difficile immaginare che interesse questa possa rivestire. In realtà le immagini che solitamente vogliamo rappresentare contengono un insieme di soggetti di numero relativamente piccolo rispetto al numero dei pixel, ed per ognuno di essi vi sono solitamente zone che variano abbastanza poco nello spettro dei colori e presentano un forte effetto di continuità. In effetti si evince dai risultati sperimentali che ogni campione è fortemente connesso agli altri, ma dare una quantificazione matematica di questo è molto difficile proprio perché entra in gioco il fattore umano: non possiamo quantificare con precisione la regolarità mediamente presente nelle immagini che per noi rappresentano potenzialmente un significato. Possiamo trarre tuttavia a livello empirico una conclusione interessante: osservando che punti adiacenti hanno spesso colori simili, volendo costruire un modello di previsione per un determinato campione è conveniente considerare non solo i campioni immediatamente precedenti ma anche gli altri ad esso adiacenti nella rappresentazione a pixel in entrambe le direzioni tenendo così in considerazione la natura bidimensionale del dato. Una tecnica simile viene utilizzata nell algoritmo di compressione del formato PNG oltre che in questo lavoro. 1.2 Tecniche di compressione In questa sezione si vedranno varie tecniche di compressione esistenti. Si inizierà con il Run Length Encoding, uno degli algoritmi più semplici, e si procederà con le codifiche tramite alberi di Huffman ed aritmetica tese a raggiungere l ottimalità definita dall entropia di Shannon. Quindi si descriverà l algoritmo Lempel Ziv Welch ed una sua popolare variante; queste tecniche sono tuttora fra le più utilizzate e supportate nella compressione di dati. Infine verranno descritti due algoritmi più recenti che si stanno imponendo per la loro efficacia: la Burrows Wheeler Transform, una trasformazione che permette di riorganizzare l informazione in modo da poter effettuare una compressione efficiente anche con l applicazione di tecniche molto semplici, ed il Prediction by Parzial Matching, un algoritmo che fa uso di modelli di ordine elevato per la stima delle probabilità dei simboli del messaggio Run length encoding Una delle più semplici tecniche di compressione è la codifica di sequenze uguali (Run Length Encoding, RLE). Questo algoritmo si basa sull idea che una sequenza di simboli consecutivi dello stesso tipo può essere codificata in modo compatto memorizzando solo il carattere e la lunghezza della sequenza. Il RLE è il modo più naturale per codificare dati binari dove sequenze di uni e di zeri si alternano raramente, e per questo è nato per la codifica dei dati trasmessi dai fax. In un documento stampato da elaborare infatti è naturale aspettarsi grandi zone di solo bianco intervallate da brevi zone nere in corrispondenza dei caratteri, e dopo il campionamento questo significa esattamente lunghe sequenze di un simbolo (per convenzione, 0 per il bianco) o dell altro (1 per il nero). In tal caso questa tecnica restituirà il numero di zeri consecutivi alternato con il numero di uno. Per consentire la decompressione a questo punto occorre definire una codifica univocamente decifrabile per i valori ottenuti. Una metodologia precisa per fare ciò sarà data in seguito; per avere un idea del problema basti notare che scrivendo sequenzialmente dei numeri su un

15 CAPITOLO 1. LA COMPRESSIONE 15 canale di comunicazione o su di un dispositivo di memorizzazione un osservatore non ha modo di sapere quando un numero è terminato e quando inizia il successivo (ad esempio, la sequenza potrebbe rappresentare 87 e 210 così come 872 e 10). La soluzione più semplice da adottare è quella di scrivere le lunghezze delle sequenze con un numero di bit determinato a priori. In questo caso, allocando n bit per ogni numero, si possono rappresentare quantità nel campo n 1; nel caso di sequenze di lunghezza maggiore sarà necessario spezzare il numero in due valori distinti. Per specificare se la sequenza è di uno o di zeri si può aggiungere un bit in testa o in fondo al codice per specificare il tipo di simbolo, o semplicemente imporre implicitamente che le sequenze dei due valori si alternino. In questo caso le ipotesi su cui ci si basa per la compressione sono facilmente individuabili: considerando infatti di aver allocato n bit per numero ottenuto, per ogni sequenza di k simboli consecutivi con k > n ci sarà un guadagno di k n bit (trascuriamo il caso k 2 n ), per k < n la quantità n k rappresenterà invece una perdita. In alternativa, per una compressione migliore nulla ci impedisce di codificare i valori di output dell algoritmo con un altra tecnica di compressione come per esempio tramite alberi di Huffman. Questo è un esempio di come spesso le tecniche di compressione raggiungano le migliori prestazioni mettendo in serie vari algoritmi. Il RLE è tuttora utilizzato su di alcuni dispositivi poiché la sua semplicità combinata con l utilizzo di codici a lunghezza fissa lo rendono molto semplice da realizzare anche con un piccolo circuito hardware ed il processo di decompressione è estremamente rapido. Oltre alla messa in serie con un altro codificatore, gli sviluppi di questa tecnica sono vari, e sono tesi soprattutto a rendere possibile una buona compressione di dati anche non binari. In questi casi uno dei problemi principali da risolvere è quello di limitare l aumento di volume del dato causato da zone irregolari senza sequenze di simboli consecutivi, ed una delle soluzioni proposte è quella di inserire dei caratteri di controllo che specifichino che un determinato numero di byte che seguono non devono venire codificati. Nonostante le migliorie, il RLE difficilmente viene applicato direttamente ai dati da comprimere, ma in alcuni casi è utile in combinazione con altre tecniche Codifiche entropiche: alberi di Huffman e codifica aritmetica Grazie alla teoria di Shannon dati una serie di simboli con determinate frequenze siamo in grado di determinare il numero di bit da utilizzare per ogni carattere. Gli alberi di Huffman sono una struttura ideata per elaborare una codifica univocamente decifrabile dove ad ogni carattere viene associato un codice di tale lunghezza ottimale. Innanzitutto vediamo una proprietà che ci garantisce una corretta decodificabilità di un messaggio: Proprietà del prefisso: Una codifica gode di questa proprietà se nessun codice assegnato è prefisso di un altro codice. È chiaro che una codifica così composta permette in fase di decompressione di determinare un simbolo appena il suo codice è stato letto. Il modo più semplice per costruirne una con questa proprietà è quella di costruire un trie binario, un particolare tipo di albero binario dove soltanto le foglie contengono i valori delle chiavi.

16 CAPITOLO 1. LA COMPRESSIONE 16 Associando a questo punto i valori da codificare alle foglie ed i bit zero ed uno ai due archi uscenti da ogni nodo, si definisce come codifica di un determinato simbolo la sequenza di bit da percorrere per arrivare dalla radice al carattere interessato. È chiaro che una codifica così definita soddisfa la proprietà del prefisso, e si può considerare il trie come un albero decisionale da usare in fase di decodifica. Resta il problema di trovare un trie ottimale nei confronti delle nostre ipotesi. Questo può esser fatto grazie al seguente algoritmo dovuto ad Huffman e presentato in [Huff52]. La formulazione originale dell autore è del tutto equivalente a questa dal punto di vista del risultato, ma nel documento originale è espressa in modo diverso senza fare uso di strutture ad albero. L algoritmo di seguito tuttavia rispecchia maggiormente la realizzazione di questa tecnica su di un calcolatore. Consideriamo di avere un insieme di simboli da codificare, di cui conosciamo le frequenze nel messaggio da comprimere. I passi da eseguire sono 1. Creare un insieme di alberi formati da un unica foglia contente ognuna uno dei simboli. Ad ogni albero si associa la frequenza del carattere stesso. 2. Finché l insieme contiene più di un albero, rimuovere i due alberi con frequenza associata minore, ed aggiungere un albero che abbia come figli i due elementi rimossi, associandogli la somma delle due frequenze. Quando l algoritmo termina, l unico albero rimasto nell insieme definisce la codifica ottimale a bit interi per la situazione delineata. Tale albero è detto albero di Huffman. Da notare che per permettere la decodifica da parte di un decompressore è necessario memorizzare l albero stesso in testa al messaggio. F = Codifica generata F = 7 V = 1 F = 2 0 F = 5 1 F = 3 V = 4 Simbolo Codice F = 1 F = 1 V = 2 V = 3 Figura 1.2: Un albero di Huffman Uno dei problemi della codifica tramite alberi di Huffman è la necessità di conoscere a priori le frequenze dei simboli. In alcuni casi questa non è desiderabile, in quanto alcuni algoritmi si pongono il problema di effettuare la compressione senza eseguire una doppia passata sui dati per motivi di efficienza. In altri casi avere tale informazione non è proprio possibile: nell eventualità per esempio di voler comprimere dati trasmessi da un modem il flusso di dati è indeterminatamente lungo e

17 CAPITOLO 1. LA COMPRESSIONE 17 non è mai interamente a disposizione. Sono state proposte diverse soluzioni a questi problemi, tra cui: 1. Utilizzare un albero di Huffman relativo agli ultimi dati memorizzati, e ricrearne uno nuovo periodicamente. I criteri per le ricreazione possono essere vari, da una suddivisione a blocchi (ex. cambiare albero ogni 100Kb di dati) al rilevamento di grandi variazioni delle frequenze del messaggio. 2. Utilizzare un albero di Huffman adattivo. Tali alberi sono stati proposti e sviluppati in seguito ai lavori di Huffman, ed operano tenendo conto delle variazioni di frequenza dei simboli ed effettuano delle rotazioni per adattarsi alla caratteristiche del dato in ingresso. In questo caso le trasformazioni dell albero sono ricostruibili in fase di decodifica utilizzando simmetricamente la stessa tecnica, e definendo una configurazione iniziale dell albero nell algoritmo non è necessario memorizzare alcuna informazione su questa struttura. Un vantaggio di entrambe le due tecniche sopra descritte è l adattività, la capacità di adattarsi a variazioni del dato in ingresso. Questo è una qualità molto importante nel caso in cui ci si trovi a trattare con dati le cui proprietà statistiche cambiano rapidamente e di cui non conosciamo le caratteristiche a priori. Un altro limite degli alberi di Huffman è la necessità di utilizzare un numero intero di bit per simbolo. Questo produce una codifica perfetta solo quando tutte le probabilità dei simboli sono potenze negative di due; in caso contrario la differenza tra il numero di bit da utilizzare e quello realmente utilizzato è misura della distanza dall ottimalità. Questo valore è solitamente molto piccolo quando il numero di simboli è sufficientemente alto ed ha una distribuzione abbastanza uniforme, e al contrario può diventare notevolmente grande quando esiste un simbolo con probabilità di comparire molto maggiore del 50%. Per avvicinarsi maggiormente all ottimalità si può utilizzare un altra tecnica detta codifica aritmetica. La codifica aritmetica è stata ideata per la prima volta da Elias in [El63] come pura teoria matematica, ed è stata sviluppata sul piano pratico da Rissanen in [Ris75] quasi in contemporanea con altri autori quali Pasco e Langdon. A portarla alla popolarità sono state tuttavia le trattazioni sviluppate da Witten, Neal, Cleary e Bell come [WNC87] o il successivo [BCW90]. Il suo obiettivo è quello di codificare ogni simbolo ottimalmente indipendentemente da quanti bit esso richieda, sia esso un numero intero o meno. Osserviamo innanzitutto che un modo alternativo di imporre che un simbolo deve essere codificato con log 2 p i bit è di decidere che quel simbolo deve coprire una parte pari a p i delle possibili codifiche. Prendiamo ad esempio un carattere con probabilità 25%. Shannon ci dice di codificare tale simbolo con 2 bit. Elaborando un qualsiasi codice con la proprietà del prefisso, notiamo che ciò vieta l assegnazione agli altri simboli di tutti i codici che iniziano con quei due bit, che sono appunto il 25% di tutti quelli possibili. Iniziamo innanzitutto vedendo la teoria riguardante la codifica aritmetica, per poi analizzare in seguito come questa possa effettivamente venir realizzata. Al primo passo partizioniamo il campo dei reali compresi tra zero ed uno, assegnando ad ogni

18 CAPITOLO 1. LA COMPRESSIONE 18 simbolo dell alfabeto un intervallo di ampiezza pari alla sua probabilità. Supponiamo ora di voler codificare l intera sequenza da comprimere con un unico numero reale. Dopo aver trovato i due estremi dell intervallo a e b relativo al primo simbolo del messaggio, imponiamo che il messaggio debba essere rappresentato con un numero compreso fra questi limiti, definenti quello che chiameremo intervallo di confidenza. Al momento della lettura del secondo simbolo partizioniamo anche questo spazio, assegnando nuovamente ad ogni simbolo un sottointervallo proporzionale alla sua frequenza. In dipendenza dal secondo simbolo, otterremo un nuovo intervallo di confidenza a e b. Iterando il procedimento, alla fine del messaggio possiamo memorizzare un numero reale che cada nell attuale intervallo rappresentante l intero messaggio. Conseguentemente alle osservazioni fatte precedentemente, il numero di bit necessario per la codifica di tale numero reale sarà ottimale nei confronti del limite entropico della comprimibilità. Nell esempio nelle tabelle 1.1 e 1.2 si potrebbe codificare la sequenza studiata con un qualsiasi numero nell intervallo [ , [. Per quanto riguarda la decodifica, sarà sufficiente partizionare l intervallo di confidenza inizializzato a in modo analogo al codificatore, e ad ogni passo verificare a quale zona appartenga il numero letto, suddividendo ulteriormente quindi l intervallo in modo analogo ed iterando. Simbolo Probabilità Intervallo assegnato in [0,1[ A 0.4 [0,0.4[ B 0.2 [0.4,0.6[ C 0.2 [0.6,0.8[ D 0.1 [0.8,0.9[ E 0.1 [0.9,1[ Tabella 1.1: Esempio di distribuzione di probabilità dei simboli Simbolo Intervallo, Intervallo, Ampiezza estremo sinistro estremo destro dell intervallo A D B A E C D Tabella 1.2: Codifica aritmetica di ADBAECD con frequenza date Ci sono molti problemi per la realizzabilità di questo algoritmo così come è descritto sopra. Primo fra tutti, già con pochi caratteri potremmo aver bisogno di un grande numero di cifre per distinguere i due estremi dell intervallo e questo diviene proibitivo anche utilizzando numeri ad alta precisione. Inoltre, utilizzando l aritmetica a virgola mobile di un calcolatore, oltre a rallentare notevolmente il procedimento, si può generare una perdita di informazioni dovuta all arrotondamento che potrebbe

19 CAPITOLO 1. LA COMPRESSIONE 19 rendere impossibile una corretta decodifica. Per aggirare questi problemi, la codifica aritmetica viene realizzata rappresentando gli estremi dell intervallo di confidenza con interi a 32 bit di cui solo i primi 31 bit verranno effettivamente utilizzati mentre l ultimo bit verrà lasciato libero per prevenire overflow durante le operazioni di somma. Si possono rappresentare così le prime 31 cifre binarie di un numero compreso tra zero ed uno; in altre parole si realizza un aritmetica a virgola fissa con 31 bit di mantissa. A questo punto il principale problema ancora da risolvere è l underflow, il rischio di ottenere un intervallo troppo piccolo che renda impossibile un ulteriore partizionamento. Per questo vengono utilizzate delle operazioni di scalamento: appena in fase di codifica si è sicuri di poter scrivere un bit, si manda questo risultato in output e l intervallo viene riadattato in modo da riferirsi solo ai bit successivi. Nel dettaglio, definendo come l ed r gli estremi sinistro e destro dell intervallo dopo la codifica di un simbolo ed m la rappresentazione di 0.5 nel nostro modello (in questo caso 2 30 ), le operazioni di scalamento sono: E1 Quando r è minore di m, sappiamo che il primo bit da restituire in output è uno zero. Memorizziamo questo output, e riadattiamo l intervallo nei confronti del numero ancora da codificare moltiplicando per due l ed r. Nel dettaglio delle implementazioni, a questo punto viene sommato uno ad r per tener conto di tutti i valori utilizzabili Scalamento di tipo e1: intervallo espanso da [0.2, 0.4[ a [0.4, 0.8[ Restituito in output il bit Per ogni espansione di tipo e3 eseguita immediatamente prima di questa, viene dato in output un altro bit pari ad uno. Figura 1.3: Esempio di scalamento di tipo E1 E2 Quando l è maggiore di m, per certo il primo bit del messaggio codificato dovrà essere un uno. Dopo aver restituito tale risultato, sottraiamo m da l e da r, ed aumentiamo l intervallo come nel punto precedente. Nella maggior parte dei casi queste due tecniche sarebbero sufficienti. Resta però da considerare il caso in cui il valore dell intervallo converga a m portando ad un underflow senza che nessuna delle due operazioni precedenti sia possibile. Per questo esiste una terza operazione di scalamento: E3 Quando l è maggiore del primo quarto dell intervallo 2 29 ed r è minore del terzo quarto ad entrambi viene sottratto il valore del primo quarto, e quindi si espande l intervallo come sopra. Non sapendo in che metà cada il risultato, l output del prossimo bit viene posticipato, ma il codificatore memorizza che è

20 CAPITOLO 1. LA COMPRESSIONE Scalamento di tipo e2: intervallo espanso da [0.6, 0.9[ a [0.2, 0.8[ Restituito in output il bit Per ogni espansione di tipo e3 eseguita immediatamente prima di questa, viene dato in output un altro bit pari a zero. Figura 1.4: Esempio di scalamento di tipo E2 stata effettuata un operazione di questo tipo. Si può dimostrare che al momento di eseguire uno scalamento di tipo E1 o E2 si determina che il risultato esatto da restituire è, rispettivamente, uno o zero. Dunque quando sono stati eseguiti n scalamenti di tipo E3, il primo scalamento successivo di diverso tipo restituirà n bit aggiuntivi del tipo appropriato Scalamento di tipo e3: intervallo espanso da [0.4, 0.7[ a [0.3,0.9[ Output del bit posticipato al primo scalamento di altro tipo successivo; tale bit sara 0 per uno scalamento di tipo e2 o 1 per uno scalamento di tipo e1 Figura 1.5: Esempio di scalamento di tipo E3 Ultimi accorgimenti usati nelle implementazioni sono l aggiunta di opportuni bit in coda al messaggio per garantire la decodificabilità di tutti i simboli e l uso di un carattere di fuga con probabilità minima per indicare la fine della sequenza compressa. Per quanto riguarda la decompressione si dovrà operare in modo del tutto simmetrico. Inizialmente dovranno venir letti 31 bit dal dato compresso e si dovrà determinare che intervallo, e quindi che simbolo, identifichi tale quantità. Quindi sarà sufficiente eseguire gli stessi scalamenti che sarebbero necessari in fase di codifica leggendo bit dove durante la compressione questi sono stati scritti e procedere fino ad incontrare il carattere di fine messaggio. Una caratteristica importante della codifica aritmetica è che permette di variare la distribuzione di probabilità tra un simbolo e l altro. Questo rende semplice la realizzazione in primo luogo di un modello adattivo dove le frequenze dei simboli vengono via via aggiornate. In seconda analisi, possiamo osservare che anche l utilizzo di un modello di ordine superiore può essere realizzata in modo molto naturale, semplicemente considerando ad ogni passo la distribuzione di probabilità di simboli nel contesto considerato. In entrambi i casi per garantire l esatta decompressione è

21 CAPITOLO 1. LA COMPRESSIONE 21 sufficiente che appena un simbolo viene osservato, sia il codificatore che il decodificatore aggiornino il proprio modello nello stesso modo. La scelta fra l utilizzo degli alberi di Huffman e la codifica aritmetica è molto discussa; è vero che quest ultima solitamente si avvicina maggiormente all ottimalità, ma coinvolge anche un numero maggiore di operazioni per la lettura e la scrittura di ogni simbolo, appesantendo così la complessità a scapito dei tempi di esecuzione. L opzione migliore deve essere determinata di caso in caso; in generale l utilizzo degli alberi di Huffman può dare risultati molto soddisfacenti soprattutto in contesti dove si riesce a tenere la distanza dall ottimalità sotto una soglia sufficientemente piccola Lempel Ziv Welch e sue evoluzioni Uno degli algoritmi di compressione più noti ed utilizzati è il Lempel Ziv Welch (LZW), dai nomi degli autori. Sviluppato inizialmente in un articolo di Lempel e Ziv [LZ77], l idea iniziale fu rivista e migliorata da Welch qualche anno più tardi in [Wel84]. Il LZW opera sostituendo a sequenze di caratteri ripetute dei codici numerici. L algoritmo fa uso di un buffer di caratteri da processare e di una struttura detta dizionario, formata da un insieme di coppie di stringhe e di numeri naturali rappresentanti i codici associati; il dizionario è inizializzato con i simboli dell alfabeto e dai primi n naturali. Durante il processo di compressione il messaggio viene esaminato sequenzialmente, e per ogni carattere letto si eseguono le seguenti azioni: - Se il contenuto del buffer concatenato al nuovo carattere forma una stringa presente nel dizionario, il carattere viene aggiunto in fondo al buffer. - In caso contrario viene dato come output il codice relativo alla stringa presente nel buffer, la stringa che non è stata trovata viene aggiunta al dizionario con assegnato un nuovo codice ed infine il carattere letto sostituisce il precedente contenuto del buffer. Per quanto riguarda i valori dati in output è necessario selezionare un formato per la loro codifica. Una soluzione semplice ma già efficace è quella di scrivere i codici a formato fisso con un numero di bit determinato dalla grandezza del dizionario. L algoritmo LZW così implementato crea una codifica a numero di bit fisso per sequenze di lunghezza variabile, in contrapposizione a metodi come gli alberi di Huffman che utilizzano un numero di bit variabile per dati in ingresso di uguale dimensione. Con tale approccio si ottiene di comprimere efficientemente le sequenze più lunghe del vocabolario, mentre quelle più corte non subiranno alcuna riduzione o addirittura, se il codice occupa più bit della stringa originale, saranno espanse. L efficacia del metodo sta nel fatto che se nel messaggio ci sono stringhe che si ripetono frequentemente, le sequenze più lunghe del dizionario avranno tali stringhe come prefisso permettendo la codifica con pochi bit dei dati ridondanti. Nelle implementazioni, per limitare la memoria occupata dal dizionario, solitamente si limita la lunghezza dei codici utilizzabili a 12 o 13 bit; di conseguenza il dizionario avrà una dimensione massima di 2 12 o 2 13 sequenze, e al momento del suo totale riempimento sarà necessario cessare di inserire nuovi valori utilizzando invece quelli già presenti.

22 CAPITOLO 1. LA COMPRESSIONE 22 Per la decompressione occorre operare in modo speculare. Una delle parti più interessanti di questo algoritmo è che il dizionario non deve essere memorizzato con i dati, ma può essere ricostruito in fase di decodifica. Infatti sarà sufficiente che, per ogni stringa decodificata, il decompressore aggiunga al suo dizionario la sequenza formata dalla stringa decodificata al passo precedente concatenata con il primo carattere della sequenza letta. Questo provoca un ritardo di un passo rispetto a quello che fa il compressore, che inserisce invece la sequenza corrispondente in base alla stringa nel buffer al passo corrente. Ciò può causare la lettura di un valore mancante al dizionario in fase di decodifica; l unica situazione dove questo si verifica tuttavia è quando si presenta due volte consecutivamente la stessa sequenza causando in fase di codifica l utilizzo di un codice che è stato appena inserito nella tabella. Sapendo ciò, per risolvere il problema il decodificatore non deve fare altro che considerare l ultima stringa letta e, essendo questa necessariamente anche la sequenza successiva, concatenarci in coda il suo primo carattere aggiungendo al vocabolario il valore ottenuto ed associandolo al codice mancante. L algoritmo LZW, sebbene datato, è ancora utilizzato in molte applicazioni e sfruttato da diversi formati file come il GIF. È particolarmente efficace con dati dove ci sono sequenze frequentemente ripetute, come testo o immagini con pochi colori. È stato inoltre una base importante per molti algoritmi nati dalla sua evoluzione o da sue varianti. Una variante dell algoritmo LZW viene utilizzata nella libreria di compressione zlib, utilizzata da numerosi programmi tra cui il gzip, lo zip e nel formato png. Questa tecnica consiste nel trovare sequenze uguali nei dati in ingresso e di codificare le occorrenze successive alla prima con una coppia (distanza, lunghezza), dove la prima quantità rappresenta la distanza, in byte, tra le due occorrenze e la seconda indica di quanti byte è composta la stringa ripetuta. I caratteri in ingresso vengono codificati con un albero di Huffman dove saranno presenti una serie di valori che indicano che il valore letto è un determinato simbolo del testo, ed altri indicanti che è stata trovata una sequenza nota di una determinata lunghezza. In quest ultimo caso con un altro albero di Huffman viene codificata di seguito anche la quantità rappresentante la distanza. Per l individuazione delle stringhe duplicate viene utilizzata una tabella hash dove vengono inserite informazioni sulle sequenze trovate. Per evitare il sovraccarico della tabella, alcuni dei valori devono venire scartati, e l algoritmo solitamente tende a conservare i valori trovati più recentemente. La gestione di questa struttura è solitamente configurabile a seconda se si preferisce una compressione più forte a scapito della velocità di esecuzione e della memoria utilizzata, o se si accetta di ottenere file lievemente più grandi a favore di una minor occupazione di tempo e risorse; per questo i programmi che utilizzano questo algoritmo mettono solitamente a disposizione diversi livelli di compressione. L algoritmo di decompressione è stato ideato per ottimizzare più possibile il tempo di esecuzione. Uno dei colli di bottiglia in questa fase è la ricerca dei simboli negli alberi di Huffman. Questa viene quindi fatta riorganizzando l informazione dell al-

23 CAPITOLO 1. LA COMPRESSIONE 23 bero in una serie di tabelle. Per ogni tabella viene considerato un numero n di bit, ed una di queste viene definita come la prima a cui accedere. Letti n bit dal messaggio codificato, in ogni tabella si può trovare una coppia (carattere decodificato, bit utilizzati) indicante che un simbolo è univocabilmente determinabile da quel codice, e per la sua decodifica sono stati utilizzati un determinato numero di bit (nulla vieta che la codifica del carattere ne siano stati impiegati meno di n). Nel caso invece che i bit letti non siano sufficienti a determinare un simbolo, nella tabella si trova un puntatore ad un altra tabella che in modo analogo processerà gli n bit successivi. La convenienza di questo metodo sta nel fatto che i simboli a comparire più frequentemente sono proprio quelli con pochi bit, che saranno quindi rintracciabili con pochi accessi. Utilizzando altre tecniche, generalmente si può ottenere un livello di compressione molto migliore che con la metodologia sopra descritta. Tuttavia per la sua semplicità, rapidità di esecuzione e configurabilità questo rimane uno degli algoritmi di compressione universalmente più utilizzati e supportati Prediction by partial matching Come detto precedentemente, a seguito dell invenzione della compressione aritmetica uno dei passi più naturali per tentare di aumentare il livello di compressione ottenibile è tentare di considerare una distribuzione di probabilità data da un modello di ordine elevato. La raccolta dei dati necessari per una corretta modellazione sale tuttavia esponenzialmente con il crescere dell ordine, ed inoltre volendo realizzare un algoritmo che esegue la compressione in un unica passata sui dati, al momento di codificare i primi simboli spesso non si hanno a disposizione abbastanza informazioni per una buona stima delle probabilità. Per ovviare a questi problemi Cleary e Witten hanno proposto nel 1984 [CW84] un metodo basato sulle predizioni per corrispondenze parziali (prediction by partial matching, PPM). L algoritmo tiene conto di più modelli contemporaneamente fino ad un ordine massimo impostato al momento dell esecuzione. Al momento dell osservazione di un simbolo, tutte le frequenze vengono aggiornate; questo significa che nel modello di ordine n si deve tener conto che nel contesto degli n 1 caratteri precedenti è comparso un determinato carattere. Se a questo punto troviamo un determinato contesto comparso n volte a seguito del quale un determinato simbolo è comparso m volte, potremmo stimare la possibilità di riosservare questo simbolo in un uguale contesto con la quantità n/m. Al momento di codificare un carattere, l algoritmo cerca quindi una distribuzione di probabilità per questo simbolo. Come primo tentativo considera il contesto relativo al modello di ordine maggiore. Nel caso in cui il carattere che segue sia già stato visto in tale contesto, questo viene codificato con la probabilità data dal modello in considerazione. Altrimenti viene scritto un carattere speciale detto di fuga ed il sistema regredisce al modello di ordine minore. Questa operazione se necessario viene ripetuta fino ad arrivare al modello di ordine zero, dove il simbolo viene codificato

24 CAPITOLO 1. LA COMPRESSIONE 24 senza alcuna elaborazione. Per consentire la codifica deve essere allocata una determinata probabilità al simbolo di fuga, riducendo così quelle degli altri simboli. È difficile immaginare una soluzione puramente razionale a questo problema, in quanto si tratta di stimare con quanta facilità si può verificare un evento mai osservato prima. Per questo tale problema, detto anche della frequenza zero (zero frequency problem) viene affrontato solitamente in base ad una stima empirica o a risultati sperimentali. Cleary e Witten nel loro primo documento sul PPM dell 84 propongono due metodi: Chiamato c(ϕ) il numero di occorrenze di un generico carattere ϕ, p(ϕ) la probabilità allocata per questo evento, ɛ la possibilità del carattere di fuga, C il numero di volte in cui è comparso il contesto considerato e q il numero di caratteri mai comparsi in questo contesto, si può: 1. Imporre p(ϕ) = c(ϕ)/(c + 1). Si verifica che p(ɛ) = 1 (p(ϕ)) = 1/(1 + C) 2. Imporre p(ϕ) = (c(ϕ) 1)/C. Si trova che p(ɛ) = 1 (p(ϕ)) = q/c Entrambe queste due proposte si basano sull idea che la probabilità che in un determinato contesto compaia un simbolo nuovo è tanto più bassa quante più volte quel contesto è stato osservato. La stima più o meno accurata di ɛ incide notevolmente sulla compressione ottenuta dal metodo, in quanto soprattutto all inizio del messaggio tale carattere andrà codificato molto spesso. Numerosi sono stati gli studi tesi a migliorare questa tecnica, originariamente intesa unicamente per la compressione di testo ma in seguito utilizzata anche per dati generici. I principali miglioramenti consistono da un lato in una migliore stima del parametro ɛ, dall altro in una ottimizzazione delle risorse occupate da questo algoritmo. Si può osservare infatti che la raccolta di dati necessari a raggiungere un modello elevato richiede grandi quantità di memoria e di tempo; per questo le tecniche basate su PPM sono solitamente considerate molto efficaci ma computazionalmente impegnative. Tra le principali evoluzioni, particolarmente degne di nota sono [How93] e [Shk02], su cui sono basate numerose implementazioni dell algoritmo usate in molti programmi Burrows Wheeler transform Un altro algoritmo utilizzato per la compressione è la trasformazione di Burrows e Wheeler (Burrows Wheeler Transofrm, BWT). Tale operazione non comprime di per se i dati, anzi ne provoca una lieve espansione. Tuttavia se il messaggio in ingresso è strutturato, il risultato prodotto contiene lunghe sequenze di caratteri uguali consecutivi consentendo una buona compressione anche con tecniche molto semplici. Analizziamo innanzitutto il funzionamento dell algoritmo e come questo possa essere invertito; in seguito vedremo le motivazioni su perché e sotto quali ipotesi il risultato prodotto gode di particolari qualità. Per semplificare la spiegazione senza eccedere in tecnicismi, il testo sarà accompagnato da un esempio.

25 CAPITOLO 1. LA COMPRESSIONE 25 Consideriamo un blocco di testo di lunghezza n dal nostro messaggio in ingresso. Consideriamo come esempio la stringa ALASTARA. Per effettuare la BWT eseguiamo i seguenti passi: 1. Costruiamo la matrice virtuale formata dalle n rotazioni cicliche del blocco di dati in considerazione. Per virtuale si intende che in una implementazione reale non questa non verrà realmente creata, ma la sua esistenza sarà simulata come spiegato in seguito. La situazione iniziale dell esempio si può vedere nella figura 1.6 A L A S T A R A A A L A S T A R R A A L A S T A A R A A L A S T T A R A A L A S S T A R A A L A A S T A R A A L L A S T A R A A Figura 1.6: Configurazione iniziale della BWT 2. Ordiniamo lessicograficamente le stringhe nella matrice. Nella figura 1.7 si può vedere il risultato di questa operazione sulla stringa di esempio. A A L A S T A R A L A S T A R A A R A A L A S T A S T A R A A L L A S T A R A A R A A L A S T A S T A R A A L A T A R A A L A S Figura 1.7: BWT: Matrice delle rotazioni cicliche ordinate

26 CAPITOLO 1. LA COMPRESSIONE L output della BWT è formato dall ultima colonna della matrice e da un indice rappresentante la posizione della stringa originaria nella matrice, detto indice primario. In questo caso, il risultato è RATLAAAS ed il numero 1. A A L A S T A R A L A S T A R A A R A A L A S T A S T A R A A L L A S T A R A A R A A L A S T A S T A R A A L A T A R A A L A S Figura 1.8: Output della Burrows Wheeler transform Il tipo di dato restituito dalla BWT comprende quindi una permutazione dei dati originali ed un numero. Già nel nostro esempio si nota come tre delle quattro A presenti risultino consecutive nell output. Si noti che il costo per memorizzare la chiave primaria è pari alla parte intera superiore di log 2 n (nell esempio tre bit) e dunque considerando blocchi sufficientemente grandi questo può diventare, in proporzione al messaggio da comprimere, piccolo a piacere. Sarà esposto ora l algoritmo per l inversione della BWT. Chiamiamo il risultato della prima trasformazione L. 1. Come primo passo, ordinare i caratteri presenti in L. Considerando che la matrice utilizzata era stata ordinata, si verifica facilmente che con questa operazione se ne ottiene la prima colonna, che chiameremo F. Notare che L ed F sono entrambe permutazioni del messaggio iniziale. Nell esempio si ottiene la situazione in figura Costruiamo il vettore dei predecessori. Tale struttura contiene nella generica posizione i la posizione che il carattere i della stringa L ha assunto in F. Nel caso in cui lo stesso carattere compaia più volte, associamo l i-esima occorrenza di un determinato carattere in L con all i-esima occorrenza dello stesso carattere in F. Nell esempio, come si può vedere dall illustrazione 1.10, si ottiene il vettore [5, 0, 7, 4, 1, 2, 3, 6]. Ricordandosi che la matrice è formata da rotazioni cicliche della chiave, si può dimostrare che l i-esimo indice del vettore indica la posizione del carattere che precede l i-esimo simbolo di F nella sequenza iniziale. 3. Grazie alla conoscenza dell indice primario k, sappiamo che l ultimo carattere del messaggio è il k-esimo carattere di L. Grazie al vettore V costruito sopra,

27 CAPITOLO 1. LA COMPRESSIONE 27 F A A A A L R S T L R A T L A A A S Figura 1.9: Inversione della BWT: calcolo del vettore dei primi caratteri F L V A A R A 5 0 A A L R S T T L A A A S Figura 1.10: Calcolo del vettore dei predecessori nell inversione della BWT sappiamo che il suo predecessore è nella posizione V [k], ed il carattere che precede quest ultimo ha indice V [V [k]]. Iterando il procedimento, si ricostruisce facilmente l intero messaggio. Dati iniziali: V = [5, 0, 7, 4, 1, 2, 3, 6] L = [R, A, T, L, A, A, A, S] K = 1 Esecuzione dell algoritmo: M[7] = L[K] = L[1] = A M[6] = L[V[1]] = L[0] = R M[5] = L[V[0]] = L[5] = A M[4] = L[V[5]] = L[2] = T M[3] = L[V[2]] = L[7] = S M[2] = L[V[7]] = L[6] = A

28 CAPITOLO 1. LA COMPRESSIONE 28 Chiave primaria K = 1 L R A T L A A A S V Passo Posizione del carattere Figura 1.11: Ricostruzione finale del messaggio iniziale della BWT M[1] = L[V[6]] = L[3] = L M[0] = L[V[3]] = L[4] = A Risultato: M = [A, L, A, S, T, A, R, A] = "ALASTARA" L algoritmo di decompressione può essere reso molto semplice rappresentando F con un vettore di dimensione pari all alfabeto usato che conta le occorrenze cumulative di ogni simbolo. In altre parole, chiamando O tale vettore, poniamo nella posizione i + 1 il numero di volte che l i-esimo carattere dell alfabeto o uno che lo precede compare. Considerando d ora in poi il nostro alfabeto formato dai 256 valori possibili di un byte, in questo modo sappiamo che tutti i valori compresi tra F [O[i]] ed F [O[i + 1]] saranno uguali ad i (consideriamo O[0] = 0). Con questa rappresentazione si può verificare che l ordinamento richiesto al punto uno può essere eseguito con un unica passata sui dati, in modo analogo al procedimento del counting sort. Presupponendo che la variabile index sia inizializzata al valore della chiave primaria, l intero algoritmo di inversione della BWT può essere riassunto nel seguente codice: for (int i = 0; i < n; i++) { O[L[i] + 1] ++; } // Conteggio delle occorrenze for (int i = 1; i < 256; i++) { O[L[i]] += O[L[i - 1]]; } // Calcolo occorrenze cumulative for (int i = 0; i < n; i++) { V[i] = O[L[i]]; O[L[i]] ++; } // Calcolo del vettore dei predecessori for (int i = n - 1; i >= 0; i--)

29 CAPITOLO 1. LA COMPRESSIONE 29 { M[i] = L[index]; index = V[index]; } // Ricostruzione del messaggio Anche l operazione di trasformazione può essere ottimizzata. Uno dei primi accorgimenti da utilizzare consiste nel rappresentare le rotazioni circolari del messaggio ognuna con un indice che indica la posizione del suo carattere iniziale nel messaggio originale. A questo punto si procede con l ordinamento senza mai creare realmente la matrice, considerando che al momento di confrontare due indici sarà necessario considerare le corrispondenti rotazioni. Per effettuare efficientemente questa operazione, gli autori consigliano un algoritmo che combini attentamente radixsort e quicksort, suggerendo inoltre vari miglioramenti da adottare per sfruttare le peculiarità dei dati da ordinare. A questo punto, dobbiamo guardare al perché della maggiore comprimibilità del messaggio trasformato, e sotto quali condizioni questa è presente. Per farlo, consideriamo di eseguire l algoritmo per un blocco di dimensione n molto grande, come in pratica è necessario fare per ottenere buoni risultati. Pensiamo a cosa succede se una determinata sequenza compare molto spesso nel testo. In questo caso dopo l ordinamento avremo numerose stringhe consecutive che iniziano con tale sequenza, e molte altre che iniziano con il secondo carattere della sequenza considerata. In questo ultimo caso, considerando che l ultimo carattere di ogni rotazione è precedente al primo nel messaggio originale, in corrispondenza a queste serie la BWT darà in output lunghe sequenze consecutive del primo carattere della stringa. Per fare un esempio, considerando un blocco di testo inglese, troveremo numerose occorrenze della parola the. Dopo l ordinamento, ci saranno molte stringhe consecutive che iniziano con he. L output corrispondente sarà quindi ricco di lettere t consecutive. Ciò ci permette di arrivare alle ipotesi su cui si basa la BWT: questa è efficace nel caso in cui il contesto di un determinato simbolo predica con cura il simbolo stesso. Nel nostro esempio abbiamo raggiunto il risultato sperato perché ogni carattere diverso da A rappresenta una buona predizione per questa lettera. Per questo tale tecnica non differisce molto come presupposti da metodi come il PPM e, per blocchi abbastanza grandi che permettano di trovare consecutivamente nella matrice ordinata stringhe con prefissi uguali anche di molti caratteri, l effetto ottenuto dopo un apposita compressione è paragonabile a quello riscontrabile dopo una modellazione di ordine elevato. Per questo Burrows e Wheeler nel loro articolo affermano che la BWT permette di ottenere livelli di compressione molto vicini ai massimi raggiunti con tempi di esecuzione paragonabili invece alle tecniche più rapide. Dopo la BWT per una compressione ottimale occorre tuttavia selezionare una tecnica che sfrutti al meglio le caratteristiche che si sono create. Gli autori propongono un algoritmo di spostamento in testa (move to front, MTF) seguito da un codificatore aritmetico o un albero di Huffman. Il MTF funziona nel seguente modo: 1. All inizio dell algoritmo, un vettore di lunghezza pari all alfabeto viene inizializzato con i simboli utilizzati. Questo vettore deve rappresentare sempre una permutazione di tutti i caratteri. 2. Si leggono in serie i caratteri dell input. Per ognuno viene dato in output la

30 CAPITOLO 1. LA COMPRESSIONE 30 sua posizione nel vettore, e quindi tale simbolo viene rimosso e reinserito in testa alla struttura. Il codificatore MTF rappresenta con numeri poco elevati caratteri che si sono presentati recentemente; considerato quello che ci aspettiamo come output dalla trasformazione descritto sopra, avrà ottime probabilità di produrre una grande quantità di valori vicini allo zero, dando ottimo materiale al compressore che segue. Molti sono gli studi effettuati nei confronti della BWT. Alcuni dei miglioramenti proposti sono tesi a migliorare ulteriormente i tempi di esecuzione, in particolare l operazione di ordinamento. Altre proposte coinvolgono invece il tipo di algoritmi da applicare dopo la trasformazione, tra cui degli affinamenti del codificatore MTF e l aggiunta di alcune tecniche evolute dell RLE da applicare prima o dopo il codificatore MTF. Per citare uno degli ultimi lavori a nome di tutti si potrebbe nominare [Jue03], contenente tra l altro una panoramica delle principali pubblicazioni precedenti. Una delle implementazioni più note della compressione tramite BWT si chiama bzip2 ed è utilizzata da vari programmi di compressione come l ultima versione del celebre WinZip o il 7zip. 1.3 Formati compressi esistenti In questa sezione verranno descritti dei formati file compressi facenti uso delle tecniche esposte in precedenza. La prima sottosezione è dedicata a tre formati di utilizzo generico: lo zip, il rar ed il 7zip. Nella seconda si vedranno i due formati per immagini senza perdita attualmente più utilizzati in internet, il gif ed il png, analizzando come questi sfruttino le regolarità tipiche delle immagini. Infine verrà brevemente descritto l algoritmo di compressione usato nel jpeg; nonostante in questo caso si parli di compressione con perdita tale paragrafo è interessante sia per capire il funzionamento di questo formato così diffuso sia per introdurne un evoluzione, nominata jpeg2 o jpeg2000, che offre una modalità lossless e verrà utilizzata per confronto nella parte di questo lavoro dedicata alla sperimentazione Zip, rar e 7z Vediamo ora alcuni dei formati compressi esistenti e di quali tecniche essi facciano uso. I tipi di file descritti di seguito possono essere utilizzati per la compressione di qualsiasi tipo di dato; gli algoritmi utilizzati non hanno dunque a disposizione a priori alcuna informazione su eventuali caratteristiche particolari sull informazione da codificare. Lo zip è probabilmente il formato compresso più utilizzato. Basato su un evoluzione dell algoritmo LZW descritta precedentemente, le metodologie di compressione e decompressione e le specifiche di formato sono note permettendo una portabilità molto ampia e l utilizzo su diversi sistemi operativi e tramite vari programmi. Uno dei suoi vantaggi principali è la rapidità e la scarsa necessità di risorse per la codifica e la decodifica.

31 CAPITOLO 1. LA COMPRESSIONE 31 Un altro formato molto utilizzato è il rar, acronimo di Roshall ARchive, dal nome del creatore. L algoritmo per la compressione è proprietario, anche se è noto che l autore lo ha ottenuto applicando delle modifiche alla tecnica PPM. È invece di libera distribuzione il programma per la decompressione sotto forma di file eseguibili per diverse piattaforme o addirittura di codice sorgente, a patto che esso non venga sfruttato per la creazione di un compressore corrispondente; per questo motivo sebbene esista un solo programma per la creazione di file RAR, la loro decompressione è supportata da una varietà di applicazioni. Solitamente l interazione con file RAR è più lenta rispetto al formato ZIP, ma il livello di compressione è notevolmente migliore in particolare per file di tipo multimediale come immagini o file audio. Il formato 7z è meno noto ma ugualmente interessante. Creato dagli sviluppatori dell applicazione 7zip, il codice utilizzato per la sua gestione è interamente opensource e si basa sulle più moderne tecniche di compressione, tra cui BWT, PPMD, un implementazione del PPM di Shkarin proposta nel documento citato [Shk02], e sull LZA, un altra variante del noto LZW. Il programma offerto permette di utilizzare uno qualsiasi di questi tre metodi e di parametrizzare, oltre che il livello di compressione, la quantità di risorse messe a disposizione. Gli autori affermano che secondo i loro test il livello di compressione supera in modo rilevante altri formati come lo ZIP ed il RAR; a discapito di questo formato bisogna dire tuttavia che la sua gestione pare essere la più lenta delle tre qui descritte. Grazie alla sua natura di codice aperto, la gestione dei file 7z è supportata da diverse applicazioni per la compressione anche se sembra che la diffusione del formato sia molto scarsa GIF e PNG Uno dei formati più utilizzati tuttora in internet è il Graphics Interchange Format (GIF). Numerose sono le funzionalità offerte dal formato, tanto per nominarne alcune la possibilità di rappresentare animazioni, ottenuta memorizzando più immagini consecutive e definendo dei codici di controllo del flusso, e la capacità di visualizzare una versione di minore qualità dell immagine avendo a disposizione solo una parte iniziale del file. Formati con tale caratteristica sono detti streamable; solitamente questo effetto si può ottenere mettendo in testa al file un opportuno campione dei pixel a disposizione. Per la compressione di un immagine viene applicato il generico algoritmo LZW. Uno dei più grandi limiti del formato è il supporto di un massimo di 256 colori, definiti secondo una tavolozza all inizio del file. La compressione in un file gif è dunque senza perdita, ma nel caso in cui l immagine originaria contenga un numero maggiore di colori per la sua trasformazione in questo formato si dovrà effettuare innanzitutto una trasformazione lossy. Per minimizzare l errore percepito da un osservatore in questa fase viene spesso applicato un effetto detto di dithering, interessante nell ambito di come la perdita di dati in una trasformazione venga attenuata nei confronti della percezione umana. Il primo passo da eseguire è la selezione dei 256 colori da utilizzare. A questo punto, arrotondando il colore in ogni punto a quello più simile tra quelli disposizione, si rischia di creare un effetto di forte discontinuità in zone che nell immagine originarie presentavano invece sfumature morbide. Con il dithering, considerata una zona con un determinato colore, si cerca di simularne la percezione tramite l accostamento di

32 CAPITOLO 1. LA COMPRESSIONE 32 punti di colore diverso in proporzioni variabili. Differenti sfumature di arancione per esempio possono essere simulate tramite la vicinanza di punti gialli e rossi. L efficacia dell effetto creato diminuisce al crescere dalla varietà di colori dell immagine originale e migliora per immagini a alta risoluzione dove un pixel, essendo di piccole dimensioni, è difficilmente distinguibile al di fuori del proprio contesto. Ne vediamo un esempio in figura Immagine in 256 sfumature di grigio Immagine rappresentata con due soli colori grazie al dithering Figura 1.12: Esempio di dithering Per supplire alle carenze del formato GIF, la W3C ha sviluppato un nuovo formato immagine per le reti che sostituisse quello vecchio, detto Portable Network Graphics (PNG). Gli obiettivi principali del PNG erano la portabilità, il supporto di varie funzionalità quali la trasparenza e la streamability, la rappresentazione di immagini con un numero di colori fino a 2 24 ed una buona compressione. L approccio per quest ultima caratteristica è quello che più interessa nei confronti di questo lavoro; viene infatti un realizzato un modello di previsioni strutturato in modo diverso da quelli visti in precedenza. Prima di utilizzare un compressore per l immagine, questa viene sottoposta ad un filtro. Un filtro è una funzione che non varia le dimensioni del dato, ma sperabilmente ne cambia la distribuzione dei simboli rendendolo più facilmente comprimibile. Questo viene fatto grazie ad una stima del valore di un byte rappresentante un determinato punto (o uno dei suoi colori) basata sui byte rappresentanti i punti adiacenti. Tale quantità viene sottratta al valore del punto nell aritmetica modulo 256. In questo modo presumendo di fare delle previsioni che si avvicinino ai valori effettivi otterremo numerosi valori prossimi allo 0, rendendo il dato facilmente comprimibile. Per rendere possibile la ricostruzione dell immagine dopo tale elaborazione, è necessario tuttavia definire un ordinamento sui punti ed utilizzare per la previsione di un determinato valore solo quelli che lo precedono, in modo che un decodificatore possa scorrere i dati ordinatamente e disporre delle previsioni fatte al momento della codifica. I filtri del PNG considerano un punto precedente ad un altro se questo compare alla sua sinistra, al di sotto di esso o diagonalmente in basso e a sinistra. Definiamo x come il valore da stimare, a come il valore del punto immediatamente alla sua sinistra, b il punto immediatamente al di sotto e c il punto alla sinistra di b e sotto a. Detto f(x) il valore stimato, i filtri utilizzabili in un file PNG sono i seguenti; ognuno di loro sarà accompagnato da una breve motivazione.

33 CAPITOLO 1. LA COMPRESSIONE 33 A C X B Figura 1.13: Punti utilizzati nel filtraggio PNG 0. f(x) = 0 (nessun filtraggio) 1. f(x) = a 2. f(x) = b Questi due filtri sono adatti alle zone di colore abbastanza regolari dove il valore di un punto possa essere una buona stima del punto adiacente 3. f(x) = (a + b)/2 La divisione è intesa come divisione intera. I presupposti di questo filtro non differiscono molto dai precedenti; fare la media può tuttavia dare stime migliori in zone lievemente sfumate. 4. f(x) = P aethp redictor(a, b, c) dove la funzione PaethPredictor è definita dal seguente pseudo codice: p = a + b - c; pa = abs(p - a); pb = abs(p - b); pc = abs(p - c); if pa <= pb and pa <= pc then return pa else if pb <= pc then return pb else return pc; Il filtro di Paeth seleziona come stima il valore adiacente al punto che minimizza il gradiente dell immagine. In altre parole si seleziona il punto che meno si discosta da p, valore ottenibile usando come stima con un approssimazione lineare (graficamente, a, b, c e p sono complanari). Il codificatore utilizzato per creare il file PNG può selezionare uno qualsiasi dei filtri per tutta l immagine, oppure può procedere in modo adattivo variando il filtro applicato a seconda della zona dell immagine. Le informazioni sui filtri selezionati vanno codificate nel file PNG; una buona selezione dei filtri influenza notevolmente l efficacia della compressione. Dopo questa operazione, il dato risultante viene compresso tramite la libreria zlib descritta precedentemente. Il filtraggio è un buon esempio di come si possano sfruttare caratteristiche note del dato per ottenere una migliore compressione; i filtri utilizzati infatti si avvalgono di regolarità presenti in molte immagini e permettono di tenere in considerazione la correlazione fra i punti in entrambe le direzioni orizzontale o verticale. Grazie alle tecniche utilizzate risulta che un file PNG sia mediamente di un 15-20% più piccolo della stessa immagine codificata nel formato GIF.

34 CAPITOLO 1. LA COMPRESSIONE Jpeg e sue evoluzioni Il formato jpeg (joint photographic experts group) è forse il formato di più vasto utilizzo per la memorizzazione di immagini. La compressione utilizzata è lossy, e questo permette di ottenere file di dimensioni molto piccole rispetto all originale. La qualità visiva dell immagine ottenuta può essere regolata come desiderato permettendo livelli di compressione maggiori o minori. L algoritmo di codifica si basa sulla trasformata di Fourier, una formula matematica di vasto utilizzo in moltissimi campi. Normalmente, la trasformazione richiede una funzione in ingresso e produce un altra funzione come risultato; avendo a che fare con una sequenza di campioni, viene utilizzata una trasformata analoga nel discreto, detta trasformata discreta di Fourier (discrete Fourier transform, DFT) che trasforma un vettore o una matrice in un altra struttura di uguali dimensioni. Attraverso l applicazione diretta delle formule che esprimono la DFT, il tempo impiegato è proporzionale ad n 2. Fortunatamente, esiste un algoritmo detto trasformazione veloce di Fourier (fast Fourier transform, FFT) che opera con una complessità proporzionale ad n log n utilizzando un procedimento di tipo divide et impera. Per tutte le trasformazioni sopra citate esiste la relativa trasformazione inversa. La teoria riguardante tali operazioni è matematicamente complessa e la sua trattazione va al di là degli scopi di questa descrizione. È interessante vedere invece in che modo la FFT sia utile per la compressione. La trasformata discreta di Fourier gode di un interessante proprietà: se il vettore in ingresso contiene dati abbastanza regolari, numerosi coefficienti della trasformata saranno molto vicini a zero. Per dati regolari si deve intendere valori che assomigliano al campionamento di una funzione continua senza grandi oscillazioni. La compressione jpg dunque dà buoni risultati soprattutto per immagini senza grandi discontinuità o contorni netti, ed è da sconsigliare per soggetti con grandi contrasti contenenti per esempio scritte o grafici: in questo caso si avrà o una scarsa compressione o una notevole perdita di dati. L algoritmo di compressione jpeg in breve consiste nei seguenti passi: 1. Suddivisione dell immagine in quadrati di pixel 8 per 8, ed applicazione della trasformata discreta del coseno (discrete cosine transform, DCT). Tale operazione è del tutto analoga alla DFT e può essere calcolata in tempo proporzionale ad n log n in modo analogo alla FFT. 2. Quantizzazione: ogni coefficiente viene arrotondato ad un numero razionale. L output della DCT infatti dà come risultato una serie di numeri reali non rappresentabili su di un calcolatore con un numero finito di cifre. È in questa fase che avviene la perdita di dati irreversibile; se la DCT potesse essere calcolata in aritmetica esatta l applicazione della sua inversa ricostruirebbe esattamente i dati originali. La granularità della quantizzazione è variabile e determina la qualità e le dimensioni dell immagine compressa. Secondo le ipotesi di regolarità fatte, dopo questo passo otteniamo una matrice con numerosi valori uguali a zero. 3. Codifica: la matrice dei coefficienti quantizzati viene visitata in un ordine a zigzag che consente di incontrare con buona probabilità gli zeri consecutiva-

35 CAPITOLO 1. LA COMPRESSIONE 35 mente. I valori ottenuti vengono codificati o tramite RLE seguito da codifica di Huffman, o con codifica aritmetica. La compressione lossy permette anche con piccole perdite di dati grandi fattori di compressione, e ci si potrebbe chiedere dunque quale sia l effettiva utilità di una compressione senza perdita. Esistono tuttavia numerosi casi in cui è utile utilizzare metodi lossless come i seguenti per nominarne alcuni: - Casi in cui l immagine dovrà essere processata da un calcolatore. L errore introdotto infatti anche se impercettibile per la percezione umana potrebbe avere effetti indesiderati su di un calcolo automatico. - Nel caso in cui si debba comprimere e decomprimere un immagine più volte, per esempio per effettuarvi delle modifiche, l errore in una codifica lossy si propagherebbe ad ogni elaborazione degenerando rapidamente la qualità. - Immagini in cui la compressione con perdita è particolarmente inefficace, introducendo errori particolarmente indesiderati od ottenendo un basso fattore di compressione. Il gruppo del jpeg ha evoluto il formato in molte direzioni. È stata studiata una modalità del jpeg senza perdita (lossless jpeg) sviluppata ulteriormente nel formato JPEG-LS, dove si fa uso di un algoritmo di compressione lossless o quasi lossless, dove quest ultimo offre una perdita di dati molto limitata e controllabile dove l errore introdotto è relativo solo al bit meno significativo di ogni campione. In un altro ambito è stato creato il formato JBIG, utile per la codifica di immagini e due strati. Gli ultimi studi sono tesi tuttavia allo sviluppo del formato jpeg2000 creato per sostituire il vecchio standard. Il Jpeg2000 o jpeg2 è un ulteriore evoluzione nella compressione delle immagini. Si basa su di un meccanismo simile alla trasformata di Fourier, ma mentre questa utilizza come funzioni base le funzioni trigonometriche, il jpeg2 utilizza una base di funzioni adattive dette wavelets. Un altro grande cambiamento nell algoritmo è quello di elaborare l immagine in modo globale senza una suddivisione in zone come nel vecchio jpg. Con questo nuovo algoritmo la perdita di qualità è visivamente meno evidente di quella del vecchio jpeg e quando percepibile crea un effetto di sfocatura soprattutto nelle zone di maggiore discontinuità. Per il jpeg2000 sono stati sviluppati numerosi algoritmi per l inclusione di diverse funzionalità come la streamability, la possibilità di effettuare la compressione ad una specifica dimensione data, la definizione di una regione di interesse dove aumentare la qualità e la definizione di zone di trasparenza. Cosa più interessante nei confronti di questo lavoro, il jpeg 2000 comprende una modalità di compressione senza perdita di dati. Questo formato pare avere tutte le caratteristiche per imporsi per molti utilizzi, e per quanto riguarda la compressione a parità di qualità i file jp2 sono mediamente il 15% più piccoli dei file jpg. La diffusione di questo formato tuttavia è tuttora scarsissima, forse perché il suo utilizzo non è del tutto libero ma è regolato da una serie di licenze e proprietà intellettuali.

36 Capitolo 2 Il formato file 2.1 Funzionamento dell algoritmo In questa sezione verrà descritto il funzionamento dell algoritmo di compressione proposto; i particolari su come gli oggetti in cui viene scomposta l immagine vengano codificati efficientemente verranno descritti in seguito. La descrizione inizierà con una panoramica in modo da dare un idea globale della tecnica utilizzata; in seguito verrà data invece una visione schematica e particolareggiata di tutte le operazioni eseguite. Un esempio completo dell esecuzione dell algoritmo è riportato in appendice a pagina Panoramica dell algoritmo Questo paragrafo si occupa di mostrare il funzionamento globale dell algoritmo di compressione in modo da permetterne una visione di insieme prima di affrontarne una specifica formale. L algoritmo proposto fa uso di diverse tecniche di cui alcune, come il filtraggio o l utilizzo di RLE ed alberi di Huffman, sono state riprese e riadattate da algoritmi esistenti ed altre, come il filtraggio per colore, la scomposizione in strati e l uso di poliomini, sono state sviluppate in questo stesso lavoro. L algoritmo di compressione sviluppato ha come dominio immagini rappresentate con 24 bit per pixel, di cui otto per ognuno dei colori primari blu, verde e rosso. Di seguito tali informazioni saranno viste come una matrice di byte a tre dimensioni di cui due rappresentano la larghezza e l altezza della griglia dei campioni ed la terzo il colore primario di riferimento. Gli indici della matrice sono ordinati dal punto dell immagine visivamente in basso a sinistra a quello in alto a destra; per quanto riguarda i colori i valori 0, 1 e 2 saranno associati rispettivamente al blu, al verde ed al rosso. L algoritmo consiste principalmente in tre fasi: filtraggio, scomposizione e compressione. Nelle prime due il dato in ingresso non varia di dimensioni ma viene riorganizzato in modo conveniente per poter essere maggiormente ridotto durante l ultima fase. Analogamente, per effettuare la decompressione si procederà con le tre fasi di decompressione, ricostruzione ed antifiltraggio. 36

37 CAPITOLO 2. IL FORMATO FILE 37 Immagine sorgente Filtraggio Scomposizione Compressione Immagine compressa Figura 2.1: Fasi della compressione Immagine compressa Decompressione Ricostruzione Rimozione dei filtri Immagine sorgente Figura 2.2: Fasi della decompressione Nella fase di filtraggio i valori della matrice vengono cambiati per ottenere una distribuzione migliore. In particolare, si cerca di ottenere numerose occorrenze di numeri piccoli ed un numero ridotto di valori elevati; in fase di compressione i primi avranno infatti un costo di memorizzazione minore. Questa fase è divisa in tre parti: 1. Filtraggio standard: viene effettuata una previsione del valore di ogni punto basata sui byte precedenti rappresentanti lo stesso colore. Un byte si dice precedente ad un altro se è su di una colonna di indice minore o se è sulla stessa colonna ma su di una riga di indice minore. Le funzioni di previsioni utilizzate si basano su regolarità presenti in molte immagini, e saranno descritte nel prossimo capitolo. Al posto di ogni valore viene sostituita la differenza modulo 256 con la sua stima. 2. Filtraggio fra colori: viene effettuata un ulteriore previsione del valore di ogni punto basata sui byte rappresentanti colori precedenti nell ordine blu, verde e rosso. Questa operazione si avvale del fatto che dopo il primo passo di filtraggio i valori lontani dallo zero modulo 256 corrispondono ai cambiamenti di tonalità maggiori nell immagine, e che solitamente tali variazioni si riflettono su più colori. Di nuovo, ad ogni valore viene sostituita la sua differenza modulo 256 dal valore stimato. 3. Riassegnazione: Ogni valore ottenuto viene sostituito ad un altro secondo una permutazione definita sui 256 valori possibili. Questo è utile per assicurarsi che i valori più frequenti siano i numeri più piccoli. Fase di filtraggio Immagine sorgente Determinazione e applicazione filtri Determinazione e applicazione filtri per colore Riassegnazione dei valori Immagine filtrata Figura 2.3: Fase di filtraggio

38 CAPITOLO 2. IL FORMATO FILE 38 Dopo questa fase ci si aspetta di ottenere nella matrice valori alti per punti che rappresentano un irregolarità difficilmente prevedibile, come accade per esempio nei contorni, e numeri bassi per zone di colore uniforme o sufficientemente continuo. Nella seconda fase la matrice viene scomposta in 24 matrici di uguale larghezza ed altezza ma contenente singoli bit, dette anche strati. Ognuna di queste matrici sarà relativa ad un bit in una determinata posizione nella rappresentazione dei byte e ad un determinato colore. Una ad esempio conterrà i bit meno significativi dei valori rappresentanti il colore blu ed un altra conterrà i più significativi dei byte corrispondenti al rosso. Dopo un accurata operazione di filtraggio, gli strati conterranno dati in buona approssimazione indipendenti fra loro, permettendo una buona compressione anche elaborati indipendentemente uno dall altro. Questa suddivisione è necessaria per applicare gli algoritmi di compressione descritti di seguito, ed è inoltre un interessante operazione di scomposizione in quanto permette la separazione di parti del dato più o meno caotiche e l applicazione di modelli di compressione differenti a strati con diverse caratteristiche. Fase di scomposizione Immagine filtrata Scomposizione dell immagine in 24 strati monodimensionali Ventiquattro strati Figura 2.4: Fase di scomposizione Infine, ad ogni strato viene applicata una funzione di compressione. Opzionalmente, per ognuno di essi, è possibile specificare uno strato base e codificare soltanto le differenze che distinguono i due. Come detto sopra tuttavia un buon filtraggio rende la correlazione tra strati molto bassa e questa operazione diventa quindi di scarsa efficienza se non addirittura dannosa per la compressione; è preferibile dunque tralasciarla, guadagnando così tempo in fase di compressione e decompressione. Questa possibilità, sviluppata in una delle prime versioni dell algoritmo, viene tuttavia lasciata a disposizione nel formato come funzionalità aggiuntiva. A questo punto ad ogni strato viene applicata una delle seguenti funzioni di compressione: 1. Compressione tramite poliomini: questa è una delle parti più innovative di tutto il processo. In questa fase i punti della matrice uguali ad uno vengono raggruppati in un insieme di poliomini convessi orizzontalmente e verticalmente; si dice poliomino un insieme discreto di punti connessi fra loro, e la condizione di convessità è verificata se per ogni riga ed ogni colonna è presente un unica sequenza di punti consecutivi. Una definizione formale di poliomino sarà data in seguito nella trattazione della loro codifica. Questo algoritmo permette di

39 CAPITOLO 2. IL FORMATO FILE 39 codificare efficientemente gruppi di punti contigui fra loro, senza perdere efficienza nel caso di punti sparsi. Questa tecnica è conveniente quando utilizzata per gli strati relativi ai bit più significativi dove è maggiormente probabile che valori vicini nella matrice filtrata siano rappresentati da punti di valore uno adiacenti nello strato; in altre parole ci si avvale del fatto che irregolarità nell immagine come bordi o zone con rapidi cambiamenti di tonalità sono solitamente rappresentate da più punti vicini o adiacenti tra loro. La codifica dei poliomini viene fatta con un algoritmo che ricorda il Run Length Encoding ma che permette di sfruttare la natura bidimensionale del dato guadagnando così in efficienza. 2. Compressione tramite RLE ed alberi di Huffman: tecnica che dà buoni risultati quasi in ogni caso, anche se non efficace come la precedente in caso di dati meno caotici. I punti della matrice vengono scorsi sequenzialmente e le sequenze di zeri e di uno consecutivi vengono codificate tramite un albero di Huffman. Per sfruttare la correlazione dei dati in entrambe le direzioni, è possibile definire un ordine di visita a zigzag per ottenere sequenze di simboli uguali più lunghe che consentono la codifica con un numero minore di simboli. 3. Codifica senza elaborazione: lo strato viene codificato così come è senza alcuna compressione. Questo può essere necessario per matrici particolarmente caotiche dove non è possibile ridurre l informazione in ingresso. In tali casi infatti un tentativo di compressione può causare addirittura l aumento di dimensione del dato; il fatto di aver isolato dal resto dell immagine una parte incomprimibile permette dunque una maggiore compressione della parte restante. La mancanza di particolari elaborazioni inoltre rende estremamente rapida la codifica e la decodifica di queste parti del dato in ingresso. Fase di compressione Fase di compressione Compressione tramite poliomini Ventiquattro strati monodimensionali Scelta dei metodi di compressione Compressione tramite RLE ed alberi di Huffman Immagine compressa Scrittura dello strato senza compressione Figura 2.5: Fase di compressione degli strati

40 CAPITOLO 2. IL FORMATO FILE Descrizione dei filtri utilizzati Di seguito si vedrà la definizione dei filtri utilizzati con un breve commento per giustificarne il funzionamento secondo le ipotesi di continuità considerate o per esprimerne i contesti di maggiore efficacia. Ad ognuno di loro viene assegnato un numero che verrà utilizzato per la loro identificazione in fase di codifica. La numerazione non è casuale; si è cercato di assegnare i primi valori ai filtri solitamente più utilizzati poiché sarà possibile specificare in fase di codifica che solo quelli fino ad un determinato numero sono stati impiegati risparmiando sui loro costi di memorizzazione. Viene definita qua un ampia varietà di funzioni; quali e quante utilizzarne è una scelta che spetta al codificatore. I punti utilizzati per la previsione di un pixel x sono a, il punto alla sua sinistra, b, il punto immediatamente al di sotto, c, il punto diagonalmente in basso a sinistra e d, il punto in alto a sinistra rispetto al punto da stimare. Il risultato della previsione è indicato con f(x); tutte le divisioni effettuate sono intese come divisioni intere. D A C X B Figura 2.6: Punti utilizzati per il filtraggio 1. f(x) = 0 Nessun filtro viene applicato; utile per zone molto caotiche. 2. f(x) = a 4. f(x) = b 5. f(x) = c 7. f(x) = d Uno dei punti adiacenti viene utilizzato come stima. Utile per zone abbastanza regolari dove punti vicini hanno valore simile; ognuno di questi può essere conveniente nei casi, rispettivamente, dove la correlazione sia più forte in orizzontale, verticale o in una delle due direzioni diagonali. 8. f(x) = a + (b c)/2 9. f(x) = b + (a c)/2 Il punto inferiore o sinistro viene utilizzato come stima di base; a questo valore si somma una valutazione della variazione dell immagine proporzionale a quella presente nei punti vicini. 3. f(x) = (a + b)/2 10. f(x) = (a + b + c + d + 1)/4

41 CAPITOLO 2. IL FORMATO FILE f(x) = (a + d)/2 Per valutare la previsione viene fatta una media di due o di tutti e quattro i punti adiacenti. Tali funzioni sono utili soprattutto in parti di immagine sfumate o con piccole variazioni. La somma di uno nel filtro numero 10 rappresenta un efficiente arrotondamento per difetto. 6. f(x) = a + b c se 0 a + b c < 256 f(x) = 0 se a + b c < 0 f(x) = 255 se a + b c > 255 Filtro lineare; viene utilizzata come stima il valore geometricamente complanare ai tre punti utilizzati. La stima viene limitata all interno del dominio dei valori possibili. 12. f(x) è il filtro di Paeth, definito dal seguente pseudo codice: p = a + b - c; pa = abs(p - a); pb = abs(p - b); pc = abs(p - c); if pa <= pb and pa <= pc then f(x) = a else if pb <= pc then f(x) = b else return f(x) = c; Il filtro di Paeth seleziona il punto adiacente che minimizza il gradiente dell immagine nel punto, cioè quello che si avvicina maggiormente al valore p corrispondente al filtro lineare. Utile soprattutto per zone con blocchi di colore uniforme. 0. f(x) definita dal seguente algoritmo: Se c è compreso tra a e b, f(x) è uguale al filtro lineare altrimenti f(x) è uguale al filtro di Paeth Tale filtro è un ottimo compromesso tra il filtro lineare ed il filtro di Paeth. Innanzitutto valuta se il punto in basso a sinistra è minore di a e b; in questo caso stima che l immagine sta crescendo in intensità di colore, ed utilizza come stima il maggiore tra a e b. Analogamente se c è maggiore degli altri due punti, probabilmente i valori stanno descrescendo ed il numero minore dei tre sarà preso come stima. Infine se il punto c è compreso tra a e b si presume che l immagine nella zona interessata sia abbastanza stabile e viene applicato il filtro lineare. Questo filtro combina bene le capacità di adattarsi a grandi variazioni e di dare buone stime in zone invece più regolari e per questo ha un buon comportamento in numerosi contesti. Nel caso in cui una funzione filtro faccia riferimento a dei punti non disponibili perché alle estremità dell immagine, la funzione f(x) viene sostituita dalla seguente: f(x) = a se disponibile, altrimenti f(x) = b se disponibile, altrimenti

42 CAPITOLO 2. IL FORMATO FILE 42 f(x) = 0 Dopo l applicazione dei filtri vengono utilizzati i filtri per colore. Tali funzioni effettuano una stima del valore di ogni byte basandosi sui valori degli altri colori relativi allo stesso punto. Si dica p[0] il byte relativo al blu, p[1] quello relativo al verde, p[2] quello relativo al rosso e p[x] il punto da stimare. Le tre funzioni utilizzate sono: 1. f(p[x]) = 0 0. se x = 0 allora f(p[x]) = 0, altrimenti f(p[x]) = f(p[x 1]) 2. se x = 0 allora f(p[x]) = 0, altrimenti f(p[x]) = f(p[0]) I filtri uno e due si basano sul fatto che dopo la prima operazione di filtraggio si ottengono spesso valori simili per byte relativi allo stesso pixel; questo deriva dal fatto che variazioni di tonalità nell immagine che producono valori più alti dopo il filtraggio spesso si riflettono su più colori contemporaneamente. Quanto detto per la numerazione dei filtri vale anche per i filtri per colore Schema di funzionamento Verrà descritto ora in modo accurato l intero schema di funzionamento dell algoritmo di compressione e di decompressione, suddivisibile concettualmente nei seguenti passi. L implementazione potrà essere realizzata anche effettuando più fasi contemporaneamente per esempio per motivi di efficienza a patto di ottenere un risultato equivalente. Tutte le operazioni necessarie per la codifica dei vari dati citati saranno invece descritte in seguito. Per la compressione si dovranno eseguire i seguenti passi, riassunti in figura 2.7. Filtraggio: l immagine viene suddivisa in zone quadrate di n pixel di lato, con n determinato dall algoritmo di compressione e multiplo di due; ad ogni zona potrà essere applicata una funzione filtro diversa. L immagine viene quindi scorsa a partire dal punto di indice di riga e di colonna maggiore prima decrescendo l indice di riga, e appena questo raggiunge lo zero riportandola al valore massimo e diminuendo di uno l indice di colonna. Per quanto riguarda i colori l ordine di scorrimento è chiaramente irrilevante. Ad ogni punto viene sostituita la sua differenza modulo 256 dal valore stimato dalla funzione filtro relativa alla zona a cui appartiene il pixel in questione. Filtraggio per colori: l immagine viene suddivisa in zone quadrate di n pixel per lato, con n determinato dal compressore, multiplo di due e non necessariamente uguale ad n. L immagine viene scorsa in un qualsiasi ordine che faccia precedere ad ogni valore rappresentante un colore primario di un punto i valori rappresentanti i colori successivi nell ordine blu, verde e rosso. Ad ogni byte viene sottratta modulo 256 il valore della previsione fatta in quel punto con la funzione associata alla zona interessata. Riassegnazione: il compressore genera un vettore di 256 elementi contenente una permutazione dei valori da 0 a 255. Ad ogni valore i dell immagine viene sostituito il numero contenuto nel vettore alla posizione i.

43 CAPITOLO 2. IL FORMATO FILE 43 Le informazioni sulle dimensioni delle zone, sui filtri utilizzati e sul vettore di riassegnazione verranno codificate nell intestazione del file come descritto in seguito. Il prossimo passo da eseguire è quello della scomposizione: La matrice rimanente viene scomposta in 24 matrici distinte contenenti valori binari. La matrice n conterrà il bit meno significativo di ordine n/3 relativo al colore n modulo 3. Chiaramente gli indici di riga e di colonna delle matrici ottenute saranno corrispondenti a quelli della matrice iniziale. Confronto tra strati, opzionale: si può procedere in due modi. Il primo consiste nello scegliere uno strato precedente e sostituire ad ogni punto della matrice il risultato dello xor (l or esclusivo, espresso in tabella 2.1) con il corrispondente dell altro strato. Nel secondo si suddivide lo strato in quadrati di 16 per 16 punti e per ognuna di queste zone si seleziona uno dei sette strati precedenti da utilizzare per il confronto; analogamente alla prima opzione, ogni punto viene messo in xor con il corrispettivo della matrice selezionata per la zona di appartenenza. Scelta di un metodo di compressione: per ogni strato viene selezionata una modalità di compressione fra le tre a disposizione: compressione tramite poliomini, compressione tramite RLE e alberi di Huffman, scrittura senza elaborazione. A B A xor B Tabella 2.1: Tabella di verità dello xor Analogamente alle informazione sui filtri, i dati sul confronto fra strati effettuato e sull algoritmo di compressione scelto verranno codificati nell intestazione di ogni strato. Codifica tramite poliomini: i punti uguali ad uno nella matrice vengono raggruppati in una serie di poliomini convessi orizzontalmente e verticalmente; nel file ogni poliomino viene codificato come un numero rappresentante la sua posizione, una coppia rappresentante le sue dimensioni ed una serie di interi specificanti la sua forma. Le posizioni di ogni poliomino vengono espresse come distanze dall ultimo incontrato, dove una distanza è quantificata con il numero di punti incontrati scorrendo l immagine da sinistra a destra e al raggiungimento dal valore massimo delle ordinate passando al primo punto della riga successiva. A queste quantità viene sottratto il numero di punti incontrati di cui si conosce già il valore grazie ad informazioni date da altri poliomini; una definizione formale di tali informazioni sarà data nel capitolo riguardante la codifica di strati tramite poliomini. Le distanze e le dimensioni dei poliomini vengono codificate tramite due diversi alberi di Huffman che verranno codificati in testa allo strato compresso.

44 CAPITOLO 2. IL FORMATO FILE 44 Codifica tramite RLE ed alberi di Huffman: innanzitutto deve essere determinato un ordine di visita tra i due a disposizione. Il primo consiste semplicemente nello scorrere l immagine da sinistra a destra e dal basso all alto. Il secondo si divide in quattro passi, di cui al primo si va di un punto verso l alto, al secondo ed al quarto di un punto a destra ed al terzo di un punto verso il basso; in questo modo si scorrono due righe alla volta, ed appena l indice di colonna raggiunge il massimo si ripete l operazione per le due righe successive. Durante la visita dell immagine si contano le occorrenze consecutive di zeri o di uno incontrati, e si raggruppano in una serie di coppie di interi ognuna contenente due lunghezze una di una sequenza di zeri e l altra di una sequenza di uno. I numeri ottenuti vengono codificati con un albero di Huffman, che verrà memorizzato in testa allo strato. Codifica senza elaborazione: Lo strato viene scorso dal punto in basso a sinistra al punto in alto a destra, prima per righe e poi per colonne. Ogni bit incontrato viene scritto in output senza alcuna ulteriore elaborazione. Verrà ora formalmente descritto il simmetrico algoritmo di decodifica, riassunto in figura 2.8; il primo passo consiste nella decompressione degli strati, che a seconda del tipo di strato corrisponde ad uno dei seguenti: Decompressione da uno strato compresso tramite poliomini: innanzitutto vengono letti i due alberi di Huffman relativi alle distanze ed alle dimensioni, e viene creata una matrice di bit contenente solo zeri. Dal file compresso vengono letti alternativamente una distanza ed un poliomino; quest ultimo viene inserito nella matrice nel punto di indirizzo determinato dalla distanza letta. Come in fase di compressione, la distanza è relativa al poliomino precedente e tiene conto solo dei punti di cui non conosciamo il valore. La decompressione termina quando la matrice destinazione è stata scorsa completamente. Decompressione di uno strato compresso tramite RLE ed alberi di Huffman: al primo passo viene letto il tipo di ordine di visita utilizzato, codificato nell intestazione, e l albero di Huffman, e viene creata una matrice di soli zeri delle opportune dimensioni. Quindi si utilizza l albero per leggere dal flusso di bit compressi le sequenze di zeri e di uno; con tali informazioni si scorre la matrice e si ricostruisce il valore iniziale di ogni bit. Lettura di uno strato scritto senza elaborazione: il file compresso viene letto bit a bit e tali valori vengono inseriti nella matrice destinazione dal punto in basso a sinistra a quello in alto a destra procedendo prima per righe e poi per colonne. Se effettuata in fase di compressione, a questo punto sarà necessario effettuare l operazione inversa del confronto fra strati: Ogni punto viene messo in or esclusivo con il punto corrispondente di uno strato precedente. Le informazioni su quali strati devono venir utilizzati per quali punti devono venir lette dall intestazione dello strato; per il resto questa operazione è identica a quella fatta in fase di compressione, visto che una

45 CAPITOLO 2. IL FORMATO FILE 45 Immagine sorgente Determinazione e applicazione filtri Determinazione e applicazione filtri per colore Riassegnazione dei valori Fase di filtraggio Scomposizione dell immagine in 24 strati monodimensionali Fase di scomposizione Compressione tramite poliomini Scelta dei metodi di compressione Compressione tramite RLE ed alberi di Huffman Fase di compressione Scrittura dello strato senza compressione Immagine compressa Figura 2.7: Schema del meccanismo di compressione doppia applicazione dell operatore xor con lo stesso argomento restituisce il valore iniziale. A questo punto deve venir ricostruita la matrice a tre dimensioni rappresentante l immagine filtrata: Ricostruzione: ogni valore con determinati indici di riga e di colonna delle

46 CAPITOLO 2. IL FORMATO FILE 46 matrici di bit viene utilizzato per ricostruire i corrispondenti tre byte rappresentanti il pixel corrispondente. Infine, nella fase di antifiltraggio vengono rimossi i filtri applicati all immagine: Inversione della riassegnazione: il vettore di permutazione viene letto dall intestazione del file, e viene utilizzato per invertire l operazione di riassegnazione. Per fare questo ad ogni valore dell immagine i viene sostituito l indice rappresentante la posizione che il valore i assume nel vettore. Rimozione del filtro di colore: ad ogni punto viene sommata modulo 256 la previsione fatta per tale punto dalla funzione di filtraggio per colore. Per disporre delle previsioni fatte in fase di codifica, per ogni pixel deve essere essere visitato prima il colore blu, quindi il verde e poi il rosso. Le informazioni sulle funzioni filtro utilizzate e le zone a cui esse si riferiscono devono venir lette dall intestazione del file. Rimozione dei filtri: ad ogni punto viene sommata modulo 256 la previsione fatta per tale punto dalla funzione filtro relativa a quella zona. Come sopra, le funzioni utilizzate per ogni zona sono specificate nel file. Per effettuare la stessa previsione fatta in fase di filtraggio è necessario visitare l immagine dal basso in alto e da sinistra a destra, procedendo prima per colonne e poi per righe. 2.2 Uso di matrici di bit In questa sezione si descriverà come vengono gestite le matrici di singoli bit utilizzate dall algoritmo per molteplici scopi. Se ne definirà una rappresentazione a byte da utilizzare per la memorizzazione e la lettura su flussi di input ed output, e saranno descritte una serie di codifiche per numeri interi ognuna ottimizzata per un determinato contesto Rappresentazione e codifica a formato fisso Durante l algoritmo di compressione si avrà a che fare con delle strutture dati che concettualmente devono gestire e contenere valori binari. Queste da un lato sono le matrici binarie utilizzate per la rappresentazione degli strati; d altro lato la gestione a singoli bit è necessaria per la lettura e la scrittura del file compresso. Entrambe queste casistiche vengono trattate con lo stesso approccio; l unica differenza consiste nel fatto che nel secondo caso l elaborazione dei dati sarà sempre sequenziale mentre nel primo ogni lettura o scrittura sarà associata ad una determinata posizione rappresentata con una coppia di indici. L architettura di un elaboratore solitamente non permette di gestire direttamente singoli bit. Per questo ad ogni vettore di bit utilizzato verrà associato un relativo vettore di byte. La corrispondenza viene realizzata nel seguente modo: un bit in posizione n nella prima struttura viene associato al bit di posizione n modulo 8 del byte n/8 della seconda. Si dice che un bit è in posizione k di un byte se è il k-esimo

47 CAPITOLO 2. IL FORMATO FILE 47 Immagine compressa Decompressione strato compresso tramite poliomini Lettura del tipo di strato Decompressione strato compresso tramite RLE ed H. Fase di decompressione Lettura strato non compresso Ricostruzione dell immagine dai 24 strati Fase di ricostruzione Riassegnazione inversa Rimozione filtri per colore Rimozione filtri standard Fase di antifiltraggio Immagine sorgente Figura 2.8: Schema del meccanismo di decompressione bit meno significativo. Tale definizione si estende facilmente per matrici di bit; considerando di voler accedere al bit di indici di colonna e di riga x ed y in una matrice di larghezza l, si calcola il valore n come y l+x e si procede come nel caso precedente. Uno dei metodi di codifica più semplici utilizzati nel file è quella a formato fisso.

48 CAPITOLO 2. IL FORMATO FILE 48 Vettore di bit Vettore di byte Tabella 2.2: Corrispondenza fra matrici di bit e di byte In tale caso un operazione di scrittura dovrà specificare due interi, uno rappresentante la quantità da scrivere e l altro il numero di bit da utilizzare; l operazione di lettura richiederà il secondo di questi valori. Considerando la rappresentrazione binaria senza segno del numero specificato, i bit vengono scritti dal meno significativo al più significativo. Essendo questo metodo utilizzato per la scrittura sequenziale, la scrittura di ogni bit sul vettore destinazione viene fatta nell indice successivo a quello dell ultimo bit immesso; la lettura avviene ovviamente in modo del tutto simmetrico. La scrittura di singoli bit è un semplice sottocaso di quanto descritto sopra dove viene codificato un unico valore binario. Valore Numero di bit Bit scritti Matrice di bit Tabella 2.3: Risultato di alcun scritture a formato fisso Codifica in domini finiti La codifica in un dominio finito viene utilizzata per ottimizzare la scrittura di interi che possono assumere solo un determinato numero di valori consecutivi. Tale metodo presuppone di non aver a disposizione nessuna informazione sulla distribuzione di probabilità, ed è teso semplicemente a risparmiare, dove possibile, qualche bit rispetto alla codifica a formato fisso. Si descriverà ora come questa codifica venga utilizzata quando dobbiamo scrivere un valore che in fase di decodifica sapremo maggiore o uguale a 0 e minore di un intero k. La scrittura richiede due valori in ingresso, di cui il primo è il numero da codificare n ed il secondo è la cardinalità del dominio k. Il numero di bit utilizzati sarà uguale alla parte intera inferiore o superiore del logaritmo in base due di k. L algoritmo innanzitutto scrive un numero di bit pari alla prima di queste quantità a partire dal meno significativo della rappresentazione binaria di n, rappresentandone così un numero minore o uguale. L ultimo eventuale bit viene scritto soltanto se il valore rappresentato dai bit già scritti concatenato con il bit uno genera un numero minore di k. In altre parole nei casi in cui la lettura degli n 1 bit meno significativi del valore da scrivere permettono di sapere che per essere compreso nel campo specificato questo deve avere l ultimo bit necessariamente pari a zero, quest ultimo

49 CAPITOLO 2. IL FORMATO FILE 49 bit viene omesso. La decodifica richiede il valore di k e procede in modo analogo, arrestando la lettura appena il valore in ingresso può essere determinato. Codifica nel dominio [0, 6[ Valore Codifica Tabella 2.4: Codifica nel dominio finito [0, 6[ In questa codifica ci sono due casi particolari. Nel primo k è una potenza di due, ed il risultato è uguale a quello di una codifica a formato fisso. Nel secondo k è uguale ed uno; in questo caso limite l unico valore possibile da codificare è lo zero, che quindi verrà codificato senza scrivere nessun bit. La tecnica descritta sopra viene anche utilizzata per codificare interi n in domini compresi tra i due valori k e k. In questo caso viene applicato lo stesso algoritmo con argomenti k = k k ed n = n k in fase di scrittura; durante la lettura sarà sufficiente sommare k al valore letto per riottenere il numero decodificato. Si riconduce a questo algoritmo la codifica di vettori in domini finiti. In questo caso l obiettivo è di codificare un vettore di interi [a 0... a l ] dato un altro vettore [m 0... m l ] tale che in fase di decodifica sapremo che ogni a i è maggiore o uguale a zero e minore di m i. In quasto caso si impone n = l a i i 1 i=0 j=0 (m j ) k = l i=0 È facilmente verificabile che si può ricostruire il vettore a dato il vettore m tramite la formula j=0 m i i 1 a i = (n/ m j ) mod m i dove la divisione è intesa come intera ed il simbolo mod rappresenta l operazione di modulo. I valori n e k vengono scritti e letti con il solito algoritmo di codifica in un dominio finito; l operazione di lettura dovrà specificare il vettore m e restituirà i valori del vettore a.

50 CAPITOLO 2. IL FORMATO FILE 50 Codifica di un vettore con limiti (2,3,2) Equivalente alla codifica nel dominio [0,12[ Vettore Numero associato Codifica [0,0,0] [1,0,0] [0,1,0] [1,1,0] [0,2,0] [1,2,0] [0,0,1] [1,0,1] [0,1,1] [1,1,1] [0,2,1] [1,2,1] Tabella 2.5: Codifica di vettori con limiti (2,3,2) Codifica a formato variabile La codifica a formato variabile è stata ideata per la scrittura di valori interi non limitati in uno specifico campo e con probabilità di comparire decrescente al salire della grandezza dei numeri. Verrà utilizzato un algoritmo che assegna pochi bit per la codifica dei valori vicini allo zero ed un numero maggiore ai numeri più alti. Con questa tecnica non si raggiunge l ottimalità raggiungibile per esempio con alberi di Huffman, ma si utilizza un algoritmo rapido per ottenerne un approssimazione secondo le ipotesi date; questo è utile nel caso in cui debbano venir codificati numerosi valori che compaiono soltanto una volta nel messaggio, rendendo l albero di Huffman molto grande e di conseguenza lento da gestire e pesante da memorizzare. L univoca decodificabilità è facilmente verificabile sia grazie all algoritmo di lettura sia sfruttando la proprietà del prefisso, rispettata da questa tecnica. L algoritmo di scrittura richiede due interi, un numero n da codificare ed una quantità k chiamata numero di bit di base, ed è espresso nei seguenti passi: 1. Si inizializza un valore b = k 2. Finché n 2 b, si impone n = n 2 b e quindi b = b Vengono scritti in output b k bit di valore 1 seguiti da uno zero 4. Viene scritto in output il numero n a formato fisso con b bit L algoritmo di lettura deve avere k a disposizione, e consiste nei seguenti passi: 1. Si inizializza b = k e n = 0 2. Finché il bit letto in ingresso è 1 si impone n = n + 2 b e quindi b = b Ad n viene sommato il valore letto a formato fisso con b bit

51 CAPITOLO 2. IL FORMATO FILE 51 Questo algoritmo di codifica può essere visto più semplicemente come una specifica dei bit da utilizzare per la scrittura seguito da una codifica a formato fisso. Per ottimizzare il numero di bit utilizzati, si tiene conto che se un numero è codificato con b bit allora non sarebbe stato possibile codificarlo con meno; questo spiega la sottrazione n = n 2 b al passo 2 della scrittura e l analoga somma in fase di lettura. Il parametro k determina il numero minimo di bit da utilizzare e varia la codifica dei valori. Per k uguale o vicino a zero si ottiene una codifica con un numero inferiore di bit dei valori minori, mentre per k grande si utilizzano più bit per valori piccoli ma le lunghezze dei codici crescono più lentamente al salire di n. Questo parametro quindi va determinato in base a quanto effettivamente le frequenze dei valori maggiori siano stimate minori di quelle dei valori più piccoli. Bit di base = 0 Valore Codifica Tabella 2.6: Codifica a formato variabile con 0 bit di base 2.3 Codifica tramite alberi di Huffman In questa sezione si vedrà come vengono gestiti gli alberi di Huffman utilizzati. Si inizierà con le convenzioni utilizzate per la scrittura e la lettura tramite queste strutture e quindi si mostrerà una codifica per includere questi alberi nel file compresso. Infine verrà descritta la tecnica per la compressione di un intero strato tramite Run Length Encoding ed alberi di Huffman Uso degli alberi di Huffman Durante la codifica del file la maggior parte dei valori numerici viene scritta tramite alberi di Huffman. Questa struttura è definita come un albero binario dove ogni foglia contiene uno dei possibili valori da codificare, ed ogni nodo non terminale deve avere due figli. Per convenzione, ad ogni arco che collega un nodo con il suo figlio sinistro è associato il bit di valore zero, mentre ogni arco che porta ad un figlio destro viene assegnato il valore uno. La codifica di ogni valore è definita come il

52 CAPITOLO 2. IL FORMATO FILE 52 Bit di base = 2 Valore Codifica Tabella 2.7: Codifica a formato variabile con 2 bit di base cammino che collega la foglia corrispondente con la radice dell albero, e la lunghezza in bit di tale codice sarà quindi uguale al numero di nodi non foglia incontrati in questo percorso. Un caso limite di questa definizione si presenta quando si utilizza un albero con un unico nodo; questo significa che nei dati codificati è presente un solo valore. In tale situazione la codifica di tale numero verrà fatta con zero bit, ed analogamente un operazione di lettura restituirà questo valore senza leggere alcuna informazione. Gli alberi di Huffman sono intesi per assegnare una codifica ottimale ai valori del dominio considerato date determinate frequenze. Visto che tali strutture verranno memorizzate nel file e non calcolate in modo adattivo a seconda dei dati scritti la responsabilità dell ottimalità della codifica generata spetta all implementazione realizzata. Le frequenze dei simboli utilizzate per la costruzione dell albero possono essere determinate esattamente, considerando tutti i valori presenti o stimate, analizzando un campione di caratteri significativo e risparmiando così sui tempi di elaborazione. L unico requisito fondamentale è ovviamente che ogni valore da codificare sia presente nell albero Codifica degli alberi di Huffman Gli alberi di Huffman utilizzati dovranno essere memorizzati insieme ai dati compressi; è dunque necessario elaborare anche per loro una codifica conveniente. Nella seguente descrizione si presuppone che ogni valore da codificare sia minore di un numero noto n. Il numero di bit per esprimere uno di tali numeri è dunque log 2 n ; nell algoritmo utilizzato n sarà sempre una potenza di due. La scrittura di un albero viene fatta secondo un algoritmo ricorsivo descritto dalle seguenti istruzioni:

53 CAPITOLO 2. IL FORMATO FILE Se la radice dell albero è una foglia, viene scritto il bit uno e la chiave contenuta a formato fisso con log 2 n bit. 2. Se la radice è un nodo interno, viene scritto prima il bit zero, quindi il sottoalbero sinistro ed infine il figlio destro. La funzione di lettura è del tutto simmetrica: 1. Viene letto un bit dall albero codificato. 2. Se il bit è uno, viene decodificato un valore a formato fisso con log 2 n bit. L albero letto è formato da una sola foglia che ha come chiave il valore ottenuto. 3. Se il bit è zero, l albero letto ha come radice un nodo non foglia che ha come figli sinistro e destro i due alberi ottenuti ripetendo l algoritmo dal passo 1. Tale codifica è univocamente decifrabile a patto che ogni nodo abbia due figli o nessuno, ipotesi che abbiamo imposto nella definizione di albero di Huffman. Il numero di valori da codificare tramite un albero non deve essere necessariamente uguale ad n, ma può anche essere un numero inferiore k evitando così di inserire nell albero numeri che non compaiono mai fra i dati da comprimere. Si può dimostrare per induzione che ogni albero binario con k nodi foglie ha esattamente k 1 nodi non terminali. Considerando che ogni nodo dell albero richiede un bit per la propria codifica più log 2 n bit se si tratta di una foglia, la codifica di un albero di Huffman relativo a k valori richiede esattamente k( log 2 n + 2) 1 bit. Un alternativa per la codifica degli alberi di Huffman poteva essere quella di memorizzare le frequenze dei simboli e definire un algoritmo per la costruzione dell albero a partire da tali informazioni. Tale politica tuttavia sarebbe più complessa da specificare e da esprimere e inoltre risulterebbe meno efficiente nei riguardi dello spazio occupato in quanto non permetterebbe di omettere i valori inutilizzati Codifica di strati tramite RLE ed alberi di Huffman Vediamo ora come un intero strato venga codificato tramite l applicazione delle tecniche di RLE e di Huffman. Innanzitutto è necessario scegliere uno dei due ordini di visita dello strato a disposizione, di cui il primo sarà più vantaggioso dal punto di vista della semplicità e della rapidità di esecuzione, mentre il secondo permetterà una compressione maggiore. Le due possibilità sono le seguenti: 1. Lo strato viene scorso da sinistra a destra e dal basso all alto procedendo prima per righe e poi per colonne. Si ricordi che nella rappresentazione usata il punto (0, 0) è nell angolo in basso a sinistra. 2. Si imposta come punto di partenza il punto in basso a sinistra. Quindi si procede ripetendo una sequenza di quattro passi, dove al primo si considera il punto immediatamente sopra, al secondo ed al quarto il punto alla destra ed al terzo il punto al di sotto. Appena tale procedimento porterebbe ad un punto oltre il limite orizzontale dell immagine, si passa al punto più a sinistra della prima riga non ancora analizzata. Nel caso in cui nell immagine resti soltanto

54 CAPITOLO 2. IL FORMATO FILE 54 una riga da visitare questa sarà scorsa sequenzialmente da sinistra a destra. Tale procedimento, eseguendo un cambio di direzione ad ogni passo, permette di processare consecutivamente punti vicini sia orizzontalmente e verticalmente rendendo più probabile trovare lunghe sequenza di uno o di zeri Figura 2.9: Esempio di ordine di visita standard Figura 2.10: Esempio di ordine di visita a zigzag Figura 2.11: Un secondo esempio di ordine di visita standard A questo punto l algoritmo di codifica consiste nei seguenti passi: 1. Lettura del valore del bit corrente, ed avanzamento di un passo nell ordine di visita utilizzato. 2. Se il bit ha lo stesso valore del precedente, si aumenta di uno la lunghezza di sequenza corrente; altrimenti, si memorizza tale valore e si inizia nuovamente tale conto a partire da uno. Per quanto riguarda il primo valore, si opera come se il valore precedente fosse stato zero.

55 CAPITOLO 2. IL FORMATO FILE Figura 2.12: Un secondo esempio ordine di visita a zigzag 3. A meno che non siano stati visitati tutti i bit dello strato, si ripete l algoritmo dal punto uno. A questo punto si è ottenuta una sequenza di numeri interi. Li raggruppiamo a coppie di numeri consecutivi, aggiungendo uno zero in coda se la quantità di valori è dispari. Quindi controlliamo che il primo valore di ogni coppia (rappresentante una sequenza di zeri consecutivi) sia minore di 64 ed il secondo di 16; se tali vincoli non sono rispettati alcune coppie andranno spezzate in più coppie equivalenti. Ad esempio, (100, 8) dovrà diventare (63, 0) e (37, 8) e (54, 30) diverrà (54, 15) e (0, 15). Con tale procedimento ci assicuriamo di avere un massimo di = 1024 coppie da codificare. L asimmetria delle limitazioni è motivata dal fatto che poiché durante l operazione di filtraggio si tenta di minimizzare i valori ottenuti, in questa fase ci aspettiamo un numero maggiore di valori uguali a zero. Le coppie ottenute vengono codificate con un albero di Huffman. Avendo definito tale struttura per i numeri interi, ad ogni coppia (a, b) viene assegnato un valore pari a v = a 16 + b; se le limitazioni sono rispettate è facile vedere come si possa riottenere a = v/16 ed b = v mod 16 utilizzando le operazioni di modulo e divisione fra interi. L albero di Huffman utilizzato verrà codificato in testa allo strato compresso. Troviamo un esempio di creazione delle coppie e dei valori associati con i due ordini di visita nelle figure 2.13 e L algoritmo di decompressione è del tutto simmetrico; in breve: 1. Viene letto l albero di Huffman. 2. Utilizzando tale struttura, si leggono i valori v e si ricavano le coppie di sequenze. 3. Seguendo lo stesso ordine di visita, si assegna ordinatamente ad ogni bit il valore appropriato. Una delle operazioni eseguite in questa fase pensata per migliorare la compressione è il raggruppamento a coppie delle lunghezze delle sequenze. In questo modo innanzitutto si ottiene un grande numero di simboli e si diminuisce l errore commesso assegnando ad ogni coppia un codice con numero di bit intero. Nei risultati sperimentali, la differenza di dimensioni rispetto al limite entropico del modello di ordine uno

56 CAPITOLO 2. IL FORMATO FILE 56 Coppie di sequenze (2,2) (3,1) (2,3) (1,2) (4,1) (2,2) (1,2) (3,3) (1,2) (3,0) Valori associati Figura 2.13: Codifica tramite RLE ed Huffman con ordine di visita standard Coppie di sequenze (4,4) (1,1) (3,3) (1,1) (3,2) (1,1) (5,4) (1,2) (3,0) Valori associati Figura 2.14: Codifica tramite RLE ed Huffman con ordine di visita a zigzag di tali coppie varia tra lo 0.5% ed l 1%, distanza abbastanza piccola da giustificare l utilizzo degli alberi di Huffman rispetto per esempio ad una codifica aritmetica favorendo così di una maggiore velocità di esecuzione. In secondo luogo, si tiene conto in questo modo della correlazione tra i due valori che compongono la coppia. Questo è utile poiché è sensato aspettarsi che nello strato ci siano zone con una distribuzione di punti più dense di altre, e dunque sequenze più lunghe di zeri probabilmente saranno vicine a sequenze più brevi di uno. 2.4 Uso e codifica di poliomini In questa sezione si definisce come vengano letti e scritti i poliomini in funzione delle codifiche di interi definite nella descrizione delle matrici di bit. Quindi si vedrà come i singoli poliomini vengano composti insieme ad altre informazioni specificanti la loro posizione per esprimere in modo compatto un intero strato dell immagine Codifica di poliomini Vediamo innanzitutto una serie di definizioni necessarie per descrivere gli oggetti in questione.

57 CAPITOLO 2. IL FORMATO FILE 57 Una cella è un quadrato di lato unitario di vertici (i, j), (i + 1, j), (i, j + 1) e (i + 1, j + 1) dove i e j sono numeri naturali. Si dice insieme discreto un insieme di celle distinte. Una colonna i è formata dalle celle con ascisse comprese fra i ed i + 1; analogamente una riga j è formata da tutte le celle con ordinate fra j e j + 1. Due celle a e b di un insieme discreto si dicono connesse se esiste una sequenza di celle c 0... c n appartenenti a tale insieme tali che c 0 = a, c n = b e per ogni i c i è adiacente a c i+1 verticalmente o orizzontalmente. Un poliomino è un insieme discreto di celle dove ogni coppia dei suoi elementi è connessa. Un poliomino si dice convesso se ogni sua riga o colonna è a sua volta connessa. Nella rappresentazione utilizzata, una cella corrisponde ad un punto di valore uno in una matrice di valori binari rappresentante uno strato dell immagine. Durante la compressione, tutti i valori uno di uno strato verranno raggruppati in un insieme di poliomini convessi che verranno quindi opportunamente codificati. Il modo in cui questi vengono scelti dipende dal codificatore e sarà descritto in seguito. La codifica di un poliomino viene fatta in tre fasi: nella prima vengono scritte le dimensioni verticali ed orizzontali, nella seconda si codificano i punti di contatto e nella terza si definiscono tutte le informazioni rimanenti. Nel caso in cui il poliomino sia un quadrato di un unico punto o un rettangolo di altezza o larghezza pari ad uno le ultime due fasi producono sempre un output di zero bit, e dunque possono essere saltate. Per quanto riguarda la prima fase, si considerano come dimensioni del poliomino l altezza e la larghezza del rettangolo più piccolo con i lati paralleli agli assi che contiene interamente il poliomino. A questo punto se tutte e due le dimensioni sono minori di 9 ed almeno una è diversa da 8, viene codificata la quantità (h 1) 8+l 1 con un albero di Huffman dove h ed l sono rispettivamente l altezza e la larghezza in questione. Altrimenti viene innanzitutto scritto il codice 63 con lo stesso albero e quindi il valore della larghezza meno uno nel formato a bit variabile con un numero di bit di base uguale a tre. A questo punto se il valore scritto è minore di 7 sappiamo che è l altezza ad avere un valore maggiore o uguale di otto, e si codifica il valore h 8 di nuovo a bit variabili con un numero di bit di base pari a tre; altrimenti si scrive il valore a cui è stato sottratto uno a formato variabile ma con bit di base pari a zero. Si noti che essendo l altezza e la larghezza numeri sicuramenti maggiori di zero per utilizzare tutti i valori dell albero di Huffman e per risparmiare bit nella codifica a bit variabile tali quantità vengono sempre diminuite di uno prima della codifica. Questo procedimento ed il suo simmetrico algoritmo di lettura sono riassunti nelle figure 2.15 e Da qui in avanti la codifica varia a seconda della dimensione maggiore del poliomino. Si vedrà infatti che il costo di memorizzazione di un poliomino sarà proporzionale ad n log 2 m dove n ed m sono una l altezza e l altra la larghezza; è quindi conveniente porre m uguale alla maggiore. La descrizione di seguito specificherà la codifica nel caso in cui l altezza sia maggiore o uguale alla larghezza; in caso contrario prima di procedere si dovrà considerare il poliomino come se fosse ruotato di

58 CAPITOLO 2. IL FORMATO FILE 58 no Scrittura con Huffman di v = (h - 1) * 8 + l - 1 Inizio scrittura dati altezza h e larghezza l h > 8 o l > 8 o (h = 8 e l = 8) si writevbit(h - 8, 3) si Scrittura con Huffamn di 63; writevbit(l-1,3) l < 8 no writevbit(h - 1,0) Figura 2.15: Scrittura delle dimensioni di un poliomino no Altezza h = v / Larghezza l = v mod Lettura con l albero di Huffman di v v = 63 si Altezza h = readvbit(3) + 8 si Larghezza l = readvbit(3) + 1 l < 8 no Altezza h = readvbit(0) + 1 Figura 2.16: Lettura delle dimensioni di un poliomino novanta gradi in senso antiorario. In altre parole, si dovranno visitare righe invece che colonne e considerare distanze dal lato sinistro invece che da quello inferiore così come dal lato destro invece che da quello superiore. Si può vedere un esempio di rotazione in figura Al secondo passo si codificano i punti di contatto del poliomino. Si consideri il rettangolo definente le sue dimensioni; si sa per certo che il poliomino avrà delle celle di contatto con tutti i suoi lati. Si valuta la distanza dal lato sinistro di tale rettangolo dalle prime celle da sinistra a destra che toccano i lati inferiore e superiore; per distanza si intende il numero delle celle vuote che separano i due elementi. Questi due valori vengono codificati come un vettore nel dominio finito definito da un altro vettore con due elementi pari alla larghezza. Un esempio è riportato in figura Nel terzo passo si codificano una serie di distanze tramite codifica in domini finiti in modo da definire tutti i punti del poliomino. Tutte le colonne vengono visitate, e per ognuna vengono scritte due quantità indicanti il numero di celle vuote che inter-

59 CAPITOLO 2. IL FORMATO FILE 59 Figura 2.17: Rotazione di un poliomino corrono dal lato inferiore del rettangolo limite alla cella più in basso del poliomino su tale colonna e la distanza fra l ultima cella di questa colonna ed il lato superiore. Per definire il campo in cui queste quantità possono variare bisogna considerare le informazioni che a tale punto saranno note al decodificatore. Per fare questo in fase di scrittura e di lettura vengono usati quattro vettori di lunghezza pari alla larghezza del poliomino. Due rappresenteranno il limite minimo e massimo del primo punto di ogni colonna, e gli altri due limiteranno analogamente l ultimo punto. Al momento di scrivere una distanza sarà sufficiente codificarne il valore nel campo definito dai due relativi valori nei vettori associati. Dopo ogni scrittura o lettura tali valori verranno aggiornati per le colonne che seguono secondo determinate regole derivanti da varie ipotesi fatte tra cui una rielaborazione del concetto di convessità: se un poliomino è convesso questo equivale a dire che detto i l indice del punto di contatto con il lato inferiore, per valori maggiori di i il valore delle distanze dal lato inferiore saranno crescenti rispetto all indice di colonna, mentre per valori minori saranno decrescenti. Un ragionamento analogo viene fatto per le distanze dal lato superiore dove tali quantità decrescono dalla colonna zero al punto di contatto e crescono a seguire. Di seguito sono descritte le regole utilizzate. Si considerino i vettori minlow e maxlow i limiti minimo e massimo delle distanze dal lato inferiore e minhigh e maxhigh gli stessi limiti per le distanze dal lato superiore. Si dicono inoltre plow e phigh le posizioni dei punti di contatto scritti con il lato inferiore e superiore ed h l altezza del poliomino e l la larghezza. Inizializzazione: minlow[i] = 0 i minhigh[i] = 0 i maxlow[i] = h 1 i maxhigh[i] = h 1 i Scrittura o lettura punti di contatto: Detto j l indice del punto di contatto inferiore e k quello del punto superiore, si impone per conoscenza della distanza della colonna maxlow[j] = 0

60 CAPITOLO 2. IL FORMATO FILE 60 maxhigh[k] = 0 e si prende nota del fatto che i due punti di contatto sono i primi con le assegnazioni minlow[i] = 1 i < j minhigh[i] = 1 i < k Codifica di una distanza dal lato inferiore con indice di colonna maggiore di plow: Detto k l indice di colonna e d la distanza, si impone per le condizione di convessità maxlow[i] = min(maxlow[i], d) plow < i < k minlow[i] = max(minlow[i], d) k < i < l e se k > 0 per la condizione di connessione maxhigh[k 1] = min(maxhigh[k 1], h d 1) Codifica di una distanza dal lato inferiore con indice di colonna minore di plow: Detto k l indice di colonna e d la distanza, si impone per le condizione di convessità maxlow[i] = min(maxlow[i], d) k < i < plow minlow[i] = max(minlow[i], d) 0 i < k e se k < l 2 per la condizione di connessione maxhigh[k + 1] = min(maxhigh[k + 1], h d 1) Codifica di una distanza dal lato superiore con indice di colonna maggiore di phigh: Detto k l indice di colonna e d la distanza, si impone per le condizione di convessità maxhigh[i] = min(maxhigh[i], d) phigh < i < k minhigh[i] = max(minhigh[i], d) k < i < l e se k > 0 per la condizione di connessione maxlow[k 1] = min(maxlow[k 1], h d 1) Codifica di una distanza dal lato superiore con indice di colonna minore di phigh: Detto k l indice di colonna e d la distanza, si impone per le condizione di convessità maxhigh[i] = min(maxhigh[i], d) k < i < phigh minhigh[i] = max(minhigh[i], d) 0 i < k e se k < l 2 per la condizione di connessione maxlow[k + 1] = min(maxlow[k + 1], h d 1)

61 CAPITOLO 2. IL FORMATO FILE 61 Dopo ogni codifica di colonna di indice k per corretto ordinamento dei punti maxlow[k] = min(maxlow[k], h minhigh[k] 1) maxhigh[k] = min(maxhigh[k], h minlow[k] 1) L ordine di visita è definito in modo da massimizzare le informazioni note, osservando che queste sono maggiori per ogni colonna se questa non è adiacente ad un altra colonna già descritta. L ordine è definito dalla seguente funzione in pseudocodice che riceve in ingresso due interi rappresentanti gli estremi dell intervallo da visitare, chiamata inizialmente su 0 e l 1. Visit(l, r) = codifica(l) codifica(r) Visit_rec(l + 1, r - 1) Visit_rec(l, r) = if (l < r) { med = (l + r) / 2 codifica(med) Visit_rec(l, med - 1) Visit_rec(med + 1, r) } Di seguito dalla figura 2.18 alla 2.29 si trova un esempio completo di codifica di un poliomino dove si possono vedere ad ogni passo i valori scritti (o, del tutto simmetricamente, i valori letti) ed i relativi aggiornamenti dei vettori limite. minhigh maxhigh distanza superiori distanze inferiori maxlow minlow Figura 2.18: Codifica di un poliomino, situazione iniziale

62 CAPITOLO 2. IL FORMATO FILE 62 minhigh maxhigh distanza superiori Scrittura dei punti di contatto: (2, 1) con i massimi (4, 4) distanze inferiori maxlow minlow Figura 2.19: Codifica di un poliomino, scrittura punti di contatto minhigh maxhigh distanza superiori Scrittura della distanza inferiore della colonna 0: 4 nel campo [1,7] distanze inferiori maxlow minlow Figura 2.20: Codifica di un poliomino, primo passo

63 CAPITOLO 2. IL FORMATO FILE 63 minhigh maxhigh distanza superiori Scrittura della distanza superiore della colonna 0: 1 nel campo [1,3] distanze inferiori maxlow minlow Figura 2.21: Codifica di un poliomino, secondo passo minhigh maxhigh distanza superiori Scrittura della distanza inferiore della colonna 4: 2 nel campo [0,7] distanze inferiori maxlow minlow Figura 2.22: Codifica di un poliomino, terzo passo

64 CAPITOLO 2. IL FORMATO FILE 64 minhigh maxhigh distanza superiori Scrittura della distanza superiore della colonna 4: 3 nel campo [0,5] distanze inferiori maxlow minlow Figura 2.23: Codifica di un poliomino, quarto passo minhigh maxhigh distanza superiori Scrittura della distanza inferiore della colonna 2: 0 nel campo [0,0] (nessun bit impiegato) distanze inferiori maxlow minlow Figura 2.24: Codifica di un poliomino, quinto passo

65 CAPITOLO 2. IL FORMATO FILE 65 minhigh maxhigh distanza superiori Scrittura della distanza superiore della colonna 2: 1 nel campo [0,3] distanze inferiori maxlow minlow Figura 2.25: Codifica di un poliomino, sesto passo minhigh maxhigh distanza superiori Scrittura della distanza inferiore della colonna 1: 2 nel campo [1,4] distanze inferiori maxlow minlow Figura 2.26: Codifica di un poliomino, settimo passo

66 CAPITOLO 2. IL FORMATO FILE 66 minhigh maxhigh distanza superiori Scrittura della distanza superiore della colonna 1: 0 nel campo [0,0] (nessun bit utilizzato) distanze inferiori maxlow minlow Figura 2.27: Codifica di un poliomino, ottavo passo minhigh maxhigh distanza superiori Scrittura della distanza inferiore della colonna 3: 0 nel campo [0,2] distanze inferiori maxlow minlow Figura 2.28: Codifica di un poliomino, nono passo

67 CAPITOLO 2. IL FORMATO FILE 67 minhigh maxhigh distanza superiori Scrittura della distanza superiore della colonna 3: 2 nel campo [1,3] distanze inferiori maxlow minlow Figura 2.29: Codifica di un poliomino, decimo passo Una volta codificate tutte le distanze l algoritmo di codifica termina. È semplice vedere come il procedimento sia invertibile imponendo al momento della lettura di ogni valore le stesse condizioni per la limitazione dei valori. In fase di decodifica, una volta ottenuti gli indici del primo e dell ultimo punto di ogni colonna sarà sufficiente aggiungere tutte le celle fra essi compresi, presenti per l ipotesi di convessità. Tale codifica è simile al RLE in quanto si avvale di codifiche di zeri consecutivi intuendo così le posizioni delle celle del poliomino; grazie alle condizioni sopra descritte tuttavia si riesce a sfruttare la correlazione dei dati in entrambe le direzioni ottenendo risultati migliori di quelli che risulterebbero da una semplice codifica RLE delle colonne. Tale tecnica è tuttavia computazionalmente impegnativa e deve essere utilizzata con parsimonia nel processo di compressione Codifica di strati tramite poliomini La codifica di uno strato con poliomini avviene tramite una serie di scrittura di distanze alternate con codifiche di poliomini. Si inizia e si termina con la codifica di una distanza. L immagine viene scorsa dal punto in basso a sinistra al punto in alto a destra prima per righe e quindi per colonne. Durante tutto il processo si deve tener conto di un insieme di punti detti noti; tali rappresentano i valori che già si conoscono in base a ciò che già è stato codificato. Tale insieme viene aggiornato ad ogni codifica o lettura di un poliomino con le seguenti regole: Ogni cella appartenente ad un poliomino è un punto noto.

68 CAPITOLO 2. IL FORMATO FILE 68 Se il poliomino è formato da un unico punto, i punti al di sopra di esso ed alla sua destra sono noti. Se il poliomino ha larghezza uno, il punto al di sopra del suo punto superiore è noto. Se il poliomino ha altezza uno, il punto alla destra del suo punto maggiormente a destra è noto. Sarà chiaro dalla descrizione in seguito che assegnare punti noti al di sotto o sulla stessa riga a sinistra del poliomino è inutile in quanto questi sono stati sicuramente già visitati. Tali condizioni impongono dei vincoli sulla scomposizione in poliomini; in particolare: Un poliomino di dimensioni uno per uno dovrà avere alla sua destra ed al di sopra due punti o noti o pari a zero Un poliomino di larghezza uno dovrà avere al di sopra di se un punto noto o pari a zero Un poliomino di altezza uno dovrà avere alla sua destra un punto noto o pari a zero Tali limitazioni sono vincolanti ma sensate; infatti per ogni poliomino che non le rispetti se ne può considerare uno che lo comprenda che non ha costo di memorizzazione maggiore, permettendo di codificare più informazioni allo stesso prezzo. A questo punto la codifica di uno strato avviene in modo molto semplice secondo i seguenti passi. Si tiene conto con una variabile della distanza attuale e per ogni punto nell ordine di visita si esegue uno dei seguenti: Se il punto considerato è noto secondo le definizioni date, non si esegue nessuna azione. Se il punto non è noto ed è uguale a zero, si incrementa di uno la variabile per le distanze. Se il punto non è noto ed è uguale ad uno, si seleziona un poliomino che lo contenga. Quindi si codifica la distanza con un albero di Huffman; se minore di 63, questa viene scritta direttamente, altrimenti viene codificato il numero sessantatre seguito dalla codifica a formato variabile della distanza meno 63 con un numero di bit di base pari ad sei. Quindi viene codificato il poliomino trovato e vengono aggiornate le informazioni sui punti noti. Alla fine dello strato si scrive la distanza attuale con la solita modalità e si pone fine alla codifica. I due alberi di Huffman utilizzati, uno per le distanze ed uno per le dimensioni dei poliomini, vengono codificati in testa allo strato in questo ordine. Un esempio completo della codifica di un piccolo strato tramite poliomini appare di seguito nelle figure dalla 2.30 alla 2.36; i quadrati in grigio rappresentano i punti noti, mentre quelli bianchi e neri sono i punti non noti pari rispettivamente a zero e ad uno.

69 CAPITOLO 2. IL FORMATO FILE 69 Figura 2.30: Strato da codificare tramite poliomini, situazione iniziale Codifica della distanza 2 Codifica del poliomino 1 2 Figura 2.31: Codifica di uno strato tramite poliomini, primo passo Codifica della distanza 3 Codifica del poliomino Figura 2.32: Codifica di uno strato tramite poliomini, secondo passo Codifica della distanza 3 Codifica del poliomino Figura 2.33: Codifica di uno strato tramite poliomini, terzo passo 2.5 Uso e codifica dei filtri In questa sezione si vedrà come vengono codificate le informazioni riguardanti la fase di filtraggio, comprensive della lista dei filtri standard e per colore utilizzati e del vettore di riassegnazione. Tali dati verranno inseriti all interno dell intestazione del file compresso come descritto in seguito.

70 CAPITOLO 2. IL FORMATO FILE 70 Codifica della distanza Codifica del poliomino Figura 2.34: Codifica di uno strato tramite poliomini, quarto passo Codifica della distanza 1 1 Codifica del poliomino Figura 2.35: Codifica di uno strato tramite poliomini, quinto passo Codifica della distanza Figura 2.36: Codifica di uno strato tramite poliomini, sesto passo Codifica dei filtri selezionati Si considerano già note le dimensioni delle diverse zone di applicazione ed un numero n indicante che ogni filtro utilizzato ha indice minore di esso, in quanto tali informazioni sono codificate nell intestazione. La codifica dei filtri selezionati comprende una serie di scritture a formato fisso con un numero di bit pari a log 2 n. I filtri utilizzati per le singole zone vengono scritti partendo dalla zona più in basso a sinistra a quella più in alto e a destra, procedendo da sinistra a destra e dal basso all alto. Se la larghezza o l altezza dell immagine non sono multipli del lato di una zona sarà necessario considerare zone più piccole alle estremità destra e superiore; un esempio di numerazione delle zone di un immagine è in figura Al termine di queste scritture se il numero di bit scritti per codificare i filtri non è un multiplo di otto, si scrivono una serie di bit uguali a zero fino a ottenere questa condizione; questo permette di essere sicuri che la codifica dei filtri occupi sempre un numero intero di byte. Si può verificare che il numero di bit utilizzati per la codifica dei filtri è z log 2 n /8 8 dove z è il numero delle zone dell immagine che può essere calcolato come (l/d) (h/d) dove l ed h sono rispettivamente la larghezza e l altezza

71 CAPITOLO 2. IL FORMATO FILE 71 dell immagine e d è la dimensione del lato delle zone di filtraggio Figura 2.37: Esempio di numerazione delle zone di filtraggio La scrittura dei filtri per colore avviene dopo la codifica dei filtri sopra descritta. La codifica utilizzata è la stessa considerando eventualmente che i valori dei parametri riguardanti il numero dei filtri usati e le dimensioni delle zone di filtraggio non sono necessariamente uguali Codifica della mappa di valori La mappa di valori definisce la riassegnazione fatta durante la terza fase di filtraggio. La codifica avviene scrivendo ordinatamente al crescere di un indice i che va da 0 a 255 il numero che è stato sostituito ad ogni byte di valore i nell immagine iniziale. La scrittura di ogni valore viene fatta a formato fisso con otto bit; essendo la mappa di valori scritta sempre a partire da un indice di bit multiplo di otto, questo può essere fatto semplicemente scrivendo sequenzialmente 256 byte sul file compresso rappresentanti con i valori in questione. Per essere invertibile l operazione di riassegnazione deve essere fatta in base ad una permutazione; nel file quindi ci si aspetta in questa fase la presenza di 256 valori distinti, ed una diversa conformazione è segnale di una situazione di errore. 2.6 Codifica delle matrici di bit compresse In questa sezione si vedrà come le matrici di bit compresse create con i metodi finora descritti vengano incapsulate in un intestazione che specifica le informazioni necessarie alla loro decodifica. Quindi si vedrà la specifica dell intestazione del file e come tutte le parti che compongono l immagine compressa vengano unite fra loro Codifica di strati e intestazione Ogni strato deve venir codificato con uno degli algoritmi descritti precedentemente. Il flusso di bit generato dovrà essere scritto di seguito ad un intestazione che definisca le informazione di base riguardanti lo strato. L inizio di tale pacchetto di informazioni deve sempre essere in un bit che ha come indice un multiplo di otto e dunque all inizio di un byte nella rappresentazione fisica del file; se la codifica precedente si era conclusa in un punto diverso dovranno venir scritti dei bit di valore zero fino

72 CAPITOLO 2. IL FORMATO FILE 72 ad ottenere tale condizione. L intestazione è specificata di seguito ed è composta da una serie di campi scritti a formato di bit fisso. Codice di inizio strato, 16 bit: Vengono scritti i due numeri 76 ed 89 a formato fisso con 8 bit ciascuno; in codici ascii questi due valori rappresentano le lettere LY, specificanti l inizio di uno strato. Tali valori servono da controllo per il decodificatore per assicurarsi che il punto di inizio lettura dello strato sia corretto. Tipo, 2 bit: Il codice specifica la modalità di codifica dello strato dove il valore 0 rappresenta uno strato compresso tramite poliomini, il numero 1 una compressione con RLE ed Huffman ed il numero 2 una codifica senza compressione. Larghezza, 16 bit: Il codice specifica la larghezza della matrice binaria rappresentante lo strato. Gli strati sono chiaramente tutti delle stesse dimensioni dell immagine, ma la replicazione di tale informazione permette una maggiore indipendenza concettuale e progettistica degli oggetti che formano il file compresso. Altezza, 16 bit: Il codice corrisponde all altezza dello strato. Colore, 2 bit: Specifica del colore a cui si riferisce lo strato, dove 0 corrisponde al blu, 1 al rosso e 2 al verde. Bit, 3 bit: Specifica del bit rappresentato dallo strato, dove un valore k indica il k-esimo bit meno significativo. Codice hash, 32 bit: Tale quantità è un codice hash definito sui punti dello strato originale, e può essere utilizzata per verificare la corretta ricostruzione dopo la decompressione. Il codice hash è definito dalla formula bit + colore + n i=0 (b[i] 2i mod 16 ) mod 2 30 dove b è il vettore corrispondente alla rappresentazione a byte. Tale formula è stata ideata per generare notevoli variazioni del risultato anche in corrispondenza di piccoli cambiamenti del dato in ingresso in modo da rilevare con ottime probabilità qualsiasi errore nella ricostruzione dello strato. Inoltre tale formula permette un calcolo molto rapido in quanto le operazioni di modulo, elevamento a potenza e prodotto possono essere calcolate con operatori di bit shift e di and bit a bit. Strato base, 5 bit: Numero che identifica lo strato di base utilizzato con cui è stato eseguito lo xor prima della compressione. Se uguale a zero, tale fase è stata saltata. Altrimenti se minore di 27 lo strato utilizzato è uguale a quello indicato del numero letto n meno uno; secondo l ordinamento definito tale strato è relativo al colore (n 1) mod 3 ed al bit 8 (n 1)/3. Infine se tale quantità è 27, sono stati utilizzati strati variabili per zone diverse come specificato di seguito. Specifica strati base, bit variabili: Campo utilizzato solo se il numero di strato di base è 27. Per ogni zona 16 per 16 o frazione dello strato viene specificato con 3 bit lo strato base utilizzato; un valore k in uno strato n indica che è stato

73 CAPITOLO 2. IL FORMATO FILE 73 utilizzato lo strato n k. Chiaramente questa codifica consente di utilizzare solo i sette strati precedenti. La prima zona è formata dai punti nel quadrato di angoli (0, 0), (0, 15), (15, 0) e (15, 15), e le successive sono numerate procedendo da sinistra a destra e quindi dal basso all alto. Le zone adiacenti al lato destro e superiore dello strato possono risultare di dimensioni minori delle altre se la larghezza o l altezza non sono multipli di 16. Si può verificare che il numero di bit scritti, detta l la larghezza ed h l altezza, è w/16 h/16 dove il simbolo / indica la divisione intera. Inversione, 1 bit: Codice indicante se uguale ad uno che prima della compressione ogni bit è stato invertito di valore. Tale opzione non viene mai utilizzata nell algoritmo proposto, ma è stata inserita nel formato del file per consentire diverse politiche di compressione alle varie implementazioni. Zigzag, 1 bit: Se lo strato è compresso tramite RLE ed Huffman, un valore uguale ad uno indica che l ordine di visita è quello a zigzag mentre un valore pari a zero specifica un ordine di visita standard da sinistra a destra e dal basso all alto. Se per lo strato sono stato utilizzate altre codifiche, il campo non viene utilizzato e deve essere impostato ad un valore arbitrario. Numero di poliomini, 32 bit: Se lo strato è stato compresso tramite poliomini, tale quantità indica il numero di distanze presenti e di conseguenza il numero di poliomini più uno. Questo valore può essere utilizzato come conferma dell esattezza della ricostruzione dello strato vista la delicatezza dell algoritmo. Per strati che usano altre codifiche tale campo deve essere imposto a zero o ad un altro valore arbitrario. Dopo tale intestazione si trova la codifica dello strato compresso nelle seguenti modalità: Nel caso di compressione tramite poliomini, viene scritto l albero di Huffman relativo alle distanze seguito da quello associato alle dimensioni dei poliomini. Infine si troverà una sequenza alternata di codifica di distanze e di poliomini, come esposto in precedenza. Nel caso di compressione tramite Huffman, viene scritto l albero di Huffman utilizzato e quindi le coppie di lunghezze di sequenze, come specificato nel relativo capitolo. Nel caso di uno strato non compresso, vengono scritti tutti i bit dello strato dal punto più basso a sinistra procedendo prima da sinistra a destra e quindi dal basso all alto Codifica del file: intestazione e composizione Si vedrà ora come è composta l intestazione e come l intero file è composto dalle sue parti. L intestazione per maggiore semplicità è formata da campi che occupano sempre un numero di bit multiplo di otto permettendo una gestione a byte. La sua composizione è la seguente:

74 CAPITOLO 2. IL FORMATO FILE 74 Stringa di identificazione, 57 byte: Per l identificazione del tipo di file viene inserita una stringa di controllo corrispondente a PCF, Polyomino Compressed Format. Author Stefano Brocchi. Versione, 1 byte: Numero cardinale indicante la versione del codificatore utilizzato. La versione qui descritta è la 1.0. Sotto versione, 1 byte: Numero indicante la sottoversione del codificatore utilizzato. Intestazione BMP, 54 byte: Viene qui incapsulata l intera intestazione del file BMP di origine. Essendo l algoritmo utilizzato solo per immagini a 24 bit per pixel, la lunghezza di tale struttura nel file compresso è sempre di 54 byte; in altri contesti potrebbe essere più estesa a causa della presenza di una tavolozza di colori. Tale intestazione contiene dal byte 18 al byte 21 la larghezza dell immagine e dal byte 22 al byte 25 l altezza considerando che i byte di indice minore rappresentano le cifre meno significative. Le altre informazioni contenute non sono utilizzate dall algoritmo ma sono necessarie al momento della ricostruzione del file per non perdere traccia di altre informazioni come la risoluzione di stampa dell immagine in pixel per pollice. Codice hash, 4 byte: Un intero relativo all immagine sorgente che può essere utilizzato per controllare l esattezza della ricostruzione in fase di decompressione. Scritto dal byte meno significativo, tale codice hash è definito dalla h 1 j=0 2 k=0 m[i][j][k] (i + 1) (j + 1) (k + 1) mod 232 dove m è funzione l 1 i=0 la matrice rappresentante l immagine, h è la sua altezza ed l la sua larghezza. Tale funzione è pensata per generare cambiamenti significativi del valore in u- scita anche con piccole variazioni dei valori in ingresso in modo da rilevare con ottime probabilità qualsiasi differenza fra l immagine ottenuta e l originale. Numero di filtri, 1 byte: Tale numero n indica che tutti i filtri utilizzati hanno indice minore di n. Tale informazione verrà utilizzata al momento della codifica dei filtri. Numero di filtri per colore, 1 byte: Analogamente al campo precedente, questa quantità indica il limite dei filtri per colore utilizzati. Passo per determinazione dei filtri, 1 byte: Intero che indica quanti punti sono stati utilizzati per la determinazione dei filtri in rapporto al numero totale; un valore di uno vuol dire che tutti i punti sono stati considerati, un valore di due ad esempio indica che ne è stata utilizzata la metà. Tale informazione è presente solo a titolo informativo. Dimensione delle zone di filtraggio, 1 byte: Numero che rappresenta la lunghezza del lato di una singola zona di filtraggio. Dimensione delle zone di filtraggio per colore, 1 byte: Numero che rappresenta la lunghezza del lato di una singola zona di filtraggio per colore. Codifica dei filtri utilizzati, numero di byte variabile: Campo per la codifica dei filtri utilizzati nelle singole zone, come descritto in precedenza. Per definizione

75 CAPITOLO 2. IL FORMATO FILE 75 tale campo pur essendo di dimensioni variabili deve sempre occupare un numero intero di byte. Codifica dei filtri per colore utilizzati, numero di byte variabile: Campo per la codifica dei filtri per colore, come spiegato in precedenza. Codifica della mappa dei valori, 256 byte: Specifica del vettore permutazione con il quale è stata eseguita la riassegnazione di valori, come descritto nei capitoli antecedenti. Dopo l intestazione, nel file sono presenti i 24 strati rappresentanti l immagine. Gli strati devono essere ordinati prima per colore nell ordine blu, verde e rosso e quindi per bit dal più significativo al meno significativo.

76 Capitolo 3 L algoritmo di codifica 3.1 Scelta dei filtri Si descriveranno in questa sezione le politiche adottate per la determinazione dei filtri da utilizzare e per la scelta del vettore di riassegnazione. Si mostrerà come viene creato un modello che stimi l ottimalità di una scelta invece che di un altra sotto determinate ipotesi, in modo da ottenere dopo la prima fase dell algoritmo un dato facilmente comprimibile senza compromettere la velocità di esecuzione del programma Criteri di ottimalità Per ottenere buoni risultati in fase di compressione sia dal punto di vista dello spazio utilizzato che da quello del tempo impiegato è molto importante una selezione accurata dei filtri da utilizzare, e per questo a tale operazione è stata riservata un attenzione particolare. Essendo il filtraggio la prima delle operazioni eseguite su di un immagine, è molto difficile prevedere tutti gli effetti che l applicazione di una funzione invece che di un altra avrà nell intero processo. Per questo viene costruito un modello che approssimi al meglio il costo di memorizzazione delle singole zone. Tale modello è stato sviluppato sia pensando al resto del procedimento dal punto di vista teorico sia in base ai risultati della sperimentazione eseguita in fase di sviluppo. L algoritmo considerato per la determinazione dei filtri da applicare considera sequenzialmente le zone dell immagine e per ognuna di esse applica tutti filtri messi a disposizione. Ogni valore ottenuto viene passato al modello che restituisce un valore rappresentante il suo costo di memorizzazione; il filtro da utilizzare per la zona sarà chiaramente quello che genera il valore minore. In questo procedimento vi sono tre variabili impostabili al momento della compressione: il numero di filtri da considerare, il numero di punti da usare come campione e la dimensione della zona considerata. Sebbene questi possano essere impostati direttamente dall utente, è importante fornire dei valori di default che garantiscano buoni risultati. Per quanto riguarda il numero di filtri questo è inizializzato a 12; questo significa che tutti i filtri vengono utilizzati ad eccezione del filtro di Paeth, che si è rivelato di scarsa utilità. Tutti i punti vengono utilizzati come campione; in alternativa viene offerta la possibilità di considerarne solo 1 ogni n per un numero specificato. Queste due 76

77 CAPITOLO 3. L ALGORITMO DI CODIFICA 77 opzioni presuppongono che i tempi di compressione, al contrario di quelli di decompressione, non siano critici in quanto solitamente per un immagine tale operazione avviene soltanto una tantum. Di conseguenza si presume che una compressione anche di poco migliore giustifichi un aumento dei tempi. Inoltre una migliore operazione di filtraggio rafforza e velocizza la compressione vera e propria, di modo che buona parte del tempo speso in questa fase venga risparmiato in seguito. Per quanto riguarda il lato della zona di filtraggio questo è imposto ad 8 pixel, un buon compromesso tra zone troppo piccole che occuperebbero troppo spazio per la loro specifica in cambio di un troppo lieve guadagno in seguito e zone troppo grandi che invece comprometterebbero la granularità del filtraggio. Il modello utilizzato stima il costo di una zona in base agli errori fatti da o- gni funzione di filtraggio nello stimare i suoi pixel. Sono stati utilizzati i seguenti presupposti: 1. In fase di filtraggio per colore i valori cambiati generano un uguale miglioramento per tutti i diversi filtri a disposizione. In altre parole, si considera che questa fase abbia lo stesso comportamento indipendentemente dal primo filtro utilizzato. 2. In fase di riassegnazione verranno assegnati i valori più bassi ai numeri più frequenti. Come descritto in seguito tale presupposto è vero per costruzione. 3. Dopo la fase di filtraggio i valori più frequenti saranno quelli in valore assoluto minori considerando la rappresentazione con segno tra 128 e 127 (si ricordi che stiamo operando in modulo 256). Questo avviene presupponendo la bontà delle varie funzioni di filtraggio e quindi che la distribuzione degli errori ottenuti siano una funzione con massimo in zero e decrescente al crescere del modulo dell argomento. Questo significa che nel caso più probabile i filtri stimeranno esattamente il valore del punto, ed in quello immediatamente meno probabile la stima sarà sbagliata di uno e così via. Tale ipotesi si è rivelata sensata anche nei confronti dei risultati sperimentali in particolare per i valori di errore minori. 4. In fase di compressione, ogni valore ottenuto ha un costo pari alla somma dei costi dei valori binari in cui viene scomposto. Questi variano a seconda dello strato dove questi si trovano secondo il sottomodello descritto di seguito. Detto ciò, viene creato un sottomodello di costi per i punti nei diversi strati. Si presuppone infatti che in uno strato dove sono presenti molti punti il costo di uno di essi sia molto basso, mentre per strati meno caotici un bit di valore uno abbia un prezzo di memorizzazione più alto. Questo per due motivi: innanzitutto nel secondo caso l indirizzamento fatto tramite distanze è meno oneroso, e secondariamente è più facile trovare degli uno adiacenti in strati dove ve ne sono molti, cosa che migliora entrambi i metodi di compressione a disposizione. Si considera inoltre che il numero di punti in uno strato relativo ad un bit più significativo è solitamente minore rispetto a quello di un bit meno significativo; il costo di un punto in uno strato sarà quindi minore per bit meno significativi. Questo dipende dalle ipotesi 2 e 3 sulla bontà della stima dei filtri e sul metodo di riassegnazione. La quantificazione

78 CAPITOLO 3. L ALGORITMO DI CODIFICA 78 fatta dei costi dei punti nei diversi strati si basa inoltre su prove sperimentali eseguite in fase di costruzione del modello e corrisponde ai valori [3, 6, 9, 12, 16, 20, 22, 24] ordinati a partire dallo strati relativo al bit meno significativo. Il primo valore non sarà utilizzato ed è presente solo per completezza. Determinati i costi dei singoli strati, si stima il prezzo di un errore fatto in fase di filtraggio nel seguente modo: 1. Si considera la quantità n pari alla differenza in valore assoluto tra il valore del punto ed la stima eseguita dal filtro. 2. Se il numero è minore di 128, si ipotizza che questo venga riassegnato approssimativamente a n 2. Tale valore viene scomposto in bit, e si determina il costo sommando il prezzo dei singoli bit definito dal vettore dei costi del sottomodello. 3. Se il numero è maggiore o uguale a 128, la stima sulla riassegnazione viene considerata imprecisa e per valutare il costo si usa una funzione che cresce linearmente con la grandezza di n. Data l imprevedibilità della riassegnazione per questi valori meno probabili viene considerato un costo minimo di 50 per migliorare la stabilità della stima; in formule il costo stimato è 50+(n 128)/2. In sintesi il processo di determinazione dei filtri viene riassunto nei seguenti passi: 1. Calcolo del costo di ogni possibile errore tra 0 e 256. Tali valori vengono memorizzati in un vettore c. 2. Scorrimento delle zone di filtraggio dell immagine. Per ogni zona viene eseguito il seguente 3. Per ogni valore della zona vengono applicati i filtri a disposizione e viene calcolato l errore e pari alla differenza tra il valore del punto e la stima effettuata dal filtro. Per ogni errore viene calcolato un costo associato pari a c[e] e sommando i costi di tutti i punti si ottiene il costo dell intera zona relativamente al filtro in questione. Viene scelto il filtro che ottiene il costo minore. È da notare che l applicazione di questo modello non pesa sulla complessità dell algoritmo in quanto il calcolo del vettore dei costi avviene solo una volta per immagine ed ha costo relativamente molto piccolo, dopo questa operazione la stima del costo di un determinato valore si ottiene semplicemente con un accesso ad un vettore. Il solito modello di costi viene applicato per determinare i filtri per colore. Per quanto riguarda i parametri di default in questo secondo passo vengono utilizzati 3 filtri (tutti), i punti vengono tutti utilizzati come campione e le zone sono quadrati di pixel di lato 8. Tutti e tre i parametri sono comunque configurabili dall utente come nel caso precedente.

79 CAPITOLO 3. L ALGORITMO DI CODIFICA Scelta della riassegnazione dei valori La fase di riassegnazione dei valori è necessaria per definire in che modo ogni byte debba venir scomposto in otto bit. Per effettuare la scomposizione in strati infatti è necessario definire una funzione biunivoca che associ ad un intero compreso da 0 a 255 otto valori binari; la tecnica utilizzata per fare questo è di sfruttare la riassegnazione per cambiare ogni valore presente in un altro intero nello stesso intervallo e poi di utilizzare la normale rappresentazione binaria dei numeri utilizzati per ottenere i valori binari associati. La politica per la riassegnazione dei valori semplicemente assegna ordinanamente gli interi da 0 a 255 a partire dal valore di byte più frequente al più raro. Il conteggio delle occorrenze viene fatto in fase di filtraggio per colore e dunque richiede un costo computazionale aggiuntivo molto piccolo. Con tale tecnica si cerca di accumulare le parti di informazione più caotiche negli strati relativi ai bit meno significativi facendo in modo che i valori più frequenti siano rappresentati con pochi bit appartenenti agli strati con più basso costo di memorizzazione. Una politica alternativa che si sarebbe potuta adottare consiste nell assegnare i valori in modo da minimizzare il numero di bit pari ad uno generati negli strati. Con questa tecnica verrebbero assegnati ordinatamente dal valore più frequente i byte 0, 1, 2, 2 2, 2 3,..., 2 7 in modo che al byte più frequente siano associati zero bit di valore uno e ai sette successivi uno soltanto. La sequenza potrebbe proseguire per esempio con i numeri 2 + 1, , in modo da assegnare soli 2 uno per i numeri successivi. Ovviamente l applicazione di tale politica richiederebbe l uso di un modello diverso nelle precedenti fasi di filtraggio. Tale tecnica si è tuttavia rivelata sconveniente poiché pur generando meno punti questi risultano distribuiti in modo più uniforme negli strati aumentandone così notevolmente il costo medio. Nelle prove sperimentali si è infatti verificato che ridistribuendo così gli uno se ne diminuisce il costo negli strati relativi ai bit più significativi, ma tale guadagno non è sufficiente a bilanciare l aumento di costo che si provoca negli uno degli strati meno significativi. Un altro svantaggio di questa tecnica rispetto a quella adottata è che i bit di valore uno risultano essere molto meno raggruppati rendendo così più difficile la compressione. Questo accade perché questa non gode della proprietà descritta in seguito. La tecnica di riassegnazione scelta favorisce inoltre la vicinanza di valori simili e quindi di bit uguali negli strati ottenuti. Infatti come descritto nella terza ipotesi usata in fase di filtraggio è probabile che valori con frequenza simili siano vicini in valore assoluto. Dunque ci si aspetta di ottenere valori vicini tra loro in punti adiacenti sia in zone dell immagine regolari, dove il modulo dei valori dopo il filtraggio risulta basso, sia in zone di contorno o in altro modo irregolari, dove i numeri ottenuti saranno in maggioranza elevati in valore assoluto.

80 CAPITOLO 3. L ALGORITMO DI CODIFICA Codifica degli strati In questa sezione verranno descritte le funzioni di scelta che il programma effettua durante l esecuzione nella fase di compressione degli strati. Verranno mostrati i criteri per lo smistamento degli strati dell immagine fra le varie tecniche di compressione a disposizione; si vedrà quindi come vengano selezionati i poliomini in cui viene scomposta una matrice di bit, ed infine si descriverà e si motiverà la politica adottata per la gestione degli alberi di Huffman Scelta del metodo di compressione ottimale Come si è visto per ogni strato è possibile applicare una diversa funzione di compressione. Occorre dunque definire un metodo che ne selezioni una ottimale avendo a disposizione alcune delle caratteristiche dello strato. Le informazioni utilizzate per tale scelta sono l indice del bit al quale si riferisce lo strato e la densità di valori uno nella matrice binaria da comprimere; ci si aspetta infatti che più quest ultima quantità si avvicina al 50% più lo strato in questione è caotico e meno comprimibile. Dopo l operazione di riassegnazione, eseguita come descritto precedentemente, si può dimostrare che la densità di zeri in uno strato è sempre maggiore del 50%; questo deriva dal fatto che per ogni bit della rappresentazione binaria dei byte ottenuti dopo questa fase il valore zero ricorre sempre più frequentemente in quanto abbiamo assegnato agli interi più frequenti numeri minori. L indice del bit al quale si riferisce ogni strato è utile perché nelle matrici rappresentanti i bit più significativi ci si aspetta una maggiore regolarità e quindi più vicinanza tra i bit pari ad uno, caratteristica sfruttabile maggiormente dalla compressione tramite poliomini. Dunque sarà definita di seguito una funzione che data una quantità d tra 50 e 100 rappresentante la densità percentuale degli zeri ed il numero b di bit dello strato restituisca uno dei tre metodi di compressione a disposizione. 1. Se d + b > 90, si utilizza il metodo di compressione tramite poliomini 2. Altrimenti, se b > 52, si utilizza il metodo di compressione tramite RLE ed Huffman 3. Altrimenti, si scrive lo strato non compresso In tutti e tre questi casi se la compressione dello strato occupa più memoria dello strato stesso, si passa alla tecnica successiva. Essendo il primo caso utilizzato solo per strati molto regolari questo si verifica solo nel tentativo di compressione con RLE ed Huffman. Nel caso 3 si sceglie di non tentare nemmeno la compressione in quanto molto probabilmente non sarà possibile ridurre il dato o comunque il guadagno ottenuto sarà molto piccolo; una scrittura diretta dunque consentirà un buon guadagno di tempo. La funzione usata è stata selezionata ed aggiustata anche in base ai risultati sperimentali. Come nel caso precedente, anche al punto uno c è un accorgimento per ottimizzare i tempi in quanto valori compresi tra 85 e 90 danno circa gli stessi risultati per quanto riguarda lo spazio utilizzato ma sfruttando più spesso la seconda tecnica si permette una compressione ed una decompressione più rapida. Inoltre

81 CAPITOLO 3. L ALGORITMO DI CODIFICA 81 per aumentare ulteriormente l efficienza dell algoritmo il numero di zeri in uno strato viene conteggiato durante la scomposizione dell immagine e dunque non richiede passate aggiuntive. Nelle immagini compresse durante la sperimentazione mediamente uno strato o due vengono codificati così come sono mentre gli altri vengono spartiti in modo uguale tra le due tecniche di compressione con una lieve prevalenza del metodo che fa uso di RLE ed alberi di Huffman; nei casi di maggiore comprimibilità si ottengono più strati che verranno compressi tramite poliomini mentre in quelli maggiormente caotici si verifica più spesso la codifica senza compressione Scelta del poliomino ottimale Durante la compressione è necessario per ogni punto incontrato trovare un poliomino in cui esso è compreso tale che una volta raggruppati tutti i punti dello strato in un insieme di poliomini questo possa venir compresso occupando il minore spazio possibile. L algoritmo che effettua tale scelta crea una serie di candidati grazie a delle operazioni di espansione che dato un poliomino cercano di crearne un altro che lo contenga aggiungendovi dei punti. L insieme in questione viene creato nel seguente modo; le operazioni di espansione saranno descritte in seguito. 1. Il primo poliomino candidato è formato dal punto in questione 2. Si consideri l ultimo poliomino aggiunto all insieme. Si tenta innanzitutto di espanderlo orizzontalmente; se possibile, tale operazione genera un altro poliomino da aggiungere all insieme. Altrimenti si tenta un espansione verticale, trovando eventualmente un altro poliomino. Se nessuna di queste due è possibile si pone fine all algoritmo, altrimenti si ripete il punto 2. Tale tecnica sfrutta due diverse operazioni di espansione. Queste fanno uso di due valori booleani che tengono conto se l immagine può crescere verso destra o verso sinistra. Secondo le ipotesi di convessità infatti se esistono due righe consecutive del poliomino tali che l estremo sinistro di quella di indice maggiore è più a destra di quello della riga di indice minore allora tutti gli estremi sinistri delle righe successive saranno limitati da quello della riga precedente. Lo stesso vale chiaramente per gli estremi destri in modo del tutto simmetrico. Espansione orizzontale: si considera la riga del poliomino di indice maggiore (la più alta rispetto all immagine). Finché il punto immediatamente alla sua sinistra non è noto ed è pari ad uno si aggiunge al poliomino tenendo eventualmente conto della limitazione imposta dalla riga precedente se il punto non può crescere a sinistra. Dopo di ciò se il punto estremo sinistro è più a destra di quello della riga precedente, si impone che il poliomino e tutti quelli derivati dalla sua espansione non possano crescere a sinistra. L operazione descritta viene eseguita simmetricamente anche per la direzione destra. Espansione verticale: si considera la riga del poliomino di indice maggiore e si cerca il primo punto da sinistra a destra immediatamente sopra tale riga che ha valore uno e non è noto. Si aggiunge tale punto al poliomino.

82 CAPITOLO 3. L ALGORITMO DI CODIFICA 82 A questo punto si seleziona fra i poliomini candidati quello che massimizza una funzione di guadagno che considera come argomenti il numero di punti appartenenti al poliomino e le sue dimensioni. Tale funzione usa una stima del costo di memorizzazione delle colonne e dei punti di contatto del poliomino derivata dalle sue dimensioni. Detta M la maggiore tra larghezza ed altezza, m la minore e p il numero di punti nel poliomino, tale funzione è la seguente: c(m, m, p) = p 2 log 2 m log 2 M (m 1) 2 dove il secondo termine quantifica il costo dei punti di contatto e l ultimo il prezzo di memorizzazione delle colonne o righe. La parte intera inferiore viene utilizzata in modo da poter calcolare il logaritmo in modo rapido utilizzando shift di bit. Si noti che utilizzando tale formula per la scelta del poliomino migliore si è sempre sicuri di rispettare le condizioni imposte in fase di scomposizione di uno strato. La tecnica descritta cerca di avvicinarsi all ottimalità tenendo conto anche dei costi computazionali. Sarebbe infatti troppo impegnativo in fatto di tempi cercare di fare una stima più esatta del costo di ogni poliomino, eseguendo per esempio la codifica per ogni candidato e misurandone così il costo esatto. Inoltre l insieme dei poliomini candidati non è completo in quanto si potrebbe considerare che l espansione verticale in alcuni casi può venir fatta non solo relativamente al primo punto della riga ma anche rispetto ad altri punti. È difficile tuttavia pensare a situazioni in cui un ipotetica funzione ottimale generi risultati apprezzabilmente migliori di questa. Con tale metodo si ottiene dunque un buon fattore di compressione in tempi ragionevolmente brevi Gestione degli alberi di Huffman Gli alberi di Huffman vengono utilizzati per la memorizzazione delle coppie di sequenze negli strati compressi tramite RLE e per la codifica di distanze e delle dimensioni negli strati dove si fa uso di poliomini. L algoritmo utilizzato opera immettendo i simboli in ingresso in una struttura dati provvisoria e conteggiandone le occorrenze. Al termine dei simboli si disporrà dei valori esatti delle frequenze e si dovrà costruire di conseguenza l albero da utilizzare, scorrendo quindi i simboli incontrati e codificandoli nel file compresso. È tuttavia opportuno porre un limite al numero di simboli da inserire in tale struttura provvisoria in quanto fino al momento della codifica tali valori occuperanno una quantità di memoria considerevolmente più alta di quando saranno memorizzati con una notevole richiesta di risorse. Inoltre una volta ottenuto un campione sufficientemente grande da utilizzare come stima per le frequenze si può risparmiare del tempo in fase di codifica scrivendo direttamente i valori sul file compresso. In compenso la costruzione di un albero prima di conoscere tutti i simboli implica di non poter escludere dall albero quelli mai utilizzati causando un occupazione di spazio maggiore. Le due quantità limite utilizzate per strati compressi con poliomini o tramite RLE ed Huffman sono rispettivamente e La differenza di più di un ordine di grandezza è giustificata innanzitutto dal fatto che la memorizzazione di poliomini in una struttura intermedia è onerosa dal punto di vista della memoria occupata e secondariamente perché gli alberi utilizzati nella seconda tecnica hanno un dominio di simboli molto più esteso e traggono un

83 CAPITOLO 3. L ALGORITMO DI CODIFICA 83 guadagno maggiore dall operazione di potatura descritta di seguito. Le casistiche da considerare sono dunque due, una relativa a quando il numero di simboli è minore del limite e l altra a quando solo un campione di questi sarà inserito nella struttura intermedia. Nel primo di questi casi, l albero di Huffman viene costruito avendo a disposizione la distribuzione esatta delle probabilità dei simboli. Dopo la sua costruzione viene eseguita un operazione di potatura che rimuove gli elementi che non compaiono mai permettendo la memorizzazione dell albero in uno spazio minore. Tale operazione viene fatta chiamando sulla radice una funzione che esegue i seguenti passi: 1. Finché il nodo argomento ha un figlio con frequenza pari a zero, tale nodo diventa una copia dell altro suo figlio che invece viene eliminato 2. Se il nodo selezionato non è una foglia, si ripete l algoritmo dal punto uno su entrambi i figli. Tale operazione va fatta prima della codifica in quanto cambia i codici assegnati ad ogni simbolo. Con tale tecnica si permette inoltre una codifica dei simboli lievemente migliore in quanto vengono rimossi dei codici inutili. Un esempio di potatura è in figura 3.1 dove i valori 2 e 3 vengono rimossi dall albero in quanto presentano una frequenza pari a zero. F: 12 F: 12 F: 7 V: 1 F: 5 F: 7 V: 1 F: 5 F: 12 F: 0 F: 5 V: 4 F: 0 F: 5 V: 4 F: 7 F: 5 V: 1 V: 4 F: 0 F: 0 V: 2 V: 3 F: 0 F: 0 V: 2 V: 3 Figura 3.1: Potatura di un albero di Huffman Nel caso in cui invece il numero dei simboli è maggiore del limite imposto, l albero di Huffman viene costruito a partire dalle frequenza dei simboli campione presenti nella struttura dati ausiliaria al momento del suo riempimento. Quindi tutti i valori contenuti vengono codificati e tutti i simboli successivi vengono scritti direttamente sul file. Al momento della costruzione dell albero ai simboli con frequenza zero viene assegnata una frequenza virtuale pari ad uno. Questo per due motivi: innanzitutto si rischierebbe altrimenti di creare un albero molto sbilanciato che assegna ad alcuni simboli con frequenza zero un numero molto grande di bit ed un numero molto limitato ad altri; questo può accadere se, in fase di costruzione dell albero, nel momento della ricerca delle due frequenze minori in caso di parità si seleziona sempre quelli di indice minore o maggiore causando la costruzione di una parte dell albero in modo degenere. Secondariamente così si evita di assegnare probabilità maggiori a simboli

84 CAPITOLO 3. L ALGORITMO DI CODIFICA 84 con frequenze anche molto piccole rispetto ad un grande numero di valori che non sono stati mai incontrati effettuando una stima molto irrealistica. 3.3 Realizzazione dell algoritmo In questa sezione si mostrerà come è stato creato il programma che implementa l algoritmo proposto. La prima fase realizzativa descritta è quella della progettazione, dove le funzionalità vengono suddivise in una serie di classi che interagiscono fra loro. Quindi si mosterà come il programma è stato ottimizzato e reso di rapida esecuzione, e si discuteranno i requisiti di memoria necessari. Verrà esposta una funzionalità sperimentale di compressione con perdita realizzata senza apportare modifiche all algoritmo o al formato file ma applicando una trasformazione che precede il normale processo di compressione. Infine sarà presentato il programma realizzato e verranno esposte le sue varie modalità di utilizzo Progettazione e descrizione delle classi L algoritmo descritto è stato realizzato nel linguaggio Java. Questo linguaggio permette la portabilità delle classi realizzate su di una qualsiasi macchina dotata di Java virtual machine ed offre costrutti molto semplici da comprendere anche per chi non ha una conoscenza approfondita del linguaggio; queste sono due caratteristiche molto importanti per la presentazione di un nuovo algoritmo in quanto se ne facilita così la sperimentazione e lo studio. Inoltre nelle nuove Java virtual machine è presente un compilatore Just In Time (JIT) che permette la compilazione in codice nativo dei vari metodi al momento della loro esecuzione; in questo modo si permette un notevole miglioramento dei tempi di esecuzione senza rinunciare ai vantaggi offerti da una JVM come la sicurezza e la portabilità. Grazie a tale artificio la differenza di prestazioni tra Java ed altri linguaggi compilati come il C si è assottigliata notevolmente, permettendo l implementazione del programma in questo linguaggio mantenendo buoni tempi di esecuzione. Inoltre visto il supporto che la maggior parte dei browser web offre è stato possibile realizzare un applet che permette la visualizzazione su di un sito di un immagine nel formato file qui sviluppato senza alcuna conoscenza del formato stesso lato client. Per una buona realizzazione di un applicazione complessa è fondamentale anteporre alla scrittura del codice una fase di progettazione accurata che suddivida il programma da realizzare in una serie di classi ognuna adibita ad un determinato insieme di funzionalità. Saranno rispettati inoltre gli obbiettivi principali della programmazione a oggetti con particolare attenzione per la riusabilità e l estendibilità. Le classi utilizzate e le loro interazioni sono rappresentate nel diagramma 3.2; per non sovraccaricare il grafico sono state omesse classi fornite nella JRE come i vari stream di input ed output. Il diagramma è concettualmente divisibile in tre parti. La colonna sinistra del grafico rappresenta le classi di interfaccia del programma con il quale l utente può interagire direttamente; sostanzialmente in questi oggetti le operazioni riguardanti la compressione o la decompressione vengono semplicemente inoltrate alle clas-

85 CAPITOLO 3. L ALGORITMO DI CODIFICA 85 Usa Estende numstack pcf BmpImage Stack pcfviewer Layer Poly HTree bitmatrix pcfapplet cpoly streamable BitMatrix readingthread Figura 3.2: Schema delle classi si successive. Alla colonna centrale appartengono le classi che contengono il cuore dell algoritmo di compressione e formano la struttura del file compresso. Tali classi sono in ordine gerarchico: la prima, BmpImage, rappresenta un immagine non compressa che verrà a sua volta scomposta in 24 strati rappresentati dalla classe Layer. Se compresso tramite poliomini, uno strato verrà a sua volta rappresentato da un insieme di oggetti Poly selezionati da un insieme di poliomini candidati associati ad istanze della classe cpoly. La colonna di classi destra infine rappresenta le strutture dati di base tra cui i vettori di bit e gli alberi di Huffman. Per permettere la riutilizzazione anche parziale del codice sviluppato in altri contesti e per facilitare l inclusione della tecnica di compressione proposta in eventuali applicazioni è stata generata una documentazione del codice sotto forma di Javadoc; questi comprendono una serie di pagine HTML che permettono attraverso i collegamenti ipertestuali una consultazione rapida della notevole quantità di dati messi a disposizione. Tra le informazioni messe a disposizione si trova una descrizione delle funzionalità di ogni classe ed un elencazione dei significati dei parametri in ingresso ed in uscita da ogni metodo realizzato. Si vedrà ora il funzionamento ed i compiti assegnati ad ogni classe.

86 CAPITOLO 3. L ALGORITMO DI CODIFICA 86 bitmatrix Classe adibita alla rappresentazione di matrici e vettori di bit. Mette a disposizione metodi per l assegnazione e l estrazione di determinati bit data una determinata posizione ed offre tutte le modalità di lettura e di scrittura sequenziale utilizzate nel formato. Sono presenti inoltre metodi per l input e l output di matrici di bit su file o altri flussi di IO. streamablebitmatrix Classe che estende la precedente offrendo la possibilità di avere a disposizione al momento della lettura della matrice di bit da un flusso di input i bit già letti anche se l operazione di lettura non è ancora terminata; questo implica di avviare un processo parallelo che legga le informazioni in entrata in modo da rendere la chiamata al relativo metodo non bloccante. Nel caso in cui il collo di bottiglia dei tempi sia proprio l operazione di input come ci si aspetta se l immagine compressa è su di un sito remoto, questo permette di effettuare in parallelo la decompressione e la lettura in modo che al termine dell input del file compresso gli strati saranno già stati tutti decompressi. readingthread Thread utilizzato dalla classe precedente per la lettura in parallelo da un flusso in input. Mette a disposizione un metodo per sapere fino a che l informazione è stata letta in modo da poter mettere in attesa un operazione di lettura se il dato richiesto non è ancora disponibile. HTree Classe rappresentante un albero di Huffman. Tale oggetto viene creato in funzione di due vettori rappresentanti i simboli utilizzati e le loro frequenze. I metodi realizzano la scrittura e la lettura di valori tramite tale albero e la memorizzazione ed il ripristino dell albero stesso da una matrice di bit come descritto precedentemente. È presente inoltre il metodo che esegue la potatura dell albero rimuovendo i valori con frequenza zero. Stack Classe messa a disposizione dalla JRE nel pacchetto java.util ed utilizzata come struttura dati intermedia in fase di compressione. Questa classe non viene intesa come una vera e propria pila ma è definita in Java come un estensione di un vettore dinamico che offre modalità di accesso ed inserzione sia in testa sia in una posizione generica. Il suo utilizzo è stato adottato per la sua duttilità e dinamicità. numstack Estensione della classe Stack creata per la gestione diretta di numeri interi.

87 CAPITOLO 3. L ALGORITMO DI CODIFICA 87 bytematrix Classe rappresentante una matrice tridimensionale di byte. Utile per poter variare la rappresentazione fisica di tale struttura, in quanto l allocazione di una matrice a tre dimensioni in Java occupa molto più spazio rispetto ad un vettore contenente le stesse informazioni. Si permette inoltre così una maggiore ottimizzazione degli accessi alla matrice grazie a dei metodi specifici utilizzati per scorrere la matrice in modo sequenziale come avviene durante le operazioni di filtraggio. cpoly Classe rappresentante un poliomino non compresso. Offre funzionalità che implementano le espansioni orizzontali e verticali ed una funzione che genera una stima del costo del poliomino secondo la formula vista in precedenza. Mette inoltre a disposizione un metodo per ottenere il poliomino compresso associato. Poly Classe rappresentante un poliomino memorizzato per colonne e dunque parzialmente compresso. In questa classe è presente il metodo che dato uno strato, la matrice dei punti noti ed il punto a cui è arrivata la codifica, restituisce il poliomino ottimale da codificare. Sono inoltre presenti metodi per l input e l output su flussi di bit a partire da un determinato albero di Huffman relativo alle dimensioni, come definito dalla codifica. Layer Classe associata ad uno strato dell immagine. Mette a disposizione i metodi per la codifica e la decodifica relativamente a tutti e tre i metodi descritti; per la decompressione non deve essere necessariamente noto a priori il metodo utilizzato, in quanto è possibile richiamare il metodo generico che inoltrerà la chiamata a seconda delle informazioni nell intestazione. Analogamente è presente il metodo che determina l algoritmo di compressione migliore. Viene qui implementata inoltre la scomposizione in strati che data una matrice a tre dimensioni restituisce 24 oggetti di tipo strato. Sono presenti inoltre i metodi per il confronto tra strati e la lettura e scrittura delle zone di base e dell intestazione. Infine una serie di funzioni consentono la manipolazione dei parametri variabili del programma. BmpImage Classe rappresentante un immagine non compressa. Mette a disposizione le funzioni necessarie per tutte e tre le operazioni di filtraggio e le loro inverse, oltre che per la determinazione dei filtri ottimali. È presente un metodo che esegue la compressione, prima filtrando l immagine, quindi scomponendola in strati ed infine richiamando le funzioni di compressione presenti negli oggetti di tipo Layer. L operazione che esegue la decompressione avverrà in modo del tutto simmetrico richiamando inoltre un metodo della classe adibito alla ricostruzione dell immagine dai 24 strati che la compongono. Esistono inoltre i metodi relativi alla lettura ed alla scrittura dei filtri selezionati e della mappa dei valori. In questa classe sono presenti inoltre le funzioni

88 CAPITOLO 3. L ALGORITMO DI CODIFICA 88 per la lettura e la scrittura di immagini in formato BMP. Infine è possibile attraverso una varietà di metodi cambiare i parametri variabili dell algoritmo. pcfviewer Classe per la visualizzazione di immagini compresse. Dato in ingresso un nome di file compresso o un oggetto di tipo BmpImage, tale classe provvede a visualizzarne il contenuto su schermo in una finestra di apposite dimensioni. Se l immagine supera le dimensioni del desktop, sarà effettuato un ridimensionamento ed una visualizzazione a dimensioni ridotte. pcf Classe di interfaccia per la compressione e la decompressione. Funzionante da riga di comando, supporta una serie di opzioni per la variazione dei parametri dell algoritmo che verranno inoltrate alle classi che si occupano della codifica e della decodifica. pcfapplet Applet per la visualizzazione di immagini compresse all interno di un browser web. L url del file compresso relativo o assoluto deve essere fornito come parametro e l immagine sarà visualizzata nella zona relativa all applet stessa Ottimizzazione dei tempi L implementazione è stata realizzata prestando particolare attenzione a mantenere limitati i tempi di esecuzione, in particolare durante l operazione di decompressione. Si presume infatti che per un immagine l operazione di codifica venga eseguita molto più raramente della sua inversa e che in questo primo caso il fattore tempo non sia critico. I principali accorgimenti utilizzati sono elencati di seguito: Utilizzo degli operatori bit a bit Gli operatori bit a bit permettono di manipolare valori a partire dalla loro rappresentazione binaria e la loro rapidità è diverse volte maggiore di altri operatori come la moltiplicazione o la divisione, che sono stati il più possibile evitati. Gli operatori bit a bit utilizzati sono i seguenti, riportati nella notazione utilizzata in java: >> shift destro: tutti i bit vengono traslati di n posizioni verso destra; gli n bit più a destra del numero originale dunque verranno scartati e gli n bit più a sinistra verranno riempiti con il bit di segno del numero. >>> shift destro senza segno: tutti i bit vengono traslati di n posizioni verso destra; al contrario dell operatore precedente tuttavia i bit più a destra vengono riempiti con zeri. << shift sinistro: tutti i bit vengono traslati di n posizioni verso sinistra; gli n bit più a sinistra del numero originale dunque verranno scartati e gli n bit più a destra verranno riempiti con zeri.

89 CAPITOLO 3. L ALGORITMO DI CODIFICA 89 ˆ xor: ogni bit del risultato sarà uno se i due bit degli operandi nella stessa posizione hanno valore diverso, zero altrimenti. & and ogni bit del risultato sarà uno se i due bit degli operandi nella stessa posizione sono uguali ad uno, zero altrimenti. or: ogni bit del risultato sarà uno se almeno uno dei due bit degli operandi nella stessa posizione è uguali ad uno, zero altrimenti. Con tali operatori vengono effettuate rapidamente le moltiplicazioni, le divisioni ed i moduli con argomenti pari a potenze di due. In particolare sono stati utilizzati nella classe bitmatrix che, gestendo l input e l output a basso livello, potrebbe costituire facilmente se mal implementato il collo di bottiglia dell algoritmo. Considerato che il valore val è il byte contenente il bit di riferimento ed off è la posizione del bit, di seguito sono riportate in pseudocodice le funzioni per l estrazione e l assegnazione di valori di bit: setbit(val, off, b): if (b == 0) { val = val & ((1 << off) ^ 255) } else { val = val (1 << off) } getbit(val, off): return (val >>> off) & 1 xorbit(val, off, b): val = val ^ (1 << off) L utilizzo di tale tecnica nella classe bitmatrix al posto delle operazioni di divisione e moltiplicazione velocizza l esecuzione dell algoritmo di circa un fattore 2.5. Assenza di controlli a basso livello Essendo i metodi della classe bitmatrix richiamati molto di frequente, non vengono eseguiti controlli sui parametri in ingresso; questo vuol dire che in determinati casi se gli argomenti dei metodi non sono coerenti, facendo per esempio riferimento a punti fuori dai limiti della matrice o cercando di imporre un valore binario ad un numero maggiore di uno, l oggetto potrebbe avere dei comportamenti anomali. Tali situazioni non accadono grazie alla correttezza delle classi chiamanti, e tale accorgimento consente un miglioramento dei tempi di esecuzione di circa un 10-15%. Nulla impedisce comunque a chi volesse riutilizzare il codice per altri impieghi di estendere la classe inserendo tali controlli. Gestione della matrice di byte La classe bytematrix gestisce la matrice tridimensionale rappresentante l immagine con un vettore ad un unica dimensione e creando una corrispondenza biunivoca tra

90 CAPITOLO 3. L ALGORITMO DI CODIFICA 90 l indirizzamento logico a tre dimensioni con i valori x, y e z ad un indirizzo fisico di valore x d h + y h + z dove d ed h sono rispettivamente la profondità e l altezza della matrice. L accesso ad un elemento richiede dunque in generale tre prodotti (tali operazioni sarebbero comunque implicite se la matrice fosse stata rappresentata direttamente in tre dimensioni); memorizzando il valore d h al momento della creazione della matrice si riduce tale numero a due, ma ciò è comunque indesiderabile visto che questa sarebbe un operazione pesante. Dunque nelle implementazioni dei metodi per lo scorrimento sequenziale della matrice l indirizzo viene calcolato tramite somme o sottrazioni dall indirizzo precedente, ed in modo simile vengono calcolate le posizioni dei punti usati nel filtraggio. Ad esempio, detto cur il punto a cui è arrivato lo scorrimento sequenziale, il punto in basso alla sua sinistra può venir calcolato come cur d d h dove d h è un numero già noto come descritto prima. Dunque l intera operazione di filtraggio e la sua inversa vengono interamente eseguite senza effettuare prodotti o divisioni (quelle definite nei filtri vengono calcolate con shift di bit). Ciò velocizza l operazione di rimozione ed applicazione dei filtri di circa un 25%. Scomposizione della matrice Durante la scomposizione della matrice ogni suo byte deve venir scomposto in bit ed ognuno di questi deve venir assegnato allo strato relativo alla sua posizione. Tuttavia dopo il filtraggio ci si aspetta di avere molti valori piccoli; unito al fatto che i valori di uno strato vengono inizializzati a zero, si può risparmiare del tempo fermandosi quando tutti i bit uguali ad uno sono stati inseriti. Considerando che val è il valore da scomporre ed s è il vettore rappresentante gli strati relativi al colore in considerazione, il seguente pseudocodice realizzerebbe la scomposizione in modo banale: for (int b = 0; b < 8; b ++) { l[b].setbit(x,y,val & 1); val = val >>> 1; } La condizione del for è stata invece scritta in modo più efficiente: for (int b = 0; val > 0; b ++) { l[b].setbit(x,y,val & 1); val = val >>> 1; } In questo modo si risparmia un 30-35% del tempo impiegato per la scomposizione. In questa fase inoltre si conteggia per ogni strato quanti valori pari ad uno sono presenti in modo da selezionare efficientemente il metodo di compressione. Rimozione dei filtri Le tre operazioni di rimozione dei filtri vengono eseguite con un unica passata dell immagine; per ogni terna di byte rappresentanti un pixel viene innanzitutto eseguita la riassegnazione inversa, quindi vengono rimossi i filtri per colore ed infine

91 CAPITOLO 3. L ALGORITMO DI CODIFICA 91 i filtri standard. Questo non diminuisce le operazioni da effettuare, ma trae vantaggio dal principio di località visto che tutti i dati vengono scorsi un unica volta. Per quanto riguarda i filtri da utilizzare per l inversione, questi sono memorizzati in un vettore e l identificazione del filtro da utilizzare per un determinato punto richiede un prodotto e l accesso a questa struttura. Sfruttando tuttavia il fatto che i filtri utilizzati durante uno scorrimento sequenziale variano solo quando l indice di riga o di colonna è multiplo del lato di una zona di filtraggio, questi vengono ricalcolati solo in questo caso. Si riducono così i tempi per la rimozione dei tre filtri di circa un 25%. Tali tecniche unite a numerosi altri accorgimenti minori ed un attenta stesura del codice rendono l esecuzione dell algoritmo rapida ed efficiente. Un analisi dei tempi di esecuzione ottenuti verrà esposta nella parte di questo lavoro relativa alla sperimentazione del programma Requisiti di memoria Per l esecuzione della compressione e della decompressione è necessaria una quantità di memoria pari al doppio di quella occupata dall immagine non compressa sia in fase di compressione che in fase di decompressione; tale quantità viene utilizzata nelle fasi dove si passa dalla rappresentazione in strati monodimensionali a quella in una matrice tridimensionale e viceversa, in quanto entrambe queste strutture con dimensione pari all immagine vengono rappresentate contemporaneamente. Le strutture dati utilizzate nelle restanti fasi dell algoritmo hanno dimensioni ridotte ed a meno di trattare con immagini molto piccole non causano il superamento di tale soglia. La quantità di memoria richiesta dunque può essere notevole ma considerando lo stato di tecnologia attuale non rappresenta un problema in quanto le dimensioni di un immagine sono solitamente inferiori di circa due ordini di grandezza rispetto a quelle a disposizione in un calcolatore; per fare esempio un immagine bitmap di dimensioni pixel occupa circa 2.3 MB ed una di circa 5.6 MB, e non è insolito avere a disposizione computer con memorie di 256 o 512 MB. Considerando comunque immagini molto grandi con una risoluzione molto elevata effettivamente l algoritmo risulta impossibile da applicare. In seguito sarà proposta comunque una possibile evoluzione del programma che tramite una diversa organizzazione dei dati nel file compresso permette l applicazione del solito algoritmo con quantità di memoria drasticamente minori Una funzionalità aggiuntiva: il filtro lossy Sebbene l algoritmo sviluppato sia senza perdita, è stata fatta anche una breve ricerca per quanto riguarda la compressione lossy che viene quindi offerta come funzionalità aggiuntiva del programma. Questa viene fatta senza imporre modifiche al formato ma effettuando una trasformazione sull immagine da comprimere prima di applicare l algoritmo. Tale operazione è formata innanzitutto dall operazione standard di determinazione dei filtri e quindi dall applicazione di un filtro con perdita basato sui filtri normalmente applicati. Il filtro lossy richiede come argomento un intero n rappresentante il livello di perdita. Quindi considera ogni byte dell immagine e la sua stima effettuata tramite

92 CAPITOLO 3. L ALGORITMO DI CODIFICA 92 il filtro scelto per la sua zona ed impone che la differenza tra i due sia un multiplo di 2 n arrotondando il valore del byte dell immagine al numero più vicino che soddisfa tale condizione; nel caso in cui il valore selezionato sia equidistante da due interi di questo tipo si seleziona quello che restituisce il numero più vicino a zero modulo 256. Dopo tale operazione ed il filtraggio ci si aspetta che ogni valore sia un multiplo di 2 n, proprietà che perdura anche dopo il filtraggio per colore visto che la sottrazione propaga questa proprietà dai suoi argomenti al risultato. Dunque il bit meno significativi di ogni valore saranno uguale a zero e gli n 3 strati rappresentanti questi bit, che solitamente sono i più caotici ed i meno comprimibili, saranno formati da soli zeri. L idea alla base di questa operazione è quella di guadagnare spazio rimuovendo i dati meno significativi dall immagine. Per quanto riguarda le ripercussioni sulla percezione visiva di questa trasformazione si presume queste siano buone in quanto si avvicina ogni punto dell immagine al valore di una sua stima basata su ipotesi di continuità. Il problema più grave si presenta per n elevati quando per l operazione di arrotondamento avviene che in zone con valori che variano lievemente si creano brusche discontinuità molto percettibili. Per questi motivi il valore suggerito per n è uno; in questo modo si garantisce che qualunque sia l immagine l errore sarà molto piccolo ed impercettibile alla vista. Il bit meno significativo infatti influenza molto poco la sfumatura di colore e per molte immagini rappresenta solo un rumore di fondo generato durante l acquisizione. In certi casi può accadere che anche altri livelli diano risultato molto buoni, in particolare quando non sono presenti molte sfumature. In ogni caso tale tecnica offre delle caratteristiche spesso assenti in altri formati lossy: 1. Controllo dell errore: per qualsiasi immagine che venga passata al filtro lossy, sappiamo che al massimo l errore su ogni byte sarà di 2 n 1. Inoltre l errore medio è solitamente piccolo rispetto a questo intervallo per le ipotesi di continuità dei filtri; in altre parole è molto probabile in un immagine trovare molti valori che si avvicinano ai valori stimati. Per valori piccoli di n l errore medio si avvicina alla quantità n/2. 2. Non propagazione dell errore: una doppia applicazione del filtro lossy chiaramente non introduce errori cumulativi. Inoltre è semplice osservare che se un immagine viene passata dal filtro lossy e compressa ed in seguito riaperta e ricompressa in modo lossless il livello di compressione è lo stesso ottenibile dopo la trasformazione lossy, a patto ovviamente di utilizzare gli stessi filtri. Questo è utile nel caso in cui un immagine compressa in modo lossy debba venir aperta per subire qualche piccolo ritocco; in questa situazione la parte non modificata gode ancora della maggiore comprimibilità data dal filtro lossy. 3. Miglioramento dei tempi: creando dopo la scomposizione degli strati vuoti codificabili e decodificabili molto rapidamente, si migliorano i tempi di compressione e di decompressione dell immagine Presentazione del programma e suo utilizzo Il programma sviluppato si interfaccia con l utente in tre diverse modalità corrispondenti alle tre classi pcf, pcfviewer e pcfapplet. Le modalità di utilizzo ed il loro

93 CAPITOLO 3. L ALGORITMO DI CODIFICA 93 funzionamento sono descritti di seguito. Classe pcf - programma principale per la compressione e la decompressione La classe pcf è la principale di quelle presentate all utente ed esegue le molteplici funzionalità dell algoritmo per quanto riguarda la compressione e la decompressione. Sono offerte inoltre una varietà di opzioni per variare le modalità di esecuzione. La lingua scelta per la comunicazione con l utente per eventuali messaggio in uscita è l inglese; questo è utile per rendere l algoritmo più semplicemente utilizzabile da qualsiasi tipo di utente. Tale classe funziona da linea di comando, e la sua sintassi è la seguente: pcf {file sorgente} [{file destinazione}] [-c -u] [-ic] [-iu] [-fast] [-view] [-v] [-fv] [-console] [-hc] [-lc] [-lossy:1-4] [-check] [-lcheck] [-h] [-d:0-4] [-f:1-12] [-cf:1-3] [-fzd:4-128] [-cfzd:4-128] [-zz:0 1] Dove la classe pcf appartiene al pacchetto pcf. Un esempio di utilizzo potrebbe essere dato dal comando java pcf.pcf immagine.bmp. Di seguito è spiegato il significato dei vari parametri: File sorgente: Il file da comprimere o decomprimere. Se l opzione di compressione -c o -u non è specificata, questo determina l azione di default da eseguire, in particolare se l estenzione del file è.bmp questo viene compresso e se l estensione è.pcf questo viene decompresso. Nel primo di questi casi, il file sorgente deve essere un file BMP che usa 24 bit per pixel. File destinazione: Il nome del file da scrivere; se questo esiste già verrà sovrascritto. Se questo non è presente verrà generato un nome file automaticamente aggiungendo la giusta estenzione al nome del file sorgente. c Comprime il file sorgente u Decomprime il file sorgente iu Stampa su standard output le informazioni di intestazione dell immagine non compressa, come la risoluzione di stampa e le dimensioni in pixel. ic Stampa su standard output le informazioni di intestazione del file compresso, tra cui la versione del compressore, le dimensioni delle zone di filtraggio ed il numero di filtri utilizzati. hc Stampa su schermo il codice hash dell immagine. v Stampa la versione dell algoritmo di compressione utilizzato. fv Stampa la versione dell algoritmo utilizzata per il file compresso. console Stampa informazioni dettagliate sullo svolgimento dell algoritmo. h Stampa una schermata di aiuto con la descrizione dei parametri utilizzabili.

94 CAPITOLO 3. L ALGORITMO DI CODIFICA 94 lc Opzione utilizzabile in fase di compressione, abilita il confronto tra strati. Come detto in precedenza, tale opzione molto raramente migliora la quantità della compressione ma in compenso peggiora i tempi di esecuzione e richiede più memoria; chiaramente tale opzione è sconsigliata. d:1-16 Specifica in fase di compressione ogni quanti punti sarà selezionato un pixel campione per la determinazione dei filtri. Il valore di default è uno (tutti i punti vengono considerati) ma alzando questo valore a valori come 3 o 4 si possono ottenere tempi di compressione minori con un piccolo sacrificio di spazio; utilizzare numeri maggiori tuttavia può voler dire perdere il tempo risparmiato in fase di compressione, in quanto il dato risultante dal filtraggio risulterebbe maggiormente caotico; per questo valori maggiori di 4 sono sconsigliati. fn:1-13 Specifica il numero di filtri da utilizzare in fase di compressione. La quantità di default è 12; si può risparmiare tempo a prezzo di una compressione lievemente peggiore diminuendo tale quantità. Se i filtri di indice maggiore non vengono mai utilizzati, è possibile che tale quantità venga ridotta dall algoritmo automaticamente. cfn: 1-3 Specifica in fase di compressione il numero di filtri per colore da utilizzare. Come sopra, numeri minori di quello di default 3 possono velocizzare il procedimento. Anche tale quantità in alcuni casi può venir ridotta automaticamente. fzd: Numero che deve essere multiplo di due. Questa quantità specifica la dimensione del lato del quadrato rappresentante una zona di filtraggio. Numeri minori consentono di dettagliare meglio questa operazione, numeri maggiori consentono un risparmio di spazio per la memorizzazione dei filtri. Il valore di default è 8 ed è quello complessivamente ottimale rispetto al campione di immagini utilizzate nella sperimentazione; in alcuni casi si possono ottenere risultati lievemente migliori in compressione variando questa quantità, in particolare con le dimensioni 16 o 32. cfzd: In modo del tutto analogo all opzione precedente, con questa si può variare la dimensione di una zona di filtraggio per colore. zz: 0-1 Abilita (1) o disabilita (0) la visita a zigzag negli strati compressi tramite RLE ed Huffman. Rimuovere questa opzione attivata per default vuol dire ottenere file lievemente più grandi ma permettere una decompressione lievemente più veloce. fast Attiva la compressione rapida. Questa è in realtà una metaopzione di comodo che aggiusta altri parametri in modo da ottenere il massimo rapporto fra compressione ottenuta e tempo utilizzato. Questa opzione è inattiva per default poiché si presume che essendo l operazione di compressione eseguita molto raramente, anche un piccolo guadagno di spazio giustifica una compressione più lenta. L insieme di opzioni impostate sono fn = 6, d = 4, zz = 0, fzd = 16, cfzd = 16. Con questa funzionalità si velocizzano i tempi di compressione di circa un 20% ed i tempi di decompressione di un 5-10% con un aumento di dimensioni dei file prodotti intorno al 3-4%. Se vengono specificate altre opzioni in modo contraddittorio a queste, le successive sostituiranno le precedenti. Per

95 CAPITOLO 3. L ALGORITMO DI CODIFICA 95 esempio, il comando pcf immagine.bmp -fast -fn:7 utilizza i parametri fn = 7, d = 4, zz = 0, fzd = 16 e cfzd = 16. lossy:1-4 Applica il filtro lossy prima della compressione con livello di perdita n. Valori maggiori di 4 non sono permessi a causa dell eccessiva perdita di qualità. check Impone che in fase di decompressione venga controllata l esattezza della ricostruzione dell immagine tramite il controllo del codice hash, scrivendo su standard output un messaggio che ne confermi la correttezza o eventualmente segnali un errore. Se questa opzione non viene specificata, tale controllo viene omesso. lcheck Impone il controllo dell esattezza della ricostruzione di ogni strato. Al contrario dell opzione precedente viene fatta una stampa su schermo solo in caso di errore; la conferma dell esattezza di tutti gli strati appesantirebbe infatti l output e viene fatta solo se l opzione console è attivata. view Visualizza l immagine su schermo. Se utilizzata durante una compressione con perdita l immagine visualizzata è quella ottenuta dopo il passaggio dal filtro lossy. Per effettuare tale operazione viene richiamata la classe pcfviewer. Classe pcfviewer: visualizzazione dell immagine compressa in finestra La classe pcfviewer è un semplice visualizzatore di immagini. Si permette così la visualizzazione di file compressi senza effettuare il passaggio da un file bmp intermedio. Funzionante da linea di comando, la classe si aspetta come primo ed unico parametro il nome del file compresso. Classe pcfapplet: visualizzazione dell immagine compressa su browser La classe pcfapplet permette l utilizzo di file compressi con l algoritmo qui sviluppato su di un sito web anche senza nessuna compatibilità lato client richiedendo solo il supporto del linguaggio java da parte del browser. L applet si aspetta un unico parametro di nome image contenente il nome del file da visualizzare comprensivo eventualmente di un percorso assoluto o relativo. Il codice html per la visualizzazione di un immagine dovrà essere cambiato per esempio dal seguente: <img src="immagine.png" width="450" height="300"> al codice richiamante l applet: <applet code="pcf.pcfapplet.class" width="450" height="300"> <param name="image" value="immagine.pcf"> </applet> Tale porzione di codice richiede che l applet sia visibile dal percorso della pagina così come le altri classi necessarie alla decompressione; in caso contrario devono essere specificati i parametri che descrivono un percorso per esempio tramite l opzione HTML codebase. L applet esegue la decodifica dell immagine utilizzando una matrice di bit streamable, in modo da consentire la decompressione anche prima del termine

96 CAPITOLO 3. L ALGORITMO DI CODIFICA 96 dello scaricamento dell immagine. In questo modo i tempi di attesa dell utente dati dall algoritmo di decodifica sono dati solo dalle fasi di ricostruzione dell immagine e di rimozione dei filtri, costituenti solo una piccola fetta minima dei tempi impiegati durante la decompressione.

97 Capitolo 4 Sperimentazione 4.1 Presentazione del campione di immagini In questa sezione ci si occuperà del campione di immagini selezionato per effettuare la sperimentazione. Si mostrerà come i dati siano stati scelti in modo da considerare le casistiche più interessanti al variare di caratteristiche che possono influenzare la compressione. È presente inoltre una descrizione delle qualità salienti di tutte le immagini, in modo da poter valutare in fase di analisi dei risultati che caratteristiche influenzino maggiormente l efficacia dell algoritmo proposto Criteri di scelta del campione di immagini Per eseguire una sperimentazione accurata e valutare le prestazioni dell algoritmo e come queste reagiscano davanti a varie caratteristiche dell immagine, è opportuno selezionare una serie di immagini che si differenzino nei confronti di determinati fattori. Di seguito saranno elencate le caratteristiche usate come criteri di scelta del campione. Origine dell immagine: Le immagini studiate differiscono per quanto riguarda la loro origine; sono state considerate sia immagini ottenute da dispositivi di acquisizione come macchine fotografiche o scanner sia create direttamente da elaborazioni digitali sia generate tramite l applicazione di ritocchi digitali a fotografie. Nel caso di immagini acquisite, ci si aspetta un rumore di fondo che può influenzare la compressione. Qualità: Alcune delle immagini scelte presentano imperfezioni per quanto riguarda la loro qualità a causa per esempio di acquisizione tramite scanner a bassa precisione. Tali imperfezioni possono influenzare l efficienza dei vari algoritmi di compressione in vari modi. Dimensioni: Le immagini selezionate si differenziano notevolmente per quanto riguarda le loro dimensioni in pixel. Questo permette di studiare come l algoritmo migliori o peggiori le sue prestazioni al crescere della mole di dati da processare. Colorazione: Il numero di colori in un immagine influenza la quantità di infor- 97

98 CAPITOLO 4. SPERIMENTAZIONE 98 mazione in essa contenuta. Nel campione sono presenti sia immagini molto colorate sia immagini con poche tonalità o con zone di colore uniforme. Questo aiuta a capire come cambino le prestazioni nei casi di alta o bassa comprimibilità; vi sono anche due immagini in tonalità di grigio per verificare in che modo i vari algoritmi di compressione usati per il confronto si adattino a questa caratteristica. Quantità di contorni: Ci si aspetta che un immagine con molti contorni sia di minore comprimibilità rispetto ad una con un numero di soggetti limitato. Un contorno è sostanzialmente una zona ricca di informazione; si cerca dunque di capire quanto tale caratteristica influenzi i vari algoritmi. Insieme alla quantità di colori utilizzati, questa caratteristica può considerarsi un indicatore di regolarità dell immagine Descrizione delle caratteristiche salienti delle immagini Per comprendere dai risultati i punti forti e deboli di un algoritmo è necessario cercare di isolare le caratteristiche che lo avvantaggiano maggiormente nei confronti degli altri. Per questo si procederà di seguito alla descrizione delle caratteristiche salienti delle immagini nel campione scelto. Bavoil rose, 1024 * 640 pixel Immagine realizzata in computer grafica rappresentante una rosa coperta di rugiada in primo piano con uno sfondo sfumato di colore verde. Blame1, 1033 * 768 pixel Immagine fumettistica in sfumature di grigio presentante grandi campi di colore uniforme. Blue-seascape, 800 * 600 pixel Immagine creata in modo artificiale rappresentante uno schizzo di un paesaggio marittimo con l utilizzo di linee nette di diverse sfumature di blu. Bluesphere, 1600 * 1200 pixel Immagine realizzata al computer rappresentante una pavimentazione irregolare con al centro una piccola sfera blu che riflette l ambiente circostante. È presente un effetto di luce proveniente dalla destra dell immagine che rende tutto l ambiente rappresentato lievemente sfumato. Bosque-del-apache-tree, 423 * 640 pixel Immagine rappresentante un albero davanti ad un lago con della vegetazione che si confonde con il riflesso dell albero stesso. L immagine alterna zone molto irregolari in corrispondenza dei rami dell albero con colori abbastanza uniformi nelle zone rappresentanti l acqua ed il cielo.

99 CAPITOLO 4. SPERIMENTAZIONE 99 Brewing storm, 1024 * 768 pixel Immagine rappresentante un bosco con un cielo che presagisce una tempesta incombente. I colori utilizzati sono limitati alla tonalità più scure. All immagine è stata applicata un elaborazione digitale che realizza un effetto a mosaico. Chess clip1, 206 * 228 pixel L immagine rappresenta una foto ravvicinata di una scacchiera con contorni netti in primo piano e una perdita di messa a fuoco per quanto riguarda lo sfondo. Dali - Die Beständigkeit der Erinnerung, 469 * 340 pixel Piccola immagine rappresentante la celebre persistenza della memoria di Dalì. L immagine presenta delle imperfezioni dovute probabilmente ad un sistema di acquisizione di bassa qualità. Dice, 1024 * 768 pixel Immagine realizzata artificialmente rappresentante una distesa di dadi uno accanto all altro. I colori utilizzati sono limitati e molto uniformi. Earth from space, 1600 * 1200 pixel Immagine creata al computer rappresentante la terra vista dallo spazio. Si alternano contorni netti ed irregolarità nella rappresentazione del globo con il fondo stellato prevalentemente nero. Entrata duomo, 720 * 1080 pixel Fotografia ottenuta tramite una macchina fotografica digitale rappresentante un entrata del duomo di Firenze. La foto è stata fatta in modo da catturare l immagine del campanile ed uno scorcio di cielo; l immagine è molto irregolare per quanto riguarda l edificio e la sua facciata e presenta invece solo sfumature di blu sullo sfondo. Firenze smn, 1024 * 683 pixel Fotografia rappresentante la facciata della chiesa di Santa Maria Novella con una grande porzione di cielo sullo sfondo. Immagine nel complesso abbastanza regolare. Fishes, 416 * 312 pixel Immagine rappresentante dei pesci in un acquario. L immagine è molto sfumata a causa dell effetto di rifrazione dell acqua. Florence, 735 * 420 pixel Foto paesaggistica di Firenze. L immagine ha molti contorni netti nella zona rappresentante la città ed è più uniforme nella parte superiore con il cielo.

100 CAPITOLO 4. SPERIMENTAZIONE 100 Fractczaczka, 782 * 569 pixel Immagine rappresentante un frattale. Sono presenti molti contorni netti ma un numero limitato di colori. From overlook 3, 720 * 576 pixel Immagine che rappresenta un canyon visto da un punto di osservazione elevato. Sono presenti numerosi contorni netti ma poche sfumature di colore. Frozen-flower, 350 * 262 pixel Foto di un fiore rimasto congelato in una struttura di ghiaccio. L immagine è molto irregolare per quanto riguarda colori e contorni. Galaxybirth, 1024 * 768 pixel Immagine rappresentante un immagine spaziale creata tramite un calcolatore. Il fondo dell immagine è principalmente nero e su di esso compare la rappresentazione di una galassia in sfumature rosse e bianche. Gatto, 1024 * 769 pixel Foto di un gatto adagiato su di una coperta. Immagine mediamente varia per quanto riguarda colori e contorni in tutta la sua estensione. Hack-lse , 1024 * 768 pixel Immagine fumettistica rappresentante una bambina ed uno sfondo astratto con un effetto di luce ricco di colori e senza contorni netti. Keyboard, 432 * 285 pixel Immagine rappresentante alcuni tasti di una tastiera visti da vicino. I colori utilizzati sono prevalentemente tonalità di blu. Labyrinth, 632 * 470 pixel Immagine rappresentante un labirinto bianco su fondo nero. Immagine ad alto contrasto molto ricca di contorni e povera di colori. Leaf-dying-in-light, 648 * 432 pixel Foto di una foglia secca sotto la luce; lo sfondo è sfumato a causa della perdita di messa a fuoco. Presenti contorni molto distinti in primo piano ed ampie sfumature in secondo. L uso di colori è abbastanza ricco. Leaves, 300 * 388 pixel Immagine delle foglie di un albero in un periodo autunnale con molti controni netti e cambi improvvisi di colore.

101 CAPITOLO 4. SPERIMENTAZIONE 101 Lenna, 512 * 512 pixel Questa immagine rappresentante Lena Soderberg è dagli anni settanta una delle più utilizzate per test su elaborazione di immagini per quanto riguarda compressione o vari algoritmi di rielaborazione; l immagine è più nota con il nome di Lenna per incoraggiare la corretta pronuncia nella lingua inglese. Vi è rappresentato un volto di donna con un cappello piumato, e vi si alternano zone regolari e caotiche. Piccione, 1080 * 720 pixel Immagine rappresentante un primo piano di un piccione, con uno sfondo erboso in secondo piano leggermente fuori fuoco. Immagine acquisita tramite una macchina fotografica digitale. Pine tree arch, 720 * 576 pixel Immagine che rappresenta un canyon su di uno sfondo bianco. I colori utilizzati sono limitati principalmente a sfumature rosso arancioni. Ponte vecchio, 800 * 533 pixel Immagine rappresentante il celeberrimo ponte di Firenze. Più regolare per colori e contorni nella zona superiore con il cielo e nella parte inferiore con l acqua, questa fotografia contiene zone più caotiche nella sua parte centrale contenente la figura del ponte stesso. Power of bryce, 1024 * 768 pixel Immagine realizzata artificialmente con una figura astratta in sfumature di rosso nella parte centrale e due bande di colore bianco sopra e sotto di questa. I colori utilizzati sono in numero limitato; vi sono contorni molto netti unicamente nella parte centrale. Rain, 939 * 547 pixel Questa immagine rappresenta una superficie esposta alla caduta di gocce di pioggia. I colori usati sono principalmente tonalità rossastre, e la fotografia è pienamente a fuoco soltanto nella parte in primo piano. Red blue and grey, 1024 * 768 pixel Immagine rappresentante un motivo astratto molto vario per quanto riguarda colori e contorni. Red n yellow cana lily, 640 * 484 pixel Primo piano di un fiore estremamente colorato in sfumature rosse e gialle.

102 CAPITOLO 4. SPERIMENTAZIONE 102 Rock, 400 * 223 pixel Sezione di una roccia con venature di vari colori ricoperta da una superficie lucida che crea un riflesso della luce a cui la pietra è esposta. Sphere, 399 * 399 pixel Immagine realizzata in computer grafica rappresentante una sfera arancione di colore non uniforme grazie ad un effetto di rendering con delle piccole sfere bianche applicate sulla sua superficie rappresentate invece da sequenze di punti sempre uguali. Tree texture, 620 * 620 pixel Texture rappresentante la corteccia di un albero. Sono presenti un buon numero di colori e numerosi contorni. Vangogh - Autoritratto, 662 * 800 pixel Autoritratto del celebre autore con tratteggi neri su fondo bianco. Vangogh starrynight little, 225 * 180 pixel Immagine molto piccola rappresentante il famoso lavoro intitolato Notte stellata. L andamento dell immagine è abbastanza irregolare nei colori e nei contorni. Zampillo fontana, 800 * 1200 pixel Fotografia digitale rappresentante uno zampillo di una fontana sullo sfondo di una serie di case. L immagine è molto varia per quanto riguarda colori e contorni 4.2 Risultati della sperimentazione In questa sezione di vedranno i risultati ottenuti dall algoritmo proposto per quanto riguarda tempi impiegati e fattore di compressione ottenuto. Le dimensioni dei file creati verranno quindi confrontate con quelle altri formati compressi di comune utilizzo Confronto con altri formati file esistenti La tabella 4.1 mostra le prestazioni dell algoritmo sviluppato in questo lavoro con i parametri di default, nominato Polyomino Compressed Format (pcf) versione 1.0. Le dimensioni dei file sono indicate in KByte; le colonna più a destra indicano il fattore di compressione sia in rapporto al file BMP originale sia in bit per byte. Quest ultima unità di misura è molto utilizzata per quanto riguarda la compressione e specifica quanti bit mediamente sono stati utilizzati per codificare un byte del dato originale. Si mostreranno ora le prestazioni dell algoritmo sviluppati al confronto con altri formati file compressi di utilizzo diffuso. Prima di procedere con i risultati

103 CAPITOLO 4. SPERIMENTAZIONE 103 Nome file bmp (KB) pcf (KB) F. comp. b per B bavoil rose : blame : blue-seascape : bluesphere : bosque-del-apache-tree : brewing storm : chess clip : dali - die bestandigkeit de : dice : earth from space : entrata duomo : firenze smn : fishes : florence : fractczaczka : from overlook : frozen-flower : galaxybirth : gatto : hack-lse : keyboard : labyrinth : leaf-dying-in-light : leaves : lenna : piccione : pine tree arch : ponte vecchio : power of bryce : rain : red blue and grey : red n yellow canna lily : rock : sphere : tree texture : vangogh - autoritratto : vangogh starrynight little : zampillo fontana : Totale : Tabella 4.1: Risultati della compressione verrà presentata una descrizione dei parametri di compressione utilizzati per i vari algoritmi.

104 CAPITOLO 4. SPERIMENTAZIONE 104 Portable Network Graphics Il livello di compressione ottenuto nel formato PNG può variare molto a seconda dei filtri utilizzati; l utilizzo di un filtraggio adattivo ottiene solitamente i risultati migliori. Per la compressione in questo formato è stato utilizzato un programma creato appositamente per l ottimizzazione delle dimensioni delle immagini che determina automaticamente la configurazione di filtri migliore. È stato disattivato inoltre l ordine di visita interlacciato utile alla streamability che può però aumentare le dimensioni del file. Nei file selezionati non sono presenti informazioni riguardanti un eventuale trasparenza dei punti; in caso contrario per eseguire un confronto equo sarebbe stato necessario rimuovere tali dati. ZIP I file ZIP sono stati compressi utilizzando un programma di compressione supportante vari formati chiamato IZArc; i file prodotti sono lievemente più piccoli di quelli ottenibili con il celebre WinZip versione 8.1. Quest ultimo programma ha introdotto dalla versione 9 un nuovo formato ZIP che sfrutta gli algoritmi PPMd e bzip2; il funzionamento di tali tecniche è tuttavia implementato anche nel formato 7z che secondo alcuni benchmark risulta migliore. Per questo i file ZIP realizzati sono relativi al formato standard. Il livello di compressione impostato è quello massimo; per quanto riguarda la dimensione totale dei file ottenuti è stato fatto un tentativo di compressione di tutte le immagini in un unico archivio, ma il file ottenuto era lievemente più grande della somma dei singoli e questa opzione è stata scartata come sconveniente. 7z I file 7zip sono stati generati con l omonimo programma open source. Per ogni immagine sono stati utilizzati tutti e tre gli algoritmi messi a disposizione ed è stato selezionato il file più piccolo. Il livello di compressione impostato è Ultra (il migliore) e per quanto riguarda la memoria massima messa a disposizione è stato selezionato per ogni tecnica il valore uguale o immediatamente inferiore a 512 MB. Come sopra, la compressione di molti file in un unico archivio non ha portato alcun vantaggio. RAR I file sono stati creati con il programma WinRar 3.18; l ultima versione disponibile è la 3.51 ma il fattore di compressione ottenibile è esattamente lo stesso in quanto i cambiamenti apportati riguardano altri aspetti del programma. Il livello di compressione è quello massimo; di nuovo, comprimere tutte le immagini insieme non ha generato nessun guadagno. JP2 Per creare file Jp2 è stato utilizzato un codificatore sviluppato dalla Kakadu Software, la cui versione di base da linea di comando è messa a disposizione gratuitamente per scopi non commerciali. Il programma può essere trovato all indirizzo il comando utilizzato per la compressione è stato

105 CAPITOLO 4. SPERIMENTAZIONE 105 kdu_compress -i immagine.bmp -o immagine.jp2 -Creversible=yes dove l ultima opzione specifica la reversibilità della trasformazione e quindi l utilizzo della compressione lossless. Nella tabella 4.2 vengono confrontate le prestazioni dell algoritmo sviluppato nei confronti degli altri formati. Nella tabella successiva 4.3 sono indicate le differenze di dimensioni dei file relative all algoritmo pcf secondo la formula (pd f d)/pd dove pd è la dimensione del file pcf ed fd è quella del formato interessato. Viene riportata inoltre di seguito la tabella 4.4 indicante le dimensioni dei file ottenuti tramite la compressione veloce; il miglioramento delle prestazioni in fatto di tempi di questa modalità sarà descritta nel prossimo capitolo Tempi impiegati Per eseguire l algoritmo di compressione è stata utilizzata una macchina di prova con le seguenti caratteristiche salienti: Processore Athlon MB di memoria RAM DDR 400 Java virtual machine Queste sono le qualità che influenzano i tempi di esecuzione del programma, e fra queste la più significativa è la velocità del processore. I tempi impiegati per le 38 immagini campione rappresentanti KB di dati sono i seguenti; in tabella 4.5 si trovano dei tempi di esecuzioni medi per alcune dimensioni immagini di dimensioni comuni. Tempo di compressione: 119 secondi, processati 500 KByte / sec Tempo di compressione veloce: 95 secondi, processati 626 KByte / sec Tempo di decompressione: 38 secondi, generati 1565 KByte / sec I tempi di compressione e decompressione mediamente diminuiscono al crescere della comprimibilità dell immagine. Essendo la decompressione la parte più importante dal punto di vista dei tempi è stata eseguita un analisi accurata di come i tempi di esecuzione siano partizionati tra le diverse operazioni; è risultato che circa il 70% del tempo impiegato per la decodifica viene utilizzato per la decompressione degli strati, ed il restante 30% si suddivide equamente tra le operazioni di ricostruzione dell immagine dagli strati e di rimozione dei filtri. Le operazioni di input ed output non sono state considerate, ma se relative ad un disco fisso richiedono comunque un tempo di esecuzione trascurabile. Il programma realizzato genera dunque un attesa percettibile ad un utente sia in fase di codifica che di decodifica. Per velocizzare il primo processo si può comunque utilizzare l opzione di compressione veloce permettendo un risparmio di tempo di

106 CAPITOLO 4. SPERIMENTAZIONE 106 File - dim. (KB) bmp pcf png zip rar jp2 7z bavoil rose blame blue-seascape bluesphere bosque-del-apache-tree brewing storm chess clip dali - die b. der e dice earth from space entrata duomo firenze smn fishes florence fractczaczka from overlook frozen-flower galaxybirth gatto hack-lse keyboard labyrinth leaf-dying-in-light leaves lenna piccione pine tree arch ponte vecchio power of bryce rain red blue and grey red n yellow canna lily rock sphere tree texture vangogh - autoritratto vangogh starrynight l zampillo fontana Totale Tabella 4.2: Confronto dei risultati con altri formati circa il 20% con un aumento delle dimensioni dei file del solo 3%. In fase di decompressione l attesa solitamente si attesta intorno a pochi secondi, rappresentanti un tempo accettabile; inoltre nel caso questa l immagine debba venir visualizzata su di

107 CAPITOLO 4. SPERIMENTAZIONE 107 Nome file pcf-png pcf-zip pcf-rar pcf-jp2 pcf-7z bavoil rose -27 % -62 % -34 % -14 % -16 % blame1-57 % -61 % -47 % 4 % 2 % blue-seascape -40 % -83 % -27 % -4 % -4 % bluesphere -47 % -76 % -57 % -46 % -14 % bosque-del-apache-tree -12 % -42 % -9 % 2 % -20 % brewing storm -24 % -87 % -15 % -18 % -43 % chess clip1-30 % -84 % -31 % 5 % -61 % dali - die bestandigkeit de -12 % -12 % -10 % -121 % 12 % dice -9 % -21 % -24 % -39 % 7 % earth from space -33 % -75 % -55 % -1 % -21 % entrata duomo -38 % -105 % -8 % 0 % -59 % firenze smn -32 % -63 % -33 % -1 % -28 % fishes -15 % -49 % -7 % 9 % -40 % florence -12 % -43 % -11 % 2 % -25 % fractczaczka -43 % -88 % -60 % -2 % -31 % from overlook 3-33 % -65 % 1 % 2 % -32 % frozen-flower -24 % -56 % -31 % 0 % -34 % galaxybirth -14 % -14 % -14 % 1 % 13 % gatto -33 % -103 % -24 % 1 % -43 % hack-lse % -101 % -33 % -3 % -64 % keyboard -35 % -77 % -7 % 2 % -27 % labyrinth -22 % 16 % 1 % -299 % 50 % leaf-dying-in-light -23 % -76 % -16 % -1 % -43 % leaves -13 % -36 % -21 % -1 % -22 % lenna -7 % -65 % -9 % 0 % -31 % piccione -32 % -142 % -4 % 7 % -81 % pine tree arch -32 % -70 % -6 % 4 % -26 % ponte vecchio -25 % -68 % -10 % 2 % -38 % power of bryce -22 % -50 % -52 % -31 % -8 % rain -29 % -87 % 2 % -5 % -46 % red blue and grey -15 % -23 % -19 % -3 % 1 % red n yellow canna lily -28 % -106 % -20 % 1 % -77 % rock -28 % -49 % -41 % 3 % -31 % sphere -1 % 34 % 38 % -128 % 57 % tree texture -24 % -69 % 28 % 5 % 25 % vangogh - autoritratto 6 % -35 % -26 % -10 % 7 % vangogh starrynight little -11 % -23 % -22 % 1 % -12 % zampillo fontana -30 % -93 % -7 % 2 % -51 % Totale -26 % -70 % -20 % -5 % -28 % Tabella 4.3: Differenza di dimensioni relativa rispetto agli altri formati un browser tramite applet a meno che la velocità di download sia maggiore di quella di decompressione sarà necessario attendere solo i tempi relativi alla ricostruzione dell immagine ed alla rimozione dei filtri, attesa che può essere compensata tuttavia

108 CAPITOLO 4. SPERIMENTAZIONE 108 Nome file Dim. pcf veloce (KB) Dim. pcf standard (KB) bavoil rose blame blue-seascape bluesphere bosque-del-apache-tree brewing storm chess clip dali - die b. der e dice earth from space entrata duomo firenze smn fishes florence fractczaczka from overlook frozen-flower galaxybirth gatto hack-lse keyboard labyrinth leaf-dying-in-light leaves lenna piccione pine tree arch ponte vecchio power of bryce rain red blue and grey red n yellow canna lily rock sphere tree texture vangogh - autoritratto vangogh starrynight zampillo fontana Totale Tabella 4.4: Risultati della compressione veloce dal risparmio di tempo di scaricamento ottenuto grazie alla compressione dell algoritmo proposto. In seguito saranno comunque proposte delle evoluzioni del programma, come la trasformazione del codice in un linguaggio più a basso livello, che potranno

109 CAPITOLO 4. SPERIMENTAZIONE 109 Dimensioni Dimensioni Compres- Compres- Decompresin pixel in KB sione sione veloce sione 512 * sec. 1.2 sec. 0.5 sec. 640 * sec. 1.4 sec. 0.6 sec. 800 * sec. 2.2 sec. 0.9 sec * sec. 3.7 sec. 1.5 sec * sec. 6.1 sec. 2.5 sec * sec. 9.0 sec. 3.6 sec. Tabella 4.5: Tempi di esecuzione consentire l esecuzione dell algoritmo con tempi di esecuzione molto minori Risultati della compressione lossy Sebbene si parli soltanto di una funzionalità aggiuntiva, si vedranno di seguito in tabella 4.6 i risultati in compressione della modalità lossy con livello di perdita pari ad uno confrontati con le stesse immagini compresse in modalità lossless. Come si può vedere la modalità lossy pur scartando una quantità di informazione dell immagine relativa solo al bit meno significativo sugli otto presenti in ogni campione ottiene una compressione di circa il 25% migliore. Dall esecuzione del programma si può osservare che l errore assoluto medio introdotto per ogni byte è in 34 immagini su 38 compreso tra 0.45 e 0.55; questa è una quantità molto esigua che molto difficilmente può intaccare la qualità visiva dell immagine. Per avere un idea dell ordine di grandezza delle dimensioni di altri formati lossy, si può vedere nella tabella 4.7 un confronto tra le dimensioni dei file lossy ottenuti con immagini compresse in JPEG al livello di qualità massimo. Come detto sopra, tali quantità servono solo per definire gli ordini di grandezza in quanto per fare un confronto preciso occorrerebbe misurare l errore introdotto dal formato JPEG e compararlo con quello generato dall algoritmo qui descritto. Inoltre per molte immagini è possibile ottenere file JPEG anche molto più piccoli senza creare grandi differenza visive dall originale mentre la qualità delle immagini pcf degenera rapidamente al salire del livello di perdita. Tuttavia l aver ottenuto risultati paragonabili ad un formato così ampiamente diffuso insieme alle altre caratteristiche interessanti descritte in precedenza come la non propagazione dell errore in caso di compressioni lossy multiple incoraggia l ulteriore sviluppo delle tecniche lossy da applicare in combinazione con l algoritmo sviluppato; alcune idee per possibili ricerche da effettuare in questa direzione sono esposte nei capitoli successivi. 4.3 Conclusioni della sperimentazione In questa sezione si trarranno delle conclusioni relative ai risultati ottenuti. Alla luce di questa analisi, verranno proposte delle possibili evoluzioni del programma sviluppato.

110 CAPITOLO 4. SPERIMENTAZIONE 110 Nome file Standard lossless pcf 1 bit lossy pcf bavoil rose blame blue-seascape bluesphere bosque-del-apache-tree brewing storm chess clip dali - die bestandigkeit de dice earth from space entrata duomo firenze smn fishes florence fractczaczka from overlook frozen-flower galaxybirth gatto hack-lse keyboard labyrinth leaf-dying-in-light leaves lenna piccione pine tree arch ponte vecchio power of bryce rain red blue and grey red n yellow canna lily rock sphere tree texture vangogh - autoritratto vangogh starrynight little zampillo fontana Totale Tabella 4.6: Risultati della compressione con perdita di un bit Analisi dei risultati ottenuti Le prestazioni dell algoritmo sviluppato sono molto soddisfacenti in quanto la somma delle dimensioni delle immagini compresse è la minore nei confronti di tutti i

111 CAPITOLO 4. SPERIMENTAZIONE 111 Nome file 1 bit lossy pcf Jpeg alta qualità bavoil rose blame blue-seascape bluesphere bosque-del-apache-tree brewing storm chess clip dali - die bestandigkeit de dice earth from space entrata duomo firenze smn fishes florence fractczaczka from overlook frozen-flower galaxybirth gatto hack-lse keyboard labyrinth leaf-dying-in-light leaves lenna piccione pine tree arch ponte vecchio power of bryce rain red blue and grey red n yellow canna lily rock sphere tree texture vangogh - autoritratto vangogh starrynight little zampillo fontana Totale Tabella 4.7: Confronto della compressione con perdita con il formato jpeg formati scelti per la comparazione. È interessante comunque fare un analisi più approfondita e cercare di isolare i fattori che danno vantaggio ad un algoritmo invece che ad un altro.

112 CAPITOLO 4. SPERIMENTAZIONE 112 I file JP2 sono quelli più simili in dimensioni ai file pcf. La maggior parte delle immagini compresse in questo nuovo formato JPEG è lievemente più piccola dei file relativi all algoritmo sviluppato di quantità che variano dall 1% al 5%; il vantaggio massimo di questo formato è rappresentato da un picco del 9%. In una parte minore delle immagini invece l algoritmo proposto risulta notevolmente migliore, addirittura di un fattore quattro per l immagine labyrinth rappresentante comunque un caso molto particolare e di quantità notevoli anche per altre immagini. Ciò che maggiormente danneggia la compressione JP2 è la presenza di forti discontinuità nell immagine. I presupposti di continuità fatti nei formati grafici compressi sono la causa di tale degenerazione di prestazioni; altri algoritmi sembrano tuttavia reagire meglio di fronte a questi dati inaspettati. In conclusione, i file jp2 occupano quantità di spazio lievemente minore nella maggior parte dei casi ma per determinate immagini sono invece molto più grandi, in particolare nei casi con forti discontinuità più facilmente riscontrabili in immagini realizzate tramite elaborazioni grafiche. I file PNG sono notevolmente più grandi dei file generati dall algoritmo sviluppato; i risultati migliori sono dati da immagini con vaste zone uniformi (come bosquedel-apache-tree o galaxybirth) o con particolari regolarità (sphere, dice, vangogh - autoritratto). Questo è causato dall algoritmo generico applicato dopo il filtraggio che permette di catturare caratteristiche ridondanti che solitamente non ci si aspetta in un immagine. Ad eccezione di un immagine lievemente più piccola, i file risultanti sono tutti più grandi dei relativi file pcf di un valore medio del 26%. L algoritmo ZIP ha prodotto file di dimensioni molto maggiori degli altri, con prestazioni migliori nelle stesse immagini dove il formato PNG ha un buon comportamento. Questo è comunque un risultato atteso in quanto il formato compresso non è specializzato per le immagini; è un metro di paragone utile soprattutto per valutare come le ipotesi fatte nei confronti della natura dell informazione nei vari algoritmi migliorino la compressione ottenibile. È necessario inoltre sottolineare come la compressione e la decompressione in questo formato sia notevolmente più veloce rispetto a tutte le altre utilizzate. L algoritmo 7z ha prodotto risultati interessanti soprattutto per immagini con particolari regolarità come sphere, labyrinth o dice ottenendo in diversi casi il risultato migliore e dimostrando l efficienza delle tecniche utilizzate. La ripetizione di sequenze di punti che solitamente non viene rilevata da algoritmi di compressione grafica viene evidentemente sfruttata appieno in questo formato; d altra parte i risultati per immagini senza queste caratteristiche sono notevolmente peggiori. La dimensione totale dei file compressi in 7z è del 28% più grande dei file pcf. L algoritmo RAR ha dimostrato di avere effettivamente qualità interessanti nei confronti di dati rappresentanti immagini in quanto si è rivelato globalmente il miglior algoritmo di compressione generico nei confronti del campione scelto creando file addirittura più piccoli del formato grafico PNG ed ottenendo un occupazione di spazio maggiore del solo 20% rispetto ai file pcf. Purtroppo dall osservazione del campione di immagini non è stato possibile trarre alcuna conclusione su quali

113 CAPITOLO 4. SPERIMENTAZIONE 113 caratteristiche migliorino o peggiorino l efficacia di questa tecnica nei confronti delle altre Possibili evoluzioni dell algoritmo Un buon lavoro deve essere sia un buon punto di arrivo sia un buon punto di partenza. Per questo sebbene l algoritmo abbia raggiunto risultati soddisfacenti è importante pensare a come questo possa essere ulteriormente sviluppato per ottenere prestazioni ancora migliori o supportare funzionalità aggiuntive. Di seguito si trovano una serie di possibili sviluppi su cui sarebbe possibile lavorare ulteriormente. Miglioramento del fattore di compressione Non è escluso che l algoritmo di compressione abbia ancora del margine di guadagno. Di seguito sono riportati una serie di cambiamenti che potrebbero migliorare il fattore di compressione nelle varie fasi. Ognuno di questi sarebbe facilmente integrabile nell algoritmo esistente con modifiche marginali al programma creato. Definizione ed aggiunta di altri filtri: La definizione di funzioni di previsioni migliori aumenterebbero sicuramente la comprimibilità del dato già nella prima fase dell algoritmo. Definizione di un modello di scelta dei filtri migliore: Il modello per la scelta dei filtri tiene conto solo di un numero limitato di fattori; questi possono essere affinati tenendo conto di altre caratteristiche che si vengono a creare dopo il filtraggio, per esempio prediligendo filtri che generano valori simili in punti adiacenti. Definizione di una diversa scomposizione in strati: La scomposizione di strati monodimensionali crea alcuni strati molto caotici ed altri molto ordinati ottenendo un buon fattore di compressione; non è escludibile tuttavia che esistano altre strategie in grado di generare dati maggiormente comprimibili. Potrebbe essere vantaggioso inoltre definire una scomposizione più complessa, che per esempio scomponga un valore in funzione dei precedenti in base a qualche criterio di guadagno. Definizione di un altro criterio di scomposizione in poliomini: è possibile che una tecnica diversa di scomposizione in poliomini porti ad una compressione migliore tenendo conto di altri fattori che ora non sono considerati. Miglioramento dei tempi di esecuzione I tempi di esecuzione dell algoritmo potrebbero essere migliorati riscrivendo il programma in un linguaggio più a basso livello che permetta la compilazione ed un ottimizzazione del codice maggiore grazie ad una gestione più capillare delle operazioni eseguite spesso difficile da realizzare in un linguaggio di alto livello.

114 CAPITOLO 4. SPERIMENTAZIONE 114 Realizzazione della streamability e riduzione dei requisiti di memoria Nel file compresso gli strati sono memorizzati uno dopo l altro. Questo favorisce la semplicità del formato e della progettazione rendendo l algoritmo più semplicemente comprensibile ma impone in fase di decompressione di doverne leggere uno per intero prima di passare al successivo; si potrebbe pensare di organizzare i dati in modo diverso per garantire nuove caratteristiche. Infatti scrivendo in fase di compressione ciclicamente una parte di dimensioni ridotte per ogni strato, per esempio due righe, durante la decodifica si potrebbe decomprimere la parte di immagine relativa prima di elaborare per intero tutti gli strati rendendo disponibile tali informazioni ad un programma che le richieda come un visualizzatore. Così si permette la streamability; inoltre le informazioni decompresse, ad eccezione dell ultima riga decodificata da utilizzare per la rimozione dei filtri, non sarebbero più necessarie per la decompressione del resto dell immagine e questo permetterebbe un drastico abbassamento dei requisiti di memoria durante la decompressione a due righe di pixel dell immagine più le poco ingombranti strutture dati utilizzate. Tutto questo può essere fatto con una riorganizzazione dei dati e senza grandi modifiche concettuali all algoritmo ma solo con qualche cambiamento realizzativo. Aggiunta di informazioni ausiliarie Al formato file potrebbero essere aggiunte tutta una serie di informazioni ausiliarie utili in varie circostanze come il supporto della trasparenza, informazioni sull origine dell immagine o vari altri dati presenti in altri formati. Miglioramento della compressione lossy Possono essere elaborate tecniche lossy con prestazioni migliori di quella esistente. Alcune idee realizzabili sono: Correzione applicata in fase di decompressione: Studiando gli effetti visivi causati dalla perdita di dati lossy, si potrebbe effettuare una trasformazione dopo la decompressione che li compensi. Per esempio relativamente alla tecnica sviluppata considerando che si tendono a creare per livelli di perdita alti forti discontinuità in zone in origine sfumate si potrebbe applicare un algoritmo di sfumatura dei contorni o di dithering. Applicazione di un filtro lossy migliore: L algoritmo lossy utilizzato è estremamente semplice; si potrebbe pensare di studiarne uno che operi tenendo conto maggiormente di fattori visivi o che calcoli in modo migliore il guadagno ottenuto introducendo una determinata modifica ad un punto dell immagine. Decimazione del campione: Si potrebbe tentare di ottenere una compressione lossy riducendo il numero di campioni utilizzati e comprimendo senza perdita questo numero ridotto di punti. Per la ricostruzione dell immagine originale si potrebbe utilizzare un algoritmo di scalamento che utilizzi ipotesi di continuità per stimare il valore dei punti rimossi; potrebbe essere vantaggioso inoltre includere nel file compresso un piccolo pacchetto di informazioni che dia delle indicazione utili in questa fase di ricostruzione.

115 Conclusioni In questo lavoro è stato sviluppato un algoritmo di compressione senza perdita per immagini. Sono state utilizzate in combinazione tecniche già esistenti, come l operazione di filtraggio e gli alberi di Huffman, con approcci nuovi, come il filtraggio per colore, la suddivisione del dato da comprimere in strati binari e la scomposizione in poliomini. È stato definita una vera e propria specifica di formato per file generati dall algoritmo. In tale modo si permette l utilizzo e lo sviluppo della tecnica studiata anche da parte di terzi; nel formato sono state incluse varie informazioni tra cui una serie di codici hash utili per verificare l esattezza della ricostruzione dell immagine e la sua eguaglianza con l originale. È stata studiata l ottimalità al variare di scelte effettuabili in fase di compressione ed i suoi compromessi nei confronti dei tempi di esecuzione; sono state adottate varie politiche decisionali spesso basate su di un modello quando l analisi di tutti i dati a disposizione sarebbe stata troppo complessa. Il programma che implementa l algoritmo è stato sviluppato in Java. Sono state create tre classi di interfaccia; una realizza la codifica e la decodifica al variare dei vari parametri permettendo così di ottenere livelli di compressione lievemente minori in un tempo ridotto o di cercare di minimizzare le dimensione dei file compressi cambiando le impostazioni di default. Un altra classe implementa un visualizzatore che permette la visione delle immagini compresse senza passare da un file intermedio. Infine è stata creata un applet che permette la visualizzazione delle immagini su di una pagina web effettuando la decompressione in parallelo allo scaricamento. È stata elaborata inoltre una trasformazione con perdita di dati da effettuare prima dell applicazione dell algoritmo a vantaggio di una compressione maggiore. Sebbene questo non sia l argomento principale di questo lavoro, tale funzionalità ha dato risultati promettenti che incoraggiano ulteriori studi in questa direzione. Infine è stata eseguita una sperimentazione su di un campione di immagini selezionate in modo da differenziarsi per quanto riguarda origine, dimensioni e regolarità nei colori e nei contorni. L algoritmo è stato confrontato con altri formati compressi senza perdita sia di utilizzo generico (zip, rar e 7z) sia specializzati per immagini (png, jpeg2). La dimensione dei file prodotti dall algoritmo proposto è lievemente più piccola di quella dei file jp2 e notevolmente minore nei confronti 115

116 CONCLUSIONI 116 degli altri formati. L algoritmo sviluppato già nella forma qui presentata produce risultati molto buoni ma non per questo non può subire ulteriori evoluzioni. Per questo sono stati proposti nei capitoli conclusivi degli sviluppi sia per l aggiunta di altre funzionalità al formato file sia per il miglioramento dell algoritmo dal punto di vista del fattore di compressione ottenuto e delle risorse di tempo e di memoria occupate.

117 Bibliografia Sha48 C. E. Shannon, A Mathematical Theory of Communication, The Bell System Technical Journal, Vol. 27, pp , , Luglio, Ottobre, 1948 Huff52 D.A. Huffman, A Method for the Construction of Minimum-Redundancy Codes, Proceedings of the I.R.E, Settembre 1952 El63 P. Elias, in N. Abramson, Information theory and coding, Mac-Graw Hill book Co., Inc. New York, 1963 Ris75 J. J. Rissanen, Generalized Kraft inequality for arithmetic coding, IBM Research report RJ 1591, Giugno 1975 WNC87 I.H. Witten, R.M. Neal and J.G. Cleary, Arithmetic Coding for Data Compression, Communications of the ACM, pp , Giugno, 1987 BCW90 T. Bell, J.G. Cleary and I. H. Witten, Text compression. Prentice-Hall, Inc., LZ77 J. Ziv, A. Lempel, A Universal Algorithm for Sequential Data Compression, IEEE Transactions on Information Theory, Vol. 23, No. 3, pp , 1977 Wel84 T. Welch, A technique for high-performance data compression, IEEE Computer, vol. 16, no. 6, pp. 8 19, Giugno 1984 CW84 J.G. Cleary, I.H. Witten, Data Compression Using Adaptive Coding and Partial String Matching, IEEE transactions on communications, Aol. COM-32, n. 4, Aprile 1984 How93 P.G. Howard, The Design and Analysis of Efficient Lossless Data Compression System, PhD thesis, Brown University, 1993 Shk02 D. Shkarin, PPM: One step to practicality. In Proceedings of the IEEE Data Compression Conference 2002, Snowbird, Utah, Storer, J.A. And Cohn, M. Eds , 2002 BW94 M. Burrows, D.J. Wheeler, A Block-Sorting Lossless Data Compression Algorithm. Technical report, Digital Equipment Corporation, Palo Alto, California, 1994 Jue03 Abel Juergen, Improvements to the Burrows-Wheeler Compression Algorithm: After BWT Stages, University Duisburg-Essen,

118 Appendice: un esempio di esecuzione dell algoritmo In questa parte verrà mostrato il funzionamento dell algoritmo applicato ad un immagine in modo da dare un idea concreta a proposito delle operazioni svolte. L immagine considerata è Lenna, divenuta uno standard nello studio di elaborazioni grafiche, in figura 4.1. Figura 4.1: Lenna L immagine può essere vista come sovrapposizione di tre immagini monocromatiche ognuna rappresentante uno dei tre colori primari blu, verde e rosso. La vista per colori di Lenna si può osservare in figura 4.2. A questo punto la prima operazione da effettuare per l applicazione dell algoritmo proposto è il filtraggio. Per mostrare l evoluzione dei valori numerici rappresentanti l immagine se ne considererà un particolare di otto pixel per otto pixel contenente i punti di ascisse compresa tra 384 e 392 e di ordinata maggiore o uguale di 392 e minore di 400. L estrazione del particolare dall immagine si può vedere in figura 4.3. Tale insieme di pixel viene a sua volta scomposto per colori come si vede in figura 4.4. Ogni punto ottenuto è rappresentato numericamente da un valore compreso tra 0 e 255 indicante l intensità del suo colore. Le matrici di interi per i punti del particolare sono espresse in figura

119 APPENDICE: UN ESEMPIO DI ESECUZIONE DELL ALGORITMO 119 Lenna Lenna, parte blu Lenna, parte verde Lenna, parte rossa Figura 4.2: Lenna: scomposizione per colore Figura 4.3: Lenna: particolare A questo punto si procede con il filtraggio standard. Il filtro selezionato per il particolare studiato è il numero 5. In questo caso si utilizza come previsione di ogni punto il valore del pixel rappresentante lo stesso colore in basso a sinistra rispetto al valore da stimare. Ad ogni valore viene sottratta la sua stima; l operazione di filtraggio è mostrata in figura 4.6. Si noti che nel risultato i valori sono rappresentati nell intervallo [-128, 127] equivalente al campo [0, 255] in modulo 256. L utilità della fase di filtraggio si può intuire notando che la maggior parte dei valori ottenuti sono in modulo minori di sedici; questo provoca una distribuzione delle probabilità dei simboli molto sbilanciata verso i valori minori, consentendo una comprimibilità

120 APPENDICE: UN ESEMPIO DI ESECUZIONE DELL ALGORITMO 120 Lenna, particolare Parte blu Parte verde Parte rossa Figura 4.4: Lenna: particolare scomposto per colore Figura 4.5: Lenna: valori numerici rappresentanti il particolare maggiore. L applicazione successiva del filtraggio per colore effettua di nuovo una stima per ogni punto utilizzando però per ogni punti valori che rappresentano gli altri colori dello stesso pixel. Per il particolare selezionato l algoritmo ha selezionato il filtro uno, che seleziona il valore rappresentante il colore precedente nell ordine blu, verde e rosso. Di nuovo le stime ottenute vengono sottratte ai valori iniziali. L esecuzione di questa fase si può vedere in figura 4.7. Il guadagno ottenuto è meno evidente rispetto al filtraggio standard. Si possono notare tuttavia dei miglioramenti se si considerano le somme dei valori assoluti dei

121 APPENDICE: UN ESEMPIO DI ESECUZIONE DELL ALGORITMO 121 Previsione Previsione Previsione Differenza Differenza Differenza Figura 4.6: Lenna: filtraggio del particolare punti del particolare; queste quantità sono infatti misura dell errore commesso nella stima di ogni punto e valori minori indicano una minore comprimibilità. Questi dati sono rappresentati in tabella 4.8. In modo del tutto analogo si può osservare come l entropia di ordine uno dei simboli diminuisca con il procedere del filtraggio in tabella 4.9; si consideri inoltre che l entropia iniziale del particolare è minore di quella dell immagine in quanto avendo considerato solo pochi punti molti valori non compaiono mai e non vengono considerati nel calcolo.

122 APPENDICE: UN ESEMPIO DI ESECUZIONE DELL ALGORITMO 122 Previsione Previsione Differenza Differenza Figura 4.7: Lenna: filtraggio per colore del particolare Colore Errore dopo Errore dopo il il filtraggio filtraggio per colore Blu Verde Rosso Tabella 4.8: Errori sulle previsioni dopo il filtraggio

123 APPENDICE: UN ESEMPIO DI ESECUZIONE DELL ALGORITMO 123 Colore Entropia Entropia dopo Entropia dopo il iniziale il filtraggio filtraggio per colore Blu Verde Rosso Tabella 4.9: Entropia del particolare prima e dopo il filtraggio Il risultato del filtraggio dell immagine si può vedere graficamente in figura 4.8 dove gli errori maggiori sono rappresentati con tonalità di grigio più brillanti. Si noti che i punti dove sono presenti gli errori maggiori sono quelli di contorno o comunque appartengono a zone particolarmente irregolari. Figura 4.8: Visualizzazione per colori di Lenna dopo il filtraggio In figura 4.9 è invece rappresentata l immagine dopo il filtraggio per colore. Le differenze prodotte da questa operazione sono visivamente poco evidenti; di nuovo il miglioramento introdotto può essere visto analizzando i cambiamenti del valore dell entropia del modello di ordine uno durante la fase di filtraggio mostrati in tabella In questo specifico caso comunque il miglioramento in comprimibilità dato da questa fase è abbastanza basso rispetto a quello ottenibile in altre immagini. Figura 4.9: Visualizzazione per colori di Lenna dopo il filtraggio per colore Infine l immagine viene scomposta in ventiquattro strati binari, otto per ogni colore, e per ognuno di essi viene selezionato un metodo di compressione a seconda della sua regolarità. Gli strati sono rappresentati graficamente nelle figure 4.10,

124 APPENDICE: UN ESEMPIO DI ESECUZIONE DELL ALGORITMO 124 Colore Entropia Entropia dopo Entropia dopo il iniziale il filtraggio filtraggio per colore Blu Verde Rosso Tabella 4.10: Entropia dell immagine prima e dopo il filtraggio 4.11 e 4.12; si noti che al contrario delle immagini precedenti, rappresentate in 256 tonalità, le seguenti sono esclusivamente nei due colori bianco e nero coerentemente con la natura binaria dell informazione. Gli strati compressi vengono uniti all intestazione contenente informazioni sull immagine e sui filtri selezionati, formando così il file pcf compresso. La composizione si può vedere per intero nella tabella 4.11 dove si può osservare la suddivisione degli strati fra i metodi di compressione a disposizione e le dimensioni di ognuno di essi dopo la compressione. Per alcuni esempi riguardanti la codifica degli strati, si rimanda agli esempi nelle figure a pagina 69 per quanto riguarda l uso dei poliomini e nelle immagini 2.13 e 2.14 a pagina 56 relative alla compressione con RLE ed alberi di Huffman. Nelle tabelle 4.12 e 4.13 sono mostrate le composizioni dei singoli strati compressi rispettivamente tramite poliomini o con RLE ed alberi di Huffman. Tali quantità comprendono lo spazio utilizzato per l intestazione e per gli alberi di Huffman; sono presenti inoltre i bit impiegati per codificare le distanze ed i poliomini nel primo caso o lo spazio occupato dalle coppie di sequenze nel secondo.

125 APPENDICE: UN ESEMPIO DI ESECUZIONE DELL ALGORITMO 125 Bit 0 Zeri: 54% Compresso con: Huffman e RLE Bit 1 Zeri: 54% Compresso con: Huffman e RLE Bit 2 Zeri: 58% Compresso con: Huffman e RLE Bit 3 Zeri: 65% Compresso con: Huffman e RLE Bit 4 Zeri: 82% Compresso con: Huffman e RLE Bit 5 Zeri: 96% Compresso con: Poliomini Bit 6 Zeri: 99% Compresso con: Poliomini Bit 7 Zeri: > 99% Compresso con: Poliomini Figura 4.10: Strati per il colore blu

126 APPENDICE: UN ESEMPIO DI ESECUZIONE DELL ALGORITMO 126 Bit 0 Zeri: 54% Compresso con: Huffman e RLE Bit 1 Zeri: 55% Compresso con: Huffman e RLE Bit 2 Zeri: 60% Compresso con: Huffman e RLE Bit 3 Zeri: 72% Compresso con: Huffman e RLE Bit 4 Zeri: 90% Compresso con: Poliomini Bit 5 Zeri: 98% Compresso con: Poliomini Bit 6 Zeri: > 99% Compresso con: Poliomini Bit 7 Zeri: > 99% Compresso con: Poliomini Figura 4.11: Strati per il colore verde

127 APPENDICE: UN ESEMPIO DI ESECUZIONE DELL ALGORITMO 127 Bit 0 Zeri: 55% Compresso con: Huffman e RLE Bit 1 Zeri: 57% Compresso con: Huffman e RLE Bit 2 Zeri: 65% Compresso con: Huffman e RLE Bit 3 Zeri: 80% Compresso con: Huffman e RLE Bit 4 Zeri: 93% Compresso con: Poliomini Bit 5 Zeri: 99% Compresso con: Poliomini Bit 6 Zeri: > 99% Compresso con: Poliomini Bit 7 Zeri: > 99% Compresso con: Poliomini Figura 4.12: Strati per il colore rosso

128 APPENDICE: UN ESEMPIO DI ESECUZIONE DELL ALGORITMO 128 Strato Bit Colore Zeri Compresso con Dimensioni Intestazione KB 0 7 Blu 99.9 % Poliomini 122 byte 1 7 Verde 99.9 % Poliomini 35 byte 2 7 Rosso 99.9 % Poliomini 23 byte 3 6 Blu 99 % Poliomini 1.5 KB 4 6 Verde 99.8 % Poliomini 622 byte 5 6 Rosso 99.9 % Poliomini 332 byte 6 5 Blu 96 % Poliomini 7.3 KB 7 5 Verde 98 % Poliomini 3.7 KB 8 5 Rosso 99 % Poliomini 2.3 KB 9 4 Blu 82 % RLE ed Huffman 21.8 KB 10 4 Verde 90 % Poliomini 15.7 KB 11 4 Rosso 93 % Poliomini 10.7 KB 12 3 Blu 65 % RLE ed Huffman 30.5 KB 13 3 Verde 71 % RLE ed Huffman 28.1 KB 14 3 Rosso 80 % RLE ed Huffman 23.0 KB 15 2 Blu 58 % RLE ed Huffman 32.0 KB 16 2 Verde 60 % RLE ed Huffman 31.6 KB 17 2 Rosso 65 % RLE ed Huffman 30.4 KB 18 1 Blu 54 % RLE ed Huffman 32.3 KB 19 1 Verde 55 % RLE ed Huffman 32.3 KB 20 1 Rosso 57 % RLE ed Huffman 32.1 KB 21 0 Blu 54 % RLE ed Huffman 32.3 KB 22 0 Verde 54 % RLE ed Huffman 32.3 KB 23 0 Rosso 55 % RLE ed Huffman 32.3 KB Totale file KB Tabella 4.11: Composizione del file compresso Strato Intestazione Albero di Huffman Distanze Poliomini Totale 0 16 byte 15 byte 84 byte 7 byte 122 byte 1 16 byte 3 byte 15 byte 1 byte 35 byte 2 16 byte 3 byte 4 byte 0 byte 23 byte 3 16 byte 34 byte 1.4 KB 230 byte 1.5 KB 4 16 byte 33 byte 513 byte 60 byte 622 byte 5 16 byte 23 byte 270 byte 23 byte 332 byte 6 16 byte 75 byte 5.8 KB 1.5 KB 7.3 KB 7 16 byte 73 byte 3.0 KB 644 byte 3.7 KB 8 16 byte 71 byte 2.0 KB 352 byte 2.3 KB byte 76 byte 11.7 KB 3.9 KB 15.7 KB byte 76 byte 8.2 KB 2.4 KB 10.7 KB Tabella 4.12: Composizione degli strati compressi tramite poliomini

129 APPENDICE: UN ESEMPIO DI ESECUZIONE DELL ALGORITMO 129 Strato Intestazione Alberi di Huffman Coppie di sequenze Totale 9 16 byte 333 byte 21.5 KB 21.8 KB byte 219 byte 30.3 KB 30.5 KB byte 310 byte 27.8 KB 28.1 KB byte 358 byte 22.6 KB 23.0 KB byte 207 byte 31.8 KB 32.0 KB byte 206 byte 31.4 KB 31.6 KB byte 268 byte 30.2 KB 30.4 KB byte 201 byte 32.1 KB 32.3 KB byte 192 byte 32.1 KB 32.3 KB byte 196 byte 31.9 KB 32.1 KB byte 169 byte 32.1 KB 32.3 KB byte 235 byte 32.1 KB 32.3 KB byte 256 byte 32.0 KB 32.3 KB Tabella 4.13: Composizione degli strati compressi tramite RLE ed Huffman

Algoritmi e strutture dati. Codici di Huffman

Algoritmi e strutture dati. Codici di Huffman Algoritmi e strutture dati Codici di Huffman Memorizzazione dei dati Quando un file viene memorizzato, esso va memorizzato in qualche formato binario Modo più semplice: memorizzare il codice ASCII per

Подробнее

Codifiche a lunghezza variabile

Codifiche a lunghezza variabile Sistemi Multimediali Codifiche a lunghezza variabile Marco Gribaudo [email protected], [email protected] Assegnazione del codice Come visto in precedenza, per poter memorizzare o trasmettere un

Подробнее

Alessandro Pellegrini

Alessandro Pellegrini Esercitazione sulle Rappresentazioni Numeriche Esistono 1 tipi di persone al mondo: quelli che conoscono il codice binario e quelli che non lo conoscono Alessandro Pellegrini Cosa studiare prima Conversione

Подробнее

Informatica. Rappresentazione binaria Per esempio +101010000 diventa +0.10101 10 18/10/2007. Introduzione ai sistemi informatici 1

Informatica. Rappresentazione binaria Per esempio +101010000 diventa +0.10101 10 18/10/2007. Introduzione ai sistemi informatici 1 Informatica Pietro Storniolo [email protected] http://www.pa.icar.cnr.it/storniolo/info200708 Numeri razionali Cifre più significative: : sono le cifre associate ai pesi maggiori per i numeri maggiori

Подробнее

2) Codici univocamente decifrabili e codici a prefisso.

2) Codici univocamente decifrabili e codici a prefisso. Argomenti della Lezione ) Codici di sorgente 2) Codici univocamente decifrabili e codici a prefisso. 3) Disuguaglianza di Kraft 4) Primo Teorema di Shannon 5) Codifica di Huffman Codifica di sorgente Il

Подробнее

Corso di Informatica Generale (C. L. Economia e Commercio) Ing. Valerio Lacagnina Rappresentazione in virgola mobile

Corso di Informatica Generale (C. L. Economia e Commercio) Ing. Valerio Lacagnina Rappresentazione in virgola mobile Problemi connessi all utilizzo di un numero di bit limitato Abbiamo visto quali sono i vantaggi dell utilizzo della rappresentazione in complemento alla base: corrispondenza biunivoca fra rappresentazione

Подробнее

Siamo così arrivati all aritmetica modulare, ma anche a individuare alcuni aspetti di come funziona l aritmetica del calcolatore come vedremo.

Siamo così arrivati all aritmetica modulare, ma anche a individuare alcuni aspetti di come funziona l aritmetica del calcolatore come vedremo. DALLE PESATE ALL ARITMETICA FINITA IN BASE 2 Si è trovato, partendo da un problema concreto, che con la base 2, utilizzando alcune potenze della base, operando con solo addizioni, posso ottenere tutti

Подробнее

Il concetto di valore medio in generale

Il concetto di valore medio in generale Il concetto di valore medio in generale Nella statistica descrittiva si distinguono solitamente due tipi di medie: - le medie analitiche, che soddisfano ad una condizione di invarianza e si calcolano tenendo

Подробнее

APPUNTI DI MATEMATICA LE FRAZIONI ALGEBRICHE ALESSANDRO BOCCONI

APPUNTI DI MATEMATICA LE FRAZIONI ALGEBRICHE ALESSANDRO BOCCONI APPUNTI DI MATEMATICA LE FRAZIONI ALGEBRICHE ALESSANDRO BOCCONI Indice 1 Le frazioni algebriche 1.1 Il minimo comune multiplo e il Massimo Comun Divisore fra polinomi........ 1. Le frazioni algebriche....................................

Подробнее

Un ripasso di aritmetica: Rappresentazione binaria - operazioni. riporti

Un ripasso di aritmetica: Rappresentazione binaria - operazioni. riporti Un ripasso di aritmetica: Rappresentazione binaria - operazioni A queste rappresentazioni si possono applicare le operazioni aritmetiche: riporti 1 1 0 + 1 0 = 1 0 0 24 Un ripasso di aritmetica: Rappresentazione

Подробнее

Introduzione all analisi dei segnali digitali.

Introduzione all analisi dei segnali digitali. Introduzione all analisi dei segnali digitali. Lezioni per il corso di Laboratorio di Fisica IV Isidoro Ferrante A.A. 2001/2002 1 Segnali analogici Si dice segnale la variazione di una qualsiasi grandezza

Подробнее

Corrispondenze e funzioni

Corrispondenze e funzioni Corrispondenze e funzioni L attività fondamentale della mente umana consiste nello stabilire corrispondenze e relazioni tra oggetti; è anche per questo motivo che il concetto di corrispondenza è uno dei

Подробнее

Corso di Calcolo Numerico

Corso di Calcolo Numerico Corso di Calcolo Numerico Dott.ssa M.C. De Bonis Università degli Studi della Basilicata, Potenza Facoltà di Ingegneria Corso di Laurea in Ingegneria Meccanica Sistemi di Numerazione Sistema decimale La

Подробнее

4 3 4 = 4 x 10 2 + 3 x 10 1 + 4 x 10 0 aaa 10 2 10 1 10 0

4 3 4 = 4 x 10 2 + 3 x 10 1 + 4 x 10 0 aaa 10 2 10 1 10 0 Rappresentazione dei numeri I numeri che siamo abituati ad utilizzare sono espressi utilizzando il sistema di numerazione decimale, che si chiama così perché utilizza 0 cifre (0,,2,3,4,5,6,7,8,9). Si dice

Подробнее

Informatica grafica e Multimedialità. 4 Immagini grafiche

Informatica grafica e Multimedialità. 4 Immagini grafiche Immagini raster e vettoriali Le immagini grafiche si distinguono in due classi differenti: immagini raster e immagini vettoriali. Le immagini raster, dette anche pittoriche o pixel-oriented, dividono l

Подробнее

Strutturazione logica dei dati: i file

Strutturazione logica dei dati: i file Strutturazione logica dei dati: i file Informazioni più complesse possono essere composte a partire da informazioni elementari Esempio di una banca: supponiamo di voler mantenere all'interno di un computer

Подробнее

Informatica. Rappresentazione dei numeri Numerazione binaria

Informatica. Rappresentazione dei numeri Numerazione binaria Informatica Rappresentazione dei numeri Numerazione binaria Sistemi di numerazione Non posizionali: numerazione romana Posizionali: viene associato un peso a ciascuna posizione all interno della rappresentazione

Подробнее

Capitolo 13: L offerta dell impresa e il surplus del produttore

Capitolo 13: L offerta dell impresa e il surplus del produttore Capitolo 13: L offerta dell impresa e il surplus del produttore 13.1: Introduzione L analisi dei due capitoli precedenti ha fornito tutti i concetti necessari per affrontare l argomento di questo capitolo:

Подробнее

Convertitori numerici in Excel

Convertitori numerici in Excel ISTITUTO DI ISTRUZIONE SUPERIORE G. M. ANGIOY CARBONIA Convertitori numerici in Excel Prof. G. Ciaschetti Come attività di laboratorio, vogliamo realizzare dei convertitori numerici con Microsoft Excel

Подробнее

Elaborazione testi: immagini

Elaborazione testi: immagini by Studio Elfra sas Gestione Immagini Aggiornato a Aprile 2009 Informatica di base 1 Elaborazione testi: immagini Il testo di un documento di Word può essere integrato con immagini di vario tipo: 2 1 Elaborazione

Подробнее

Informatica 3. LEZIONE 21: Ricerca su liste e tecniche di hashing. Modulo 1: Algoritmi sequenziali e basati su liste Modulo 2: Hashing

Informatica 3. LEZIONE 21: Ricerca su liste e tecniche di hashing. Modulo 1: Algoritmi sequenziali e basati su liste Modulo 2: Hashing Informatica 3 LEZIONE 21: Ricerca su liste e tecniche di hashing Modulo 1: Algoritmi sequenziali e basati su liste Modulo 2: Hashing Informatica 3 Lezione 21 - Modulo 1 Algoritmi sequenziali e basati su

Подробнее

Il campionamento. La digitalizzazione. Teoria e pratica. La rappresentazione digitale delle immagini. La rappresentazione digitale delle immagini

Il campionamento. La digitalizzazione. Teoria e pratica. La rappresentazione digitale delle immagini. La rappresentazione digitale delle immagini ACQUISIZIONE ED ELABORAZIONE DELLE IMMAGINI Teoria e pratica La digitalizzazione La digitalizzazione di oggetti legati a fenomeni di tipo analogico, avviene attraverso due parametri fondamentali: Il numero

Подробнее

Rappresentazione dei numeri in un calcolatore

Rappresentazione dei numeri in un calcolatore Corso di Calcolatori Elettronici I A.A. 2010-2011 Rappresentazione dei numeri in un calcolatore Lezione 2 Università degli Studi di Napoli Federico II Facoltà di Ingegneria Rappresentazione dei numeri

Подробнее

Determinare la grandezza della sottorete

Determinare la grandezza della sottorete Determinare la grandezza della sottorete Ogni rete IP possiede due indirizzi non assegnabili direttamente agli host l indirizzo della rete a cui appartiene e l'indirizzo di broadcast. Quando si creano

Подробнее

risulta (x) = 1 se x < 0.

risulta (x) = 1 se x < 0. Questo file si pone come obiettivo quello di mostrarvi come lo studio di una funzione reale di una variabile reale, nella cui espressione compare un qualche valore assoluto, possa essere svolto senza necessariamente

Подробнее

Corso di Matematica per la Chimica

Corso di Matematica per la Chimica Dott.ssa Maria Carmela De Bonis a.a. 203-4 I sistemi lineari Generalità sui sistemi lineari Molti problemi dell ingegneria, della fisica, della chimica, dell informatica e dell economia, si modellizzano

Подробнее

la scienza della rappresentazione e della elaborazione dell informazione

la scienza della rappresentazione e della elaborazione dell informazione Sistema binario Sommario informatica rappresentare informazioni la differenza Analogico/Digitale i sistemi di numerazione posizionali il sistema binario Informatica Definizione la scienza della rappresentazione

Подробнее

LE FUNZIONI A DUE VARIABILI

LE FUNZIONI A DUE VARIABILI Capitolo I LE FUNZIONI A DUE VARIABILI In questo primo capitolo introduciamo alcune definizioni di base delle funzioni reali a due variabili reali. Nel seguito R denoterà l insieme dei numeri reali mentre

Подробнее

Sistema operativo: Gestione della memoria

Sistema operativo: Gestione della memoria Dipartimento di Elettronica ed Informazione Politecnico di Milano Informatica e CAD (c.i.) - ICA Prof. Pierluigi Plebani A.A. 2008/2009 Sistema operativo: Gestione della memoria La presente dispensa e

Подробнее

Altri metodi di indicizzazione

Altri metodi di indicizzazione Organizzazione a indici su più livelli Altri metodi di indicizzazione Al crescere della dimensione del file l organizzazione sequenziale a indice diventa inefficiente: in lettura a causa del crescere del

Подробнее

La distribuzione Normale. La distribuzione Normale

La distribuzione Normale. La distribuzione Normale La Distribuzione Normale o Gaussiana è la distribuzione più importante ed utilizzata in tutta la statistica La curva delle frequenze della distribuzione Normale ha una forma caratteristica, simile ad una

Подробнее

Sommario. Definizione di informatica. Definizione di un calcolatore come esecutore. Gli algoritmi.

Sommario. Definizione di informatica. Definizione di un calcolatore come esecutore. Gli algoritmi. Algoritmi 1 Sommario Definizione di informatica. Definizione di un calcolatore come esecutore. Gli algoritmi. 2 Informatica Nome Informatica=informazione+automatica. Definizione Scienza che si occupa dell

Подробнее

ESEMPIO 1: eseguire il complemento a 10 di 765

ESEMPIO 1: eseguire il complemento a 10 di 765 COMPLEMENTO A 10 DI UN NUMERO DECIMALE Sia dato un numero N 10 in base 10 di n cifre. Il complemento a 10 di tale numero (N ) si ottiene sottraendo il numero stesso a 10 n. ESEMPIO 1: eseguire il complemento

Подробнее

Informatica B a.a 2005/06 (Meccanici 4 squadra) PhD. Ing. Michele Folgheraiter

Informatica B a.a 2005/06 (Meccanici 4 squadra) PhD. Ing. Michele Folgheraiter Informatica B a.a 2005/06 (Meccanici 4 squadra) Scaglione: da PO a ZZZZ PhD. Ing. Michele Folgheraiter Architettura del Calcolatore Macchina di von Neumann Il calcolatore moderno è basato su un architettura

Подробнее

OCCUPATI SETTORE DI ATTIVITA' ECONOMICA

OCCUPATI SETTORE DI ATTIVITA' ECONOMICA ESERCIZIO 1 La tabella seguente contiene i dati relativi alla composizione degli occupati in Italia relativamente ai tre macrosettori di attività (agricoltura, industria e altre attività) negli anni 1971

Подробнее

Guida all uso di Java Diagrammi ER

Guida all uso di Java Diagrammi ER Guida all uso di Java Diagrammi ER Ver. 1.1 Alessandro Ballini 16/5/2004 Questa guida ha lo scopo di mostrare gli aspetti fondamentali dell utilizzo dell applicazione Java Diagrammi ER. Inizieremo con

Подробнее

Introduzione alla teoria dei database relazionali. Come progettare un database

Introduzione alla teoria dei database relazionali. Come progettare un database Introduzione alla teoria dei database relazionali Come progettare un database La struttura delle relazioni Dopo la prima fase di individuazione concettuale delle entità e degli attributi è necessario passare

Подробнее

Introduzione. Classificazione di Flynn... 2 Macchine a pipeline... 3 Macchine vettoriali e Array Processor... 4 Macchine MIMD... 6

Introduzione. Classificazione di Flynn... 2 Macchine a pipeline... 3 Macchine vettoriali e Array Processor... 4 Macchine MIMD... 6 Appunti di Calcolatori Elettronici Esecuzione di istruzioni in parallelo Introduzione... 1 Classificazione di Flynn... 2 Macchine a pipeline... 3 Macchine vettoriali e Array Processor... 4 Macchine MIMD...

Подробнее

Capitolo 3. L applicazione Java Diagrammi ER. 3.1 La finestra iniziale, il menu e la barra pulsanti

Capitolo 3. L applicazione Java Diagrammi ER. 3.1 La finestra iniziale, il menu e la barra pulsanti Capitolo 3 L applicazione Java Diagrammi ER Dopo le fasi di analisi, progettazione ed implementazione il software è stato compilato ed ora è pronto all uso; in questo capitolo mostreremo passo passo tutta

Подробнее

Logica e codifica binaria dell informazione

Logica e codifica binaria dell informazione Politecnico di Milano Corsi di Laurea in Ingegneria Matematica e Ingegneria Fisica Dipartimento di Elettronica ed Informazione Logica e codifica binaria dell informazione Anno Accademico 2002 2003 L. Muttoni

Подробнее

Lezione 10: Il problema del consumatore: Preferenze e scelta ottimale

Lezione 10: Il problema del consumatore: Preferenze e scelta ottimale Corso di Scienza Economica (Economia Politica) prof. G. Di Bartolomeo Lezione 10: Il problema del consumatore: Preferenze e scelta ottimale Facoltà di Scienze della Comunicazione Università di Teramo Scelta

Подробнее

Soluzione dell esercizio del 2 Febbraio 2004

Soluzione dell esercizio del 2 Febbraio 2004 Soluzione dell esercizio del 2 Febbraio 2004 1. Casi d uso I casi d uso sono riportati in Figura 1. Figura 1: Diagramma dei casi d uso. E evidenziato un sotto caso di uso. 2. Modello concettuale Osserviamo

Подробнее

Appunti sulla Macchina di Turing. Macchina di Turing

Appunti sulla Macchina di Turing. Macchina di Turing Macchina di Turing Una macchina di Turing è costituita dai seguenti elementi (vedi fig. 1): a) una unità di memoria, detta memoria esterna, consistente in un nastro illimitato in entrambi i sensi e suddiviso

Подробнее

Come visto precedentemente l equazione integro differenziale rappresentativa dell equilibrio elettrico di un circuito RLC è la seguente: 1 = (1)

Come visto precedentemente l equazione integro differenziale rappresentativa dell equilibrio elettrico di un circuito RLC è la seguente: 1 = (1) Transitori Analisi nel dominio del tempo Ricordiamo che si definisce transitorio il periodo di tempo che intercorre nel passaggio, di un sistema, da uno stato energetico ad un altro, non è comunque sempre

Подробнее

Transitori del primo ordine

Transitori del primo ordine Università di Ferrara Corso di Elettrotecnica Transitori del primo ordine Si consideri il circuito in figura, composto da un generatore ideale di tensione, una resistenza ed una capacità. I tre bipoli

Подробнее

Gestione della memoria centrale

Gestione della memoria centrale Gestione della memoria centrale Un programma per essere eseguito deve risiedere in memoria principale e lo stesso vale per i dati su cui esso opera In un sistema multitasking molti processi vengono eseguiti

Подробнее

C M A P M IONAM A E M NT N O

C M A P M IONAM A E M NT N O IMMAGINE DIGITALE Nelle immagini digitali, il contenuto fotografico (radiometria) viene registrato sotto forma di numeri. Si giunge a tale rappresentazione (RASTER) suddividendo l immagine fotografica

Подробнее

SISTEMI DI NUMERAZIONE E CODICI

SISTEMI DI NUMERAZIONE E CODICI SISTEMI DI NUMERAZIONE E CODICI Il Sistema di Numerazione Decimale Il sistema decimale o sistema di numerazione a base dieci usa dieci cifre, dette cifre decimali, da O a 9. Il sistema decimale è un sistema

Подробнее

Matematica generale CTF

Matematica generale CTF Successioni numeriche 19 agosto 2015 Definizione di successione Monotonìa e limitatezza Forme indeterminate Successioni infinitesime Comportamento asintotico Criterio del rapporto per le successioni Definizione

Подробнее

Lezione 8. La macchina universale

Lezione 8. La macchina universale Lezione 8 Algoritmi La macchina universale Un elaboratore o computer è una macchina digitale, elettronica, automatica capace di effettuare trasformazioni o elaborazioni su i dati digitale= l informazione

Подробнее

Dispense di Informatica per l ITG Valadier

Dispense di Informatica per l ITG Valadier La notazione binaria Dispense di Informatica per l ITG Valadier Le informazioni dentro il computer All interno di un calcolatore tutte le informazioni sono memorizzate sottoforma di lunghe sequenze di

Подробнее

APPUNTI SU PROBLEMI CON CALCOLO PERCENTUALE

APPUNTI SU PROBLEMI CON CALCOLO PERCENTUALE APPUNTI SU PROBLEMI CON CALCOLO PERCENTUALE 1. Proporzionalità diretta e proporzionalità inversa Analizziamo le seguenti formule Peso Lordo = Peso Netto + Tara Ricavo = Utile + Costo Rata = Importo + Interesse

Подробнее

CALCOLO COMBINATORIO

CALCOLO COMBINATORIO CALCOLO COMBINATORIO 1 Modi di formare gruppi di k oggetti presi da n dati 11 disposizioni semplici, permutazioni Dati n oggetti distinti a 1,, a n si chiamano disposizioni semplici di questi oggetti,

Подробнее

Analisi e diagramma di Pareto

Analisi e diagramma di Pareto Analisi e diagramma di Pareto L'analisi di Pareto è una metodologia statistica utilizzata per individuare i problemi più rilevanti nella situazione in esame e quindi le priorità di intervento. L'obiettivo

Подробнее

Rappresentazione delle informazioni

Rappresentazione delle informazioni Rappresentazione delle informazioni Abbiamo informazioni (numeri, caratteri, immagini, suoni, video... ) che vogliamo rappresentare (e poter elaborare) in un calcolatore. Per motivi tecnologici un calcolatore

Подробнее

Amplificatori Audio di Potenza

Amplificatori Audio di Potenza Amplificatori Audio di Potenza Un amplificatore, semplificando al massimo, può essere visto come un oggetto in grado di aumentare il livello di un segnale. Ha quindi, generalmente, due porte: un ingresso

Подробнее

Complemento al corso di Fondamenti di Informatica I corsi di laurea in ingegneria, settore dell informazione Università la Sapienza Consorzio Nettuno

Complemento al corso di Fondamenti di Informatica I corsi di laurea in ingegneria, settore dell informazione Università la Sapienza Consorzio Nettuno Rappresentazione di numeri Complemento al corso di Fondamenti di Informatica I corsi di laurea in ingegneria, settore dell informazione Università la Sapienza Consorzio Nettuno Un numero e un entità teorica,

Подробнее

Fasi di creazione di un programma

Fasi di creazione di un programma Fasi di creazione di un programma 1. Studio Preliminare 2. Analisi del Sistema 6. Manutenzione e Test 3. Progettazione 5. Implementazione 4. Sviluppo 41 Sviluppo di programmi Per la costruzione di un programma

Подробнее

Colorare coi numeri La rappresentazione delle immagini

Colorare coi numeri La rappresentazione delle immagini Attività 2 Colorare coi numeri La rappresentazione delle immagini Sommario I computer memorizzano i disegni, le fotografie e le altre figure usando solo numeri. Questa attività mostra come fanno. Competenze

Подробнее

Codifica binaria dei numeri

Codifica binaria dei numeri Codifica binaria dei numeri Caso più semplice: in modo posizionale (spesso detto codifica binaria tout court) Esempio con numero naturale: con 8 bit 39 = Codifica in virgola fissa dei numeri float: si

Подробнее

Automazione Industriale (scheduling+mms) scheduling+mms. [email protected]

Automazione Industriale (scheduling+mms) scheduling+mms. adacher@dia.uniroma3.it Automazione Industriale (scheduling+mms) scheduling+mms [email protected] Introduzione Sistemi e Modelli Lo studio e l analisi di sistemi tramite una rappresentazione astratta o una sua formalizzazione

Подробнее

I sistemi di numerazione

I sistemi di numerazione I sistemi di numerazione 01-INFORMAZIONE E SUA RAPPRESENTAZIONE Sia dato un insieme finito di caratteri distinti, che chiameremo alfabeto. Utilizzando anche ripetutamente caratteri di un alfabeto, si possono

Подробнее

Psicometria (8 CFU) Corso di Laurea triennale STANDARDIZZAZIONE

Psicometria (8 CFU) Corso di Laurea triennale STANDARDIZZAZIONE Psicometria (8 CFU) Corso di Laurea triennale Un punteggio all interno di una distribuzione è in realtà privo di significato se preso da solo. Sapere che un soggetto ha ottenuto un punteggio x=52 in una

Подробнее

LA TRASMISSIONE DELLE INFORMAZIONI QUARTA PARTE 1

LA TRASMISSIONE DELLE INFORMAZIONI QUARTA PARTE 1 LA TRASMISSIONE DELLE INFORMAZIONI QUARTA PARTE 1 I CODICI 1 IL CODICE BCD 1 Somma in BCD 2 Sottrazione BCD 5 IL CODICE ECCESSO 3 20 La trasmissione delle informazioni Quarta Parte I codici Il codice BCD

Подробнее

1. PRIME PROPRIETÀ 2

1. PRIME PROPRIETÀ 2 RELAZIONI 1. Prime proprietà Il significato comune del concetto di relazione è facilmente intuibile: due elementi sono in relazione se c è un legame tra loro descritto da una certa proprietà; ad esempio,

Подробнее

Statistica e biometria. D. Bertacchi. Variabili aleatorie. V.a. discrete e continue. La densità di una v.a. discreta. Esempi.

Statistica e biometria. D. Bertacchi. Variabili aleatorie. V.a. discrete e continue. La densità di una v.a. discreta. Esempi. Iniziamo con definizione (capiremo fra poco la sua utilità): DEFINIZIONE DI VARIABILE ALEATORIA Una variabile aleatoria (in breve v.a.) X è funzione che ha come dominio Ω e come codominio R. In formule:

Подробнее

Dimensione di uno Spazio vettoriale

Dimensione di uno Spazio vettoriale Capitolo 4 Dimensione di uno Spazio vettoriale 4.1 Introduzione Dedichiamo questo capitolo ad un concetto fondamentale in algebra lineare: la dimensione di uno spazio vettoriale. Daremo una definizione

Подробнее

A intervalli regolari ogni router manda la sua tabella a tutti i vicini, e riceve quelle dei vicini.

A intervalli regolari ogni router manda la sua tabella a tutti i vicini, e riceve quelle dei vicini. Algoritmi di routing dinamici (pag.89) UdA2_L5 Nelle moderne reti si usano algoritmi dinamici, che si adattano automaticamente ai cambiamenti della rete. Questi algoritmi non sono eseguiti solo all'avvio

Подробнее

Come masterizzare dischi con Nero 11

Come masterizzare dischi con Nero 11 Come masterizzare dischi con Nero 11 Non c è dubbio che Nero è diventato un sinonimo di masterizzatore di dischi, data la lunga esperienza sul mercato. Molte persone pensano in questo programma nel momento

Подробнее

Database. Si ringrazia Marco Bertini per le slides

Database. Si ringrazia Marco Bertini per le slides Database Si ringrazia Marco Bertini per le slides Obiettivo Concetti base dati e informazioni cos è un database terminologia Modelli organizzativi flat file database relazionali Principi e linee guida

Подробнее

TECNICHE DI COMPRESSIONE DATI

TECNICHE DI COMPRESSIONE DATI TECNICHE DI COMPRESSIONE DATI COMPRESSIONE DATI La compressione produce una rappresentazione più compatta delle informazioni è come se si usassero meno parole per dire la stessa cosa in modo diverso. Esistono

Подробнее

Ai fini economici i costi di un impresa sono distinti principalmente in due gruppi: costi fissi e costi variabili. Vale ovviamente la relazione:

Ai fini economici i costi di un impresa sono distinti principalmente in due gruppi: costi fissi e costi variabili. Vale ovviamente la relazione: 1 Lastoriadiun impresa Il Signor Isacco, che ormai conosciamo per il suo consumo di caviale, decide di intraprendere l attività di produttore di caviale! (Vuole essere sicuro della qualità del caviale

Подробнее

4. Operazioni aritmetiche con i numeri binari

4. Operazioni aritmetiche con i numeri binari I Numeri Binari 4. Operazioni aritmetiche con i numeri binari Contare con i numeri binari Prima di vedere quali operazioni possiamo effettuare con i numeri binari, iniziamo ad imparare a contare in binario:

Подробнее

INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI

INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI Prima di riuscire a scrivere un programma, abbiamo bisogno di conoscere un metodo risolutivo, cioè un metodo che a partire dai dati di ingresso fornisce i risultati attesi.

Подробнее

I CIRCUITI ELETTRICI. Prima di tutto occorre mettersi d accordo anche sui nomi di alcune parti dei circuiti stessi.

I CIRCUITI ELETTRICI. Prima di tutto occorre mettersi d accordo anche sui nomi di alcune parti dei circuiti stessi. I CIRCUITI ELETTRICI Prima di tutto occorre mettersi d accordo anche sui nomi di alcune parti dei circuiti stessi. Definiamo ramo un tratto di circuito senza diramazioni (tratto evidenziato in rosso nella

Подробнее

Domande a scelta multipla 1

Domande a scelta multipla 1 Domande a scelta multipla Domande a scelta multipla 1 Rispondete alle domande seguenti, scegliendo tra le alternative proposte. Cercate di consultare i suggerimenti solo in caso di difficoltà. Dopo l elenco

Подробнее

La codifica delle immagini

La codifica delle immagini La codifica delle immagini La digitalizzazione La digitalizzazione di oggetti legati a fenomeni di tipo analogico, avviene attraverso due parametri fondamentali: 1. Il numero dei campionamenti o di misurazioni

Подробнее

Probabilità discreta

Probabilità discreta Probabilità discreta Daniele A. Gewurz 1 Che probabilità c è che succeda...? Una delle applicazioni della combinatoria è nel calcolo di probabilità discrete. Quando abbiamo a che fare con un fenomeno che

Подробнее

Testo alla base del Pitgame redatto dal prof. Yvan Lengwiler, Università di Basilea

Testo alla base del Pitgame redatto dal prof. Yvan Lengwiler, Università di Basilea Testo alla base del Pitgame redatto dal prof. Yvan Lengwiler, Università di Basilea Funzionamento di un mercato ben organizzato Nel Pitgame i giocatori che hanno poche informazioni private interagiscono

Подробнее

ControlloCosti. Cubi OLAP. Controllo Costi Manuale Cubi

ControlloCosti. Cubi OLAP. Controllo Costi Manuale Cubi ControlloCosti Cubi OLAP I cubi OLAP Un Cubo (OLAP, acronimo di On-Line Analytical Processing) è una struttura per la memorizzazione e la gestione dei dati che permette di eseguire analisi in tempi rapidi,

Подробнее

Quando troncare uno sviluppo in serie di Taylor

Quando troncare uno sviluppo in serie di Taylor Quando troncare uno sviluppo in serie di Taylor Marco Robutti October 13, 2014 Lo sviluppo in serie di Taylor di una funzione è uno strumento matematico davvero molto utile, e viene spesso utilizzato in

Подробнее

Esponenziali elogaritmi

Esponenziali elogaritmi Esponenziali elogaritmi Potenze ad esponente reale Ricordiamo che per un qualsiasi numero razionale m n prendere n>0) si pone a m n = n a m (in cui si può sempre a patto che a sia un numero reale positivo.

Подробнее

Informazione analogica e digitale

Informazione analogica e digitale L informazione L informazione si può: rappresentare elaborare gestire trasmettere reperire L informatica offre la possibilità di effettuare queste operazioni in modo automatico. Informazione analogica

Подробнее

Codifica delle Informazioni

Codifica delle Informazioni Codifica delle Informazioni Luca Bortolussi Dipartimento di Matematica e Informatica Università degli studi di Trieste Panoramica Le informazioni gestite dai sistemi di elaborazione devono essere codificate

Подробнее

la scienza della rappresentazione e della elaborazione dell informazione

la scienza della rappresentazione e della elaborazione dell informazione Sistema binario Sommario informatica rappresentare informazioni la differenza Analogico/Digitale i sistemi di numerazione posizionali il sistema binario Informatica Definizione la scienza della rappresentazione

Подробнее

Un ripasso di aritmetica: Conversione dalla base 10 alla base 16

Un ripasso di aritmetica: Conversione dalla base 10 alla base 16 Un ripasso di aritmetica: Conversione dalla base 1 alla base 16 Dato un numero N rappresentato in base dieci, la sua rappresentazione in base sedici sarà del tipo: c m c m-1... c 1 c (le c i sono cifre

Подробнее

Traduzione e adattamento a cura di Gylas per Giochi Rari

Traduzione e adattamento a cura di Gylas per Giochi Rari Traduzione e adattamento a cura di Gylas per Giochi Rari Versione 1.0 Luglio 2001 NOTA. La presente traduzione non sostituisce in alcun modo il regolamento originale del gioco; il presente documento è

Подробнее

Funzioni in C. Violetta Lonati

Funzioni in C. Violetta Lonati Università degli studi di Milano Dipartimento di Scienze dell Informazione Laboratorio di algoritmi e strutture dati Corso di laurea in Informatica Funzioni - in breve: Funzioni Definizione di funzioni

Подробнее

Esempio: dest = parolagigante, lettere = PROVA dest (dopo l'invocazione di tipo pari ) = pprrlogvgante

Esempio: dest = parolagigante, lettere = PROVA dest (dopo l'invocazione di tipo pari ) = pprrlogvgante Esercizio 0 Scambio lettere Scrivere la funzione void scambiolettere(char *dest, char *lettere, int p_o_d) che modifichi la stringa destinazione (dest), sostituendone i caratteri pari o dispari (a seconda

Подробнее

Capitolo V : Il colore nelle immagini digitali

Capitolo V : Il colore nelle immagini digitali Capitolo V : Il colore nelle immagini digitali Lavorare con il colore nelle immagini digitali L uso dei colori nella visione computerizzata e nella computer grafica implica l incorrere in determinate problematiche

Подробнее

Elementi di informatica

Elementi di informatica Elementi di informatica Sistemi di numerazione posizionali Rappresentazione dei numeri Rappresentazione dei numeri nei calcolatori rappresentazioni finalizzate ad algoritmi efficienti per le operazioni

Подробнее

Operazioni Aritmetiche e Codici in Binario Giuseppe Talarico 23/01/2013

Operazioni Aritmetiche e Codici in Binario Giuseppe Talarico 23/01/2013 Operazioni Aritmetiche e Codici in Binario Giuseppe Talarico 23/01/2013 In questo documento vengono illustrate brevemente le operazioni aritmetiche salienti e quelle logiche ad esse strettamente collegate.

Подробнее

Appunti di informatica. Lezione 2 anno accademico 2015-2016 Mario Verdicchio

Appunti di informatica. Lezione 2 anno accademico 2015-2016 Mario Verdicchio Appunti di informatica Lezione 2 anno accademico 2015-2016 Mario Verdicchio Sistema binario e logica C è un legame tra i numeri binari (0,1) e la logica, ossia la disciplina che si occupa del ragionamento

Подробнее

Giorgio Maria Di Nunzio

Giorgio Maria Di Nunzio Università degli Studi di Padova Dipartimento di Scienze Storiche, Geografiche e dell Antichità Fondamenti di Informatica A.A. 2012/2013 Giorgio Maria Di Nunzio Immagini Digitali Ä Dispense aggiuntive

Подробнее

1. Distribuzioni campionarie

1. Distribuzioni campionarie Università degli Studi di Basilicata Facoltà di Economia Corso di Laurea in Economia Aziendale - a.a. 2012/2013 lezioni di statistica del 3 e 6 giugno 2013 - di Massimo Cristallo - 1. Distribuzioni campionarie

Подробнее

CHIUSURE di MAGAZZINO di FINE ANNO

CHIUSURE di MAGAZZINO di FINE ANNO CHIUSURE di MAGAZZINO di FINE ANNO Operazioni da svolgere per il riporto delle giacenze di fine esercizio Il documento che segue ha lo scopo di illustrare le operazioni che devono essere eseguite per:

Подробнее

Obiettivi dell Analisi Numerica. Avviso. Risoluzione numerica di un modello. Analisi Numerica e Calcolo Scientifico

Obiettivi dell Analisi Numerica. Avviso. Risoluzione numerica di un modello. Analisi Numerica e Calcolo Scientifico M. Annunziato, DIPMAT Università di Salerno - Queste note non sono esaustive ai fini del corso p. 3/43 M. Annunziato, DIPMAT Università di Salerno - Queste note non sono esaustive ai fini del corso p.

Подробнее

Capitolo 2. Operazione di limite

Capitolo 2. Operazione di limite Capitolo 2 Operazione di ite In questo capitolo vogliamo occuparci dell operazione di ite, strumento indispensabile per scoprire molte proprietà delle funzioni. D ora in avanti riguarderemo i domini A

Подробнее

lo 2 2-1 - PERSONALIZZARE LA FINESTRA DI WORD 2000

lo 2 2-1 - PERSONALIZZARE LA FINESTRA DI WORD 2000 Capittol lo 2 Visualizzazione 2-1 - PERSONALIZZARE LA FINESTRA DI WORD 2000 Nel primo capitolo sono state analizzate le diverse componenti della finestra di Word 2000: barra del titolo, barra dei menu,

Подробнее