package yi.iu.processor.symmetry;

import java.awt.*;
import yi.iu.processor.*;
import yi.iu.processor.filter.*;
import yi.iu.processor.morph.*;
import yi.iu.processor.channel.*;
import yi.iu.ui.DisplayFrame;
import yi.util.ImageUtil;

public class HorizontalRspSymCal extends SymmetryProcessor
{
    int HORIZONTHRESHOLD= 180;   //how big the response could be considered as a horizontal response
    int HORLINEWIDTHTHRSH= 10;   //how width a horizontal line can accepted

    double sigma= 0;        // Standard deviation of the gaussian kernel. Don't do gaussian when sigma=0;

    public int getArguNum() { return 1;}

    public void setArgument(int i, String st)
    {
        if (st.length()==0) return;
        if (i==0) sigma= Double.valueOf(st).doubleValue();
        //if (i==1) TRIANGLELEN= Integer.valueOf(st).intValue();
    }

    public String getArgument(int i)
    {
        if (i==0) return (new Double(sigma)).toString();
        //if (i==1) return (new Integer(TRIANGLELEN)).toString();
        return null;
    }

    public String getArguName(int i)
    {
        if (i==0) return "Sigma";
        //if (i==1) return "Triangle Len";
        return null;
    }



    public HorizontalRspSymCal() {super();}
    public HorizontalRspSymCal(int _horth, int _widthth, double _sigma) {
        this();
        HORIZONTHRESHOLD= _horth;
        HORLINEWIDTHTHRSH= _widthth;
        sigma= _sigma;
    }

    public int[] getProcessed(int source[], Dimension d){
        int[][] rst= getProcessed_ex(source, d);
        rst[1]=null;rst[2]=null;System.gc();
        return rst[0];
    }

    //return 3 results:
    //0: the histogram of horizontal lines along the x axis
    //1: the labeled version of image with only horizontal lines (small region has been deleted)
    //2: the width of every region (the region not wide enough has been removed)
    public int[][] getProcessed_ex(int source[], Dimension d)
    {
        int w=d.width, h=d.height;

        int[] in= preProcess(source, d);

        // init the horizontal mask and vertical mask
        int[] hm= new int[9];
        hm[0]=hm[2]=1;hm[1]=2;
        hm[3]=hm[4]=hm[5]=0;
        hm[6]=hm[8]=-1;hm[7]=-2;
        int[] hv= new int[9];
        hv[0]=hv[6]=-1;hv[3]=-2;
        hv[1]=hv[4]=hv[7]=0;
        hv[2]=hv[8]=1;hv[5]=2;

        // mask the image
        Masker msh= new Masker(hm,3,3);
        int[] horRsp= msh.getProcessed(in, d);
        Masker msv= new Masker(hv,3,3);
        int[] verRsp= msv.getProcessed(in, d);
        for (int i=0;i<horRsp.length;i++) if (horRsp[i]<0) horRsp[i]=-horRsp[i];
        for (int i=0;i<verRsp.length;i++) if (verRsp[i]<0) verRsp[i]=-verRsp[i];

        for (int i=0;i<horRsp.length;i++) {
            //	horRsp[i]=0;
            //else if (Math.abs(verRsp[i])> HORIZONTHRESHOLD/4)
            //	horRsp[i]=0;
            //else horRsp[i]=1;
            if (horRsp[i]>verRsp[i]&&horRsp[i]> HORIZONTHRESHOLD/2)
                horRsp[i]=1;
            else
                horRsp[i]=0;
        }

        ConnectComponent cc= new ConnectComponent();
        int[] ccl= cc.getProcessed(horRsp, d);	//connected component labels
        int maxLabel= cc.getMaxLabel();
        int[] ccw= getLonger(ccl, d, HORLINEWIDTHTHRSH, maxLabel);		//connected component width

        //int[] ccv= yi.util.ImageUtil.makeImageFromBinary(ccl);
        //int[] ccv= new int[ccl.length];
        //makeImageFromGray(ccl,ccv);
        //DisplayFrame f1= new DisplayFrame(ccv, w, h);
        //f1.show();

        int[] hrst= new int[d.width];
        for (int i=0;i<d.height;i++)
            for (int j=0;j<d.width;j++)
//                hrst[j]+= horRsp[i*d.width+j];
//                hrst[j]+= ccl[i*d.width+j];
                                if (ccl[i*d.width+j]>0) hrst[j]++;

        horRsp=verRsp=null;System.gc();

        int[][] rst={hrst,ccl,ccw};
        return rst;
    }

    public int[] getLonger(int[] labels, Dimension d, int threshold, int maxLabel)
    {
        int w=d.width, h=d.height;
        int[] min= new int[maxLabel+1];
        int[] max= new int[maxLabel+1];
        for (int x=0;x<w;x++)
                for (int y=0;y<h;y++)
                        max[labels[y*w+x]]=x;
        for (int x=w-1;x>=0;x--)
                for (int y=0;y<h;y++)
                        min[labels[y*w+x]]=x;
        for (int i=1; i<=maxLabel; i++) {
                if (max[i]-min[i]<threshold) min[i]=0;
                else min[i]=max[i]-min[i];
        }
        for (int i=0;i<labels.length;i++) {
                if (labels[i]==0) continue;
                if (min[labels[i]]==0) labels[i]=0;
        }
        return min;
    }

    int[] preProcess(int[] source, Dimension d)
    {
        // make intensity image
        int[] in= (new IntensityMaker()).getProcessed(source,d);
        if (sigma>0) {
            in= (new GaussianSmooth(sigma,1.0)).getProcessed(in, d);
        }
        return in;
    }

}