Lettura e visualizzazione file di testo
Caricamento di file di testo
var strings;
function preload() {
strings = loadStrings( "assets/donnina.txt" );
}
function setup() {
print( strings );
}
carica un file di testo non formattato e restituisce un array di stringhe; in questo caso il file è stato messo nella sottocartella "assets".
visualizza il file nella console del browser attivabile cliccando con il tasto destro del mouse sulla pagina e poi su "Ispeziona".

Caricamento testo e visualizzazione sul canvas
var strings;
function preload() {
strings = loadStrings("assets/donnina.txt");
}
function setup() {
createCanvas( 310,630 );
background( 240 );
textSize( 13 );
for (var i=0; i<strings.length; i+=1) {
var lineY = 46 + i*18;
text( strings[i], 50,lineY );
}
}
coordinata y della linea di testo da visualizzare, a partire da 46 con spaziature di 18 pixel fra un ciclo e l'altro.
visualizza la linea di testo di ogni ciclo (strings[i]) nella posizione corretta (50,lineY).

Provare a modificare l'incremento della variabile iterata in modo da visualizzare solo alcune righe, ad esempio una ogni 10: for (...; ...; i+=10) {
Formato .csv (Comma Separated Values)
I dati sono memorizzati in un file di testo non formattato e con codifica UTF-8. Ogni elemento è riportato in un'unica riga con i valori dei campi separati da un ";". La prima riga può contenere i nomi dei campi sottostanti.

Nei paesi anglosassoni il separatore è costituito dalla virgola che non crea problemi con i numeri decimali.
Esempio di file .csv

I dati sono stati ricavati da:
Esempio di file .tsv (Tab Separated Values)
Il separatore è costituito da un carattere di tabulazione .

Il file si trova nella sotocartella "assets" e si chiama "bikes-mi.tsv".
Visualizzazione dati .tsv
var table;
function preload() {
table = loadTable("assets/bikes-mi.tsv", "tsv", "header");
}
function setup() {
createCanvas(450,450);
background(240);
}
function draw() {
if (frameCount < table.getRowCount()) {
var tableRow = table.getRow( frameCount-1 );
var x = tableRow.getNum( "LON" ) - 9.15;
var y = tableRow.getNum( "LAT" ) - 45.44;
var diam = tableRow.getNum( "STALLI") / 2;
ellipse( x*6000,height-y*9000, diam,diam );
}
}
carica il file "bikes-mi.tsv" indicando il formato e la presenza di una riga di intestazione.
ricava la riga di dati corrispondente al numero di fotogramma corrente.
ricava il valore numerico presente alla colonna indicata fra parentesi tonde.
i valori letti (soprattutto quelli di longitudine e latitudine) vanno adattati alle coordinate del canvas. Nel caso della latitudine il valore va anche invertito (height-y*9000).

Lettura e visualizzazione di dati strutturati
Metalinguaggio XML
Un linguaggio derivato da XML è basato su
marcatori
che possono includere
- testo (il contenuto vero e proprio)
- attributi (informazioni sul contenuto)
- altri marcatori
Marcatori, attributi e contenuto
Tutti i file XML iniziano con una dichiarazione di formato. Segue un elemento principale che contiene tutti gli altri.

marcatori: nomi degli elementi delimitati da parentesi angolari;
attributi: proprietà di ogni elemento;
testo: contenuto vero e proprio che può contenere altri elementi;
fine marcatore: per indicare il marcatore di chiusura o la sua assenza.
Linguaggi XML: ad es. RSS

