package yi.iu.processor.morph;

import yi.iu.processor.*;
import java.awt.Dimension;

public abstract class Morph extends yi.iu.processor.ImageProcessor
{
    public static final int BLOCK=0;
    public static final int DISK=1;
    int struct=DISK;
    int size=3;

    public Morph(int st, int s) {struct=st; size=s;}

    boolean[] getStruct()
    {
      return getStruct(struct, size);
    }

    public static boolean[] getStruct(int struct, int size) {
        boolean[] st=new boolean[size*size];
        if (struct==BLOCK) {
            for (int i=0;i<st.length;i++) st[i]=true;
        }
        else if (struct==DISK) {
            int r=(size-1)/2;
            for (int i=0;i<size;i++) {
                for (int j=0;j<size;j++) {
                    int temp=(i-r)*(i-r)+(j-r)*(j-r);
                    if (temp>r*r) st[i*size+j]=false;
                    else st[i*size+j]=true;
                }
            }
        }
        return st;
    }

    public static boolean[][] get2DStruct(int struct, int size) {
        boolean[][] st=new boolean[size][size];
        if (struct==BLOCK) {
            for (int i=0;i<size;i++) {
              for (int j=0;j<size;j++) {
                st[i][j]=true;
              }
            }
        }
        else if (struct==DISK) {
            int r=(size-1)/2;
            for (int i=0;i<size;i++) {
                for (int j=0;j<size;j++) {
                    int temp=(i-r)*(i-r)+(j-r)*(j-r);
                    if (temp>r*r) st[i][j]=false;
                    else st[i][j]=true;
                }
            }
        }
        return st;
    }

    public int[] getProcessedPseudoColor(int source[], Dimension d)
    {
        return null;
    }

    public void processOn(int[][] source) {
        if (source==null) {
            System.err.println("no source image to operate");
            return;
        }
        if (source[0]==null) {
            System.err.println("no source image to operate");
            return;
        }

        //change to 1-d array
        int h=source.length, w= source[0].length;
        int[] array= new int[h*w];
        int index=0;
        for (int y=0;y<h;y++)
            for (int x=0;x<w;x++) {
                array[index++]= source[y][x];
            }
        //call getProcessed
        int[] rst= getProcessed(array, new Dimension(w,h));
        //change the source to reflect the calculation
        index=0;
        for (int y=0;y<h;y++)
            for (int x=0;x<w;x++) {
                source[y][x]= rst[index++];
            }
        rst= null;
        System.gc();
    }

    /**
     * Filter out small regions.
     * @param cc_labels  the label data.  A label must be [0..max_label] or background
     *                   it will be changed after the function call
     * @param max_cc_label  the max value in data
     * @param size_threshold the threshold
     * @param background background label (could be negative)
     * @return cc_labels
     */
    public static int[] filterSmallRegions(int[] cc_labels, int max_cc_label, int size_threshold, int background) {
        // count component size
        int[] sizes = new int[max_cc_label + 1];
        int pnum = cc_labels.length;
        for (int i=0; i<pnum; i++) {
          if (cc_labels[i] == background) continue;
          sizes[cc_labels[i]]++;
        }

        // filter small component
        for (int i=0; i<=max_cc_label; i++) {
          if (sizes[i] < size_threshold) sizes[i] = background; // ok for background itself
          else sizes[i] = i;
        }
        for (int i=0; i<pnum; i++) cc_labels[i] = sizes[cc_labels[i]];
        yi.util.label.Label.sequential(cc_labels,null,true);
        return cc_labels;
    }
}