/*
 * HaarWavelet.cpp
 *
 *  Created on: Nov 9, 2008
 *      Author: alexander
 */

#include "HaarWavelet.h"


// This method pre computes the Haar wavelet fast application by Viola-Jones algorithm.
HaarWaveletFilter::HaarWaveletFilter(GBuffer *input)
{
	int i,j;
	h = input->h;
	w = input->w;

	precomputeSq = (long *)calloc (h * w, sizeof(long));
	long sum = 0;
	for (j = 0; j < w; j++)
	{
		sum += input->data[j];
		precomputeSq[j] = sum;
	}
	for (i = 1; i < h; i++)
	{
		sum = 0;
		for (j = 0; j < w; j ++)
		{
			sum += input->data[i * w + j];
			precomputeSq[i * w + j] = sum + precomputeSq[((i-1) * w) + j];
		}
	}

}

long HaarWaveletFilter::getRectangleValue(int x1, int y1, int x2, int y2)
{
	return  (precomputeSq[y2 * w + x2] - precomputeSq[y1 * w + x2] - precomputeSq[y2 * w + x1]  + precomputeSq[y1 * w + x1]);
}

GBuffer * HaarWaveletFilter::filter(int zh, int zw, int border, int *_maxx, int *_maxy)
{
	int i,j;
	int maxx=0;
	int maxy=0;
	long max = 0;
	int denum = 2 * (zh + 2 * border) * (zw + 2 * border);
	GBuffer *toReturn = new GBuffer(h,w);
	GBuffer::Telement *start;
	for (i = 0; i < h - zh - 2 * border; i++ )
	{
		start = toReturn->data + w * i;
		for (j = 0; j < w - zw - 2 * border; j++ )
		{
			int result =  2 * getRectangleValue(j + border ,i + border ,j + zw + border    , i + zh + border)
						    - getRectangleValue(j          ,i          ,j + zw + 2 * border, i + zh + 2 * border);
			if (result > max)
			{
				max = result;
				maxx = j;
				maxy = i;
			}
			*start = (uint8_t)((15 * result / denum) + 128);
			start++;
		}
	}

	if (_maxx != NULL)
		*_maxx = maxx;
	if (_maxy != NULL)
		*_maxy = maxy;

	return toReturn;
}


HaarWaveletFilter::~HaarWaveletFilter()
{
	if (precomputeSq)
		free (precomputeSq);
	precomputeSq = NULL;
	h = 0;
	w = 0;
}
