import java.applet.*;
import java.awt.*;
import java.util.*;

// copyright 2002 mel@melaxis.de

public class ColorShader extends Applet implements Runnable
{
	Image offi;
	Graphics offg;
	Thread thread;
	int w = 0, h = 0;
	int wd = 0, hd = 0;
	Color[][] pixels;
	boolean first = true;
	
	public int boxsize = 2;
	public boolean boxbigger = true;
	
	public void init()
	{
		setBackground(Color.black);
		w = getSize().width;
		h = getSize().height;
		wd = w/boxsize;
		hd = h/boxsize;
		offi = createImage(w, h);
		offg = offi.getGraphics();
		offg.setFont(new Font("SansSerif", Font.PLAIN, 10));
	}
	
	public void start()
	{
		if (thread==null)
		{
			thread = new Thread(this);
			thread.start();
		}
	}
	
	public void stop()
	{
		if (thread!=null)
		{
			thread.stop();
		}
	}
	
	public void paint(Graphics g)
	{
		g.drawImage(offi, 0, 0, this);
	}
	
	public void update(Graphics g)
	{
		paint(g);
	}
	
	private void initPixels()
	{
		pixels = new Color[wd][hd];
		Random rand = new Random();
		for (int x = 0; x < wd; x++)
		{
			for (int y = 0; y < hd; y++)
			{
				pixels[x][y] = new Color(Math.abs(rand.nextInt()) % 256, Math.abs(rand.nextInt()) % 256, 255);
			}
		}
		first = true;
	}
	
