Questo articolo apparteneva al vecchio blog (blog.danilopetrozzi.it), per cui le informazioni potrebbero non essere più aggiornate ed attendibili.

Come comprimere le immagini fino al -99% senza perdita di qualità

Poco tempo fa ho scritto un articolo riguardo la codifica in base64 delle immagini e il suo risvolto in termini di velocità di caricamento. Oggi, invece, ci occupiamo della compressione “tradizionale” delle immagini: ossia la riduzione del loro peso intrinseco, al fine di migliorare la velocità di caricamento e, quindi, il posizionamento sui motori di ricerca.

Dato che l’avevo promesso, questa lezione verrà tenuta facendo riferimento allo stesso esperimento che avevo postato sul mio Google+:

Come potete verificare da soli, la differenza tra le due immagini è di oltre il 99% ma la qualità percepita non cambia (espandendo il post di Google+ potete trovare i link alle immagini, ma ci sono anche più in basso 🙂 )

Prima vi mostrerò i risultati, e poi vi spiegherò il meccanismo per ottenerli:

L’esperimento

Dopo aver preso una immagine di base in formato .PNG, l’ho compressa con diversi metodi “famosi” e infine ho applicato quello che io chiamo la “selezione intelligente” in formato .GIF, e ho comparato i risultati. L’immagine .PNG originale pesa 2.86 MB (tantissimo), per cui non l’ho inclusa nel grafico finale, dato che avrebbe incasinato le proporzioni.

Per prima cosa, ti mostro una sotto l’altra tutte le immagini con la descrizione del metodo di compressione. Se vuoi condurre ulteriori analisi, puoi cliccare sulla thumbnail di ogni immagine per aprire il file originale:

Immagine originale nel formato .PNG

Immagine compressa in .JPG con qualità 12 su 12

Immagine compressa in .JPG con qualità 0 su 12

Immagine in formato .PNG compresso

Immagine in formato .GIF normale

Immagine .GIF con selezione a 10 colori

Immagine .GIF con selezione a 5 colori

Immagine .GIF con selezione a 3 colori

Se utilizzate un software di editing come Photoshop, avete a disposizione tutte queste metodologie. Anzi, ne avete a disposizione molte di più, come la possibilità di interlacciare le immagini per “simulare” caricamenti più veloci, ma oggi non parleremo di questo.

Dopo aver generato queste immagini, ho calcolato il peso in KB e ho riassunto tutto in un grafico facilmente comprensibile:

Risultati dell’esperimento

Come ho detto all’inizio, per evitare distorsioni eccessive ho tolto la .PNG originale dato che, in proporzione sarebbe lunga quasi dieci volte più del primo risultato nel grafico… 🙂

grafico velocità di caricamento immagini in vari formati

Et voilà! Ti hanno sempre detto che JPEG e PNG sono i migliori formati per il web, giusto? Eppure il formato ultracompresso JPEG 0/12, la cui percezione visiva è ORRIDA, pesa più del doppio della mia GIF con selezione dei colori più “permissiva”.

Che ne dici, è giunto il momento di cambiare formati? 😀

Il metodo di compressione by Danilo

Teoria

In realtà non ho scoperto nulla di trascendentale, ma dato che non ci sono guide decenti che applicano la modifica delle palette alla velocità di caricamento (e quindi alla SEO), mi permetto di dire che il metodo è by me 😀

Prima, però, serve un pò di teoria.

Cos’è un’immagine? Molti di voi diranno: è un insieme di pixel, ognuno di un colore differente, che messi insieme producono l’effetto visivo dell’immagine. Da un punto di vista generale, il concetto è giusto. La maggiorparte delle immagini presenti nel web funziona in quel modo: ogni pixel è descritto da un codice (esadecimale n in formato rgb(255,255,255)) che ne indica la tonalità. Ma non tutte le immagini funzionano così!

Le immagini .GIF, per esempio, possono sia funzionare con il metodo RGB (quello tradizionale) che con il metodo basato sull’indice. Una .GIF si dice indicizzata quando i pixel sono descritti tramite un vettore (array multidimensionale) che funge da “palette” madre. Non ci hai capito una mazza? Ok, calma, faccio un esempio 🙂

Immagina di avere un’immagine composta da 4 pixel in orizzontale composta solo da 2 colori (che si alternano). Facciamo finta di zoomare, vedresti una cosa del genere:

pixel

Nel caso di una immagine tradizionale, il “codice sorgente” è composto da pixel singoli che vengono identificati da un colore con cui “devono essere riempiti”. Dato che siamo in ambito web, probabilmente la codifica è in RGB a 24-bit, e quindi l’immagine in alto si traduce così:

RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39)

E’ un codice abbastanza lungo, se pensate che serve a identificare un’immagine di 4 pixel, no?

Il metodo basato sugli indici opera diversamente. Invece di ripetere ogni volta il colore del pixel, viene creato un array iniziale (un vettore, o indice, o palette, sono tutti sinonimi) in cui vengono inseriti i colori presenti nell’immagine e a ognuno viene assegnato un “index value”.  Sfruttando l’esempio precedente, la versione indicizzata sarebbe simile a:

(indice) [0] -> RGB(29,16,210), [1] ->RGB(16,210,39)

(immagine) [0][1][0][1]

