import java.awt.*;
import java.awt.image.*;
import java.applet.*;
import java.net.*;
import java.io.*;
import java.lang.Math;
import java.util.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.JApplet;
import javax.imageio.*;
import javax.swing.event.*;



public class symmetryDemo extends JApplet {
	
	Image edgeImage, accImage, outputImage;
	MediaTracker tracker = null;
	PixelGrabber grabber = null;
	int width = 0, height = 0;
	String fileNames[] = {"Gait_Full_Stride.png","Gait_Mid_Stride_1.png","Gait_Mid_Stride_2.png", "shapes.png","UK_Flag_(SLOW).png"};

	javax.swing.Timer timer;
	//slider constraints
	static final int SIGMA_MIN = 0;
	static final int SIGMA_MAX = 80;
	static final int SIGMA_INIT = 20;
	static int sigma=SIGMA_INIT;

	int imageNumber=0;
	static int progress=0;
	static String status;
	public int orig[] = null;
	
	Image image[] = new Image[fileNames.length];
	
	JProgressBar progressBar;
	JPanel controlPanel, selectionPanel, imagePanel, progressPanel;
	JLabel origLabel,sigmaLabel, outputLabel,edgeLabel,comboLabel,radiusLabel,intermediateLabel,processing;
	ButtonGroup radiogroup;
	JRadioButton SpacekRadio, SobelRadio, OverlayRadio, HystRadio, HoughAccRadio;
	JSlider sigmaSlider;
	JComboBox imSel;
	static sobel sobelObject;
	static symmetry symmetryOperator;
	static String intermediateimage;
	
	static Image symmetryImage, sobelImage;


