import java.io.*;
import java.awt.*;
import java.awt.color.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.geom.*;
import java.awt.datatransfer.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;

/*----- CLASSE_PRINCIPALE -----------------------------*/
public class PhotoFilter	
{
	public static void main(String[] args)
	{
		JFrame frame = new PhotoFilterFrame();
		frame.show();
	}
}

/*------ CLASSE DEL FRAME PRINCIPALE PHOTOFILTER --------------------------------*/
class PhotoFilterFrame extends JFrame implements ActionListener, ChangeListener
{
	JFrame kernelframe;
	JFrame renderframe;
	JFrame adjustcolorframe;
	JTextField explanation;
	PhotoFilterPanel canvas;
	JSlider alphaSlider;
	String photo_temp;
	JMenuItem openItem;
	JMenuItem exitItem;
	JMenuItem negativeItem;
	JMenuItem rotateItem;
	JMenuItem kernelItem;
	JMenuItem grayItem;
	JMenuItem renderItem;
	JMenuItem undoItem;
	JMenuItem colorItem;

/*-------METODO COSTRUTTORE FRAME PRINCIPALE--------*/
	public PhotoFilterFrame()
	{
		setTitle("PhotoFilter v1.0 - creato da Paolo Selva");
		setSize(400,400);
	

		addWindowListener(new WindowAdapter()
			{
				public void windowClosing(WindowEvent e)
				{ System.exit(0);}
			});

		kernelframe = new kernelFrame(this);	
		renderframe = new renderChangeFrame(this);
		adjustcolorframe = new adjustColorFrame(this);
		Container contentPane = getContentPane();
		canvas = new PhotoFilterPanel();
		contentPane.add(canvas, "Center");
		JMenu fileMenu = new JMenu("File");
		openItem = new JMenuItem("Apri...");
		openItem.addActionListener(this);
		fileMenu.add(openItem);
		exitItem = new JMenuItem("Esci");
		exitItem.addActionListener(this);
		fileMenu.addSeparator();
		fileMenu.add(exitItem);
		JMenu filtersMenu = new JMenu("Filtri & Opzioni");
		negativeItem = new JMenuItem("Negativo");
		negativeItem.addActionListener(this);
		rotateItem = new JMenuItem("Ruota immagine");
		rotateItem.addActionListener(this);
		kernelItem = new JMenuItem("Modifica Kernel");
		kernelItem.addActionListener(this);
		grayItem = new JMenuItem("Bianco & Nero");
		grayItem.addActionListener(this);
		renderItem = new JMenuItem("Cambia ImageType...");
		renderItem.addActionListener(this);
		undoItem = new JMenuItem("Undo");
		undoItem.addActionListener(this);
		colorItem = new JMenuItem("Regola HSB");
		colorItem.addActionListener(this);
		filtersMenu.add(undoItem);
		filtersMenu.addSeparator();
		filtersMenu.add(kernelItem);
		filtersMenu.add(renderItem);
		filtersMenu.addSeparator();
		filtersMenu.add(negativeItem);
		filtersMenu.add(rotateItem);
		filtersMenu.add(grayItem);
		filtersMenu.addSeparator();
		filtersMenu.add(colorItem);
		JMenuBar menuBar = new JMenuBar();
		menuBar.add(fileMenu);
		menuBar.add(filtersMenu);
		setJMenuBar(menuBar);

		alphaSlider = new JSlider();
		alphaSlider.addChangeListener(this);
		JPanel panel = new JPanel();
		panel.add(new JLabel("Alpha"));
		panel.add(alphaSlider);
		contentPane.add(panel, "North");

		explanation = new JTextField();
		explanation.setEditable(false);
		contentPane.add(explanation, "South");
		
		alphaSlider.setValue(100);
		canvas.repaint();
	}
	

/* -------- METODO DI CONTROLLO PER LO SLIDER ALPHA ---------------- */
	public void stateChanged(ChangeEvent event)
	{
		Object source = event.getSource();
		if (source == alphaSlider) canvas.setAlpha(alphaSlider.getValue());
	}


/* -- METODO DI CONTROLLO PER LE AZIONI SVOLTE NEL FRAME PRINCIPALE -- */
	public void actionPerformed(ActionEvent event)
	{
		Object source = event.getSource();

		if (source==openItem)
		{
			explanation.setText("Apri un file di immagine...");
			JFileChooser chooser = new JFileChooser();
			chooser.setCurrentDirectory(new File("."));
			chooser.setFileFilter(new javax.swing.filechooser.FileFilter()
				{ public boolean accept(File f)
					{
						String name=f.getName().toLowerCase();
						return name.endsWith(".gif") || name.endsWith(".jpg") ||
							name.endsWith(".jpeg") || f.isDirectory();
					}
				public String getDescription()
				{ return "File di immagine"; }
			});
			int r=chooser.showOpenDialog(this);
			if (r==JFileChooser.APPROVE_OPTION)
			{
				photo_temp = chooser.getSelectedFile().getAbsolutePath();
				canvas.loadPhoto(photo_temp);
				canvas.setAlpha(100);
			}
			explanation.setText("Last Action: Opened file "+photo_temp);
			canvas.repaint();
			super.repaint();
			canvas.undoSave();
		}
		
		if (source==exitItem)
		{
			System.exit(0);
		}

		if (source==negativeItem)
		{
			explanation.setText("Ultima Azione: Filtro NEGATIVO selezionato.");
			canvas.negative();
		}

		if (source==grayItem)
		{
			explanation.setText("Ultima Azione: Filtro BIANCO & NERO selezionato.");
			canvas.filterGray();
		}

		if (source==rotateItem)
		{
			explanation.setText("Ultima Azione: Immagine ruotata di 5 gradi in senso orario.");
			canvas.rotate(10);
		}

		if (source==kernelItem)
		{
			explanation.setText("Ultima Azione: Finestra di modifica del KERNEL aperta.");
			kernelframe.setLocation(this.getX()+this.getWidth()+180,this.getY()+170);
			kernelframe.show();
		}

		if (source==renderItem)
		{
			explanation.setText("Ultima Azione: Finestra di scelta IMAGETYPE aperta.");
			renderframe.setLocation(this.getX()+this.getWidth(),this.getY()+170);
			renderframe.show();
		}

		if (source==undoItem)
		{
			explanation.setText("Ultima Azione: Undo.");
			canvas.undoLoad();
		}

		if (source==colorItem)
		{
			explanation.setText("Ultima Azione: Finestra di regolazione HSB aperta.");
			adjustcolorframe.setLocation(this.getX()+this.getWidth(),this.getY());
			adjustcolorframe.show();
			canvas.undoSave();
		}

		canvas.repaint();
	}
	
}