rss: dichiarazione di linguaggio;
channel: gruppo di articoli (anche più d'uno) con informazioni iniziali sul canale;
item: articolo (anche più d'uno) con relativi dati e contenuto.
Lettura di un RSS (es. con titoli articoli)
var rss;
function preload() {
rss = loadXML( "assets/repubblica_home.xml" );
}
function setup() {
var channel = rss.getChild( "channel" );
var items = channel.getChildren( "item" );
for (var i=0; i<items.length; i++) {
var title = items[i].getChild( "title" );
print( title.getContent() );
}
}
carica un file che segue le specifiche XML e restituisce un oggetto p5.XML; il file si trova nella sottocartella "assets".
restituiscono un oggetto p5.XML che contiene il primo elemento "figlio" con il nome passato fra parentesi tonde; l'elemento viene cercato fra i diretti discendenti dell'oggetto che chiama il metodo.
restituisce un array di oggetti p5.XML con il nome passato fra parentesi tonde; gli elementi sono solo i diretti discendenti dell'oggetto che chiama il metodo.
restituisce il contenuto dell'elemento; in questo caso il testo del titolo.

Interpretazione grafica di un RSS
var rss;
function preload() {
rss = loadXML( "assets/repubblica_home.xml" );
}
function setup() {
createCanvas(400,400);
colorMode( HSB, 255 );
noStroke();
var items = rss.getChild("channel").getChildren("item");
for (var i=0; i<items.length; i++) {
var title = items[i].getChild("title").getContent();
var fillHue = title.charCodeAt(0)*99 % 255;
var diametro = title.length*2.7;
fill( fillHue,255,255, 64 );
ellipse( 200,200, diametro,diametro );
}
}
ricava l'elemento "channel" e subito dopo i relativi elementi "item" senza usare una variabile intermedia.
calcola il tono del colore dei cerchi usando il 1° carattere dei titoli moltiplicato per 99 e "tagliato" in modo da non avere mai valori superiori a 255 (% 255).
calcola il diamentro dei cerchi moltiplicando la lunghezza dei titoli per 2.7.

Provare a modificare il numero di carattere da usare (title.charCodeAt(0)) e/o il moltiplicatore (*99).
Il formato JSON (JavaScript Object Notation)
È basato sulle definizioni sintetiche di due strutture dati di base di JavaScript:
array: [valore,valore,valore]
oggetti: {chiave:valore,chiave:valore}.

chiavi: nel file sono da mettere sempre fra virgolette, a differenza di quello che succederà poi nel codice JavaScript;
valori: può essere costituito da qualsiasi tipo di dato di base (numero, stringa, booleano) o da un ulteriore oggetto o array;
array di oggetti: contenuto a sua volta nell'oogetto principale.
P5.js non prevede una classe specifica (come la p5.XML) perché il contenuto di un file JSON viene convertito facilmente in una struttura dati standard usabile direttamente attraverso le chiavi, le parentesi quadre e i punti (ad es. dati.utenti[0].nome).
Lettura e interpretazione grafica di un JSON
var milan;
function preload() {
milan = loadJSON( "assets/milan_17041006.json" );
}
function setup() {
var backGreen = (milan.main.humidity - 20) * 4;
var fillRed = (milan.main.temp - 280) * 8;
var ellipseW = (milan.main.pressure - 970) * 1.5;
background( 0, backGreen, 255 );
fill( fillRed, 0, 0 );
ellipse( 50,50, ellipseW,50 );
}
carica un file che segue le specifiche JSON e restituisce un oggetto JavaScript contenente le informazioni sul tempo di Milano alle 6:00 del 10/04/2017; il file si trova nella sottocartella "assets".
usa i campi interni dell'oggetto JavaScript per ricavare i parametri cromatici e geometrici dell'ellisse da disegnare; la temperatira (milan.main.temp) è espressa in gradi Kelvin.

I dati in tempo reale possono essere trovati attraverso una richiesta HTTP; l'indirizzo del link può essere copiato (con il tasto destro del mouse) e incollato come parametro dell'istruzione loadJSON().
Transcodifiche dei pixel
Reinterpretazione dei colori

Fonte immagine: Faces of the Earth: Sadhu
Reinterpretazione dei colori: esempio
var photo;
function preload() {
photo = loadImage("assets/putia.jpg");
}
function setup() {
createCanvas(420, 640);
noFill();
}
function draw() {
for (var i=0; i<10; ++i) {
var x = random( photo.width );
var y = random( photo.height );
var col = photo.get( x, y );
stroke( col );
ellipse( x,y, 11,11 );
}
}
carica l'immagine da cui ricavare i colori dei pixel; il file si trova nella sottocartella "assets".
ricava le coordinate di un pixel a caso tenendo conto delle dimensioni dell'immagine caricata.
leggi il colore del pixel scelto a caso.

Per ottenere una maggiore velocità nella lettura dei singoli pixels conviene usare direttamente l'array pixels:
var photo;
function preload() {
photo = loadImage("assets/putia.jpg");
}
function setup() {
createCanvas(420, 640);
photo.loadPixels();
noFill();
}
function draw() {
for (var i=0; i<1000; ++i) {
var x = int(random(photo.width));
var y = int(random(photo.height));
var iPix = (x + y*photo.width) * 4;
var col = photo.pixels.slice( iPix, iPix+3 );
stroke( col[0], col[1], col[2] );
ellipse( x,y, 11,11 );
}
}
carica i pixel dell'immagine photo nel suo array pixels.
calcola l'indice, dell'elemento dell'array, corrispondente al valore di rosso del pixel x,y; ogni pixel è rappresentato da 4 elementi dell'array pixels (rosso, verde, blu, alfa in successione).
ricava i 3 elementi dell'array pixels a partire dall'indice ricavato (iPix).
Provare a usare in modo diverso le coordinate e il colore ricavati, ad esempio con:
stroke( col[0],col[1],col[2],
line( x-20,y+2, x+20,y-2 );
Fonte immagine: Faces of the Earth: Putia
ASCII Art

Fonte immagine: TEXT-IMAGE
ASCII Art: esempio
var photo;
var font;
var letters = " ¸.-~yYzWaEg@"; // palette caratteri
var charW = 7; // larghezza caratteri
var charH = 10; // altezza caratteri
var toneDiv = 256.0 / letters.length;
function preload() {
photo = loadImage( "assets/putia.jpg" );
font = loadFont( "assets/consolas.ttf" );
}
function setup() {
createCanvas(420, 640);
background(0);
fill(255);
textFont( font, 10 );
textAlign( LEFT, TOP );
photo.resize(photo.width/charW, photo.height/charH);
photo.filter(GRAY);
for (var y=0; y<photo.height; y++) {
for (var x=0; x<photo.width; x++) {
var col = photo.get( x, y );
var tone = red(col) / toneDiv;
var letter = letters.charAt( tone );
text( letter, x*charW, y*charH );
}
}
}
divisore che permette di ricavare il tono della palette di caratteri (tone) a partire dal valore di luminosità del pixel (red(col)).
riduce le dimensioni dell'immagine in modo che a ogni pixel corrisponda un carattere della griglia.
desatura i colori dell'immagine in modo da ottenere direttamente i livelli di luminosità dei singoli pixel; l'operazione si sarebbe potuta evitare [usando poi lightness(col) anziché red(col)] ma la versione attuale di p5.js (0.5.8) non sembra riportare il valore corretto.
ricava il carattere da usare come elemento tonale nella cella (della griglia) corrispondente al pixel analizzato.

Fonte immagine: Faces of the Earth: Putia
Errori di decodifica: Glitch Art (e datamoshing)

Per le modifiche può essere utilizzato un editor di testo come Notepad++ (Windows) o TextEdit (Mac).
L'operazione è possibile anche sui video compressi (Datamosh with data corruption) ma con i video si possono usare altre tecniche legate alla compressione temporale.

Fonte immagine: Faces of the Earth: Sadhu.
Fonte GIF animata: iilluussoorr — Twin Peaks.
Computer vision

Fonte immagine: Face Morphing by Alan Yao
Computer vision: esempio
function setup() {
createCanvas(640, 480);
ellipseMode(CORNER);
strokeWeight(3);
fill(255,128);
capture = createCapture(VIDEO);
capture.size( width, height );
capture.hide();
detector = new objectdetect.detector( width, height, 1.2, objectdetect.eye );
}
function draw() {
image(capture, 0, 0);
var eyes = detector.detect( capture.elt, 1, 3 );
if (eyes) {
eyes.forEach( drawEye );
}
}
function drawEye( eye ) {
var threshold = eye[4];
if(threshold > 2) {
ellipse( eye[0], eye[1], eye[2], eye[3] );
}
}
crea un elemento HTML <video> in cui far riprodurre i fotogrammi della webcam; l'elemento viene poi nascosto (capture.hide()) per non vedere sia l'immagine catturata che quella elaborata.
crea e inizializza l'oggetto che dovrà elaborare le immagini; gli "oggetti" da riconoscere saranno gli occhi (objectdetect.eye).
effettua il riconoscimento leggendo le immagini dall'elemento <video> (capture.elt); se l'esito è positivo viene restituito un array di array di 5 elementi (2 per la posizione, 2 per le dimensioni e 1 per l'affidabilità del riconoscimento).
per ogni elemento dell'array principale (eyes) viene chiamata una funzione a cui verranno passati i dati di ogni oggetto riconosciuto (eye); la funzione è stata definita subito dopo il draw().

Per la cattura del video è richiesta l'inclusione della libreria p5.dom.js [vedi file index.html].
Per il riconoscimento degli occhi sono necessarie anche le librerie objectdetect.js e objectdetect.eye.js scaricabili dal profilo GitHub di Martin Tschirsich [vedi file index.html].
Fonte immagine: flickr.com/photos/alper/5085303527.
Visualizzazione dell'audio
Campioni audio
Semplificando, i campioni audio rappresentano la sequenza dei livelli del volume.

Le visualizzazioni che si possono ottenere sono coerenti solo con ritmi ben scanditi.
Approfondimenti: Realtime audio processing
Immagine ottenuta con Sonic Visualiser
Esecuzione di un brano audio con p5.js
L'audio può essere riprodotto, generato e analizzato attraverso la libreria p5.sound.js.
var sound;
function preload() {
sound = loadSound( 'assets/liszt.mp3' );
}
function setup() {
sound.play();
}
carica un brano audio in formato MP3 e lo rende disponibile per l'esecuzione; sono supportati anche i formati OGG, WAV e M4A ma va verificata la compatibilità con i diversi browser.
avvia l'esecuzione del brano caricato.
La libreria p5.sound.js dev'essere linkata nella pagina principale dello sketch [vedi file index.html].
Visualizzazione dei campioni audio
var sound;
function preload() {
sound = loadSound( 'assets/liszt.mp3' );
}
function setup() {
createCanvas( 300, 512 );
sound.loop();
fft = new p5.FFT();
}
function draw() {
background(0);
var samples = fft.waveform( 512 );
for (var i=0; i<samples.length; i++) {
var gray = map( samples[i], -1,1, 0,255 );
stroke( gray );
line( 0,i, width,i );
}
}
crea un'stanza della classe p5.FFT che permette di fare una serie di analisi sull'audio in esecuzione.
crea un array di 512 elementi (samples) con i campioni del frammento audio in esecuzione.
ottieni un valore di grigio (da 0 a 255) proporzionale al campione analizzato (samples[i]) che ha un intervallo diverso (da -1 a +1).

Provare a usare il secondo audio presente nella sottocartella "assets":
sound = loadSound(
Spettrogramma
Rappresenta la distribuzione delle quantità (dB) delle singole frequenze. Si ottiene da campioni audio attraverso la Trasformata di Fourier veloce (FFT: Fast Fourier Transform).

Le visualizzazioni che si possono ottenere sono coerenti solo se i brani sono suonati con pochi strumenti.
Approfondimenti: Realtime audio processing
Immagine ottenuta con Sonic Visualiser
Interpretazione grafica dello spettrogramma
var sound;
function preload() {
sound = loadSound( 'assets/like_analogue.mp3' );
}
function setup() {
createCanvas( 300, 512 );
colorMode( HSB, 360,100,100, 100 );
noStroke();
sound.loop();
fft = new p5.FFT();
}
function draw() {
background(0);
var spectrum = fft.analyze( 256 );
for (var i = 0; i<spectrum.length; i++) {
var fillHue = i*2;
var y = height - i*3.5;
var diam = spectrum[i]*0.5;
fill( fillHue,100,100, 15 );
ellipse( 150,y, diam,diam );
}
}
imposta la modalità HSB per poter impostare più facilmente i colori indicando una tonalità diversa e mantenendo la saturazione e la brillantezza al massimo.
crea un array di 256 elementi (spectrum) con i livelli di ogni banda di frequenza dell'audio in esecuzione.
calcola l'altezza del cerchio associato alla banda di frequenza invertendo il valore (come se le coordinate y partissero dal basso anziché dall'alto); la coordinata y può andare molto oltre il margine superiore ma le frequenze visualizzate meglio sono quelle più basse.
calcola un diametro proporzionale al livello della banda di frequenza corrispondente.

Provare a usare il secondo audio presente nella sottocartella "assets":
sound = loadSound(
Formato (o protocollo) MIDI
I brani musicali vengono rappresentati dai dati sugli eventi (ad es. pressione o rilascio dei tasti) di tutti gli strumenti.

Le visualizzazioni che si possono ottenere sono coerenti anche con brani suonati da molti strumenti.
Approfondimenti: Summary of MIDI Messages
Immagine ottenuta con LMMS
Visualizzazione di file MIDI
Al momento non sono disponibili librerie ufficiali per p5.js che eseguono file MIDI e forniscono le informazioni necessarie per un'interpetazione visiva.
Per JavaScript sono disponibili librerie come la MIDI.js ma l'integrazione con p5.js non è così intuitiva.