package yi.iu.processor.texture;

import java.awt.*;
import yi.iu.LawsAttrs;
import yi.iu.ui.*;
import yi.util.io.*;
import yi.iu.processor.channel.*;

/**
 * Class LawsMaker calculates the Law Texutre Energy Measures given an image.
 * This class is not changed after 1999-12-27, but I do think there are some
 * errors in this class.  For example, the image should be smoothed before the
 * calculation (Linda Shapiro, Computer Vision, Prentice Hall, 2001, p220-1).
 * I am preparing to write a new version (yi.iu.process.texture.law)
 *   - August 5th, 2002
 */
public class LawsMaker extends yi.iu.processor.channel.ChannelMaker
{
    static int CNV_KRNL_LGT= 3;
    static int PAD_LENGTH=(CNV_KRNL_LGT-1)/2;
    static public int ENER_PAD_LENGTH= 3;      //the energy on the center will be the mean of (2*ENER_PAD_LENGTH+1)^2 values
                                        //eg. ENER_PAD_LENGTH= 7 => block 15*15

    int L5[] = { 1,  4,  6,  4,  1};
    int E5[] = {-1, -2,  0,  2,  1};
    int S5[] = {-1,  0,  2,  0, -1};
    int W5[] = {-1,  2,  0, -2,  1};
    int R5[] = { 1, -4,  6, -4,  1};

    public int[] getProcessedPseudoColor(int[] source, Dimension d)
    {
        int h= d.height, w=d.width;
        int[][] info= new int[h*w][];
        int[][] las=getProcessed_ex(source, d);

        (new InfoFrame("laws", source, w, h, las)).show();
        return null;
    }

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

    public int[][] getProcessed_ex(int rgb[], Dimension d, int en_pad_len)
    {
        ENER_PAD_LENGTH= en_pad_len;
        return getProcessed_ex(rgb, d);
    }

    public int[][] getProcessed_ex(int rgb[], Dimension d)
    {
        int width=d.width, height=d.height;
            int size=width*height;

            //get the gray level image in the format of 2-D array
            int[] gray_1= (new CYMaker()).getProcessed(rgb, d);
            int[][] gray= yi.util.ImageUtil.oneD2twoD(gray_1, d);

            /*
            //calculate the convolution kernels
        calc_conv_kernels();

        //Pad the image on the four sides
                int[][] padded_img= pad_image(gray, PAD_LENGTH);
                //int[] pad_1= yi.util.ImageUtil.twoD2oneD(padded_img);
                //int[] temp= yi.util.ImageUtil.makeNewImageFromGray(pad_1);
                //(new DisplayFrame("padded",temp, padded_img[0].length, padded_img.length)).show();


            //Apply the convolution kernels to the image
                apply_conv_kernels_25(padded_img);
                System.err.println("apply done!");

                //Measure the texture energy for each one of the 25 result images
                text_energy_measure_25();

            //Combine the convolution kernels
                combine_conv_kernels();



                //Re-order the results
                return reorder_results();
                */
                return calc_laws(gray, ENER_PAD_LENGTH);
    }

