Canvas: Cambiare il colore di un’immagine e renderla semi-trasparente

Utilizzare il canvas per modificare le immaginiCon l’articolo di oggi vado a unirmi ai miei colleghi che già in passato hanno scritto riguardo l’uso del tag canvas e vi presento questo piccolo esperimento.

In uno dei nostri ultimi siti, ci sarebbe stato comodo poter usare un’unica immagine, in varianti di colore diverse, senza però dover creare una copia dell’immagine per ciascuna tonalità. L’immagine è semitrasparente ed è presentata di volta in volta su uno sfondo diverso, quindi nessuna delle tecniche utilizzate in passato mi è sembrata adatta allo scopo.

Il canvas invece sembrava adatto ma purtroppo su explorer ancora il supporto manca, quindi alla fine è risultato utile solo allo scopo di farci qualche esperimento.

L’idea è di caricare un’immagine all’interno di un canvas, convertirla in scala di grigi e aggiungere una tonalità a scelta, creando così la variante desiderata.

Caricare un’immagine all’interno del canvas

Il primo passo da fare è quello di caricare i dati dell’immagine all’interno del canvas. La sorgente verrà presa da un tag IMG.
Supponendo di non conoscere a priori la dimensione dell’immagine sorgente, impostiamo inizialmente il canvas per avere una dimensione di 0x0 pixel, per poi ridimensionarla tramite il javascript alla stessa grandezza dell’immagine sorgente.

L’html, è semplicemente costituito da questi due elementi:

<img id="source" src="data:image/gif;base64,..." alt="Hosting Home" />
<canvas id="dest" width="0" height="0"></canvas>

Da notare che nell’esempio inseriamo i dati dell’immagine direttamente nell’html codificati in base64. Questo perché a causa della same origin policy non possiamo leggere i dati di un’immagine proveniente da un dominio diverso da quello della pagina html.

A questo punto per caricare l’immagine nel canvas, ci basta utilizzare la funzione drawImage, passandogli l’elemento IMG in input.

var img = document.id('source');
var canvas = document.id('dest');

// Imposto il canvas delle stesse dimensioni dell'immagine originale
var s = img.getSize();
canvas.set('width', s.x);
canvas.set('height', s.y);
// Ora potremmo anche nascondere l'immagine originale
//img.setStyle('display', 'none');

// Disegno l'immagine all'interno del canvas
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0);

PS: per semplicità nell’esempio abbiamo utilizzato MooTools, ma il codice è abbastanza generico da essere facilmente adattabile ad altri framework javascript.

Manipoliamo l’immagine

Caricata l’immagine, possiamo leggerne i dati e passandoci l’intera immagine pixel per pixel, variarne la tonalità.

I dati dei pixel possono essere recuperati con la funzione getImageData del context.
Per motivi di performance salviamo l’array data contenente i valori in una variabile temporanea. Questa operazione velocizza notevolmente la lettura in Firefox per qualche ragione.

L’array dei dati va girato di 4 byte per volta. Questo perché i valori contenuti al suo interno sono 4 per ogni pixel, ovvero i valori dei canali RGB e A (per la trasparenza).

Per ogni pixel, calcolo quindi la luminanza (variabile basecol) e, dato che ho scelto di rendere verde il risultato, moltiplico per 1,5 il pixel del verde (non andando oltre il valore massimo di 255).

Al fine di rendere le cose più interessanti ho deciso anche di rendere completamente trasparenti i pixel bianchi.

Eccovi il risultato:
[iframe src=”//jsfiddle.net/85PBv/2/embedded/”]