Hai un minuto di tempo da dedicarmi? Ti chiedo di compilare questo questionario per darmi una mano a costruire il futuro del blog. Grazie! :)

Processare le immagini in Processing

In questo post vedremo come unire le nozioni che abbiamo appreso relativamente al caricamento e all’ utilizzo delle immagini in Processing e alle possibilità creative che abbiamo a disposizione lavorando sui singoli pixel per imparare a processore le immagini a nostro piacimento.

Riprendiamo l’immagine del gatto che abbiamo già usato in precedenza e carichiamola all’interno di un nuovo sketch. Invece di utilizzare la funzione image() per mostrarla nella finestra, questa volta andremo a caricare tutti i pixel che compongono l’immagine.

Analizziamo velocemente il codice qui sopra concentrandoci, in particolare, sulle cose che non abbiamo mai visto prima: come indicato nei commenti, oltre a caricare i pixel della finestra dobbiamo caricare anche quelli relativi all’immagine. Per farlo utilizziamo img.loadPixels(); dove img fa riferimento al nome della variabile che abbiamo dichiarato all’inizio del programma.

Con due loop for andiamo a caricare ogni singolo pixel e, utilizzando le funzioni red()green()blue() otteniamo i valori R, G e B. Attraverso pixels[pos] = color(r, g, b); assegniamo i valori al pixel sullo schermo.

Il nostro programma, in pratica, lavora come segue: che valori di rossoverdeblu ha il pixel nell’immagine che ha coordinate x = 0, y = 0? Una volta ottenuti, applica quei valori al pixel con posizione x = 0 e y = 0 della finestra. Dopodiché, il ciclo for prosegue e analizzerà il pixel con coordinate x = 1 e y = 0 e avanti così.

Con l’updatePixel() finale aggiorniamo tutti i valori presenti nell’array della finestra. Il risultato finale sarà, dunque, vedere visualizzata sullo schermo l’immagine.

La domanda che sorge spontanea è: perché dovrei scrivere tutte queste righe di codice quando avrei potuto usare la funzione image() e risparmiare un sacco di fatica? La risposta è semplice: avendo accesso ai dati grezzi dell’immagine possiamo modificarli a nostro piacimento.

Proviamo, ad esempio, ad aggiungere la riga in grassetto al nostro codice:

r = constrain(r, 0, 100);
 
pixels[pos] = color(r, g, b);

Il risultato sarà che il valore del rosso non potrà avere un valore compreso tra 0 e 255 come previsto normalmente ma sarà limitato a valori compresi tra 0, 100 grazie alla funzione constrain.

Processare le immagini in Processing

Siamo riusciti a creare il nostro primo filtro personalizzato per le immagini. Ora possiamo dare sfogo alla nostra fantasia.

Facciamo un altro esperimento: rimpiazziamo l’ultima riga di codice che abbiamo aggiunto con quella seguente:

r = map(mouseX, 0, width, 0, 255);

Il rosso ora è controllato dalla posizione x del mouse.

Usare un solo ciclo for

Prima di concludere questo post ci tengo a fare una precisazione: volendo è possibile utilizzare un solo ciclo for per ottenere lo stesso effetto riducendo, così, le righe di codice del nostro programma:

for(int i = 0; i < pixels.length; i++)

Se decidiamo di intraprendere questa strada dobbiamo eliminare la variabile pos e sostituirla con i:

float r = red(img.pixels[i]);

Come avevamo discusso nel post relativo all’array di pixel la differenza tra i due approcci dipende se consideriamo l’immagine un array monodimensionale o bidimensionale.