    //return format:
    //[index_of_pixel][index_of_attribute]
    //index_of_pixel: [0..image_size]
    //index_of_attribute: [0..13]
    int[][] calc_laws(int[][] img, int ener_pad_length)
    {
            //calculate the convolution kernels
        calc_conv_kernels();
        int h=img.length, w=img[0].length;
        int[][] l5= new int[h][w],e5= new int[h][w], s5= new int[h][w], w5= new int[h][w], r5= new int[h][w];
        int[][] r1= new int[h][w], r2= new int[h][w];

        //int[][] e= new int[h][w];
        int[][] rst= new int[h*w][14];
        int y,x,index;
        ver_conv(l5, img, L5);
        ver_conv(e5, img, E5);
        ver_conv(s5, img, S5);
        ver_conv(w5, img, W5);
        ver_conv(r5, img, R5);
        //E5L5T[y][x] + L5E5T[y][x];
        hor_conv(r1, e5, L5);
        hor_conv(r2, l5, E5);
        combine_conv(r1,r2);
        //calc_en (e, r1, ener_pad_length);
        calc_en (rst, 0, r1, ener_pad_length);

        //S5L5T[y][x] + L5S5T[y][x];
        hor_conv(r1, s5, L5);
        hor_conv(r2, l5, S5);
        combine_conv(r1,r2);
        calc_en (rst, 1, r1, ener_pad_length);

        //W5L5T[y][x] + L5W5T[y][x];
        hor_conv(r1, w5, L5);
        hor_conv(r2, l5, W5);
        combine_conv(r1,r2);
        calc_en (rst, 2, r1, ener_pad_length);

        //R5L5T[y][x] + L5R5T[y][x];
        hor_conv(r1, r5, L5);
        hor_conv(r2, l5, R5);
        combine_conv(r1,r2);
        calc_en (rst, 3, r1, ener_pad_length);
        //S5E5T[y][x] + E5S5T[y][x];
        hor_conv(r1, s5, E5);
        hor_conv(r2, e5, S5);
        combine_conv(r1,r2);
        calc_en (rst, 4, r1, ener_pad_length);
        //W5E5T[y][x] + E5W5T[y][x];
        hor_conv(r1, w5, E5);
        hor_conv(r2, e5, W5);
        combine_conv(r1,r2);
        calc_en (rst, 5, r1, ener_pad_length);
        //R5E5T[y][x] + E5R5T[y][x];
        hor_conv(r1, r5, E5);
        hor_conv(r2, e5, R5);
        combine_conv(r1,r2);
        calc_en (rst, 6, r1, ener_pad_length);
        //W5S5T[y][x] + S5W5T[y][x];
        hor_conv(r1, w5, S5);
        hor_conv(r2, s5, W5);
        combine_conv(r1,r2);
        calc_en (rst, 7, r1, ener_pad_length);
        //R5S5T[y][x] + S5R5T[y][x];
        hor_conv(r1, r5, S5);
        hor_conv(r2, s5, R5);
        combine_conv(r1,r2);
        calc_en (rst, 8, r1, ener_pad_length);
        //R5W5T[y][x] + W5R5T[y][x];
        hor_conv(r1, r5, W5);
        hor_conv(r2, w5, R5);
        combine_conv(r1,r2);
        calc_en (rst, 9, r1, ener_pad_length);

        //E5E5TR[y][x] = E5E5T[y][x] * 2;
        hor_conv(r1, e5, E5);
        double_conv(r1);
        calc_en (rst, 10, r1, ener_pad_length);
        //S5S5TR[y][x] = S5S5T[y][x] * 2;
        hor_conv(r1, s5, S5);
        double_conv(r1);
        calc_en (rst, 11, r1, ener_pad_length);
        //W5W5TR[y][x] = W5W5T[y][x] * 2;
        hor_conv(r1, w5, W5);
        double_conv(r1);
        calc_en (rst, 12, r1, ener_pad_length);
        //R5R5TR[y][x] = R5R5T[y][x] * 2;
        hor_conv(r1, r5, R5);
        double_conv(r1);
        calc_en (rst, 13, r1, ener_pad_length);

        //OutputResult.outputResult("rst", rst);
        l5=e5=s5=w5=r5=r1=r2=null;
        System.gc();
        return rst;
    }

    void ver_conv(int[][] rst, int[][] input, int[] filter)
    {
            int h=input.length, w=input[0].length;
            int pad_len= (filter.length-1)/2;

            for (int y=0; y<h; y++) {
                    for (int x=0; x<w; x++) {
                            int aux = 0;
                            for (int i=-pad_len; i<=pad_len; i++) {
                                int index= y-i;
                                if (index<0) index= -index-1;
                                else if (index>=h) index= h+h-index-1;
                                    aux += filter[i+pad_len]*input[index][x];
                                }
                            rst[y][x] = aux;
                    }
            }
    }

