/**********************************************************************************************//**
 * @file	CPU_Func_Library.h
 *
 * @author	Tomas Bravenec
 * 			
 * @brief	Declares the CPU function library class.
 **************************************************************************************************/

#ifndef CPU_FUNC_LIBRARY
#define CPU_FUNC_LIBRARY

typedef int filter_type[6][3][3];

using namespace System;

/**********************************************************************************************//**
 * @class	Cluster
 *
 * @brief	Supporting class for K-Means Clustering method.
 *
 * @author	Tomas Bravenec
 **************************************************************************************************/
class Cluster
{
public:
	void randomizeCentroid();
	void setCentroid(BYTE blue, BYTE Green, BYTE Red);
	void recalculateCentroids();
	void clearValues();
	void addRedValue(BYTE value) { sumRed += value; }
	void addBlueValue(BYTE value) { sumBlue += value; }
	void addGreenValue(BYTE value) { sumGreen += value; }
	void increaseCount() { count++; }
public:
	// Center values of a cluster
	BYTE centroidRed;
	BYTE centroidBlue;
	BYTE centroidGreen;

	// Maximum number of sum of pixel colors	18 446 744 073 709 551 615
	UInt64 sumRed;
	UInt64 sumBlue;
	UInt64 sumGreen;

	// Maximum number of subpixels in image					 4 294 967 295
	UInt32 count;
};

/**********************************************************************************************//**
 * @class	ImageProcessingCPU
 *
 * @brief	Class wrapping all CPU related image processing methods and data.
 *
 * @author	Tomas Bravenec
 **************************************************************************************************/
class ImageProcessingCPU
{
public:
	ImageProcessingCPU();
	~ImageProcessingCPU();

	// converts 24bpp RGB image to 8bpp grayscale image
	static void RGB2Gray(array<Byte>^ rgb, array<Byte, 2>^ gray, int height, int width, int stride, int threads);

	// converts 8bpp grayscale to 24bpp grayscale using 24bpp RGB (8bpp grayscale can not be displayed)
	static void Gray2RGB(array<Byte>^ rgb, array<Byte, 2>^ gray, int height, int width, int stride, int threads);

	// detects edges in 8bpp grayscale image
	// type - filter used for edge detection - 0: Sobel, 1: Prewitt, 2: Kirsch
	static void edgeDetection(array<Byte, 2>^ gray, array<Byte, 2>^ edge, int filter, int threads);

	// functions responsible for thresholding of grayscale image after edge detection
	static void thresholdEdge(array<Byte, 2>^ image, double threshold, int threads);

	// functions responsible for thresholding of grayscale image
	static void threshold(array<Byte, 2>^ image, double top, double bottom, int type, int threads);

	// function for conversion of grayscale image to negative
	static void negative(array<Byte, 2>^ image, int threads);

	// function for brightness adjustion
	static void brightness(array<Byte, 2>^ image, int brightness, int threads);

	// function for getting histogram data of grayscale image
	static void histData(array<Byte, 2>^ gray, array<double>^ hist);

	// function for running whole kmeans method on RGB image
	int kmeans(array<Byte>^ rgb, array<Byte>^ clustered, BYTE k, int maxIterations, int height, int width, int stride, int threads);

private:
	void init(int k);
	void init(int k, int iterations);
	void setMaxIterations(int iterations);
	void iterate(array<Byte>^ rgb, array<Byte>^ clustered, int height, int width, int stride, int threads);
	void newToOld();
	bool checkConvergence();
	void recalculateCentroids();
	Cluster *newCluster;
	Cluster *oldCluster;
	int clusterCount;
	int maxIterations;
};

#endif // CPU_FUNC_LIBRARY