/* -- CLASSE PER IL PANNELLO DI ASCOLTO DELL'IMMAGINE ------------- */

class PhotoFilterPanel extends JPanel
{
	BufferedImage image;	
	Image photo;
	float alpha;
	int renderInt,lastrenderInt;
	Image undoImage;
	private static Clipboard localClipboard = new Clipboard("local");

/* --- METODO DI COSTRUZIONE PER IL PANNELLO ----- */
	public PhotoFilterPanel()
	{
		photo = Toolkit.getDefaultToolkit().getImage("prova.jpg");
		renderInt = BufferedImage.TYPE_INT_ARGB;
	}

/* ---- METODO PER IL CARICAMENTO DELL'IMMAGINE --------*/
	public void loadPhoto(String np)
	{
		photo = Toolkit.getDefaultToolkit().getImage(np);
	}

/* ----- METODO PAINT DEL PANNELLO ---------------------- */
	public void paintComponent(Graphics g)
	{
		super.paintComponent(g);
		Graphics2D g2=(Graphics2D)g;

		image = new BufferedImage (getWidth(), getHeight(), renderInt);
		Graphics2D gImage = image.createGraphics();
		AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC, alpha);
		gImage.setComposite(composite);
	gImage.drawImage(photo,(getWidth()/2)-(photo.getWidth(null)/2),(getHeight()/2)-(photo.getHeight(null)/2),null);
		g2.drawImage(image, null, 0,0);
	}


/* ------ METODO PER IL SETTAGGIO DEL VALORE ALPHA TRAMITE SLIDER ----- */
	public void setAlpha(int a)
	{
		alpha = (float)a / 100.0F;
		repaint();
	}