    void hor_conv(int[][] rst, int[][] input, int[] filter)
    {
            int h=input.length, w=input[0].length;
            int pad_len= (filter.length-1)/2;

            for (int y=0; y<h; y++) {
                    for (int x=0; x<w; x++) {
                            int aux = 0;
                            for (int i=-pad_len; i<=pad_len; i++) {
                                int index= x-i;
                                if (index<0) index= -index-1;
                                else if (index>=w) index= w+w-index-1;
                                    aux += filter[i+pad_len]*input[y][index];
                                }
                            rst[y][x] = aux;
                    }
            }
    }

    void combine_conv(int[][] r1, int[][] r2)
    {
            int h=r1.length, w=r1[0].length;

            for (int y=0; y<h; y++) {
                    for (int x=0; x<w; x++) {
                            //r1[y][x]+=r2[y][x];
                            r1[y][x]=Math.abs(r1[y][x])+Math.abs(r2[y][x]);
                    }
            }
    }

    void double_conv(int[][] r)
    {
            int h=r.length, w=r[0].length;

            for (int y=0; y<h; y++) {
                    for (int x=0; x<w; x++) {
                            r[y][x]=Math.abs(r[y][x])*2;
                    }
            }
    }

    void calc_en (int[][] rst, int[][] input, int pad_len)
    {
            int h=input.length, w=input[0].length;
            int size=(2*pad_len+1)*(2*pad_len+1);

            for (int y=0; y<h; y++) {
                    for (int x=0; x<w; x++) {
                            int aux = 0;
                            for (int i=-pad_len; i<=pad_len; i++) {
                                int y_index= y-i;
                                if (y_index<0) y_index= -y_index-1;
                                else if (y_index>=h) y_index= h+h-y_index-1;
                                    //aux += filter[i+pad_len]*input[y][index];
                                    for (int j=-pad_len; j<=pad_len; j++)
                                    {
                                        int x_index= x-j;
                                    if (x_index<0) x_index= -x_index-1;
                                    else if (x_index>=w) x_index= w+w-x_index-1;
                                            aux += Math.abs(input[y_index][x_index]);
                                        }
                                }
                            rst[y][x] = aux/size;
                    }
            }
    }

    void calc_en (int[][] rst, int k, int[][] input, int pad_len)
    {
        if (pad_len<=1) return;
            int h=input.length, w=input[0].length;
            int size=(2*pad_len+1)*(2*pad_len+1);

            int index=0;
            for (int y=0; y<h; y++) {
                    for (int x=0; x<w; x++) {
                            int aux = 0;
                            for (int i=-pad_len; i<=pad_len; i++) {
                                int y_index= y-i;
                                if (y_index<0) y_index= -y_index-1;
                                else if (y_index>=h) y_index= h+h-y_index-1;
                                    //aux += filter[i+pad_len]*input[y][index];
                                    for (int j=-pad_len; j<=pad_len; j++)
                                    {
                                        int x_index= x-j;
                                    if (x_index<0) x_index= -x_index-1;
                                    else if (x_index>=w) x_index= w+w-x_index-1;
                                            aux += Math.abs(input[y_index][x_index]);
                                        }
                                }
                            rst[index++][k] = aux/size;
                    }
            }
    }

/*******************************************************************************
calculate the LAWS related staff
*******************************************************************************/

