package yi.iu.processor.canny;

import java.awt.*;
import yi.iu.ui.DisplayFrame;
import yi.util.io.ReadArgu;
import yi.util.io.OutputResult;
import yi.util.config.*;
import yi.util.io.input.*;
import yi.util.io.output.*;
import yi.util.log.*;

public class CannyGray extends CannyEdgeDetector
{
    public CannyGray() {super();}

    public CannyGray(double s, double l, double h) {
      super(s,l,h);
    }

    public int[] getProcessedPseudoColor(int source[], Dimension d)
    {
        int[] rst= getProcessed(source,d);
        yi.util.ImageUtil.makeImageFromGray(rst);
//        DisplayFrame f= new DisplayFrame(this, rst, d.width, d.height);
//        f.show();

        return rst;
    }


    public int[] canny(int[] image, Dimension d)
    {
        // Perform gaussian smoothing on the image using the input standard deviation.
        if(VERBOSE) System.err.println("Smoothing the image using a gaussian kernel.");
        int[] smoothedim= gaussian_smooth(image, d);

        // Compute the first derivative in the x and y directions.
        if(VERBOSE) System.err.println("Computing the X and Y first derivatives.");
        int[] delta_x= new int[d.width*d.height];
        int[] delta_y= new int[d.width*d.height];
        derrivative_x_y(smoothedim, d, delta_x, delta_y);

        // This option to write out the direction of the edge gradient was added
        // to make the information available for computing an edge quality figure
        // of merit.
        // Compute the direction up the gradient, in radians that are
        // specified counteclockwise from the positive x-axis.
        // double[] dir_radians= radian_direction(delta_x, delta_y, d, -1, -1);

        // Compute the magnitude of the gradient.
        if(VERBOSE) System.err.println("Computing the magnitude of the gradient.");
        int[] magnitude= magnitude_x_y(delta_x, delta_y, d);

        // Perform non-maximal suppression.
        if(VERBOSE) System.err.println("Doing the non-maximal suppression.");

        int[] nms= non_max_supp(magnitude, delta_x, delta_y, d);

        // Use hysteresis to mark the edge pixels.
        if(VERBOSE) System.err.println("Doing hysteresis thresholding.");
        int[] edge= apply_hysteresis(magnitude, nms, d);
        int[] gray = getGray(edge, magnitude);
        System.gc();
        return gray;
    }

    public int[] cannyFromDelta(int[] delta_x, int[] delta_y, Dimension d) {
        if(VERBOSE) System.err.println("Computing the magnitude of the gradient.");
        int[] magnitude= magnitude_x_y(delta_x, delta_y, d);

        // Perform non-maximal suppression.
        if(VERBOSE) System.err.println("Doing the non-maximal suppression.");

        int[] nms= non_max_supp(magnitude, delta_x, delta_y, d);

        // Use hysteresis to mark the edge pixels.
        if(VERBOSE) System.err.println("Doing hysteresis thresholding.");
        int[] edge= apply_hysteresis(magnitude, nms, d);
        int[] gray = getGray(edge, magnitude);
        System.gc();
        return gray;
    }

    public int[] getGray(int[] edge, int[] mag)
    {
      int[] gray = new int[edge.length];
      long max = 0;
      for (int i = 0; i < mag.length; i++)
        if (mag[i] > max)
          max = mag[i];
      for (int i = 0; i < edge.length; i++) {
        if (edge[i] == EDGE) {
          gray[i] = (int) (mag[i] * 128 / max) + 127;
        }
        else {
          gray[i] = 0;
        }
      }
      return gray;
    }

    public static void main(String[] args) {
      // init configuration
      Configuration.init(args);

      // get the image name
      String img_name = ReadArgu.getOption('i', args);
      if (img_name == null) {
        System.err.println("Usage: -i image_name");
        System.exit(1);
      }

      // read in image
      Image image = null;
      Dimension d = new Dimension();
      int[] pixels = null;
      try {
        image = yi.util.io.ImageReader.readImageFile(img_name);
        pixels = yi.util.io.ImageReader.getPixels(image, d);
      }
      catch (java.io.IOException e) {
        System.err.println("Can't read image " + img_name);
        e.printStackTrace();
        System.exit(2);
      }


      // process
      Configuration.setParameter("SOURCE_NAME", img_name);
      CannyGray canny = new CannyGray();
      int[] rst_img = canny.getProcessedPseudoColor(pixels, d);

      // output result
      OutputResult.outputColorImage(img_name + "." + DOU.shortName(canny.getClass().getName()) + ".pgm", rst_img, d.width, d.height);

      System.exit(0);
    }

}