import ij.*;
import ij.gui.*;
import ij.plugin.filter.PlugInFilter;
import ij.process.*;
import java.awt.Dimension;
import java.io.*;
import java.util.logging.*;
import javax.swing.JOptionPane;
import java.util.Calendar;

/**
 *
 * @authors Maria Oliva
 *          Roberta Maccarrone
 */

public class pluginDeinterlacing implements PlugInFilter{


    ImageStack stack;
    ImageStack newStack;
    ImagePlus imp;


    /*field indica il campo pari o dispari dell'immagine interlacciata
    interpolation indica il tipo di interpolazione che si vuole applicare all'immagine*/
    String field,interpolation;
    String directory;

    //array di stringhe contenente i nomi delle immagini
    String [] labels=null;

    //classe che attua il deinterlacciamento delle immagini
    Deinterlacing d=null;


    public int setup(String arg, ImagePlus imp) {
        stack=imp.getImageStack();
	return DOES_RGB+STACK_REQUIRED;
    }


    public void run(ImageProcessor ip) {

        directory=IJ.getDirectory("image");

	d = new Deinterlacing();
        ImageProcessor ipr;
        int n= stack.getSize();

        //Crea la finestra di dialogo per settare il campo e il tipo di interpolazione
         try {
            createWindow();
        } catch (IOException ex) {
            Logger.getLogger(Deinterlacing.class.getName()).log(Level.SEVERE, null, ex);
        }


      //applica la funzione di deinterlacciamento a tutte le immagine dello stack

        labels=stack.getSliceLabels();

        ColorProcessor tmp=(ColorProcessor)stack.getProcessor(1);
        String nome=stack.getSliceLabel(1);
        ipr=d.deinterlacing(tmp,field,interpolation);
        ImagePlus img=new ImagePlus(nome,ipr);
        newStack=img.getImageStack();

        /*applica il processo di deinterlacciamento a tutte le immagini dello stack
	   e le inserisce in un nuovo stack*/ 
         for(int i=2;i<=n;i++){

                tmp=(ColorProcessor)stack.getProcessor(i);
                nome=stack.getSliceLabel(i);
                ipr=d.deinterlacing(tmp,field,interpolation);
                newStack.addSlice(nome, ipr);
            }

	//visualizza in una nuova finestra lo stack delle immagini deinterlacciate
        ImagePlus newImage=new ImagePlus("immagine",newStack);
        StackWindow win=new StackWindow(newImage);



        //genera la finestra di dialogo per la scrittura del report
        GenericDialog gd= new GenericDialog("Deinterlacciamento");
        String label = "Report";
        String [] items= {"Genera Report", "Non generare report"};

        //Cartella in cui viene salvato il report
        String directory="";

        gd.addChoice(label, items, items[0]);

        gd.showDialog();
        if(gd.wasCanceled())
            return;

        String str=gd.getNextChoice();

        if(str.compareTo("Genera Report")==0){

            try {
                //Genera il report e restituisce il nome della cartella in cui viene salvato
                directory = report(field, interpolation);
            } catch (IOException ex) {
                Logger.getLogger(pluginDeinterlacing.class.getName()).log(Level.SEVERE, null, ex);
            }

            JOptionPane.showMessageDialog(null,"Il report e' stato generato nella cartella"+directory);


        }else if(str.compareTo("Non generare report")==0){

            JOptionPane.showMessageDialog(null,"Il report non e' stato generato");

        }

       //
    }

    //Finestra di dialogo che permette di scegliere i campi e il tipo di interpolazione

     public void createWindow() throws IOException{

        //Prima finestra: seleziona i campi
        GenericDialog gd=new GenericDialog("Deinterlacciamento");
        Dimension dim= new Dimension();
        dim.setSize(230,50);
        gd.setMinimumSize(dim);

        String label="Campi";
        String[] items={"Pari","Dispari"};
        gd.addChoice(label, items,items[0]);

        gd.showDialog();
        if(gd.wasCanceled())
            return;

        field=gd.getNextChoice();
        //

        //Seconda finestra: seleziona il tipo di interpolazione
        GenericDialog gd2=new GenericDialog("Deinterlacciamento");

        String label2="Interpolazione";
        String[] items2={"Replication","Bilinear","Bicubic"};
        gd2.addChoice(label2, items2, items2[0]);

        gd2.showDialog();
        if(gd2.wasCanceled())
            return;

        interpolation=gd2.getNextChoice();
        //

     }
     //