    /**** 25 2-D convolution kernels ***/
    int L5L5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int E5L5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int S5L5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int W5L5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int R5L5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];

    int L5E5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int E5E5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int S5E5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int W5E5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int R5E5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];

    int L5S5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int E5S5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int S5S5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int W5S5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int R5S5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];

    int L5W5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int E5W5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int S5W5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int W5W5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int R5W5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];

    int L5R5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int E5R5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int S5R5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int W5R5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];
    int R5R5[][]= new int[CNV_KRNL_LGT][CNV_KRNL_LGT];

    void calc_conv_kernels()
    {
            int i, j;

            for (i=0; i<CNV_KRNL_LGT; i++) {
                    for (j=0; j<CNV_KRNL_LGT; j++) {
                            L5L5[i][j] = L5[i] * L5[j];
                            E5L5[i][j] = E5[i] * L5[j];
                            S5L5[i][j] = S5[i] * L5[j];
                            W5L5[i][j] = W5[i] * L5[j];
                            R5L5[i][j] = R5[i] * L5[j];

                            L5E5[i][j] = L5[i] * E5[j];
                            E5E5[i][j] = E5[i] * E5[j];
                            S5E5[i][j] = S5[i] * E5[j];
                            W5E5[i][j] = W5[i] * E5[j];
                            R5E5[i][j] = R5[i] * E5[j];

                            L5S5[i][j] = L5[i] * S5[j];
                            E5S5[i][j] = E5[i] * S5[j];
                            S5S5[i][j] = S5[i] * S5[j];
                            W5S5[i][j] = W5[i] * S5[j];
                            R5S5[i][j] = R5[i] * S5[j];

                            L5W5[i][j] = L5[i] * W5[j];
                            E5W5[i][j] = E5[i] * W5[j];
                            S5W5[i][j] = S5[i] * W5[j];
                            W5W5[i][j] = W5[i] * W5[j];
                            R5W5[i][j] = R5[i] * W5[j];

                            L5R5[i][j] = L5[i] * R5[j];
                            E5R5[i][j] = E5[i] * R5[j];
                            S5R5[i][j] = S5[i] * R5[j];
                            W5R5[i][j] = W5[i] * R5[j];
                            R5R5[i][j] = R5[i] * R5[j];
                    }
            }
    }