/* ----- METODO DI APPLICAZIONE FILTRI ---------------- */
	public void filter(BufferedImageOp op)
	{
		BufferedImage filteredImage = new BufferedImage(image.getWidth(),image.getHeight(), image.getType());
		undoSave();
		op.filter(image,filteredImage);
		photo=(Image)filteredImage;
		repaint();
	}

/* ------ METODO DI APPLICAZIONE MATRICE ------------- */
	public void convolve(float[] elements)
	{
		Kernel kernel = new Kernel(3, 3, elements);
		ConvolveOp op = new ConvolveOp(kernel,ConvolveOp.EDGE_NO_OP,null);
		filter(op);
	}
	
/* ------ METODO DEL FILTRO NEGATIVO ----------------- */
	public void negative()
	{
		byte negative[] = new byte[256];
		for (int i=0;i<256;i++)
			negative[i]=(byte)(255-i);
		ByteLookupTable table=new ByteLookupTable (0,negative);
		LookupOp op = new LookupOp (table,null);
		filter(op);
	}	

/* ----- METODO DEL FILTRO DI ROTAZIONE -------------- */
	public void rotate(int g)
	{
		AffineTransform transform = 		AffineTransform.getRotateInstance(Math.toRadians(g),image.getWidth()/2,image.getHeight()/2);
		AffineTransformOp op = new AffineTransformOp (transform, AffineTransformOp.TYPE_BILINEAR);
		filter(op);
	}

/* ------ METODO DEL FILTRO BIANCO E NERO ---------- */
	public void filterGray()
	{		
		lastrenderInt = renderInt;
		renderInt = BufferedImage.TYPE_BYTE_GRAY;
		repaint();
	}

/* ------ METODO DI MEMORIZZAZIONE IMMAGINE IN APPUNTI ---------- */
	public void undoSave()
	{
		ImageSelection selection = new ImageSelection(photo);
		localClipboard.setContents(selection,null);
	}

/* ------ METODO DI RICHIAMO IMMAGINE DA APPUNTI ----------------- */
	public void undoLoad()
	{
		Transferable contents = localClipboard.getContents(this);
		if (contents==null) return;
		try
		{
			Image img_temp = (Image)contents.getTransferData(ImageSelection.imageFlavor);
			setImage(img_temp);
		} catch (Exception e){}
	}
		
/* ------- METODO DI SETTAGGIO IMMAGINE DA APPUNTI ---------------- */
	public void setImage(Image img1)
	{
		photo = img1;
	}

/* ------ METODO DEL FILTRO TONALITA --------------------- */
	public void filtroColore(int r, int g, int b)
	{
		ImageFilter colorfilter = new ColorFilter(r,g,b);
		ImageProducer prod = new FilteredImageSource(image.getSource(), colorfilter);
		photo = createImage(prod);
		repaint();
	}


}


