// PixelArray.cpp: implementation of the CPixelArray class.
//
//////////////////////////////////////////////////////////////////////

/** \file PixelArray.cpp
	\brief implementace třídy CPixelArray
*/

//MRXXX pokus o odchytnutí memory leaků

#include "stdafx.h"


#include "PixelArray.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
//#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(CPixelArray, CObject)

CPixelArray::CPixelArray()
{
	TRACE("Entering CPixelArray default constructor\n");
	
	m_width = 0;
	m_height = 0;
	m_depth = 0;

	m_dat = NULL;
	m_temp = NULL;


}

CPixelArray::CPixelArray(int clmns, int rws, int depth)
{
	TRACE("Entering CPixelArray constructor\n");

	m_width = clmns;
	m_height = rws;
	m_depth = depth;

	m_center.X = (float)m_width/2;
	m_center.Y = (float)m_height/2;

	m_dat = AllocMems(m_width,m_height,m_depth);
}

CPixelArray::CPixelArray(char path[])
{
	TRACE("Entering CPixelArray path constructor\n");
	TRACE("Path = %s\n", path);

	m_dat = NULL;

	Load(path);
}

CPixelArray::CPixelArray(const CPixelArray &pa)
{
	m_center = pa.m_center;
	m_width = pa.m_width;
	m_height = pa.m_width;
	m_depth = pa.m_depth;

	int x,y,k;

	m_dat = (double***) malloc (m_depth * sizeof(double**));
	
	for(k=0;k<m_depth;k++)
	{
		m_dat[k]= (double**) malloc(m_height * sizeof(double*));	
	}
	for(k=0;k<m_depth;k++)
		for(y=0;y<m_height;y++) 
		{
			m_dat[k][y] = (double*) malloc(m_width * sizeof(double));
		}	

	for(k = 0; k < m_depth; k++)
		for(y = 0; y < m_height; y++)
			for(x = 0; x < m_width; x++)
				m_dat[k][y][x] = pa.m_dat[k][y][x];

	
}

CPixelArray & CPixelArray::operator=(const CPixelArray &pa)
{
	if(this == &pa)
		return *this;

/*MR	m_center = pa.m_center;  // tady by to asi být nemělo
	m_width = pa.m_width;
	m_height = pa.m_width;
	m_depth = pa.m_depth;    MR*/

	int x,y,k;

	for(k=0;k<m_depth;k++)  
		for(y=0; y<m_height; y++)
			delete[] m_dat[k][y];

	for(k=0; k<m_depth; k++)
		delete[] m_dat[k];
	delete[] m_dat;

    m_center = pa.m_center;
	m_width = pa.m_width;
	m_height = pa.m_width;
	m_depth = pa.m_depth;


	m_dat = (double***) malloc (m_depth * sizeof(double**));
	
	for(k=0;k<m_depth;k++)
	{
		m_dat[k]= (double**) malloc(m_height * sizeof(double*));	
	}
	for(k=0;k<m_depth;k++)
		for(y=0;y<m_height;y++) 
		{
			m_dat[k][y] = (double*) malloc(m_width * sizeof(double));
		}	

	for(k = 0; k < m_depth; k++)
		for(y = 0; y < m_height; y++)
			for(x = 0; x < m_width; x++)
				m_dat[k][y][x] = pa.m_dat[k][y][x];

 return *this;
}

CPixelArray::~CPixelArray()
{
	if(m_dat != NULL) 	DeallocMem();
}


double*** CPixelArray::AllocMems(int colmns,int rows,int depth)
{
	TRACE("Allocating memory %d x %d x %d\n", colmns, rows, depth);
	
	int i;
//	m_dat = (double***) malloc (depth * sizeof(double**));
	m_dat = (double***) new double**[depth];


	//if (m_data==NULL)
	//	MessageBox(NULL, "Out of memory", "Error", MB_OK);//hlaska nedostatek pameti
	//
	for(i=0;i<depth;i++)
	{
//		m_dat[i]= (double**) malloc(rows * sizeof(double*));	
		m_dat[i] = (double**) new double*[rows];	
		//if (m_data[i]==NULL)
		//	MessageBox(NULL, "Out of memory", "Error", MB_OK);//hlaska nedostatek pameti
	}
	for(i=0;i<depth;i++)
		for(int j=0;j<rows;j++) 
		{
//			m_dat[i][j] = (double*) malloc(colmns * sizeof(double));
			m_dat[i][j] = (double*) new double[colmns];

			//if (m_data[i][j]==NULL)
			//	//MessageBox(NULL, "Out of memory", "Error", MB_OK);//hlaska nedostatek pameti
		}	
	TRACE("Allocating done\n");
	return m_dat;

}