     //Genera il report in HTML e lo salva nella cartella in cui si trovano le immagini
      public String report(String field, String interpolation)throws IOException{

        String name=JOptionPane.showInputDialog("Nome del file: ");
        String nameFile=directory+name+".html";
        FileWriter outfile=null;
	String details="Deinterlacing converte una sequenza di immagini (in RGB) interlacciate in progressive."
                     + "\nI campi pari o dispari vengono estrapolati dalle immagini e le linee mancanti vengono "
                     + "interpolate con uno dei seguenti metodi di interpolazione: replication, bilinear o bicubic.";
        Calendar c = Calendar.getInstance();
        int day = c.get(c.DAY_OF_MONTH);
        int month = c.get(c.MONTH)+1;
        int year = c.get(c.YEAR);
        int hour = c.get(java.util.Calendar.HOUR_OF_DAY);
        int minutes = c.get(java.util.Calendar.MINUTE);
        int seconds = c.get(java.util.Calendar.SECOND);
        String Date = ""+day+"/"+month+"/"+year+" "+hour+":"+minutes+":"+seconds;

        String nameImage=new String();

       for(int i=0; i<labels.length; i++){
            if(labels[i]!=null)
                nameImage=nameImage+labels[i]+"<br>";
        }

		try{
			outfile = new FileWriter(nameFile);
			outfile.write("<html><head><title>"+nameFile+"</title></head>"
                                + "<body><font size="+5+"><b>IMAGEJ REPORT</b></font><br><br>"
                                + "<font size="+4+"><b>Deinterlacing</b></font><br>"
                                + "<table cellspacing="+20+"><tr><td><b>Utente: </b></td><td>"+System.getProperty("user.name")+"</td></tr>"
                                + "<tr><td><b>Nome Report: </b></td><td>"+nameFile+"</td></tr>"
                                + "<tr><td><b>Data: </b></td><td>"+Date+"</td></tr></table>"
                                + "<b>Descrizione</b>"
                                + "<br><table cellspacing="+10+"><tr><td></td><td>"+details+"</td></tr></table>"
                                + "<b>Parametri: </b><br>"
                                + "<table cellspacing="+20+"><tr><td><b>Nome Cartella:</b></td><td>"+directory+"</td></tr>"
                                + "<tr valign="+"top"+"><td><b>Nomi Immagini:</b></td><td>"+nameImage+"</td></tr>"
                                + "<tr><td><b>Campo:</b></td><td>"+field+"</td></tr>"
                                + "<tr><td><b>Interpolazione</b></td><td>"+interpolation+"</td></tr></table></body></html>");
		}
		catch (IOException e){
			System.out.println("Errore nella creazione del file: "+e);
                        return null;

		}
		finally{
			if(outfile!=null) outfile.close();
                        return directory;
		}
    }
    //

}

class Deinterlacing{

    /*viene inizializzato dalla funzione set e scarta l'ultima riga nel caso
     in cui l'altezza e' un valore dispari o pari*/
    int bottom;

    public ImageProcessor deinterlacing(ColorProcessor ip,String field, String interpolation){

       int width=ip.getWidth();
       int height=ip.getHeight();
       ColorProcessor cp= new ColorProcessor(width,height);
       int length=height*width;

       //array temporaneo che memorizza i valori dell'immagine deinterlacciata
       int[] tmp=new int[length];


       /*k e' il valore con cui viene inizializzato l'indice delle righe dell'immagine.
       Vale 0 nel caso di righe dispari e 1 nel caso di righe pari*/
       int k=set(field,height);
       int index=0;

       //Estrae le righe pari o dispari, a secondo del k e le inserisce nell'array tmp
       for(int i=k; i<bottom; i=i+2){

           for(int j=0; j<width; j++){
               tmp[index]=ip.getPixel(j, i);
               index++;
           }

           //interpola i valori delle righe mancanti nella nuova immagine
           for(int j=0; j<width;j++){

               tmp[index]=this.interpolation(ip,i,j,interpolation);
               index++;
           }
           //

       }
       //


       //replica le ultime righe
       if(bottom!=height){
       for(int j=0; j<width; j++){
           tmp[index]=ip.getPixel(j, height-1);
           index++;
       }
       }

       if(k==1){
	       for(int j=0; j<width; j++){
			tmp[index]=ip.getPixel(j, height-1);
			index++;
	       }
	}

       //

       //inserisce l'array nel nuovo ColorProcessor e lo restituisce
       cp.setPixels(tmp);
       return cp;
       //

    }

    /*I valori di k e bottom vengono modificati in base al parametro field:
      se field e' dispari e l'altezza e' dispari viene scartata l'ultima riga
      se field e' pari e l'altezza e' pari viene scartata l'ultima riga
     */
     private int set(String field, int height){

       int k=(-1);

        if(field.compareTo("Dispari")==0){
            bottom=((height%2)==1)?height-1:height;
            k=0;
        }
        if(field.compareTo("Pari")==0){
            bottom=((height%2)==1)?height:height-1;
            k=1;
        }

        return k;
    }

    //In base al paramentro interpolation viene applicato uno dei metodi di interpolazione
    public int interpolation(ColorProcessor c, int i, int j, String interpolation){

        int value=0;

        if(interpolation.compareTo("Replication")==0){

            value=c.getPixel(j,i);
        }

        if(interpolation.compareTo("Bilinear")==0){

            value=c.getInterpolatedRGBPixel(j, i);
        }

        if(interpolation.compareTo("Bicubic")==0){

            value=((Double)(c.getBicubicInterpolatedPixel(j, i, c))).intValue();
        }

        return value;

    }


}