/*-------- CLASSE DEL FRAME PER MODIFICA DEL KERNEL ------------------- */
class kernelFrame extends JFrame implements KeyListener, ActionListener
{
	JTextField[] matrix=new JTextField[9];
	JTextField scala = new JTextField("1",3);
	JLabel scala_text = new JLabel("Fattore di scala: 1/");
	float factor=0;
	float[] kernelModified = new float[9];
	String temp;
	PhotoFilterFrame parent;
	JMenuItem blurItem;
	JMenuItem edgeItem;

/* ------ METODO DI COSTRUZIONE FRAME PER KERNEL MOD -------------- */
	public kernelFrame(PhotoFilterFrame frame_parent)
	{
		setTitle("PhotoFilter - Modificatore di Kernel");
		setSize(180,230);
		setResizable(false);

		JMenu filtri = new JMenu("Carica Filtri");
		blurItem = new JMenuItem("Effetto Nebbia");
		blurItem.addActionListener(this);
		filtri.add(blurItem);

		edgeItem = new JMenuItem("Effetto Bordi Rialzati");
		edgeItem.addActionListener(this);
		filtri.add(edgeItem);

		parent = frame_parent;

		JPanel panelContainer = new JPanel();
	
		for (int i=0;i<9;i++)
		{
			matrix[i]=new JTextField("0",4);
			matrix[i].addKeyListener(this);
			matrix[i].setHorizontalAlignment(JTextField.RIGHT);
			panelContainer.add(matrix[i]);
		}

		scala.addKeyListener(this);
		panelContainer.add(scala_text);
		panelContainer.add(scala);
		panelContainer.add(new JLabel("Note per l'uso:        "));
		panelContainer.add(new JLabel("- Enter per accettare   "));
		panelContainer.add(new JLabel("- A o D per cambiare  "));
		setContentPane(panelContainer);

		JMenuBar mb = new JMenuBar();
		mb.add(filtri);
		setJMenuBar(mb);

	}

/* ------ METODO DI CONTROLLO PER AZIONI ---------------- */
	public void actionPerformed(ActionEvent event)
	{
		Object source = event.getSource();

		if (source==blurItem)
		{
			for (int i=0; i<9; i++)	matrix[i].setText("1");
			scala.setText("9");
		}

		if (source==edgeItem)
		{
			matrix[0].setText("0");matrix[1].setText("-1");matrix[2].setText("0");
			matrix[3].setText("-1");matrix[4].setText("4");matrix[5].setText("-1");
			matrix[6].setText("0");matrix[7].setText("-1");matrix[8].setText("0");
			scala.setText("1");
		}

	}

/* ------ METODO DI CONTROLLO PRESSIONE DI UN TASTO ----------- */
	public void keyPressed(KeyEvent event)
	{
		Object source = event.getSource();
		JTextField temp = (JTextField)source;
		String string_matrix;
		char c=event.getKeyChar();
		int val=0;
		int scala_int;

		if (c==KeyEvent.VK_ENTER)
		{
			parent.explanation.setText("Kernel in azione...");
			parent.canvas.undoSave();
			factor = (float)Integer.parseInt(scala.getText());
			if (factor<=0) factor=1;
	
			for (int i=0;i<9;i++)
			{
				string_matrix=matrix[i].getText();
				kernelModified[i]=(float)Integer.parseInt(string_matrix)/factor;
			}
			
			Kernel kernel = new Kernel(3, 3, kernelModified);
			ConvolveOp op = new ConvolveOp(kernel,ConvolveOp.EDGE_NO_OP,null);
		BufferedImage filteredImage = new BufferedImage(parent.canvas.image.getWidth(),parent.canvas.image.getHeight(), parent.canvas.image.getType());
			op.filter(parent.canvas.image,filteredImage);
			parent.canvas.photo=(Image)filteredImage;
			parent.canvas.repaint();
			parent.explanation.setText("Last Action: Kernel applicated.");
		}
		if (c=='a')
		{
			val=Integer.parseInt(temp.getText());
			val++;
			temp.setText(String.valueOf(val));
			source=temp;
		}

		if (c=='d')
		{
			val=Integer.parseInt(temp.getText());
			val--;
			temp.setText(String.valueOf(val));
			source=temp;
		}

	}

/* ----- METODO DI CONTROLLO DI RILASCIO TASTI ------------ */
	public void keyReleased(KeyEvent event)
	{
	}

/* ----- METODO DI CONTROLLO DEL TIPO DI TASTO ------------- */
	public void keyTyped(KeyEvent event)
	{
	}

}


