// applet that rotates and zooms a picture
// (C)F. Bouma/Solutions Design 1996. All rights Reserved.
//
// 
// To demonstrate LFB -> Image capacity. 
// So comments about lame codingscheme to /dev/null ;------D
// Join #java (IRCNet)
////////////////////////////////////////////////////////////////
import java.applet.*;
import java.awt.*;
import java.awt.image.*;

public class zoom extends Applet implements Runnable
{
        private int     display_width=256;
        private int     display_height=256;
        private int     iw,ih;

        Thread  do_it = null;
        boolean stop_thread=false;
        boolean imageValid=false;
        boolean image2Valid=false;
        boolean zoomin=false;
        boolean thread_wait=true;
        private Image   display_image;
        private Image   source_picture;
        private Image   zoom_bg;

        private MemoryImageSource mic;

        int     zoomteller=0;
        int     pixels[];
        int     dest_pixels[] = new int[(display_width)*(display_height)];

        double  gamma;
        double  dgamma=3;

        private double  x_zoom_delta=0,y_zoom_delta=0;

        // coordinate source.
        double     xs_coords[]={-128,128,-128};
        double     ys_coords[]={-128,-128,128};
        //                    A , B , C
        //         A,B and C are used for the source square we use to
        //         read the picture information.
        //         A-----B
        //         |
        //         |
        //         C

        // coordinate destination. (for drawing).
        double     xd_coords[]={-128,128,-128};
        double     yd_coords[]={-128,-128,128};

        static  final int num_of_coords=3;

        public void init()
        {                      
                int     i;

                // stuff to do while initializing
                gamma=0;

                // calculate zoomdelta's.
                x_zoom_delta=1;
                y_zoom_delta=(92.0/150.0);

                MediaTracker tracker=new MediaTracker(this);

                // load image...
                source_picture=getImage(getDocumentBase(),"zoom.jpg");
                tracker.addImage(source_picture,0);
                try
                {
                        tracker.waitForID(0);
                        imageValid=true;
                } catch (Exception oops)
                {
                        imageValid=false;
                }

                iw=source_picture.getWidth(this);
                ih=source_picture.getHeight(this);

                pixels = new int[iw*ih];

                // load image in array.
                load_picture();
                mic=new MemoryImageSource(display_width,display_height,dest_pixels,0,display_width);
        }


        private void load_picture()
        {
                PixelGrabber grabber=new PixelGrabber(source_picture.getSource(),
                                0,0,iw,ih,pixels,0,iw);
                try
                {
                        grabber.grabPixels();
                } catch (Exception e)
                {
                        return;
                }
        } 

        private void zoom_it()
        {
                int     i;

                if(zoomin)
                {
                        for(i=0;i<3;i++)
                        {
                                if(xs_coords[i]<0)
                                {
                                        xs_coords[i]+=x_zoom_delta;
                                }
                                else
                                {
                                        xs_coords[i]-=x_zoom_delta;
                                }
                                if(ys_coords[i]<0)
                                {
                                        ys_coords[i]+=y_zoom_delta;
                                }
                                else
                                {
                                        ys_coords[i]-=y_zoom_delta;
                                }
                        }
                        zoomteller++;
                        if(zoomteller>=100)
                        {
                                zoomin=false;
                        }
                }
                else
                {
                        for(i=0;i<3;i++)
                        {
                                if(xs_coords[i]<0)
                                {
                                        xs_coords[i]-=x_zoom_delta;
                                }
                                else
                                {
                                        xs_coords[i]+=x_zoom_delta;
                                }
                                if(ys_coords[i]<0)
                                {
                                        ys_coords[i]-=y_zoom_delta;
                                }
                                else
                                {
                                        ys_coords[i]+=y_zoom_delta;
                                }
                        }
                        zoomteller--;
                        if(zoomteller<-400)
                        {
                                zoomin=true;
                        }
                }
        }

        private void array2image()
        {
                display_image=createImage(mic);
        }

        public void start()
        {                
                do_it = new Thread(this);
                do_it.start();
        }

        public void stop()
        {
                if(do_it!=null)
                {
                        do_it.stop();
                }
                do_it=null;
        }

        public boolean mouseDown(Event e, int x, int y)
        {
                if(do_it!=null)
                {
                        stop_thread=true;
                }
                else
                {
                        stop_thread=false;
                        start();
                }
                return true;
        }

        private void animate()
        {
                double  xab_delta=0,xac_delta=0;
                double  yab_delta=0,yac_delta=0;
                double  x_off=0,y_off=0;

                int     readx=0,ready=0;
                double  xa,xb,xc;
                double  ya,yb,yc;
		int	prcW;

                int     i,j;

                xa=xd_coords[0];                
                xb=xd_coords[1];                
                xc=xd_coords[2];                
                ya=yd_coords[0];                
                yb=yd_coords[1];                
                yc=yd_coords[2];                

                xab_delta=(xb-xa)/(double) (display_width);
                yab_delta=(yb-ya)/(double) (display_width);

                xac_delta=(xc-xa)/(double) (display_height);
                yac_delta=(yc-ya)/(double) (display_height);

                // transpose the rotating centre to the middle of the
                // picture.
                x_off=xa+(((double)(iw)) * 0.5);
                y_off=ya+(((double)(ih)) * 0.5);

		prcW = 0;
                for(i=0;i<display_height;i++)
                {
			//prcW = i* display_width;
                        for(j=0;j<display_width;j++)
                        {
                                readx=((int) (x_off)) & 0xff;
                                ready=((int) (y_off)) & 0xff;
                                dest_pixels[prcW++]=pixels[(ready*iw)+readx];

                                x_off+=xab_delta;
                                y_off+=yab_delta;
                        }
        		x_off=xa + (i*(xac_delta-(0.02*i))) + (((double)(iw)) * 0.5);
	            	y_off=ya + (i*(yac_delta+(0.01*i))) + (((double)(ih)) * 0.5);
               }
        }
        

        public void paint(Graphics g)
        {
                int i;
                
                if(imageValid)
                {
                        g.drawImage(display_image,0,0,this);
                }
                else
                {
                        g.drawString("Unable to load image",0,50);
                }
        }


        public void update(Graphics g)
        {
                paint(g);
        }


        void    rotate_it()
        {
                double  gamma_rad;
                double  sin_g;
                double  cos_g;

                double  xn,yn;
                double  xn2,yn2;

		int	i;

                // first update the angle. only gamma is interesting...
                gamma=(gamma+dgamma)%360;

                gamma_rad=(gamma/360)*2*Math.PI;
		
		// get the sin and cos of the angles

		sin_g=Math.sin(gamma_rad);		
		cos_g=Math.cos(gamma_rad);		

                // now rotate the coords...
                for(i=0;i<num_of_coords;i++)
                {
                        yn=ys_coords[i];
                        xn=xs_coords[i];

                        xd_coords[i]=(xn*cos_g) - (yn*sin_g);
                        yd_coords[i]=(yn*cos_g) + (xn*sin_g);
                }
        }


        public void run()
        {
                while(!stop_thread)
                {
                        if(thread_wait)
                        {
                                thread_wait=false;
                                animate();
                                array2image();
                                repaint();
                                try
                                {
                                        Thread.sleep(1000);
                                } catch(InterruptedException e) {};
                        }
                        zoom_it();
                        rotate_it();
                        animate();
                        array2image();
                        repaint();
                        
                        try
                        {
                                Thread.sleep(10);
                        } catch(InterruptedException e) {};
                }
                do_it=null;
        }
}




