package active_contour;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.awt.image.WritableRaster;
import java.awt.image.Raster;
import java.lang.Cloneable;
import java.lang.reflect.Array;

import org.opencv.core.*;
import org.opencv.highgui.Highgui;
import org.opencv.imgproc.Imgproc;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Iterator;

/**
 * Metoda pre pracu s obrazmi
 * @author Branislav Hesko
 * @version 10/04/2015
 */
public class ImageProc extends Mat {
		
		// Inicializacia premennych
		private int cols;
		private int rows;
		Mat source;
		private ArrayList curve;
		private String file;
		private byte[] arrayImg;
		private Mat resultImg;
		private String fileToWrite;
		private int matrixSizeX,matrixSizeY,rowStart,rowEnd;
		private Mat resultImage;
	/*
	 * Konstruktor nacitajuci obraz a pocitajuci jeho parametre, vysku a sirku	
	 */
	public ImageProc(String file, String description) {
		System.out.println(description);
		
		
		System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
	    source = Highgui.imread(file, Highgui.CV_LOAD_IMAGE_GRAYSCALE);
	    source.convertTo(source, CvType.CV_8UC1);
		
	    rows = source.rows();
	    cols = source.cols();
	}
	
	/*
	 * Konstruktor zapisujuci krivku metody aktivnych kontur s pouzitim gradientu do originalneho obrazu
	 */
	public ImageProc(String origFile, String file, ArrayList curve) {
		// Nacitanie obrazu
		System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
		source = Highgui.imread(origFile, Highgui.CV_LOAD_IMAGE_GRAYSCALE);
		source.convertTo(source, CvType.CV_8UC1);
		Highgui.imwrite("origvpng.png", source);

		//Vlozenie bodov do obrazu
		this.curve = curve;
		this.file = file;
		arrayImg = new byte[source.cols()* source.rows()];
		source.get(0,0,arrayImg);
		insertPoints(curve,arrayImg);
		resultImg = new Mat(source.rows(),source.cols(),CvType.CV_8UC1);
		resultImg.put(0,0, arrayImg);
		
		// Zapis do suboru
		write(file, resultImg);
	}
	
	/*
	 * Konstruktor zapisujuci krivku z metody aktivnych kontur bez vyuzitia gradientu do obrazu
	 */
	public ImageProc(String origFile, String fileToWrite, Mat contour ,int rowStart,int rowEnd ,  int matrixSizeX, int matrixSizeY ) {
		this.fileToWrite  = fileToWrite;
		this.matrixSizeX = matrixSizeX;
		this.matrixSizeY = matrixSizeY;
		this.rowStart = rowStart;
		this.rowEnd = rowEnd;
		// Nacitanie obrazu
		System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
		source = Highgui.imread(origFile, Highgui.CV_LOAD_IMAGE_COLOR);
		source.convertTo(source, CvType.CV_8UC1);
		resultImage = new Mat(matrixSizeX,matrixSizeY,CvType.CV_8UC3);
		getSubMatrix(rowStart,rowEnd, matrixSizeX,matrixSizeY).copyTo(resultImage);
		
		//System.out.println("rozmery obr su " +resultImage.cols());
		int i,j;
		// Vyber rgb hodnoty farby, metoda toByte prevedie int premennu do byte
		byte[] colorL = new byte[]{0,toByte(250),0};
		
		// Zapis do obrazu jednotlivych bodov krivky
		for(i= 0;i< contour.rows(); i++) {
			for(j = 0; j< contour.cols(); j++) {
				if(contour.get(i, j)[0] > 0) {
					resultImage.put(i,j,colorL);
				}
			}
			
		}
		// Zapis do suboru
		write(fileToWrite, resultImage);
	}
	
	// Vrati vysledny obraz metoda aktivnych kontur s vyuzitim gradientu
	public Mat getResultImage() {
		return resultImg;
	}
	
	//Vrati vysledny obraz metoda aktivnych kontur bez vyuzitia gradientu
	public Mat getResultImageAcWe() {
		return resultImage;
	}
	
	/*
	 * Vlozi body do krivky, metoda aktivnych kontur s vyuzitim gradientu
	 */
	public void insertPoints(ArrayList curve, byte[] arrayImg) {
		int a;
		for(a = 0; a < curve.size();a++) {
			//System.out.println("Array: " + arrayImg[(int) curve.get(a)]);
			arrayImg[(int) curve.get(a)] = (byte) 255;
		}
	}
	
	/*
	 * Prevod cisla do byte
	 */
	public byte toByte(int i) {
		return (byte) i;
	}

	/*
	 * Zapis do suboru
	 */
	public void  write(String fileToW, Mat matToWrite) {
		Highgui.imwrite(fileToW, matToWrite);
	}
	
	/*
	 * Vrati riadok
	 */
	public int getRow(int var) {
		return var;
	}
	
	/*
	 * vrati stlpec
	 */
	public int getCol(int var) {
		return var;
	}
	
	/*
	 * Vrati pocet stlpcov
	 */
	public int getNumCols() {
		return cols;
	}
	
	/*
	 * Vrati pocet riadkov
	 */
	public int getNumRows() {
		return rows;
	}
	
	/*
	 * Vrati maticu obrazu ako vektor
	 */
	public double[] toArray() {
		double[] imgArray = new double[cols*rows];
		source.get(0,0,imgArray);
		return imgArray;
	}
	
	/*
	* eventualny zapis do konzole
	 */
	public String toString() {
		return "Tato trieda pracuje s obrazom";
	}
	
	/*
	 * Vrati maticu obrazu
	 */
	public Mat getMat() {
		return source;
	}

	/*
	 * Vrati vyrezany obraz
	 */
	public Mat getSubMatrix(int rowStart, int rowEnd, int matrixSizeX, int matrixSizeY) {
		return source.submat(rowStart, rowStart + matrixSizeX,rowEnd , rowEnd + matrixSizeY);
	}

	
	
	
}