Abbiamo creato un indice il cui primo elemento è il colore blu, mentre il secondo elemento è il colore verde. Quando dobbiamo “descrivere” l’immagine, usiamo il numero dell’indice al posto del codice-colore, e quindi abbiamo 0-1-0-1 (blu-verde-blu-verde). L’esempio che abbiamo fatto è molto semplice, ma se proviamo a comparare la lunghezza del codice (e quindi il peso) della stessa immagine di prima, stavolta formata da 100 pixel alternati verdi e blu?

In formato tradizionale:

RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39) RGB(29,16,210) RGB(16,210,39)

In formato indicizzato:

[0] -> RGB(29,16,210), [1] ->RGB(16,210,39)

[0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1]

Anche a occhio vi accorgete della differenza di spazio occupato dalle due immagini (che visivamente sono identiche, ricordiamolo!)

Il vettore iniziale

La “magia”, quindi, la fa il vettore iniziale. Spesso viene chiamato anche palette, dato che assomiglia alla tavolozza del pittore, dove lui posiziona tutti i colori che utilizzerà nel quadro. (se nella tavolozza mette solo bianco e nero, però, non potrà pitturare con il grigio.. Poi approfondiremo questo concetto)

Anche andando a intuito, potrai già capire i casi in cui il vettore è lo strumento più idoneo da utilizzare e altri in cui è sconsigliato.

  • Se il numero di colori unici totali all’interno dell’immagine è basso, le immagini indicizzate permettono di risparmiare fino al 99% di spazio e oltre (come ho dimostrato).
  • Se il numero di colori unici totali all’interno dell’immagine è alto, il vantaggio offerto dal vettore è minore, anzi può essere nullo.

Le immagini tradizionali, essendo a 24bit, permettono di indicare ben 256^3 colori = 256 * 256 * 256 = 16.777.216 colori differenti. Se io, però, conosco in anticipo il numero di colori di cui ho bisogno, posso ridurre questo “spazio” solo alla “palette di colori di cui ho effettivamente bisogno”, grazie appunto al vettore iniziale.

Il vettore iniziale delle immagini GIF può supportare un minimo di 3 colori fino a un massimo di 256. Ecco perché questo metodo non è consigliato per immagini estremamente dettagliate o che presentano gradienti di colore (sfumature da A a B).

Se la tecnica del vettore venisse utilizzata per comprimere dei gradienti ultra-dettagliati, purtroppo ci sarebbe perdita di qualità dato che il vettore non ha a disposizione determinati colori e quindi non può mostrarli:


Immagine in JPG 12/12

Immagine in GIF con palette da 30 colori su 256

Formati indicizzati

Il formato migliore per sperimentare l’indicizzazione è indubbiamente .GIF, dato che è stato sviluppato proprio per questo motivo. Quando .GIF nacque, ci fu l’esigenza di velocizzare il caricamento e la renderizzazione delle gif animate (dato che a quel tempo non c’era sicuramente la fibra ottica..). Per ridurre al minimo il peso delle animazioni, senza alterare la qualità, il metodo dell’array venne applicato con successo a questo formato, che spopolò in brevissimo tempo.

I moderni tool di grafica come Photoshop permettono di alterare la palette delle immagini .GIF, quindi tanto vale utilizzare sempre questo formato!

Pratica

Come faccio concretamente a salvare un’immagine in formato .GIF e a scegliermi la palette dei colori? Se usi Photoshop, con un pò di smanettamento ci puoi arrivare.

Quando salvi qualcosa in formato .GIF ti viene data la possibilità di alterare la palette. Ci sono tanti metodi semi automatici (perceptual, selective, adaptive e così via) con cui puoi divertirti. Nell’esempio in basso, ho impostato la palette su Custom, e quindi mi da la possibilità di alterarla manualmente.

Come puoi vedere, in questo caso specifico il nostro vettore iniziale è composto da 0 = nero, 1 = bianco, 2 = blu, 3 = verde  (e quindi usiamo solo 4 colori invece di 256)

compressione gif con photoshop

 

Risvolti in ambito SEO

E’ facile intuire l’importanza sotto il profilo SEO di questa tecnica. Se un immagine visivamente identica passa da 2.90 MB a una ventina di KB, significa che 10 immagini di quel tipo passano da 23 Megabyte a 200 Kilobyte. Il vantaggio in termini di ranking (dato che la velocità di caricamento è un fattore di ranking) e in termini di pageviews, permanenza sul sito, e così via, è indiscutibile.

L’unico svantaggio di questo tipo di compressione è che va fatta manualmente. Non ci sono plugin magici per WordPress che lo fanno al posto nostro (magari un giorno ne sviluppo uno, chissà 😀 ).

La compressione con il vettore può essere utilissima per comprimere le immagini ridondanti di un sito (logo, header, footer, sfondo, e così via) in modo da migliorare tantissimo la velocità di caricamento di tutte le pagine con pochissime operazioni.

E tu, che ne pensi? Conoscevi questo metodo? 🙂

Danilo petrozzi

Ciao! Io sono Danilo Petrozzi, il fondatore di Eternal Curiosity. Oltre a essere un senior SEO Specialist e un Web Developer, è dall'età di 9 anni che mi appassiono a qualsiasi cosa ruoti intorno al web e all'informatica in generale.

Commenti (1)

  • Avatar

    Glauco

    |

    Ciao Danilo, complimenti ottima guida!!

    Reply

Lascia un commento