	private void updatePixels()
	{
		if (!first)
		{
			// Linke obere Ecke
			{
				Color col   = pixels[0][0];
				Color colr  = pixels[0][1];
				Color colu  = pixels[1][0];
				Color newcol = new Color(
					((col.getRed() + colr.getRed() + colu.getRed())/3),
					((col.getGreen() + colr.getGreen() + colu.getGreen())/3),
					((col.getBlue() + colr.getBlue() + colu.getBlue())/3)
				);
				pixels[0][0] = newcol;
			}
			// Rechte obere Ecke
			{
				Color col   = pixels[wd-1][0];
				Color coll  = pixels[wd-2][0];
				Color colu  = pixels[wd-1][1];
				Color newcol = new Color(
					((col.getRed() + coll.getRed() + colu.getRed())/3),
					((col.getGreen() + coll.getGreen() + colu.getGreen())/3),
					((col.getBlue() + coll.getBlue() + colu.getBlue())/3)
				);
				pixels[wd-1][0] = newcol;
			}
			// Linke untere Ecke
			{
				Color col   = pixels[0][hd-1];
				Color colr  = pixels[1][hd-1];
				Color colo  = pixels[0][hd-2];
				Color newcol = new Color(
					((col.getRed() + colr.getRed() + colo.getRed())/3),
					((col.getGreen() + colr.getGreen() + colo.getGreen())/3),
					((col.getBlue() + colr.getBlue() + colo.getBlue())/3)
				);
				pixels[0][hd-1] = newcol;
			}
			// Rechte untere Ecke
			{
				Color col   = pixels[wd-1][hd-1];
				Color coll  = pixels[wd-2][hd-1];
				Color colo  = pixels[wd-1][hd-2];
				Color newcol = new Color(
					((col.getRed() + coll.getRed() + colo.getRed())/3),
					((col.getGreen() + coll.getGreen() + colo.getGreen())/3),
					((col.getBlue() + coll.getBlue() + colo.getBlue())/3)
				);
				pixels[wd-1][hd-1] = newcol;
			}
			// Oberer Rand
			for (int x = 1; x < wd-1; x++)
			{
				Color col   = pixels[x][0];
				Color coll  = pixels[x-1][0];
				Color colr  = pixels[x+1][0];
				Color colul = pixels[x-1][1];
				Color colu  = pixels[x][1];
				Color colur = pixels[x+1][1];
				Color newcol = new Color(
					((coll.getRed() + col.getRed() + colr.getRed() +
						colul.getRed() + colu.getRed() + colur.getRed())/6),
					((coll.getGreen() + col.getGreen() + colr.getGreen() +
						colul.getGreen() + colu.getGreen() + colur.getGreen())/6),
					((coll.getBlue() + col.getBlue() + colr.getBlue() +
						colul.getBlue() + colu.getBlue() + colur.getBlue())/6)
				);
				pixels[x][0] = newcol;
			}
			// Unterer Rand
			for (int x = 1; x < wd-1; x++)
			{
				Color col   = pixels[x][hd-1];
				Color coll  = pixels[x-1][hd-1];
				Color colr  = pixels[x+1][hd-1];
				Color colul = pixels[x-1][hd-2];
				Color colu  = pixels[x][hd-2];
				Color colur = pixels[x+1][hd-2];
				Color newcol = new Color(
					((coll.getRed() + col.getRed() + colr.getRed() +
						colul.getRed() + colu.getRed() + colur.getRed())/6),
					((coll.getGreen() + col.getGreen() + colr.getGreen() +
						colul.getGreen() + colu.getGreen() + colur.getGreen())/6),
					((coll.getBlue() + col.getBlue() + colr.getBlue() +
						colul.getBlue() + colu.getBlue() + colur.getBlue())/6)
				);
				pixels[x][hd-1] = newcol;
			}
			// Linker Rand
			for (int y = 1; y < hd-1; y++)
			{
				Color col   = pixels[0][y];
				Color colo  = pixels[0][y-1];
				Color color = pixels[1][y-1];
				Color colr  = pixels[1][y];
				Color colu  = pixels[0][y+1];
				Color colur = pixels[1][y+1];
				Color newcol = new Color(
					((col.getRed() + colo.getRed() + color.getRed() +
						colr.getRed() + colu.getRed() + colur.getRed())/6),
					((col.getGreen() + colo.getGreen() + color.getGreen() +
						colr.getGreen() + colu.getGreen() + colur.getGreen())/6),
					((col.getBlue() + colo.getBlue() + color.getBlue() +
						colr.getBlue() + colu.getBlue() + colur.getBlue())/6)
				);
				pixels[0][y] = newcol;
			}
			// Rechter Rand
			for (int y = 1; y < hd-1; y++)
			{
				Color col   = pixels[wd-1][y];
				Color colo  = pixels[wd-1][y-1];
				Color colol = pixels[wd-2][y-1];
				Color coll  = pixels[wd-2][y];
				Color colu  = pixels[wd-1][y+1];
				Color colul = pixels[wd-2][y+1];
				Color newcol = new Color(
					((col.getRed() + colo.getRed() + colol.getRed() +
						coll.getRed() + colu.getRed() + colul.getRed())/6),
					((col.getGreen() + colo.getGreen() + colol.getGreen() +
						coll.getGreen() + colu.getGreen() + colul.getGreen())/6),
					((col.getBlue() + colo.getBlue() + colol.getBlue() +
						coll.getBlue() + colu.getBlue() + colul.getBlue())/6)
				);
				pixels[wd-1][y] = newcol;
			}
			// Rest
			for (int x = 1; x < wd-1; x++)
			{
				for (int y = 1; y < hd-1; y++)
				{
					Color col   = pixels[x][y];
					Color colol = pixels[x-1][y-1];
					Color colo  = pixels[x][y-1];
					Color color = pixels[x+1][y-1];
					Color coll  = pixels[x-1][y];
					Color colr  = pixels[x+1][y];
					Color colul = pixels[x-1][y+1];
					Color colu  = pixels[x][y+1];
					Color colur = pixels[x+1][y+1];
					
					Color newcol = new Color(
						((colol.getRed() + colo.getRed() + color.getRed() +
							coll.getRed() + col.getRed() + colr.getRed() +
							colul.getRed() + colu.getRed() + colur.getRed())/9),
						((colol.getGreen() + colo.getGreen() + color.getGreen() +
							coll.getGreen() + col.getGreen() + colr.getGreen() +
							colul.getGreen() + colu.getGreen() + colur.getGreen())/9),
						((colol.getBlue() + colo.getBlue() + color.getBlue() +
							coll.getBlue() + col.getBlue() + colr.getBlue() +
							colul.getBlue() + colu.getBlue() + colur.getBlue())/9)
					);
						
					pixels[x][y] = newcol;
				}
			}
		}
		else
		{
			first=false;
		}
	}
	
	private void drawPixels()
	{
		for (int x = 0; x < wd; x++)
		{
			for (int y = 0; y < hd; y++)
			{
				Color col = pixels[x][y];
				offg.setColor(col);
				offg.fillRect(x*boxsize,y*boxsize,boxsize,boxsize); 
			}
		}
	}
	
	public void run()
	{
		while (true)
		{
			try
			{
				wd = w/boxsize;
				hd = h/boxsize;
				if ((wd*boxsize)<w)
					wd++;
				if ((hd*boxsize)<h)
					hd++;
				initPixels();
				offg.setColor(Color.black);
				offg.fillRect(0,0,w,h);
				for (int i = 0; i < 7; i++)
				{
					updatePixels();
					drawPixels();
					offg.setColor(Color.white);
					offg.drawString((boxsize >= 10 ? ""+boxsize: "0"+boxsize )+"pixels", w-43, h-3);
					repaint();
					Thread.sleep(10);
				}
				if (boxbigger)
				{
					boxsize++;
					if (boxsize >= 15)
						boxbigger = false;
				}
				else
				{
					boxsize--;
					if (boxsize <= 2)
						boxbigger = true;
				}
			}
			catch (Exception ex) {}
		}
	}
}