import ij.IJ;
import ij.ImagePlus;
import ij.gui.GenericDialog;
import ij.plugin.filter.Convolver;
import ij.plugin.filter.PlugInFilter;
import ij.process.ByteProcessor;
import ij.process.ImageProcessor;
import utility.*;

/**
 * This class make the edge extraction using DroG operator.
 * @author Carmelo Pulvirenti pulvirenti.carmelo@libero.it.
 */
public class DroG_ implements PlugInFilter
{
       
       /**
        * This is the type of filter that user has choice.
        */
       private float edgeFilter[];
       
       
       /**
        * This is the threshold value.
        */
       private int threshold;
       
       
       /**
        * Show the information about this plugin.
        */
       private void showAbout()
       {
              IJ.showMessage("DroG operator","Carmelo Pulvirenti\npulvirenti.carmelo@libero.it");
       }
       
       
       
       public int setup(String arg, ImagePlus imp)
       {
              if (arg.equals("about"))
              {
                     showAbout();
                     return DONE;
              }
              
              //Cofiguration Input windows
              GenericDialog gd = new GenericDialog("Parameters for DroG");
              if (imp==null)
              {
                     gd = new GenericDialog("No Input!!");
                     gd.addMessage("No loaded image!");
                     gd.showDialog();
                     return PlugInFilter.DONE;
              }
              gd.addChoice("X-Y edge",new String[]{"X","Y"},"X");
              gd.addNumericField("Gaussian kernel size. Odd",3,0);
              gd.addNumericField("Gaussian sigma",0.5,1);
              gd.addNumericField("Threshold [0-255] ",20,0);
              gd.showDialog();
              
              if ( gd.wasCanceled() )	return DONE;
              
              int edge=gd.getNextChoiceIndex();
              short gaussianwindow = (short) gd.getNextNumber();
              float gaussiansigma  = (float) gd.getNextNumber();
              threshold= (int) gd.getNextNumber();
              
              gd.dispose();
              
              gd=new GenericDialog("Error");
              if (gaussianwindow<=0)
              {
                     gd.addMessage("The window of gaussian is negative or zero!");
                     gd.showDialog();
                     return PlugInFilter.DONE;
              }
              
              if (gaussiansigma<=0)
              {
                     gd.addMessage("Sigma is negative or zero!");
                     gd.showDialog();
                     return PlugInFilter.DONE;
              }
              
              if(gaussianwindow%2==0)
              {
                     gd.addMessage("Window isn't odd!");
                     gd.showDialog();
                     return PlugInFilter.DONE;
              }
              
              if(threshold<0||threshold>255)
              {
                     gd.addMessage("Threshold isn't between 0-255 ");
                     gd.showDialog();
                     return PlugInFilter.DONE;
              }
              
              gd.dispose();
              if(edge==0)
                     this.edgeFilter=Service.DroGX(gaussianwindow,gaussiansigma);
              else
                     this.edgeFilter=Service.DroGY(gaussianwindow,gaussiansigma);
              return PlugInFilter.DOES_ALL;
       }
       
       public void run(ImageProcessor ip)
       {
              
              ByteProcessor bp=Service.getByteProcessor(ip);
              Convolver  conv=new Convolver();
              conv.setNormalize(false);
              conv.convolve(bp,this.edgeFilter,(int)Math.sqrt(this.edgeFilter.length),(int)Math.sqrt(this.edgeFilter.length));
              ImageProcessor out = bp.duplicate();
              ImagePlus newImg = new ImagePlus("DroG Result", out);
              newImg.show();
              
              // Lut processor.
              int lut[]=new int[256];
              int i=0;
              for (;i<threshold;i++)
                     lut[i]=0;
              for(int j=i;j<lut.length;j++)
                     lut[j]=255;
              bp.applyTable(lut);
              ImagePlus newImgLut = new ImagePlus("Lut result after DroG", bp);
              newImgLut.show();
       }
}
