//@author Martynas Brašiškis, Informatikos 1 grupė, 4 kursas

//Skeletizuoja paveiksliuką Zhang-Suen algoritmu. Reikia kviesti statinį metodą skeletizuoti(int[][] paveikslelis)
//Objekto kurti nereikia. Metodui skeletizuoti paduodamas ir gaunamas kaip rezultatas dvimatis int masyvas.
//masyvo reikšmės: 0 - fono spalva (juoda), visos kitos reikšmės bus priskiriamos figūrai.

public class ZhangSuen {
	
private ZhangSuen() {}
	
public static int[][] skeletizuoti(int[][] paveikslelis)
	{
	//skeletizuoja paveiksliuką Zhang-Suen algoritmu
	
	int rows = paveikslelis[0].length;
	int columns = paveikslelis.length;
	boolean rado = true;
	int tarpinis[][] = new int[columns][rows];
	int tarpinis2[][] = new int[columns][rows];
	int[][] naujas_pav = new int[columns][rows];
	
	for (int y=0; y<rows; y++)
        for (int x=0; x<columns; x++)
        	tarpinis[x][y] = paveikslelis[x][y];
	
	
	while (rado)
		{ 
	    rado = false;
	        
	    //pirmasis pociklis
	    for (int y=0; y<rows; y++)
	            for (int x=0; x<columns; x++)
	            	{
	            	tarpinis2[x][y] = tarpinis[x][y];
	                if (tarpinis[x][y] != 0)
	                	{
	                	int[] aplinka = generuoti_aplinka(tarpinis, x, y);
	                    if ((aplinka[2]*aplinka[4]*aplinka[6] == 0) && (aplinka[4]*aplinka[6]*aplinka[0] == 0))
	                    	{
	                    	if (dvi_salygos(aplinka))
	                           {
	                           rado = true;
	                           tarpinis2[x][y] = 0;
	                           }
	                    	}
	                    }
	               }

	   //antrasis pociklis
	   for (int y=0; y<rows; y++)
	        for (int x=0; x<columns; x++)
	        	{ 
	        	naujas_pav[x][y] = tarpinis2[x][y];
	                if (naujas_pav[x][y] != 0)
	                	{
	                	int[] aplinka = generuoti_aplinka(tarpinis2, x, y);
	                    if ((aplinka[2]*aplinka[0]*aplinka[6] == 0) && (aplinka[4]*aplinka[2]*aplinka[0] == 0))
	                    	{
	                    	if (dvi_salygos(aplinka))
	                    	   {
	                    	   rado = true;
	                           naujas_pav[x][y] = 0;
	                    	   }
	                    	}
	                	}
	        	}
	    int[][] apsikeitimui = tarpinis;    
	    tarpinis = naujas_pav;
	    naujas_pav = apsikeitimui;
		}
	return naujas_pav;
	}

private static int[] generuoti_aplinka(int[][] paveikslelis, int x, int y)
	{ //generuoja masyvą su pikselio (kurio koordinatės x,y) kaimynais         
    int[] aplinka = new int[8];
    aplinka[0] = grazink_spalva(paveikslelis,x-1,y);
    aplinka[1] = grazink_spalva(paveikslelis, x-1, y-1);
    aplinka[2] = grazink_spalva(paveikslelis, x, y-1);
    aplinka[3] = grazink_spalva(paveikslelis, x+1, y-1);
    aplinka[4] = grazink_spalva(paveikslelis, x+1, y);
    aplinka[5] = grazink_spalva(paveikslelis, x+1, y+1);
    aplinka[6] = grazink_spalva(paveikslelis, x, y+1);
    aplinka[7] = grazink_spalva(paveikslelis, x-1, y+1);
    return aplinka;
	}

private static int grazink_spalva(int[][] paveikslelis, int x, int y)
	{ //grąžina atitinkamo pikselio spalvą, arba 0, jei pikselis išlenda už paveikslėlio ribų
	int rows = paveikslelis[0].length;
	int columns = paveikslelis.length;
	int spalva;
    if ((x >= columns) || (x<0) || (y >= rows) || (y<0))
        spalva = 0;
        else spalva = paveikslelis[x][y];
	return spalva;
	}

private static boolean dvi_salygos(int[] aplinka)
	{
	//grąžina true, jei pikselis ir jo aplinka tenkina pirmas 2 
	 //Zhang-Suen skeletizavimo sąlygas, false kitu atveju

    int uzpildytiKaimynai = 0;
    int pasikeitimai = 0;
    int buves = aplinka[7];
    for (int k=0; k<8; k++)
    	{
    	if (aplinka [k] != 0)  
           uzpildytiKaimynai++; //skaičiuojam 1 sąlygai
        if ((buves == 0) && (aplinka[k] != 0))
            pasikeitimai++;  //skaičiuojam 2 sąlygai
        buves = aplinka[k];
    	}
    boolean tenkina;
    if ((pasikeitimai == 1) && (uzpildytiKaimynai > 1) && (uzpildytiKaimynai < 6))
        tenkina = true;
    else tenkina = false;
    return tenkina;
	}
}