Duecentocinquanta (e rotti) sfumature di grigio

Carlo La Porta, della 5SB, ha discusso al colloquio orale dei suoi esami di stato questa mia lezione:

Persone al museoMentre osservo un quadro famoso mi concentro sulla sua bellezza e sulle emozioni che mi provoca, tralasciando gli aspetti fisici e fisiologici che me ne consentono la visione. La realtà è a colori. Il mio occhio è raggiunto da radiazioni elettromagnetiche che, a seconda della loro frequenza ed intensità, sono portatrici di colori diversi. Quanti? Poiché la frequenza è una grandezza continua, la sua misura è espressa con un numero reale e quindi esistono infiniti colori. Dal lato di chi riceve il messaggio c'è la mia retina, i cui fotorecettori (i coni che presiedono alla visione diurna e distinguono i colori, e i bastoncelli che si occupano della visione crepuscolare e notturna e vedono in black & white) sono a volte sensibilissimi come nel caso di alcuni pittori, ma distinguono pochi, tanti o tantissimi colori differenti, ma non certo infiniti. L'informazione che sarà elaborata dal mio cervello è quindi un'approssimazione della realtà fisica. Se considero che poi il cervello associa quella percezione a tutta una serie di altre informazioni, sensazioni ed emozioni immagazzinate in momenti precedenti della mia vita, ne potrei filosofeggiare che quel quadro in realtà non esiste in sé, ma se tu e io ci trovassimo ad osservarlo contemporaneamente, ne fruiremmo in modo personalissimo, dovuto alla pur impercettibile differenza dei punti di osservazione, alla sensibilità fisiologica individuale del nostro apparato visivo, alla differenza del nostro vissuto. Ciò giustifica anche scientificamente il concetto universalmente accettato che la categoria del bello sia qualcosa che abbia a che fare con il soggettivo.
mosaicoCostretti a rinchiudere le visioni più caleidoscopiche in quella scatola che chiamiamo computer, ci siamo trovati di fronte alle stesse difficoltà già affrontate dal nostro occhio e dal nostro cervello e quindi abbiamo potuto approfittare delle soluzioni che ci servivano, già quasi pronte in natura.
puntimismoI mosaici di Ravenna o alcune opere della corrente artistica dei puntinisti ci hanno dimostrato come sia possibile ottenere un'immagine policroma giustapponendo piccoli elementi monocromatici.
In analogia con la teoria fisica che la materia sia costituita da infinitesime particelle che chiamiamo atomi, l'immagine è ottenuta associando in un certo ordine quelle particelle elementari che non a caso chiamiamo pixel, cioé picture elements. La densità di pixel nell'unità di superficie è chiamata risoluzione. Normalmente si considerano i pixel quadrati e si utilizza una risoluzione verticale identica all'orizzontale. Una maggiore risoluzione comporta una maggiore fedeltà dell'immagine, ma anche un maggior consumo di memoria. Come posso comporre l'immagine accostando pixel, così posso effettuare il procedimento inverso, decomponendo l'immagine nei pixel che la costituiscono. Questo procedimento trasforma l'infinito in finito e si chiama campionamento. Suddivido l'immagine in quadratini abbastanza piccoli e stabilisco di quale colore ciascuno di essi è. Attenti: un solo colore! Si tratta del procedimento effettuato dallo scanner quando legge le immagini.
Rimane soltanto da risolvere il problema di come rappresentare il colore del pixel. In informatica l'output del processo di campionamento è sempre il risultato di una digitalizzazione, che trasforma una quantità continua in discreta e la rappresenta attraverso valori numerici, cioé trasformando ciò che in natura è analogico in digitale. Quindi i colori li devo esprimere a numeri, ma come? Qui si è copiata la natura. Infatti nella retina esistono tre tipi di cono, ciascuno sensibile a uno dei tre colori fondamentali: il rosso, il verde e il blu. Tutti i colori vengono ottenuti con un un opportuno mix di R, G e B, partendo dal caso estremo del nero che ne contiene 0 di tutti e tre, fino ad arrivare al bianco nel quale le tre componenti sono sparate al massimo. Se decidiamo ad esempio che la quantità di un colore fondamentale è espressa da un numero che varia nel range 0 → 255, abbiamo bisogno di un byte per rappresentare la componente R, un byte per la componente G e un byte per la componente B, in tutto tre byte per pixel. Se decido di operare nella maniera appena descritta, il numero di colori differenti rappresentabili è 256x256x256=16777216, una quantità ben lontana da infinito, ma che sfiderebbe il senso cromatico dei migliori pittori della storia dell'arte.
Questo tipo di rappresentazione dell'immagine è chiamata rappresentazione bitmap ed è la rappresentazione interna delle immagini. Ad esempio nella memoria video è contenuta la bitmap di questa schermata e la scheda video in questo momento sta leggendo in continuazione quei dati e illuminando ciascun pixel del colore che lo contraddistingue. Dal punto di vista dell'occupazione di memoria la bitmap è estremamente inefficiente. Infatti per un'immagine 100x100 servono già 30000 byte e non c'è nessun risparmio se i pixel sono tutti o quasi tutti dello stesso colore. Per questo motivo, quando l'immagine va memorizzata su disco e soprattutto quando va trasmessa a distanza, si utilizzano tecniche di compressione dell'immagine che puntano ad eliminare la ridondanza. I formati interni compressi più diffusi sono JPG, GIF e PNG. Naturalmente il procedimento di compressione deve essere reversibile, cioé deve essere possibile riottenere il formato BMP da uno dei formati compressi, così come si rivitalizza un liofilizzato riaggiungendo l'acqua.
Spesso si rimproverano i giovani per il loro estremismo, ricordando loro che "non esistono soltanto il bianco e il nero, ma tra i due estremi c'è un'intera gamma di tonalità di grigio". Ma quante sono queste tonalità? Nell'ipotesi dei 3x8=24 bit per rappresentare i colori, notiamo che 0/0/0 è nero e 255/255/255 è il bianco. I grigi sono quel sottoinsieme dello spazio dei colori tale che R=G=B. Quindi 50/50/50 sarà un grigio, come pure 150/150/150 sarà un grigio, ma molto più chiaro. Quindi abbiamo a disposizione 256 diversi punti di grigio; sembrano pochi rispetto ai 16 milioni e passa di colori, ma sfido un po' tutti a distinguere un 113/113/113 da un 114/114/114 adiacente.
Ci sono situazioni in cui abbiamo la necessità di trasformare un'immagine a colori nella corrispondente immagine in bianco e nero, o meglio in sfumature di grigio. Ad esempio quando dobbiamo inviare in stampa un'immagine su una stampante laser monocromatica, o semplicemente perché una foto in b/w ha sempre la sua poesia un po' retrò. Ci siamo posti quindi l'obiettivo di realizzare un software che produca da un BMP colorato il corrispondente BMP b/w.
A questo link ho trovato una descrizione soddisfacente di come è organizzato internamente il formato file BMP. Ho capito che il file è costituito da un header iniziale che contiene informazioni di servizio, tra cui trovo anche la larghezza e l'altezza in pixel dell'immagine. Di seguito all'header seguono terne di byte che rappresentano il colore di ciascun pixel. Stranezze degli informatici, i pixel sono elencati per righe ma a partire dal basso, e l'inizio di ciascuna riga deve iniziare a uno spiazzamento multiplo di 4, per cui potrebbe esserci un filler di 1, 2 o 3 byte tra la fine di una riga e l'inizio della successiva, di cui è necessario tenere conto.
Mi sono posto il problema: data la terna colorata R/G/B, come posso ottenere un unico valore V tale che il grigio V/V/V sia rappresentante del colore di partenza? Facendo una query nel mio archivio mentale ho estratto il concetto che le medie statistiche sono proprio un certo numero che, sostituito alla collezione di numeri di partenza, ne mantiene intatta una loro proprietà globale: ad esempio la somma per la media aritmetica oppure il prodotto per la media geometrica. Un'altra proprietà di tutti i tipi di media è che sono valori compresi tra il minimo e il massimo della collezione di dati che rappresentano. Quindi sono sicuro che media(R,G,B) sarà anch'essa all'interno dell'intervallo chiuso [0;255].
Vuoi vedere che fare un semplice calcoletto (R+G+B) / 3 è l'uovo di Colombo che risolve il nostro problema? Non ci resta che accettare la sfida e provarci.
Descrivo in pseudocodifica l'algoritmo (la codifica della realizzazione in linguaggio C è su un allegato a parte):

  • INIZIO
    • Chiedo all'utente il nomefileinput
    • Apro il nomefileinput in lettura
    • Mi posiziono agli spiazzamenti fissi dove sono memorizzati w (larghezza img) e h (altezza img) e leggo tali informazioni
    • Apro il file di output in scrittura (il file di output ha lo stesso nome del file di input con un prefisso g che sta a indicare grigio)
    • Leggo header da file di input e lo scrivo pari pari su file di output
    • PER r da 1 a h
      • PER c da 1 a w
        • Leggo red, green, blue da file di input
        • Calcolo grey = (red+green+blue) / 3
        • Scrivo grey, grey, grey su file di output
      • FINEPER
      • Gestisco eventuale filler di fine riga
    • FINEPER
    • Chiudo file di output
    • Chiudo file di input
  • FINE

Osservazioni finali.
La nostra ipotesi è stata confermata dai risultati ottenuti.
Félix Fénéon
Paul Signac, 92x73 cm, 1890, Museum of Modern Art, New York

Proviamo su una foto
Sasha Grey, un'attrice dalle mille sfumature
Possiamo considerarci soddisfatti.
Ciliegina sulla torta: se vi è venuto il dubbio se in inglese il colore grigio si dica grey o gray, l'approfondimento è qui.

Commenti

Post più popolari