void CPixelArray::DeallocMem()
{
 	TRACE("Deallocating memory %d x %d x %d\n", m_width, m_height, m_depth);

#ifdef _DEBUG
	Dump(afxDump);
#endif // _DEBUG

	int i;

	for(i=0;i<m_depth;i++)  
		for(int j=0; j<m_height; j++)
			delete[] m_dat[i][j];

	for(i=0; i<m_depth; i++)
		delete[] m_dat[i];
	delete[] m_dat;

	m_dat = NULL;

	TRACE("Deallocating done\n");
}

void CPixelArray::Create(int colmns, int rws, int depth)
{
	//MR tady by měl být přepis dat z hlavičky do interních proměnných objektu
	m_dat = AllocMems(colmns,rws,depth);
}

void CPixelArray::Destroy()
{
	DeallocMem();
}

bool CPixelArray::Load(const char* path)
{/*MRXXX
	IplImage* img = 0; 
  int height,width,step,channels;
  uchar *data;
  int i,j,k;

    // load an image  
  img=cvLoadImage("splash.bmp",-1);
  if(!img){
    printf("Could not load image file: splash.bmp\n");
    exit(0);
  }

  // get the image data
  height    = img->height;
  width     = img->width;
  step      = img->widthStep;
  channels  = img->nChannels;
  data      = (uchar *)img->imageData;
  printf("Processing a %dx%d image with %d channels\n",height,width,channels); 

  // create a window
  cvNamedWindow("mainWin", CV_WINDOW_AUTOSIZE); 
  cvMoveWindow("mainWin", 100, 100);

  // invert the image
  for(i=0;i<height;i++) for(j=0;j<width;j++) for(k=0;k<channels;k++)
    data[i*step+j*channels+k]=255-data[i*step+j*channels+k];

  // show the image
  cvShowImage("mainWin", img );

  // wait for a key
  cvWaitKey(0);

  // release the image
  cvReleaseImage(&img );
  return 0;*/
	 //MRXXX nemá tady to destroy být? (bylo zakomentované)
	//uvolneni pameti, pokud je jiz alokovana
	//if (m_data != NULL)
		//Destroy();

	//cvLoadImage( "", -1);
	IplImage* temp = cvLoadImage( path, -1 );
	if(temp == NULL)
		return false;

	unsigned char *dataPix = reinterpret_cast<unsigned char *>(temp->imageData);
	Create(temp->width,temp->height,temp->nChannels);

	m_height = temp->height;
	m_width = temp->width;
	m_depth = temp->nChannels;

	m_center.X = (float)m_width/2;
	m_center.Y = (float)m_height/2;


	for (int i =0; i<temp->height; i++)
	{
		for (int j=0; j<temp->width; j++)
			for (int k=0; k<temp->nChannels; k++)
				m_dat[k][i][j] = dataPix[m_depth*j+k];
			
		dataPix += temp->widthStep;
	}

	cvReleaseImage(&temp);
	return true;

}

int CPixelArray::Save(const char* path)
{
	int i,j,k;
	int retCode;
	CvSize velikost;
	velikost.width = m_width;
	velikost.height = m_height;
	IplImage* temp = cvCreateImage(velikost, IPL_DEPTH_8U, m_depth);

	unsigned char *dataPix = reinterpret_cast<unsigned char *>(temp->imageData);
	
	for (i =0; i<temp->height; i++)
	{
		for (j=0; j<temp->width; j++)
			for (k=0; k<temp->nChannels; k++)
				dataPix[m_depth*j+k] = (unsigned char) m_dat[k][i][j];
			
		dataPix += temp->widthStep;
	}
	retCode = cvSaveImage( path, temp);
	cvReleaseImage(&temp);

	return retCode;
}


void CPixelArray::Display(const char* name)
{
	CvSize velikost;

	velikost.width = m_width;
	velikost.height = m_height;
	m_temp = cvCreateImage(velikost, IPL_DEPTH_8U, m_depth);
	unsigned char *dataPix = reinterpret_cast<unsigned char *>(m_temp->imageData); 

	for (int y =0; y<m_temp->height; y++)
	{
		for (int x=0; x<m_temp->width; x++)
			for (int k=0; k<m_temp->nChannels; k++)
				dataPix[m_depth*x+k] = (unsigned char) m_dat[k][y][x];
			
		dataPix += m_temp->widthStep;
	}

	
	cvNamedWindow( name, 0);
	cvResizeWindow( name, m_width, m_height);
	cvShowImage( name, m_temp );

	cvWaitKey();

	cvReleaseImage(&m_temp);
	cvDestroyWindow(name);
}


