import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.Hashtable;
import javax.imageio.ImageIO;
import java.util.*;
import java.util.List;
import javax.imageio.*;
import javax.imageio.stream.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import java.lang.Object.*;
import java.io.*;
import javax.swing.filechooser.FileFilter;



public class GraphicEditor extends JFrame
{
 
     
   private JFileChooser fileChooser;
   private JDialog grafico;
   private JScrollPane ScrollPane;
   private BufferedImage originale = null;
   private BufferedImage copia = null;

   private String nomefile;
   private String estensione;
   private Panel pannello = new Panel();


   // File  
   protected Action apriAction;
   protected Action salvacomeAction;
   protected Action chiudiAction;
   // Immagine
   //protected Action scalaAction;
   protected Action annullaAction;
   
// Filtri
   protected Action equalizzaAction;
   protected Action incupireAction;
   protected Action schiarireAction;
   protected Action parametroAction;
   protected Action scalagrigiAction;
   protected Action negativoAction;
   protected Action logaritmicaAction;
   protected Action gaussianaAction;
   protected Action filtracanaliAction;
   protected Action sharpeningAction;
   protected Action nboxAction;
   //RilevaContoni
   protected Action sobelxAction;
   protected Action sobelyAction;
   protected Action prewittxAction;
   protected Action prewittyAction;
   protected Action laplacexAction;
   protected Action laplaceyAction;



  
   public GraphicEditor()
   {
     super("GraphicEditor");
    setSize(800, 600);
    createActions();
    JMenuBar menuBar = createMenuBar();
    JToolBar toolBar = createToolBar();
   
    this.createCenterComponent();
    getContentPane().add(BorderLayout.NORTH, toolBar);
    getContentPane().add(BorderLayout.CENTER, ScrollPane);
    setJMenuBar(menuBar);
    fileChooser = new JFileChooser();
    setVisible(true);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   
    AscoltaWindow ascolta = new AscoltaWindow(); // Ascoltatore di finestre
    addWindowListener(ascolta);

   }
   

   protected void createActions() 
   {
// File
      apriAction = new AbstractAction("Apri", new ImageIcon("img/Apri.png")) 
      { public void actionPerformed(ActionEvent e) { apri(); } };
      salvacomeAction = new AbstractAction("Salva", new ImageIcon("img/Salvac.png")) 
      { public void actionPerformed(ActionEvent e) { salvacome(); } };
     chiudiAction = new AbstractAction("Chiudi", new ImageIcon("img/Chiudi.png")) 
     { public void actionPerformed(ActionEvent e) { esci(); } };

// Immagine
 //    scalaAction = new AbstractAction("Scala Immagine", new ImageIcon("img/Scala.png")) 
   //  { public void actionPerformed(ActionEvent e) { scala(); } };
  
     annullaAction = new AbstractAction("Annulla ultima operazione", new ImageIcon("img/Annulla.png"))
     { public void actionPerformed(ActionEvent e) { annulla(); } };


// Filtri 
     equalizzaAction = new AbstractAction("Equalizza", new ImageIcon("img/Equalizza.png")) 
     { public void actionPerformed(ActionEvent e) {  equalizza(); } };
     incupireAction = new AbstractAction("Incupire", new ImageIcon("img/Incupire.png")) 
     { public void actionPerformed(ActionEvent e) { incupire();  } };
     schiarireAction = new AbstractAction("Schiarire", new ImageIcon("img/Schiarire.png")) 
     { public void actionPerformed(ActionEvent e) { schiarire(); } };
     parametroAction = new AbstractAction("Parametro", new ImageIcon("img/Parametro.png")) 
     { public void actionPerformed(ActionEvent e) { parametro(); } };
     scalagrigiAction = new AbstractAction("Scala di grigi", new ImageIcon("img/Scalagrigi.png")) 
     { public void actionPerformed(ActionEvent e) { scalagrigi(); } };
    negativoAction = new AbstractAction("Negativo", new ImageIcon("img/Negativo.png")) 
     { public void actionPerformed(ActionEvent e) { negativo(); } };
     logaritmicaAction = new AbstractAction("Logaritmica", new ImageIcon("img/Logaritmica.png")) 
     { public void actionPerformed(ActionEvent e) { logaritmica(); } };
     gaussianaAction = new AbstractAction("Gaussiana", new ImageIcon("img/Gaussiana.png")) 
     { public void actionPerformed(ActionEvent e) {  gaussiana(); } };
     filtracanaliAction = new AbstractAction("Filtra Canali", new ImageIcon("img/Filtracanali.png")) 
     { public void actionPerformed(ActionEvent e) { filtracanali(); } };
      sharpeningAction = new AbstractAction("Aumenta nitidezza", new ImageIcon("img/Sharpening.png")) 
     { public void actionPerformed(ActionEvent e) { sharpening(); } };
     nboxAction = new AbstractAction("Sfoca(NBox)", new ImageIcon("img/Nbox.png")) 
     { public void actionPerformed(ActionEvent e) { nbox(); } };

// RilevaContorni
     sobelxAction = new AbstractAction("Sobel X", new ImageIcon("img/Rileva.png")) 
     { public void actionPerformed(ActionEvent e) { sobelx(); } };
     sobelyAction = new AbstractAction("Sobel Y", new ImageIcon("img/Rileva.png")) 
     { public void actionPerformed(ActionEvent e) { sobely(); } };
     prewittxAction = new AbstractAction("Prewitt X", new ImageIcon("img/Rileva.png")) 
     { public void actionPerformed(ActionEvent e) { prewittx(); } };
     prewittyAction = new AbstractAction("Prewitt Y", new ImageIcon("img/Rileva.png")) 
     { public void actionPerformed(ActionEvent e) { prewitty(); } };
     laplacexAction = new AbstractAction("Laplace X", new ImageIcon("img/Rileva.png")) 
     { public void actionPerformed(ActionEvent e) {  laplacex(); } };
     laplaceyAction = new AbstractAction("Laplace Y", new ImageIcon("img/Rileva.png")) 
     { public void actionPerformed(ActionEvent e) { laplacey(); } };

 }