/*------ CLASSE DEL FRAME PER CAMBIARE TIPO DI RENDERING ---------- */
class renderChangeFrame extends JFrame implements ChangeListener
{
	PhotoFilterFrame parent;
	JCheckBox[] checkBox = new JCheckBox[12];
	ButtonGroup int_group = new ButtonGroup();

/* -------- METODO DI COSTRUZIONE FRAME RENDER ----------------- */
	public renderChangeFrame(PhotoFilterFrame frame_parent)
	{
		setTitle("PhotoFilter - Selezione ImageType");
		setSize(180,400);
		setResizable(false);
		
		parent = frame_parent;

		JPanel panelContainer = new JPanel();

		checkBox[0] = new JCheckBox("TYPE_3BYTE_BGR",false);
		checkBox[1] = new JCheckBox("TYPE_4BYTE_ABGR",false);
		checkBox[2] = new JCheckBox("TYPE_4BYTE_ABGR_PRE",false);
		checkBox[3] = new JCheckBox("TYPE_BYTE_BINARY",false);
		checkBox[4] = new JCheckBox("TYPE_BYTE_INDEXED",false);
		checkBox[5] = new JCheckBox("TYPE_CUSTOM",false);
		checkBox[6] = new JCheckBox("TYPE_INT_ARGB_PRE",false);
		checkBox[7] = new JCheckBox("TYPE_INT_ARGB",false);
		checkBox[8] = new JCheckBox("TYPE_INT_BGR",false);
		checkBox[9] = new JCheckBox("TYPE_INT_RGB",false);
		checkBox[10] = new JCheckBox("TYPE_USHORT_555_RGB",false);
		checkBox[11] = new JCheckBox("TYPE_USHORT_565_RGB",false);

		for (int i=0;i<12;i++) 
		{
			int_group.add(checkBox[i]);
			panelContainer.add(checkBox[i]);
			checkBox[i].addChangeListener(this);
		}
		setContentPane(panelContainer);
	}

/* ---- METODO DI CONTROLLO CAMBIAMENTO DI STATO DEI CHECKBOX -------------- */
	public void stateChanged(ChangeEvent event)
	{
		Object source = event.getSource();
		if (source == checkBox[0]) parent.canvas.renderInt = BufferedImage.TYPE_3BYTE_BGR;
		if (source == checkBox[1]) parent.canvas.renderInt = BufferedImage.TYPE_4BYTE_ABGR;
		if (source == checkBox[2]) parent.canvas.renderInt = BufferedImage.TYPE_4BYTE_ABGR_PRE;
		if (source == checkBox[3]) parent.canvas.renderInt = BufferedImage.TYPE_BYTE_BINARY;
		if (source == checkBox[4]) parent.canvas.renderInt = BufferedImage.TYPE_BYTE_INDEXED;
		if (source == checkBox[5]) parent.canvas.renderInt = BufferedImage.TYPE_CUSTOM;
		if (source == checkBox[6]) parent.canvas.renderInt = BufferedImage.TYPE_INT_ARGB_PRE;
		if (source == checkBox[7]) parent.canvas.renderInt = BufferedImage.TYPE_INT_ARGB;
		if (source == checkBox[8]) parent.canvas.renderInt = BufferedImage.TYPE_INT_BGR;
		if (source == checkBox[9]) parent.canvas.renderInt = BufferedImage.TYPE_INT_RGB;
		if (source == checkBox[10]) parent.canvas.renderInt = BufferedImage.TYPE_USHORT_555_RGB;
		if (source == checkBox[11]) parent.canvas.renderInt = BufferedImage.TYPE_USHORT_565_RGB;
		parent.canvas.repaint();
	}

}


