|
JSem: 6.2 |
Il metodo createImage()Il metodo createImage(int width, int height) della classe Component permette di creare un'immagine di larghezza width, altezza height. Attenzione questo metodo crea l'immagine solo se il peer del componente esiste (nb: il peer non è creato nel costruttore). In un'applet si può chiamare createImage() nel metodo init(); in una classe derivata da Component, nel metodo paint. Esempio:
Se lasciate il metodo paint della classe ImageFrame commentato, il codice compila ed esegue, ma non vedete l'immagine; togliendo il commento al metodo paint e ricompilando, si vede l'immagine. Il double buffering, come abbiamo già visto (cf PIP), usa il metodo createImage(w,h) per creare un'immagine fuori schermo sulla quale disegnare i vari frames di un'animazione. La classe ImageLa classe java.awt.Image è una classe astratta (quindi non si può istanziare un'immagine con new) che fornisce, tra altri, i seguenti metodi:questo metodo ritorna un int che è la larghezza dell'immagine. Si ricorda che Component implementa ImageObserver; cioè il parametro può essere un componente; in un'applet si può mettere this con riferimento all'applet. Come prima, ma con l'altezza. Ritorna un contesto grafico col quale si può disegnare sull'immagine. La classe MemoryImageSourceLa classe java.awt.image.MemoryImageSource implementa l'interfaccia ImageProducer e permette di creare un'immagine partendo da un array di int (int[]) dove ogni int dell'array corrisponde a un pixel dell'immagine (di solito si parla di array di pixels).Esempio:
L'immagine creata presenta una gradazione dal nero al verde lungo l'asse delle X e dal nero al rosso lungo l'asse delle Y; con il metodo drawImage() si disegna poi l'immagine 4 volte con varie dimensioni. Il costruttore usato qui è: MemoryImageSource(int w, int h, int[] pix, int off, int scan) dove w, h sono le dimensioni dell'immagine, int[] pix è l'array di pixels che verrà usato, int off è il punto di partenza nell'array di pixels per leggere i dati, int scan è il passo della scansione (larghezza di una linea di scansione). Di solito off = 0 e scan = w. Questo costruttore usa il modello di colori RGB di default (ci sono altri modelli, vedere la doc). In questo modello, un pixel è un int con Alpha, Red, Green, Blue (0xAARRGGBB in esadecimale). Alpha rappresenta il grado di trasparenza del pixel (trasparenza totale = 0, opacità totale = 255), è consigliato impostare Alpha = 255 in quanto gli effetti di trasparenza non vengono implementati molto bene a meno di avere dell'hardware di ottima qualità. Un int è un intero a 32 bit, ogni colore è rappresentato da 8 bit (28 = 256); negli 8 bit superiori (da 32 a 24) abbiamo Alpha, negli 8 successivi (24-16) abbiamo R, poi (16-8) G e negli ultimi 8, B. L'operatore di scorrimento a sinistra (<<) sposta a sinistra di un numero specificato di volte tutti i bit appartenenti a un valore: val << num sposta a sinistra i bit di val per il numero specificato da num. Attenzione! potreste avere delle sorprese, provate per esempio a fare girare il seguente programma:
L'output è: "il valore del nero con Alpha = 255 è : -16777216" Forse non è esattamente quello che aspettavate. Il fatto è che gli interi di Java sono interi col segno, il bit superiore contiene il segno e si ottiene il valore con il "complemento di due" cioè invertendo i bit (scambiando gli 1 con 0 e viceversa) e aggiungendo 1. Per esempio (con 8 bit): 11010110 è un numero negativo perchè il bit superiore è pieno. Invertiamo i bit: 00101001, aggiungiamo 1: 00101010, questo vale 22+23+25 = 42; quindi 11010110 = -42. Tornando all'int n che rappresenta il nero con Alpha = 255, abbiamo (con 32 bit) solo gli ultimi 8 bit pieni (i valori RGB del nero sono (0,0,0)) che corrispondono a Alpha = 255 = 20+...+27. Quindi l'ultimo bit è pieno e n è negativo. Per avere il valore invertiamo i bit: 00000000 e aggiungiamo 1: 00000001; tenuto conto che questi sono gli ultimi 8 dei 32 bit (da 20 a 231), questo vale 224 = 16777216, pertanto n = -16777216. Un altro esempio di utilizzo di MemoryImageSource Per scaricare il codice La classe PixelGrabberLa classe PixelGrabber esegue il processo inverso di MemoryImageSource, cioè PixelGrabber prende un'immagine esistente e crea da essa un array di pixels.La classe PixelGrabber implementa l'interfaccia ImageConsumer. Le interfacce ImageProducer e ImageConsumer sono complementari: un ImageProducer produce l'immagine a partire da dati, mentre un ImageConsumer fornisce dati a partire da un'immagine. Un costruttore di PixelGrabber è: PixelGrabber(Image im,int x, int y, int w, int h, int[] pix,int off, int scan) PixelGrabber elabora un rettangolo dell'immagine im, (x,y) sono le coordinate dell'angolo superiore sinistro del rettangolo, (w,h) sono le sue dimensioni, pix è l'array nel quale verrano memorizzati i dati iniziando da off; finalmente scan è il passo di scansione. Dopo avere istanziato un PixelGrabber, bisogna chiamare il suo metodo grabPixels(), questo metodo ritorna un booleano (true se è andato a buon fine, false altrimenti). Combinando PixelGrabber e MemoryImageSource è possibile manipolare le immagini. Ecco per esempio il codice di un filtro negativo:
Questa applet utilizza un parametro di nome "immagine" e di valore un file .gif o .jpg Il principio del filtro è semplice: si prendono i vari canali di colori (RGB) e se ne sottrae il valore da 255 (nb: 0xff = 255 in esadecimale). Si usa l'operatore logico & sui bit che ritorna 1 se e soltanto se entrambi i bit valgono 1. |
next content previous