   protected JToolBar createToolBar() 
   {
    JToolBar tb = new JToolBar();
    tb.add(apriAction);
    tb.add(salvacomeAction);
    tb.addSeparator();
    tb.add(annullaAction);
    return tb;
   }

   protected JMenuBar createMenuBar() 
   {
    JMenuBar menu = new JMenuBar(); 
    
    JMenu fileMenu = new JMenu("File");
      fileMenu.add(apriAction);
     
      fileMenu.add(salvacomeAction);
      fileMenu.add(chiudiAction);
    menu.add(fileMenu);

    JMenu imgMenu = new JMenu("Immagine");
    imgMenu.add(annullaAction);
     menu.add(imgMenu);
   
    JMenu filtriMenu = new JMenu("Filtri");
      filtriMenu.add(equalizzaAction);
      filtriMenu.add(incupireAction);
      filtriMenu.add(schiarireAction);
      filtriMenu.add(parametroAction);
      filtriMenu.add(scalagrigiAction);
      filtriMenu.add(negativoAction);
      filtriMenu.addSeparator();      
      filtriMenu.add(logaritmicaAction);
      filtriMenu.add(gaussianaAction);
      filtriMenu.addSeparator();
      filtriMenu.add(filtracanaliAction);
      filtriMenu.addSeparator();
      filtriMenu.add(sharpeningAction);
      filtriMenu.add(nboxAction);
    menu.add(filtriMenu);

    JMenu contorniMenu = new JMenu("RilevaContorni");
      contorniMenu.add(sobelxAction);
      contorniMenu.add(sobelyAction);
      contorniMenu.add(prewittxAction);
      contorniMenu.add(prewittyAction);
      contorniMenu.add(laplacexAction);
      contorniMenu.add(laplaceyAction);
    menu.add(contorniMenu);
    return menu;
   }

  protected void createCenterComponent() 
  {
    ScrollPane= new JScrollPane(pannello);
  }

 


