import java.applet.*;
import java.awt.*;
import java.awt.image.*;

public class Hirari extends Applet implements Runnable {
    Image base_image;
    Image img;
    HirariImageProducer hip;
    Thread thread;
    boolean paint_flag;

    public void init() {
	String image_name;
	image_name = getParameter("image");
	base_image = getImage(getDocumentBase(), image_name);
	hip = new HirariImageProducer(base_image, this, 10);
	img = createImage(hip);
	thread = null;
	paint_flag = true;
    }

/*
    public void update(Graphics g) { paint(g); }
    public void paint(Graphics g) {
	g.drawImage(img, 0, 0, this);
	paint_flag = true;
    }
*/

    public void update(Graphics g) {}
    public void paint(Graphics g) {}

    public void start() {
	if(thread == null) {
	    thread = new Thread(this);
	    thread.start();
	}
    }

    public void stop() {
	if(thread != null) {
	    thread.stop();
	    thread = null;
	}
    }

    Graphics myg = null;
    void updateScreen() {
	if(myg == null)
	    myg = getGraphics();
	myg.drawImage(img, 0, 0, this);
    }

    public void run() {
	while(true) {
	    try { Thread.sleep(100); } catch (Exception e){}
	    hip.tr += 0.1;
	    hip.produce();
	    updateScreen();
	}
    }
}

class HirariImageProducer extends ImageFrameProducer {
    public int    hr;
    public double wr;
    public double tr;


    ImagePixel srcRaster;
    int line_pixels[];
    double sine_table1[], sine_table2[];

    public HirariImageProducer(Image img, Component c, int h) {
	this(new ImagePixel(img, c), h, 1.5);
    }

    public HirariImageProducer(ImagePixel raster, int hr, double wr) {
	super(raster.width, raster.height + 2 * hr);
	this.hr = hr;
	this.wr = wr;
	srcRaster = raster;
	tr = 0.0;
	line_pixels = new int[dstW];
	sine_table1 = new double[dstW];
	sine_table2 = new double[dstW];
    }

    protected boolean update() {
	int raster[];
	int idx, height;

	height = srcRaster.height;
	raster = srcRaster.raster;
	idx = 0;

	for(int x = 0; x < dstW; x++) {
	    sine_table1[x] = Math.sin(tr + 2 * Math.PI * x / (double)dstW * wr);
	    sine_table2[x] = Math.sin(tr + 2 * Math.PI * x / (double)dstW * wr - Math.PI / 4);
	}

        for(int y = 0; y < dstH; y++) {
            for(int x = 0; x < dstW; x++) {
		int sy;
		sy = y + (int)(hr * (sine_table1[x] - 1));
		if(sy < 0 || sy >= height)
		    dst[idx++] = 0xff000000;
		else {
		    double s = 0.75 + sine_table2[x] * 0.25;
		    int pixel, red, green, blue;
		    pixel = raster[sy * dstW + x];
		    red   = ((int)((pixel & 0x00ff0000) * s)) & 0x00ff0000;
		    green = ((int)((pixel & 0x0000ff00) * s)) & 0x0000ff00;
		    blue  = ((int)((pixel & 0x000000ff) * s)) & 0x000000ff;
//		    dst[idx++] = 0xff000000 | red | green | blue;
		    dst[idx++] = ~(red | green | blue);
		}
	    }
	}
	return true;
    }
}