void CPixelArray::Clear()
{
	int x,y,k;

	for(k = 0; k < m_depth; k++)
		for(y = 0; y < m_height; y++)
			for(x = 0; x < m_width; x++)
				m_dat[k][y][x] = 0;
}


CStructures::iPoint CPixelArray::GetBasePosition(CStructures::iPoint virtualPosition)
{
	CStructures::iPoint basePoint; //MR možná by měl být float

	basePoint.X = (int)(m_center.X + virtualPosition.X); //MR aby nehlásila konverze warning
	basePoint.Y = (int)(m_center.Y - virtualPosition.Y); //MR aby nehlásila konverze warning
	if(basePoint.Y == m_height)
		basePoint.Y--;
	
	if(basePoint.Y < 0)
		int h = 6;
	
	return basePoint;
}

void CPixelArray::SetValue(int colmn, int row, int depth, float value)
{
	m_dat[depth][row][colmn] = value;
}

void CPixelArray::SetGrayPixel(int clmn, int rw, float value)
{
	m_dat[0][rw][clmn] = value;
	m_dat[1][rw][clmn] = value;
	m_dat[2][rw][clmn] = value;
}

void CPixelArray::SetGrayPixel(CStructures::iPoint point, float value)
{

	//bla bla bla
	CStructures::iPoint basePoint = GetBasePosition(point);
	
	if(basePoint.X >= m_width || basePoint.Y >= m_height||basePoint.X < 0 || basePoint.Y < 0)
	{
		TRACE("Chyba! Prekrocen rozsah pole\n");
	}
	else
	{
		m_dat[0][basePoint.Y][basePoint.X] = value;
		m_dat[1][basePoint.Y][basePoint.X] = value;
		m_dat[2][basePoint.Y][basePoint.X] = value;
	}

	
}

void CPixelArray::SetRGBPixelD(CStructures::iPoint point, CStructures::ARGBPixel pixel)
{

	CStructures::iPoint basePoint = point;
	
	if(basePoint.X >= m_width || basePoint.Y >= m_height||basePoint.X < 0 || basePoint.Y < 0)
	{
		TRACE("Chyba! Prekrocen rozsah pole\n");
	}
	else
	{
		m_dat[0][basePoint.Y][basePoint.X] = pixel.B;
		m_dat[1][basePoint.Y][basePoint.X] = pixel.G;
		m_dat[2][basePoint.Y][basePoint.X] = pixel.R;
	}
}

void CPixelArray::SetRGBPixel(CStructures::iPoint point, CStructures::ARGBPixel pixel)
{

	CStructures::iPoint basePoint = GetBasePosition(point);
	
	if(basePoint.X >= m_width || basePoint.Y >= m_height)
	{
		TRACE("Chyba! Prekrocen rozsah pole\n");
	}
	else
	{
		m_dat[0][basePoint.Y][basePoint.X] = pixel.B;
		m_dat[1][basePoint.Y][basePoint.X] = pixel.G;
		m_dat[2][basePoint.Y][basePoint.X] = pixel.R;
	}
}

double CPixelArray::GetValue(int colmn, int row, int depth)
{
	return (m_dat[depth][row][colmn]);
}

double CPixelArray::GetGrayPixel(int clmn, int rw)
{
	return m_dat[0][rw][clmn];
}


double CPixelArray::GetGrayPixel(CStructures::iPoint point)
{
	CStructures::iPoint basePoint = GetBasePosition(point);
	if(basePoint.X >= 0 && basePoint.X < m_width && basePoint.Y >= 0 && basePoint.Y < m_height )
		return m_dat[0][basePoint.Y][basePoint.X];
	else
		return 0;
}


CStructures::ARGBPixel CPixelArray::GetRGBPixel(CStructures::iPoint point)
{
	CStructures::ARGBPixel pixel = {255, 0, 0, 0};
	CStructures::iPoint basePoint = GetBasePosition(point);

	if(basePoint.X >= 0 && basePoint.X < m_width && basePoint.Y >= 0 && basePoint.Y < m_height )
	{
		pixel.B = m_dat[0][basePoint.Y][basePoint.X];
		pixel.G = m_dat[1][basePoint.Y][basePoint.X];
		pixel.R = m_dat[2][basePoint.Y][basePoint.X];
	}

	return pixel;	
}

#ifdef _DEBUG
void CPixelArray::Dump(CDumpContext& dc) const
{
	CObject::Dump(dc);

	dc << "m_width = " << m_width << "\nm_height = " << m_height << "\nm_depth = " << m_depth << "\nm_center.X =" << m_center.X << "\nm_center.Y = " << m_center.Y << "\n";
}

#endif // _DEBUG