 private void annulla() // Annulla l'ultima operazione sull'immagine
 {
  copiaImmagine(copia,originale);
  pannello.setImage(originale); ScrollPane.revalidate(); // rinnova la visualizzazione
 }

 private void equalizza()
 {
   Puntuali p = new Puntuali();
    copia=null;
    copia = new BufferedImage(originale.getWidth(),originale.getHeight(),BufferedImage.TYPE_INT_RGB);   
    copiaImmagine(originale,copia);
    originale = p.equalizza(copia);
    pannello.setImage(originale); ScrollPane.revalidate(); // rinnova la visualizzazione
 }

 private void incupire()
 {
   Puntuali p = new Puntuali();
    copia=null;
    copia = new BufferedImage(originale.getWidth(),originale.getHeight(),BufferedImage.TYPE_INT_RGB);   
    copiaImmagine(originale,copia);
    originale = p.incupire(copia);
    pannello.setImage(originale); ScrollPane.revalidate(); // rinnova la visualizzazione
 }

 private void schiarire()
 {
   Puntuali p = new Puntuali();
    copia=null;
    copia = new BufferedImage(originale.getWidth(),originale.getHeight(),BufferedImage.TYPE_INT_RGB);   
    copiaImmagine(originale,copia);
    originale = p.schiarire(copia);
    pannello.setImage(originale); ScrollPane.revalidate(); // rinnova la visualizzazione
 }

 private void negativo()
 {
   Puntuali p = new Puntuali();
    copia=null;
    copia = new BufferedImage(originale.getWidth(),originale.getHeight(),BufferedImage.TYPE_INT_RGB);   
    copiaImmagine(originale,copia);
    originale = p.negativo(copia);
    pannello.setImage(originale); ScrollPane.revalidate(); // rinnova la visualizzazione
 }

 private void scalagrigi()
 {
   Puntuali p = new Puntuali();
    copia=null;
    copia = new BufferedImage(originale.getWidth(),originale.getHeight(),BufferedImage.TYPE_INT_RGB);   
    copiaImmagine(originale,copia);
    originale = p.scalaGrigi(copia);
    pannello.setImage(originale); ScrollPane.revalidate(); // rinnova la visualizzazione
 }

 private void parametro()
 {
   Puntuali p = new Puntuali();
    copia=null;
    copia = new BufferedImage(originale.getWidth(),originale.getHeight(),BufferedImage.TYPE_INT_RGB);   
    copiaImmagine(originale,copia);
     Double par = Double.parseDouble(JOptionPane.showInputDialog("Parametro da applicare:"));

    originale = p.parametro(copia,par);
    pannello.setImage(originale); ScrollPane.revalidate(); // rinnova la visualizzazione
 }


 private void logaritmica()
 {
   Puntuali p = new Puntuali();
    copia=null;
    copia = new BufferedImage(originale.getWidth(),originale.getHeight(),BufferedImage.TYPE_INT_RGB);   
    copiaImmagine(originale,copia);
      Double L = Double.parseDouble(JOptionPane.showInputDialog("L:"));
      Double R = Double.parseDouble(JOptionPane.showInputDialog("R:"));
    
    originale = p.logaritmica(copia,R,L);
    pannello.setImage(originale); ScrollPane.revalidate(); // rinnova la visualizzazione
 }

 private void gaussiana()
 {
   Puntuali p = new Puntuali();
    copia=null;
    copia = new BufferedImage(originale.getWidth(),originale.getHeight(),BufferedImage.TYPE_INT_RGB);   
    copiaImmagine(originale,copia);
      Double L = Double.parseDouble(JOptionPane.showInputDialog("L:"));
      Double R = Double.parseDouble(JOptionPane.showInputDialog("R:"));
      Double g = Double.parseDouble(JOptionPane.showInputDialog("Fattore Gamma:"));
    
    originale = p.gaussiana(copia,R,L,g);
    pannello.setImage(originale); ScrollPane.revalidate(); // rinnova la visualizzazione
 }

