Introduzione al corso
Anche se Java è un linguaggio di programmazione vero e proprio e quindi si propone per la creazione di applicazioni di ogni tipo, deve molto del suo successo agli applet. La possibilità di animare il Web fu uno dei punti di forza per il lancio di questo nuovo linguaggio. Si era comunque subito capito come le immagini e le animazioni (che sono successioni di immagini o frame) fossero oggetti fondamentali per questo linguaggio. I programmatori della Sun hanno quindi creato il package java.awt.image, che contiene strumenti importantissimi non solo per la visualizzazione delle immagini ma anche per la loro elaborazione. L'obiettivo di questo corso è spiegare, in modo esauriente e comprensibile, l'uso e la gestione delle immagini.
Ho deciso di dividere il presente corso in varie parti in quanto gli argomenti trattati hanno bisogno di essere digeriti piano piano.
Inizieremo, dalla prossima puntata, a vedere come le immagini sono caricate e visualizzate sia in un applet che in una application.
Vedremo i metodi di caricamento e di gestione del caricamento stesso.
Vedremo poi la realizzazione di una animazione utilizzando il mediatracker.
La terza parte del corso è tra le più importanti in quanto descrive quello che è il modello Consumer/Producer ed i modelli ColorModel.
In questa parte impareremo a gestire immagini di tipo diverso da quella già previste da Java cioè jpg o gif.
Vedremo come sarà possibile leggere e visualizzare un'immagine bmp.
La quarta parte del corso riguarderà la creazione di filtri per le immagini. Vedremo, in dettaglio, l'uso della classe java.awt.image.ImageFilter.
La quinta parte riguarderà la creazione di filtri dinamici.
La sesta ed ultima parte riguarderà un esempio di elaborazione avanzata delle immagini. Cercheremo di creare i famosi frattali.
Il corso sarà corredato da esempi esaurientemente commentati.
In questo primo incontro è bene parlare brevemente del concetto fondamentale di colore. A noi non interessa certo sapere che un determinato colore è caratterizzato da una precisa lunghezza d'onda (o se si vuole frequenza inversamente proporzionale alla lunghezza d'onda stessa) all'interno delle fascia del visibile (quella costituita dalle frequenze visibili, appunto!), ma ci interessa vedere quegli aspetti utili alla programmazione in Java. Se osserviamo la classe java.awt.Color, notiamo alcuni metodi che contengono le lettere RGB o HSB. Ma cosa rappresentano queste lettere?
Fortunatamente i colori possono essere scomposti in varie parti fondamentali componendo le quali è possibile rappresentare ogni gradazione. La cosa ricorda la generazione di spazi vettoriali attraverso un vettore base. Ogni colore si può rappresentare come combinazione lineare dei colori base. RGB rappresentano, infatti, i colori Red Green Blue. Attraverso la composizione di questi colori magici è possibile la creazione di ogni colore compreso il bianco. Nella figura 1 si nota tale composizione.
Notiamo come dalla composizione del verde e del rosso sia possibile la visualizzazione del giallo, come dalla composizione del rosso e del blue sia possibile la realizzazione del viola e come dalla composizione dei tre colori sia possibile ottenere il bianco. Un'immagine si può considerare un insieme di puntini che si chiamano pixel, ciascuno caratterizzato da un colore e da una posizione. Come detto ogni pixel è rappresentato da un colore e quindi c'è bisogno di rappresentare tale colore in modo appropriato. Un modo per fare questo è proprio quello di utilizzare la scomposizione RGB. Nella classe java.awt.Color è possibile definire un oggetto attraverso la famosa terna. È sufficiente utilizzare il costruttore
Color colore = new Color(int R, int G, int B);
i cui valori interi di R,G e B vanno da 0 a 255. Nella seguente tabella ho riportato i valori corrispondenti ai colori riportati nella figura 1.
| Colore | Rosso | Verde | Blu | |---|---:|---:|---:| | Rosso | 255 | 0 | 0 | | Verde | 0 | 255 | 0 | | Blu | 0 | 0 | 255 | | Azzurro | 0 | 255 | 255 | | Viola | 255 | 0 | 255 | | Giallo | 255 | 255 | 0 | | Bianco | 255 | 255 | 255 |
(I colori in tabella sono stati creati con un editor html e le sfumature dipendono dal browser utilizzato, per cui si possono notare differenze fra un visualizzatore ed un altro. A titolo di esempio si tenga presente che Netscape visualizza le tonalità cromatiche in modalità leggermente più scura ndr.).
Nei metodi che utilizzeremo per la elaborazione delle immagini è utile considerare un altro modo di rappresentare i colori, basandosi sempre sulla scomposizione RGB ma utilizzando un unico intero invece di tre. Questo permette una più semplice gestione dei pixel in quanto, per una immagine, avremo bisogno solo di un solo vettore di pixel invece di tre. Se osserviamo la classe java.awt.Color notiamo che esiste il metodo
int RGB = colore.getRGB();
che ritorna un intero. Questo intero corrisponde al colore considerato secondo la scomposizione RGB. Abbiamo, infatti, visto che i valori delle componenti RGB vanno da 0 a 255. Sappiamo che questi valori sono ottenibili con un solo byte. In Java gli interi sono rappresentati da 32 bit e quindi 4 byte che sono piu che sufficienti per rappresentare un colore. Basterà, allora, considerare l'intero come una successione di byte ciascuno rappresentante una componente. Non si considererà l'intero come valore ma come sua rappresentazione binaria. Nella figura 2 i bit da 0-7 sono relativi al Blue, i bit da 8-15 sono relativi al Green e quelli 16-24 al Red.
Resta un byte il quale contiene le informazioni relative a quello che si chiama canale alpha. Esso gestisce la trasparenza del colore stesso: con 0 si ha trasparenza e con 255 si ha la massima visibilità o, come si dice, il colore è opaco.
Consiglio, quindi, di utilizzare questo modello per la rappresentazione dei colori in quanto contiene maggiori informazioni sui pixel di un'immagine e perché ci sono metodi che permettono una loro semplice gestione. Ovviamente non bisogna creare l'intero con shift binari o altre operazioni che potrebbero apparire complicate ma si utilizzano i metodi offerti della classe java.awt.Color. Un'ultima curiosità riguarda il fatto che la scomposizione RGB è detto modello additivo per la creazione dei colori. Esiste, infatti, anche il modello CMY Cyan-Magenta-Yellow (Ciano-Magenta-Giallo) che è detto sottrattivo. Il modello CMY è utilizzato per la stampa in quanto il colore percepito è quello corrispondente alla lunghezza d'onda riflessa dal foglio e quella riflessa è quella incidente a cui è stata sottratta quella assorbita dal foglio stesso, da cui il termine sottrattiva. Il modello RGB crea essa stessa i colori che saranno visualizzati sommando le componenti, da cui il termine additiva. Per fare un esempio la TV (RGB) si può guardare al buio mentre, nelle stesse condizioni, non si può leggere un foglio (CMY). Inizialmente non ho parlato solo di RGB ma anche di HSB. Queste lettere stanno per Hue, Saturation e Brightness (Tonalità-Saturazione-Luminosità). Più che descrivere che cosa sono queste componenti è bene vedere un esempio. Proviamo a scomporre la figura 1 nelle tre componenti HSB. Si hanno le seguenti tre figure.
Le precedenti immagini sembrano dire poco ma notiamo come rappresentino effettivamente le tre proprietà dei colori sopra rappresentati. Notiamo come essi abbiano, tranne il bianco e lo sfondo, lo stesso valore di saturazione e luminosità. I valori da assegnare alle componenti HSB sono diversi da quelli relativi alle RGB. I valori di HSB vanno da 0.0 ad 1.0 però sono da intendersi in maniera diversa per H e S e per B. Nel caso di H ed S i valori possono essere espressi da numeri tra 0.0 e 1.0 oppure in percentuali da 0 a 100. Nel caso di B si utilizza sempre un valore tra 0.0 ed 1.0 ma la gamma di valori possibili è da intendersi in un intervallo da 0 a 360 (rappresentano, infatti, un angolo) facendo le opportune proporzioni. Questo modello di rappresentazione è utilizzato spesso per la creazione di palette cioè di quelle finestre che permettono la scelta del colore in maniera intuitiva attraverso il mouse. Quando parleremo del package relativo alle immagini realizzeremo una. Come già accennato, la classe Color del package java.awt fornisce dei metodi per l'utilizzo delle componenti discusse e per la conversione tra un modello e l'altro. Riassumo velocemente tali metodi
public int getBlue(); // Fornisce la componente Blu public int getGreen(); // Fornisce la componente Verde public int getRed(); // Fornisce la componente Rossa public int getRGB(); // Ritorna l'indice RGB
Il seguente metodo permette di ottenere un oggetto Color a partire dalle componenti HSB. Notiamo come esse debbano essere float. Questo comporta dei problemi in fase di compilazione quando si specificano tali valori attraverso dei letterali: bisogna infatti inserire esplicitamente un cast.
public static Color getHSBColor(float h, float s, float b);
I metodi seguenti permettono la conversione da un modello all'altro. Il secondo ha una particolarità dovuta al vettore hsbvals: se il vettore è null, ne viene allocato uno nuovo e restituito come risultato; altrimenti vengono modificati i valori del vettore esistente.
public static int HSBtoRGB(float hue, float saturation, float brightness); public static float[] RGBtoHSB(int r, int g, int b, float hsbvals[]);
Questo mese abbiamo allora visto quelle che sono le nozioni base per iniziare a lavorare con le immagini in Java. Il prossimo mese vedremo come si carica un'immagine e come si creano delle piccole animazioni.