/*------- CLASSE DEL FRAME DI REGOLAZIONE COLORI ----------------- */
class adjustColorFrame extends JFrame implements ChangeListener, MouseListener
{
	PhotoFilterFrame parent;
	JSlider H_slider;
	JSlider S_slider;
	JSlider B_slider;
	JTextField textHue,textSat, textBri;
	colorStrips colorstripHSB = new colorStrips();
	colorStrips colorstripBASE = new colorStrips();
	colorStrips colorstripCORR = new colorStrips(Color.black);
	JLabel coloriBASE = new JLabel("Colori Base");
	JLabel coloriCAMB = new JLabel("Colori Cambiati");
	JLabel coloreCORR = new JLabel("Colore Corrente");
	JLabel specsColori = new JLabel ("Spostando gli slider, cambiano i colori.");
	int R=0,G=0,B=0;

/* ---- METODO DI COSTRUZIONE DEL FRAME REGOLAZIONE COLORI ----------- */
	public adjustColorFrame(PhotoFilterFrame frame_parent)
	{
		setTitle("PhotoFilter - Regolazione HSB");
		setSize(350,170);
		setResizable(false);
	
		parent = frame_parent;

	
		GridBagLayout gridbag = new GridBagLayout();

		JPanel panelContainer = new JPanel();
		JLabel l1 = new JLabel("Tonalità");
		JLabel l2 = new JLabel("Saturazione");
		JLabel l3 = new JLabel("Luminosità");

		H_slider = new JSlider();
		H_slider.addChangeListener(this);
		H_slider.addMouseListener(this);
		S_slider = new JSlider();
		S_slider.addChangeListener(this);
		S_slider.addMouseListener(this);
		B_slider = new JSlider();
		B_slider.addChangeListener(this);
		B_slider.addMouseListener(this);

		textHue = new JTextField("0.00");
		textSat = new JTextField("0.00");
		textBri = new JTextField("0.00");

		panelContainer.setLayout(gridbag);
		GridBagConstraints lim = new GridBagConstraints();

		lim.gridx=0;
		lim.gridy=0;
		lim.gridwidth=1;
		lim.gridheight=1;
		lim.weightx=30;
		lim.anchor=GridBagConstraints.EAST;
		gridbag.setConstraints(l1,lim);
		lim.gridy=1;
		gridbag.setConstraints(l2,lim);
		lim.gridy=2;
		gridbag.setConstraints(l3,lim);

		lim.gridx=1;
		lim.gridy=0;
		lim.gridwidth=1;
		lim.gridheight=1;
		lim.weightx=50;
		lim.anchor=GridBagConstraints.CENTER;
		gridbag.setConstraints(H_slider,lim);
		lim.gridy=1;
		gridbag.setConstraints(S_slider,lim);
		lim.gridy=2;
		gridbag.setConstraints(B_slider,lim);

		panelContainer.add(l1);
		panelContainer.add(H_slider);
		panelContainer.add(l2);
		panelContainer.add(S_slider);
		panelContainer.add(l3);
		panelContainer.add(B_slider);

		lim.gridwidth=1;
		lim.weightx=20;
		lim.gridx=2;
		lim.fill=GridBagConstraints.BOTH;

		lim.gridy=0;
		gridbag.setConstraints(textHue,lim);
		lim.gridy=1;
		gridbag.setConstraints(textSat,lim);
		lim.gridy=2;
		gridbag.setConstraints(textBri,lim);
		
		textHue.setEditable(false);
		textSat.setEditable(false);
		textBri.setEditable(false);
		panelContainer.add(textHue);
		panelContainer.add(textSat);
		panelContainer.add(textBri);

		
		lim.gridwidth=1;
		lim.gridx=1;
		lim.gridy=3;
		gridbag.setConstraints(specsColori,lim);
		panelContainer.add(specsColori);

		lim.gridwidth=2;
		lim.gridx=1;
		lim.gridy=4;
		lim.weightx=100;
		gridbag.setConstraints(colorstripBASE,lim);
		panelContainer.add(colorstripBASE);

		lim.gridwidth=1;
		lim.gridx=0;
		gridbag.setConstraints(coloriBASE,lim);
		panelContainer.add(coloriBASE);


		lim.gridwidth=2;
		lim.gridx=1;
		lim.gridy=5;
		lim.weightx=100;
		gridbag.setConstraints(colorstripHSB,lim);
		panelContainer.add(colorstripHSB);

		lim.gridwidth=1;
		lim.gridx=0;
		gridbag.setConstraints(coloriCAMB,lim);
		panelContainer.add(coloriCAMB);

		lim.gridwidth=2;
		lim.gridx=1;
		lim.gridy=6;
		lim.weightx=100;
		gridbag.setConstraints(colorstripCORR,lim);
		panelContainer.add(colorstripCORR);

		lim.gridwidth=1;
		lim.gridx=0;
		gridbag.setConstraints(coloreCORR,lim);
		panelContainer.add(coloreCORR);

		setContentPane(panelContainer);
		repaint();
	}

/* ---- METODO DI CONTROLLO CAMBIAMENTO DEGLI SLIDER --------- */
	public void stateChanged(ChangeEvent event)
	{
		int xg=0; 
		float hue=0.5f,sat=0.5f,bri=1.0f; 
		hue=(float)H_slider.getValue()/100.0f;
		sat=(float)S_slider.getValue()/100.0f;
		bri=(float)B_slider.getValue()/100.0f;
		textHue.setText(String.valueOf(hue));
		textSat.setText(String.valueOf(sat));
		textBri.setText(String.valueOf(bri));
		colorstripHSB.setColorStrip(hue*255.0f,sat,bri);
		Color co = Color.getHSBColor(hue,sat,bri);
		colorstripCORR.setColorStrip(co);
		R=co.getRed();
		G=co.getGreen();
		B=co.getBlue();
	}