 private void filtracanali()
 {
   Puntuali p = new Puntuali();
    copia=null;
    copia = new BufferedImage(originale.getWidth(),originale.getHeight(),BufferedImage.TYPE_INT_RGB);   
    copiaImmagine(originale,copia);
      Double R = Double.parseDouble(JOptionPane.showInputDialog("fattore filtro canale R:"));
      Double G = Double.parseDouble(JOptionPane.showInputDialog("fattore filtro canale G:"));
      Double B = Double.parseDouble(JOptionPane.showInputDialog("fattore filtro canale B:"));
    
    originale = p.filtraCanali(copia,R,G,B);
    pannello.setImage(originale); ScrollPane.revalidate(); // rinnova la visualizzazione
 }


 private void sharpening()
 {
  Locali l = new Locali();
    copia=null;
    copia = new BufferedImage(originale.getWidth(),originale.getHeight(),BufferedImage.TYPE_INT_RGB);   
    copiaImmagine(originale,copia);
    originale = l.sharpening(copia);
    pannello.setImage(originale); ScrollPane.revalidate(); // rinnova la visualizzazione
 }

 private void nbox()
 {
  Locali l = new Locali();
    copia=null;
    copia = new BufferedImage(originale.getWidth(),originale.getHeight(),BufferedImage.TYPE_INT_RGB);   
    copiaImmagine(originale,copia);
    int n = Integer.parseInt(JOptionPane.showInputDialog("N di Box:"));
    originale = l.nbox(copia,n);
    pannello.setImage(originale); ScrollPane.revalidate(); // rinnova la visualizzazione
 }

private void sobelx()
 {
  Locali l = new Locali();
    copia=null;
    copia = new BufferedImage(originale.getWidth(),originale.getHeight(),BufferedImage.TYPE_INT_RGB);   
    copiaImmagine(originale,copia);
    originale = l.sobelX(copia);
    pannello.setImage(originale); ScrollPane.revalidate(); // rinnova la visualizzazione
 }

private void sobely()
 {
  Locali l = new Locali();
    copia=null;
    copia = new BufferedImage(originale.getWidth(),originale.getHeight(),BufferedImage.TYPE_INT_RGB);   
    copiaImmagine(originale,copia);
    originale = l.sobelY(copia);
    pannello.setImage(originale); ScrollPane.revalidate(); // rinnova la visualizzazione
 }

private void prewittx()
 {
  Locali l = new Locali();
    copia=null;
    copia = new BufferedImage(originale.getWidth(),originale.getHeight(),BufferedImage.TYPE_INT_RGB);   
    copiaImmagine(originale,copia);
    originale = l.prewittX(copia);
    pannello.setImage(originale); ScrollPane.revalidate(); // rinnova la visualizzazione
 }

private void prewitty()
 {
  Locali l = new Locali();
    copia=null;
    copia = new BufferedImage(originale.getWidth(),originale.getHeight(),BufferedImage.TYPE_INT_RGB);   
    copiaImmagine(originale,copia);
    originale = l.prewittY(copia);
    pannello.setImage(originale); ScrollPane.revalidate(); // rinnova la visualizzazione
 }

private void laplacex()
 {
  Locali l = new Locali();
    copia=null;
    copia = new BufferedImage(originale.getWidth(),originale.getHeight(),BufferedImage.TYPE_INT_RGB);   
    copiaImmagine(originale,copia);
    originale = l.laplaceX(copia);
    pannello.setImage(originale); ScrollPane.revalidate(); // rinnova la visualizzazione
 }

private void laplacey()
 {
  Locali l = new Locali();
    copia=null;
    copia = new BufferedImage(originale.getWidth(),originale.getHeight(),BufferedImage.TYPE_INT_RGB);   
    copiaImmagine(originale,copia);
    originale = l.laplaceY(copia);
    pannello.setImage(originale); ScrollPane.revalidate(); // rinnova la visualizzazione
 }