/******************************************************************************
The functions below do not care about the memory and speed
But it is good to get the basic idea of Laws
/*****************************************************************************/
    /*********** 25 TEM images **********/
    int L5L5T[][]= null;
    int E5L5T[][]= null;
    int S5L5T[][]= null;
    int W5L5T[][]= null;
    int R5L5T[][]= null;

    int L5E5T[][]= null;
    int E5E5T[][]= null;
    int S5E5T[][]= null;
    int W5E5T[][]= null;
    int R5E5T[][]= null;

    int L5S5T[][]= null;
    int E5S5T[][]= null;
    int S5S5T[][]= null;
    int W5S5T[][]= null;
    int R5S5T[][]= null;

    int L5W5T[][]= null;
    int E5W5T[][]= null;
    int S5W5T[][]= null;
    int W5W5T[][]= null;
    int R5W5T[][]= null;

    int L5R5T[][]= null;
    int E5R5T[][]= null;
    int S5R5T[][]= null;
    int W5R5T[][]= null;
    int R5R5T[][]= null;

    /*****14 combined TEM images ********/
    int E5L5TR[][]= null;
    int S5L5TR[][]= null;
    int W5L5TR[][]= null;
    int R5L5TR[][]= null;

    int E5E5TR[][]= null;
    int S5E5TR[][]= null;
    int W5E5TR[][]= null;
    int R5E5TR[][]= null;

    int S5S5TR[][]= null;
    int W5S5TR[][]= null;
    int R5S5TR[][]= null;

    int W5W5TR[][]= null;
    int R5W5TR[][]= null;

    int R5R5TR[][]= null;

    /**********************************************************
    *		Function: apply_conv_kernels_1
    **********************************************************/
    int[][] apply_conv_kernel_1(int input[][], int pad_len, int kernel[][])
    {
            int ver_size= input.length-pad_len-pad_len;
            int hor_size= input[0].length-pad_len-pad_len;
            int output[][]= new int[ver_size][hor_size];

            int y, x, i, j, aux;

            for (y=pad_len; y<(ver_size+pad_len); y++) {
                    for (x=pad_len; x<(hor_size+pad_len); x++) {
                            aux = 0;
                            for (i=-pad_len; i<=pad_len; i++)
                                    for (j=-pad_len; j<=pad_len; j++)
                                            aux += kernel[i+pad_len][j+pad_len]*input[y-i][x-j];
                            output[y-pad_len][x-pad_len] = aux;
                    }
            }
            return output;
    }

    int[][] apply_conv_kernel_1_new(int input[][], int pad_len, int k1[], int k2[])
    {
            int ver_size= input.length-pad_len-pad_len;
            int hor_size= input[0].length-pad_len-pad_len;
            int output[][]= new int[ver_size][hor_size];

            int y, x, i, j, aux;

            int[][] temp= new int[ver_size][hor_size+pad_len+pad_len];

            for (y=pad_len; y<(ver_size+pad_len); y++) {
                    for (x=0; x<(hor_size+pad_len+pad_len); x++) {
                            aux = 0;
                            for (i=-pad_len; i<=pad_len; i++)
                                    aux += k1[i+pad_len]*input[y-i][x];
                            temp[y-pad_len][x] = aux;
                    }
            }

            for (y=0; y<ver_size; y++) {
                    for (x=pad_len; x<(hor_size+pad_len); x++) {
                            aux = 0;
                                    for (j=-pad_len; j<=pad_len; j++)
                                            aux += k2[j+pad_len]*temp[y][x-j];
                            output[y][x-pad_len] = aux;
                    }
            }
            return output;
    }

    boolean equal (int[][] a, int[][] b)
    {
        int h=a.length,w=a[0].length;
        boolean e=true;
        for (int y=0;y<h;y++) for (int x=0;x<w;x++) if (a[y][x]!=b[y][x]) e=false;
        return e;
    }

    /**********************************************************
    *		Function: apply_conv_kernels_25
    **********************************************************/
    void apply_conv_kernels_25(int[][] padded_img)
    {
            L5L5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, L5L5);
            E5L5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, E5L5);
            int[][] temp=apply_conv_kernel_1_new(padded_img, PAD_LENGTH, E5, L5);
            if (equal(E5L5T,temp)) {System.err.println("E5L5 OK");}


            S5L5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, S5L5);
            W5L5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, W5L5);
            R5L5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, R5L5);

            L5E5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, L5E5);
            E5E5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, E5E5);
            S5E5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, S5E5);
            W5E5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, W5E5);
            R5E5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, R5E5);

            L5S5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, L5S5);
            E5S5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, E5S5);
            S5S5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, S5S5);
            W5S5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, W5S5);
            R5S5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, R5S5);

            L5W5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, L5W5);
            E5W5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, E5W5);
            S5W5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, S5W5);
            W5W5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, W5W5);
            R5W5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, R5W5);
        temp=apply_conv_kernel_1_new(padded_img, PAD_LENGTH, R5, W5);
            if (equal(R5W5T,temp)) {System.err.println("E5L5 OK");}

            L5R5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, L5R5);
            E5R5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, E5R5);
            S5R5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, S5R5);
            W5R5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, W5R5);
            R5R5T= apply_conv_kernel_1(padded_img, PAD_LENGTH, R5R5);

            OutputResult.outputResult("E5L5", E5L5T);
            OutputResult.outputResult("temp", temp);
            OutputResult.outputResult("L5E5", L5E5T);
    }

    /**********************************************************
    *		Function: pad_image
    **********************************************************/
    int[][] pad_image(int img[][], int pad_len)
    {
            int ver_size= img.length;
            int hor_size= img[0].length;
            int[][] padded_img= new int[ver_size+pad_len+pad_len][hor_size+pad_len+pad_len];
            int y, x, i;

            for (y=0; y<ver_size; y++) {
                    for (x=0; x<hor_size; x++) {
                            /* Copy the original image */
                            padded_img[y+pad_len][x+pad_len] =
                                    img[y][x];

                            /* Pad the TOP edge */
                            if (y == 0) {
                                    for (i=0; i<pad_len; i++)
                                            padded_img[i][x+pad_len] =
                                                    img[pad_len-i-1][x];
                            }
                            /* Pad the LEFT edge */
                            if (x == 0) {
                                    for (i=0; i<pad_len; i++)
                                            padded_img[y+pad_len][i] =
                                                    img[y][pad_len-i-1];
                            }
                            /* Pad the BOTTOM edge */
                            if (y == ver_size-1) {
                                    for (i=0; i<pad_len; i++)
                                            padded_img[ver_size+pad_len+i][x+pad_len] =
                                                    img[ver_size-i-1][x];
                            }
                            /* Pad the RIGHT edge */
                            if (x == hor_size-1) {
                                    for (i=0; i<pad_len; i++)
                                            padded_img[y+pad_len][hor_size+pad_len+i] =
                                                    img[y][hor_size-i-1];
                            }
                    }
            }

            /* Do the corners */

            for (y=0; y<pad_len; y++) {
                    for (x=0; x<pad_len; x++) {

                            /* Upper left hand corner */
                            padded_img[y][x] = img[pad_len-y-1][pad_len-x-1];

                            /* Upper right hand corner */
                            padded_img[y][x+hor_size+pad_len] =
                                    img[pad_len-y-1][hor_size-x-1];

                            /* Lower left hand corner */
                            padded_img[y+ver_size+pad_len][x] =
                                    img[ver_size-y-1][pad_len-x-1];

                            /* Lower right hand corner */
                            padded_img[y+ver_size+pad_len][x+hor_size+pad_len] =
                                    img[ver_size-y-1][hor_size-x-1];
                    }
            }
            return padded_img;
    }

    /**********************************************************
    *		Function: text_energy_measure_1
    **********************************************************/
    int[][] text_energy_measure_1(int input[][], int pad_len)
    {
            int ver_size= input.length-pad_len-pad_len;
            int hor_size= input[0].length-pad_len-pad_len;
            int output[][]= new int[ver_size][hor_size];

        int y, x, i, j, aux;

            for (y=pad_len; y<(ver_size+pad_len); y++)
                    for (x=pad_len; x<(hor_size+pad_len); x++) {
                            aux = 0;
                            for (i=-pad_len; i<=pad_len; i++)
                                    for (j=-pad_len; j<=pad_len; j++)
                                            aux += Math.abs(input[y-i][x-j]);
                            output[y-pad_len][x-pad_len] = aux;
                    }
                return output;
    }

    /**********************************************************
    *		Function: text_energy_measure_25
    **********************************************************/
    void text_energy_measure_25()
    {
            int[][] padded_img;
            padded_img= pad_image(L5L5T, ENER_PAD_LENGTH);
            L5L5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(E5L5T, ENER_PAD_LENGTH);
            E5L5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(S5L5T, ENER_PAD_LENGTH);
            S5L5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(W5L5T, ENER_PAD_LENGTH);
            W5L5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(R5L5T, ENER_PAD_LENGTH);
            R5L5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);

            padded_img= pad_image(L5E5T, ENER_PAD_LENGTH);
            L5E5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(E5E5T, ENER_PAD_LENGTH);
            E5E5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(S5E5T, ENER_PAD_LENGTH);
            S5E5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(W5E5T, ENER_PAD_LENGTH);
            W5E5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(R5E5T, ENER_PAD_LENGTH);
            R5E5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);

            padded_img= pad_image(L5S5T, ENER_PAD_LENGTH);
            L5S5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(E5S5T, ENER_PAD_LENGTH);
            E5S5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(S5S5T, ENER_PAD_LENGTH);
            S5S5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(W5S5T, ENER_PAD_LENGTH);
            W5S5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(R5S5T, ENER_PAD_LENGTH);
            R5S5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);

            padded_img= pad_image(L5W5T, ENER_PAD_LENGTH);
            L5W5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(E5W5T, ENER_PAD_LENGTH);
            E5W5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(S5W5T, ENER_PAD_LENGTH);
            S5W5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(W5W5T, ENER_PAD_LENGTH);
            W5W5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
        padded_img= pad_image(R5W5T, ENER_PAD_LENGTH);
            R5W5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);

            padded_img= pad_image(L5R5T, ENER_PAD_LENGTH);
            L5R5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(E5R5T, ENER_PAD_LENGTH);
            E5R5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(S5R5T, ENER_PAD_LENGTH);
            S5R5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(W5R5T, ENER_PAD_LENGTH);
            W5R5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);
            padded_img= pad_image(R5R5T, ENER_PAD_LENGTH);
            R5R5T= text_energy_measure_1(padded_img, ENER_PAD_LENGTH);

    }

    /**********************************************************
    *		Function: combine_conv_kernel
    **********************************************************/
    void combine_conv_kernels()
    {
            int ver_size= E5L5T.length;
            int hor_size= E5L5T[0].length;

            E5L5TR= new int[ver_size][hor_size];
            S5L5TR= new int[ver_size][hor_size];
            W5L5TR= new int[ver_size][hor_size];
            R5L5TR= new int[ver_size][hor_size];
            S5E5TR= new int[ver_size][hor_size];
            W5E5TR= new int[ver_size][hor_size];
            R5E5TR= new int[ver_size][hor_size];
            W5S5TR= new int[ver_size][hor_size];
            R5S5TR= new int[ver_size][hor_size];
            R5W5TR= new int[ver_size][hor_size];

            E5E5TR= new int[ver_size][hor_size];
            S5S5TR= new int[ver_size][hor_size];
            W5W5TR= new int[ver_size][hor_size];
            R5R5TR= new int[ver_size][hor_size];

            int x, y; /* Loop control */

            for (y=0; y<ver_size; y++) {
                    for (x=0; x<hor_size; x++) {
                            E5L5TR[y][x] = E5L5T[y][x] + L5E5T[y][x];
                            S5L5TR[y][x] = S5L5T[y][x] + L5S5T[y][x];
                            W5L5TR[y][x] = W5L5T[y][x] + L5W5T[y][x];
                            R5L5TR[y][x] = R5L5T[y][x] + L5R5T[y][x];
                            S5E5TR[y][x] = S5E5T[y][x] + E5S5T[y][x];
                            W5E5TR[y][x] = W5E5T[y][x] + E5W5T[y][x];
                            R5E5TR[y][x] = R5E5T[y][x] + E5R5T[y][x];
                            W5S5TR[y][x] = W5S5T[y][x] + S5W5T[y][x];
                            R5S5TR[y][x] = R5S5T[y][x] + S5R5T[y][x];
                            R5W5TR[y][x] = R5W5T[y][x] + W5R5T[y][x];

                            E5E5TR[y][x] = E5E5T[y][x] * 2;
                            S5S5TR[y][x] = S5S5T[y][x] * 2;
                            W5W5TR[y][x] = W5W5T[y][x] * 2;
                            R5R5TR[y][x] = R5R5T[y][x] * 2;
                    }
            }

            return;
    }

    /**********************************************************
    *		Function: reorder_results
    **********************************************************/
    LawsAttrs[][] reorder_results()
    {
            int ver_size= E5L5TR.length;
            int hor_size= E5L5TR[0].length;
            LawsAttrs[][] las= new LawsAttrs[ver_size][hor_size];

            int x, y; /* Loop control */

            for (y=0; y<ver_size; y++) {
                    for (x=0; x<hor_size; x++) {
                        las[y][x]= new LawsAttrs (
                                E5L5TR[y][x],
                                S5L5TR[y][x],
                                W5L5TR[y][x],
                                R5L5TR[y][x],
                                S5E5TR[y][x],
                                W5E5TR[y][x],
                                R5E5TR[y][x],
                                W5S5TR[y][x],
                                R5S5TR[y][x],
                                R5W5TR[y][x],

                                E5E5TR[y][x],
                                S5S5TR[y][x],
                                W5W5TR[y][x],
                                R5R5TR[y][x]);
                        }
            }

        L5L5T=
        E5L5T=
        S5L5T=
        W5L5T=
        R5L5T=

        L5E5T=
        E5E5T=
        S5E5T=
        W5E5T=
        R5E5T=

        L5S5T=
        E5S5T=
        S5S5T=
        W5S5T=
        R5S5T=

        L5W5T=
        E5W5T=
        S5W5T=
        W5W5T=
        R5W5T=

        L5R5T=
        E5R5T=
        S5R5T=
        W5R5T=
        R5R5T=

        E5L5TR=
        S5L5TR=
        W5L5TR=
        R5L5TR=

        E5E5TR=
        S5E5TR=
        W5E5TR=
        R5E5TR=

        S5S5TR=
        W5S5TR=
        R5S5TR=

        W5W5TR=
        R5W5TR=

        R5R5TR=null;
        System.gc();

            return las;
    }

}