	public void mouseClicked(MouseEvent evt){}
	public void mouseEntered(MouseEvent evt){}
	public void mouseExited(MouseEvent evt){}
	public void mousePressed(MouseEvent evt){}

	public void mouseReleased(MouseEvent evt)
	{
		Object source = evt.getSource();
		if (source instanceof JSlider)
		{
			parent.canvas.undoLoad();
			parent.canvas.repaint();
			parent.canvas.filtroColore(R,G,B);
		}
	}
}

/*---CLASSE PER IL PANNELLO DELLA STRISCIA DI COLORE --------------- */
class colorStrips extends JPanel
{
	Color[] co=new Color[256];
	int xg=0;

/*----METODI DI COSTRUZIONE STRISCIA ---------- */
	public colorStrips()
	{
		for (int k=0; k<=255; k++)
		{
			float hu=(float)k/256.0f;
			co[k] = Color.getHSBColor(hu,1.0f,1.0f);

		}
	}

	public colorStrips(Color c)
	{
		for (int k=0; k<=255; k++) co[k] = c;
	}

	
/* ----- METODO PAINT DEL PANNELLO DELLA STRISCIA --------- */
	public void paint(Graphics g)
	{
		xg=0;
		for (int k=0; k<=255; k++)
		{
			g.setColor(co[k]);
			g.fillRect(xg,0,1,getHeight());
			xg++;
		}
	}

/* ---- METODI DI SETTAGGIO DEL COLORE PER LA STRISCIA ------ */
	public void setColorStrip(float h, float s, float b)
	{
		for (int k=0; k<=255; k++)
		{
			float hu=(float)h/255.0f;
			co[k] = Color.getHSBColor(hu,s,b);
			if (h==255) h=0;
			else h++;
		}
		repaint();
	}

	public void setColorStrip(Color c)
	{
		for (int k=0; k<=255; k++)
			co[k] = c;
		repaint();
	}

}

/*---CLASSE DEL FILTRO DEI COLORI ------------- */
class ColorFilter extends RGBImageFilter 
{
	int RED,GREEN,BLUE;

/* --- METODO DI COSTRUZIONE DEL FILTRO CON RGB -------- */
	public ColorFilter(int r, int g, int b)
	{
		RED=r;
		GREEN=g;
		BLUE=b;
		canFilterIndexColorModel = true;
	}

/*---- METODO DI SETTAGGIO DEL FILTRO ------------------ */
	public int filterRGB(int x, int y, int rgb)
	{
		int r = (rgb >> 16) & 0xff; 
		int g = (rgb >> 8) & 0xff;
		int b = (rgb >> 0) & 0xff;
		r += (RED * r) / 100;
		g += (GREEN * g) / 100;
		b += (BLUE * b) / 100;
		r = Math.min(Math.max(0, r), 255);
		g = Math.min(Math.max(0, g), 255);
		b = Math.min(Math.max(0, b), 255);
		return (rgb & 0xff000000) | (r << 16) | (g << 8) | (b << 0);
	}
}

/* ----- CLASSE PER IL SALVATAGGIO NEGLI APPUNTI --------- */
class ImageSelection implements Transferable
{
	public static final DataFlavor imageFlavor = new DataFlavor(java.awt.Image.class, "AWT Image");
	private static DataFlavor[] flavors = {imageFlavor};
	private Image theImage;

/* ---- METODO DI COSTRUZIONE --------------- */
	public ImageSelection (Image image)
	{
		theImage=image;
	}
		
/* ----- METODO DI FILTRAGGIO TIPO DATI ----------- */
	public DataFlavor[] getTransferDataFlavors()
	{
		return flavors;
	}
	
/* ----- METODO DI CONTROLLO FILTRO DATI ----------- */
	public boolean isDataFlavorSupported(DataFlavor flavor)
	{
		return flavor.equals(imageFlavor);
	}

/* ---- METODO DI PASSAGGIO DATI APPUNTI<->APPLICAZIONE --------- */
	public synchronized Object getTransferData (DataFlavor flavor) throws UnsupportedFlavorException
	{
		if (flavor.equals(imageFlavor)) return theImage;
		else throw new UnsupportedFlavorException(flavor);
	}
}