   public void apri()  //Apre la finestra per scegliere il file
   {
            int pointext=0,i =0;
            JFileChooser dialogoFile = new JFileChooser();
            dialogoFile.setAcceptAllFileFilterUsed(false);
            dialogoFile.setFileFilter(new MyFilter("png"));
            dialogoFile.setFileFilter(new MyFilter("jpeg"));
            dialogoFile.setFileFilter(new MyFilter("jpg"));

            //visualizzo il dialogo e raccolgo la risposta (ok==0 annulla==1)
            int risposta=dialogoFile.showOpenDialog((JFrame)null);

            if (risposta==dialogoFile.APPROVE_OPTION)	//Se ho premuto il tasto ok
                {
                 try
                    {
                     File dati = dialogoFile.getSelectedFile();
                     originale=ImageIO.read(dati);
                     int w=originale.getWidth();
                     int h=originale.getHeight();
                     pannello.setImage(originale);
                     pannello.setPreferredSize(new Dimension(w,h));
                    ScrollPane.revalidate();
                     this.nomefile = dati.getName();

                     for(i=0; i< nomefile.length() ; i++) 
                         {if(nomefile.charAt(i) == '.') pointext=i; }

                      estensione = nomefile.substring(pointext,nomefile.length());
                      System.out.println(this.estensione);
                       
                      this.setTitle("GraphicEditor - "+ nomefile);
                    }
                catch (Exception ex) {}
                }
   }



 public void salvacome()
    {

   
   // creo il dialogo per salvare il file
     // e lo "personalizzo"
            JFileChooser dialogoFile = new JFileChooser();
            dialogoFile.setAcceptAllFileFilterUsed(false);
            dialogoFile.setFileFilter(new MyFilter("png"));
            dialogoFile.setFileFilter(new MyFilter("jpeg"));
            dialogoFile.setFileFilter(new MyFilter("jpg"));

    int risposta2=JOptionPane.NO_OPTION;
    File f=null;
    String ext=null;
    while (risposta2==JOptionPane.NO_OPTION) //Finchè non decido di salvare o di rinunciare
    {
      //Visualizzo la finestra di dialogo
      int risposta=dialogoFile.showSaveDialog(this);
      if (risposta==dialogoFile.APPROVE_OPTION) //Se ho premuto il tasto salva
      {
        try
        {
          //Recupero il file selezionato
          f=dialogoFile.getSelectedFile();
          //Recupero l'estensione del file
          ext=dialogoFile.getFileFilter().toString();
          //Recupero il path del file
          String str=f.getCanonicalPath();
          //Se il nome del file non contiene l'estensione, la aggiungo io a mano
          if (!str.toLowerCase().endsWith("."+ext)) f=new File(str+"."+ext);
          //Se il file esiste chiedo se lo voglio sovrascrivere
          if (f.exists()) 
          risposta2=JOptionPane.showConfirmDialog(this,"Il file esiste già, lo vuoi ovrascrivere?","Sovrascrivi",JOptionPane.YES_NO_CANCEL_OPTION,JOptionPane.QUESTION_MESSAGE);
          else risposta2=JOptionPane.YES_OPTION;
        }
        catch (Exception ex) { System.out.println("errore");}
      }
      else risposta2=JOptionPane.CANCEL_OPTION;
    }
    if (risposta2==JOptionPane.YES_OPTION)
    {
      try
      {
        //Provo a salvare l'immagine
        ImageIO.write(originale,ext,f);
      }
      catch (Exception ex) {System.out.println("errore durante il savataggio");}
    }
  }       





 
 
 private void esci() { System.out.println("Libero risorse"); originale = null; copia = null; System.exit(0); }
 


 

/*
 ****************************************************
 *  Classe di ascolto degli eventi della finestra   *
 *  Si libera il riferimento alla matrice serie     *
 *  la cui memoria può essere gestita dal garbage c *
 ****************************************************
*/
  class AscoltaWindow extends WindowAdapter
  {
    // Libero le risorse allocate alla chiusura della finestra del programma
    public void windowClosing(WindowEvent e) { esci();}

  }



  private void copiaImmagine(BufferedImage origine, BufferedImage dest) /*Copia un'immagine in una di destinazione*/
    {
        Graphics2D g2=dest.createGraphics();
        g2.drawImage(origine,0,0,null);
        g2.dispose();
    }

 public static void main(String argv[]) {
    GraphicEditor m = new GraphicEditor();
  }
}


