Codice commentato di ImageChanger

Questa superclasse astratta pubblica tutte le funzioni necessarie perchè una classe sia abilitata a eseguire animazioni. Non ho utilizzato un interfaccia perchè avevo bisogno di implementare alcuni metodi comuni a tutte le classi. Di seguito mostro un implementazione di una semplice classe di animazione.

Indice

ImageChanger

Cliccate qui per il codice completo.

Di seguito dichiariamo le variabili:

  1. dest_pix contiene i pixel in formato RGB dell'immagine di destinazione.
  2. src_pix contiene i pixel in formato RGB dell'immagine sorgente.
  3. cur_pix contiene i pixel in formato RGB attualmente visualizzata.
  4. passaggi è un contatore per sapere quando una animazione è terminata.
  5. mis è il MemoryImageSource associato all'animazione.
  6. cur_img è l'Image associata a cur_pix.
  7. width E' la larghezza dell'immagine.
  8. height E' l'altezza dell'immagine.
  9. size E' la dimensione degli array di pixel.

public abstract class ImageChanger {
	
protected int[] dest_pix, src_pix;
protected int[] cur_pix;
protected int passaggi;
protected MemoryImageSource mis;
protected Image cur_img;
protected int width, height, size;

Al costruttore bisogna passare l'immagine sorgente, l'immagine di destinazione, il numero dei passaggi voluti (potrebbe essere ignorato) e un componente AWT necessario per istanziare il PixelGrabber.
Il costruttore inizia ottenendo i pixel dalle immagini passate.

public ImageChanger(Image source, Image dest, int passaggi, Component comp) 
throws DataException {
	PixelGrabber pg = new PixelGrabber(source, 0,0, source.getWidth(null), 
	source.getHeight(null), true);
	try {
		if(!pg.grabPixels())
			throw new DataException("Immagine sorgente ("+source+") non pronta.");
	} catch(InterruptedException e) { return; }
	
	src_pix = (int[])pg.getPixels();
	
	width = source.getWidth(null);
	height = source.getHeight(null);
	size = width * height;
	
	pg = new PixelGrabber(dest, 0,0, dest.getWidth(null), dest.getHeight(null), true);
	try {
		if(!pg.grabPixels())
			throw new DataException("Immagine destinazione ("+dest+") non pronta.");
	} catch(InterruptedException e) { return; }
	
	dest_pix = (int[])pg.getPixels();	
	
	this.passaggi = passaggi;

Ora creo l'array che conterrà i pixel che verranno cambiati dinamicamente e lo riempio (default) con l'immagine sorgente. Nota: se avessi utilizzato System.arraycopy avrei avuto una esecuzione più rapida.

	cur_pix = new int[size];
	for(int i=0; i<size; i++) {
		cur_pix[i] = src_pix[i];		
	}

Ora istanzio il MemoryImageSource e lo imposto perchè sviluppi animazioni. Ottengo inoltre un riferimento all'immagine dinamica.

	mis = new MemoryImageSource(width, height, cur_pix, 0, width);
	mis.setAnimated(true);
	
	cur_img = comp.createImage(mis);
}

Segue la definizione della funzione astratta step(). Il valore di ritorno indica, se maggiore di 0, che la classe non ha ancora terminato l'animazione.

public abstract int step();
}

Segue ora l'implementazione di una classe istanziabile che estenda ImageChanger.

Indice

RandomPixel

Cliccate qui per il codice completo.

Il codice qui rappresentato non è completo. Consiglio di tenere come riferimento il codice completo.
Questa classe sostituisce un numero di pixel dipendente dai passaggi scelti rimpiazzandoli con quelli dell'immagine di destinazione. I pixel vengono scelti a caso.

public class RandomPixel extends ImageChanger {

public RandomPixel(Image source, Image dest, int passaggi, Component comp) 
throws DataException {
	super(source, dest, passaggi, comp);	

Tramite l'array di boolean done[] tengo traccia di quali pixel sono stati già sostituiti.

	done = new boolean[size];
	for(int i=0; i<size; i++)
		done[i] = false;		
	pixelToDo = size / passaggi;
	count = passaggi;
	
}

L'implementazione di step() è semplice:

  1. Genero un numero a caso compreso tale che 0 < x < size.
  2. Se done[x] è true vuol dire che il pixel è già stato rimpiazzato e quindi torno a 1 altrimenti continuo.
  3. Sostituisco il pixel.
  4. Imposto done[x] = true per tenere traccia del cambiamento.
  5. Se non ho cambiato abbastanza pixel torno a 1 altrimenti ritorno il numero di step() mancanti per finire l'animazione.

public int step() {
	int num;
	for(int i=0; i<pixelToDo; i++) {
		num = (int)(Math.random() * size);
		while(done[num])
			num = (int)(Math.random() * size);
		cur_pix[num] = dest_pix[num];
		done[num] = true;
	}
	mis.newPixels();
	return --count;
}

Indice

Ultimo aggiornamento della pagina: 8 Settembre 2003

@2000 Francesco Cogno