//function declaration
double calc_psnr(CFile* file1, CFile* file2);
double calc_psnr_per_frame(CFile* file1, CFile* file2);
double psnr_average(vector<double> &value);

//function definition
double calc_psnr(CFile* file1, CFile* file2)
{
	//psnr_frame saves psnr value of each frame
	vector<double> psnr_frame;

	while ((file1 -> GetPosition() != file1 -> GetLength()) && (file2 -> GetPosition() != file2 -> GetLength()))
	{
		psnr_frame.push_back(calc_psnr_per_frame(file1,file2));
	}

	//calculate total psnr
	return psnr_average(psnr_frame);
}

double calc_psnr_per_frame(CFile* file1, CFile* file2)
{
	//set buffer and malloc memory
	unsigned char *y_data1 = new unsigned char[y_size],*y_data2 = new unsigned char[y_size];
	unsigned char *cb_data1 = new unsigned char[cb_size],*cb_data2 = new unsigned char[cb_size];
	unsigned char *cr_data1 = new unsigned char[cr_size],*cr_data2 = new unsigned char[cr_size];

	//read file
	file1 -> Read(y_data1,y_size);
	file1 -> Read(cb_data1,cb_size);
	file1 -> Read(cr_data1,cr_size);
	file2 -> Read(y_data2,y_size);
	file2 -> Read(cb_data2,cb_size);
	file2 -> Read(cr_data2,cr_size);

	//sum
	unsigned int sum = 0;
	for (unsigned int i = 0;i < y_size;++i)
		sum += (*(y_data1 + i) - *(y_data2 + i)) * (*(y_data1 + i) - *(y_data2 + i));

	//free memory
	delete [] y_data1;
	delete [] cb_data1;
	delete [] cr_data1;
	delete [] y_data2;
	delete [] cb_data2;
	delete [] cr_data2;

	//return psnr_frame
	if (sum == 0)
		return 100;
	else
		return 10 * log10(255 * 255 / double(sum / y_size));
}

double psnr_average(vector<double> &value)
{
	double sum = 0;
	int i = 0;
	for (vector<double>::iterator iter = value.begin();iter != value.end();++iter)
	{
		++i;
		sum += (*iter);
	}
	return sum / i;
}