	   	// Applet init function	
	public void init() {
		
		tracker = new MediaTracker(this);
		for(int i = 0; i < fileNames.length; i++) {
			image[i] = getImage(this.getCodeBase(),fileNames[i]);
			image[i] = image[i].getScaledInstance(256, 256, Image.SCALE_SMOOTH);
			tracker.addImage(image[i], i);
		}
		try {
			tracker.waitForAll();
		}
		catch(InterruptedException e) {
			System.out.println("error: " + e);
		}
		
		Container cont = getContentPane();
		cont.removeAll();
		cont.setBackground(Color.black);
		cont.setLayout(new BorderLayout());
		
		controlPanel = new JPanel();
		controlPanel.setLayout(new GridLayout(2,2,0,0));
		controlPanel.setBackground(new Color(192,204,226));
		imagePanel = new JPanel();
		imagePanel.setBackground(new Color(192,204,226));
		progressPanel = new JPanel();
		progressPanel.setBackground(new Color(192,204,226));
		progressPanel.setLayout(new GridLayout(2,1));
		selectionPanel = new JPanel();
		selectionPanel.setBackground(new Color(192,204,226));


		comboLabel = new JLabel("IMAGE: ");
		comboLabel.setHorizontalAlignment(JLabel.CENTER);
		controlPanel.add(comboLabel);
		sigmaLabel = new JLabel("Sigma = "+SIGMA_INIT);
		sigmaLabel.setHorizontalAlignment(JLabel.CENTER);
		controlPanel.add(sigmaLabel);


		processing = new JLabel("Processing...");
		processing.setHorizontalAlignment(JLabel.LEFT);
		progressBar = new JProgressBar(0,100);
        progressBar.setValue(0);
        progressBar.setStringPainted(true); //get space for the string
        progressBar.setString("");          //but don't paint it
		progressPanel.add(processing);
		progressPanel.add(progressBar);
		
		width = image[imageNumber].getWidth(null);
		height = image[imageNumber].getHeight(null);

		imSel = new JComboBox(fileNames);
		imageNumber = imSel.getSelectedIndex();
		imSel.addActionListener( 
			new ActionListener() {  
				public void actionPerformed(ActionEvent e) {
					imageNumber = imSel.getSelectedIndex();
					origLabel.setIcon(new ImageIcon(image[imageNumber]));	
					processImage();
				}
			}
		);
		controlPanel.add(imSel);

        timer = new javax.swing.Timer(50, new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
				int val=symmetryOperator.getProgress();
				

                progressBar.setValue(val);
				processing.setText("Processing "+ status);
            }
        });

		origLabel = new JLabel("Original Image", new ImageIcon(image[imageNumber]), JLabel.CENTER);
		origLabel.setVerticalTextPosition(JLabel.BOTTOM);
		origLabel.setHorizontalTextPosition(JLabel.CENTER);
		origLabel.setForeground(Color.blue);
		imagePanel.add(origLabel);
		
		edgeLabel = new JLabel("Intermediate Edge Image", new ImageIcon(image[imageNumber]), JLabel.CENTER);
		edgeLabel.setVerticalTextPosition(JLabel.BOTTOM);
		edgeLabel.setHorizontalTextPosition(JLabel.CENTER);
		edgeLabel.setForeground(Color.blue);
		imagePanel.add(edgeLabel);
	
		outputLabel = new JLabel("Symmetry Map", new ImageIcon(image[imageNumber]), JLabel.CENTER);
		outputLabel.setVerticalTextPosition(JLabel.BOTTOM);
		outputLabel.setHorizontalTextPosition(JLabel.CENTER);
		outputLabel.setForeground(Color.blue);
		imagePanel.add(outputLabel);

		sigmaSlider = new JSlider(JSlider.HORIZONTAL, SIGMA_MIN, SIGMA_MAX, SIGMA_INIT);
		sigmaSlider.addChangeListener(new sigmaListener());
		sigmaSlider.setMajorTickSpacing(10);
		sigmaSlider.setMinorTickSpacing(1);
		sigmaSlider.setPaintTicks(true);
		sigmaSlider.setPaintLabels(true);
		sigmaSlider.setBackground(new Color(192,204,226));
		controlPanel.add(sigmaSlider);

		cont.add(controlPanel, BorderLayout.NORTH);
		cont.add(imagePanel, BorderLayout.CENTER);
		cont.add(progressPanel, BorderLayout.SOUTH);

		processImage();

	}
	class sigmaListener implements ChangeListener {
	    public void stateChanged(ChangeEvent e) {
	        JSlider source = (JSlider)e.getSource();
	        if (!source.getValueIsAdjusting()) {
				System.out.println("sigma="+source.getValue());
				sigma=source.getValue();
				sigmaLabel.setText("Sigma = "+source.getValue());
				processImage();
	        }    
	    }
	}
	private void processImage(){
		orig=new int[width*height];
		PixelGrabber grabber = new PixelGrabber(image[imageNumber], 0, 0, width, height, orig, 0, width);
		try {
			grabber.grabPixels();
		}
		catch(InterruptedException e2) {
			System.out.println("error: " + e2);
		}
		progressBar.setMaximum(width-2);

		processing.setText("Processing...");
		imSel.setEnabled(false);
		sigmaSlider.setEnabled(false);		
		
		sobelObject = new sobel();
		symmetryOperator = new symmetry();
		
		timer.start();

		new Thread(){
			public void run(){

				double direction[] = new double[width*height];
				int direction2[] = new int[width*height];
				status="Sobel";
				sobelObject.init(orig,width,height);
				orig = sobelObject.process();
				direction=sobelObject.getDirection();
				sobelImage = createImage(new MemoryImageSource(width, height, orig, 0, width));
				double max=0, min=1000;

				//normalise angles - either 0-255 or 0-180
				double ratio=255/(Math.PI*2);
				double ratio2=180/(Math.PI*2);
				for (int Xi=1;Xi<width-1;Xi++) {
					for (int Xj=1;Xj<height-1;Xj++) {
						int M = (int)((direction[Xj*width+Xi])*ratio);
						direction[Xj*width+Xi] = ((direction[Xj*width+Xi])*ratio2);
						if(max<direction[Xj*width+Xi]) max=direction[Xj*width+Xi];
						if(min>direction[Xj*width+Xi]) min=direction[Xj*width+Xi];
						direction2[Xj*width+Xi] = 0xff000000 | (M << 16 | M << 8 | M);
					}
				}		
				//final DirectionImage = createImage(new MemoryImageSource(width, height, direction2, 0, width));
				System.out.println("max"+max);
				
				System.out.println("min"+min);

				status="Symmetry";

				symmetryOperator.init(orig,direction,(double)sigma,0f,width,height);
				orig = symmetryOperator.process();
				symmetryImage = createImage(new MemoryImageSource(width, height, orig, 0, width));


				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						outputLabel.setIcon(new ImageIcon(symmetryImage));	
						edgeLabel.setIcon(new ImageIcon(sobelImage));

						processing.setText("Done");
						imSel.setEnabled(true);
						sigmaSlider.setEnabled(true);
					}
				});
			}
		}.start();
	}

}
