import java.awt.*;
import java.awt.image.*;
import java.io.*;

// Hybrid Directional Filter
public class HF extends vectorFilter
{
	int indent;

	// Creates object and initializes data
	public HF(int size)
	{
		masksize = size;
		maskIndex = new int[masksize*masksize];
		array = new double[masksize*masksize];
		indent = (int) Math.floor(masksize/2);
	}

	// Runs the algorithm
	public void performEffect()
	{
		int counter, temp_val, temp_loc, R, G, B;
		double magV, magB;	
		int newPixels[] = new int [width*height];

		// Moves through input array pixel by pixel
		for (int y=indent;y<height-indent;y++)
		{
			for (int x=indent;x<width-indent;x++)
			{
				// Location of centre of mask
				int pointOffset = y*width+x;
				
			// VMF part

				// Calculate Index for mask
				counter = 0;
				for (int i=-indent;i<=indent;i++)
				{
					for (int j=-indent;j<=indent;j++)
					{
						maskIndex[counter] = (y+i)*width+(x+j);
						counter++;
					}
				}

				// Sorts pixels in mask by sum of distances
				calc_dist();
				b_sort();
				
				// Place VMF output in temp
				temp_val=pixels[maskIndex[0]];
				temp_loc=maskIndex[0];
				
			// BVDF part
				
				// Reset Index for mask
				counter = 0;
				for (int i=-indent;i<=indent;i++)
				{
					for (int j=-indent;j<=indent;j++)
					{
						maskIndex[counter] = (y+i)*width+(x+j);
						counter++;
					}
				}
				
				// Sorts pixels in mask by sum of angles
				calc_angle();
				b_sort();
				
			// If VMF = BVDF then output VMF result
				if (maskIndex[0] == temp_loc)
				{
					newPixels[pointOffset] = temp_val;
				}
				// Otherwise output (mag VMF/mag BVDF) mult by BVDF
				else
				{
					// Calc mag of VMF output pixel
					magV = calc_mag(temp_val);

					// Calc mag of BVDF output pixel
					R = (pixels[maskIndex[0]]>>16)&0xff;
					G = (pixels[maskIndex[0]]>>8)&0xff;
					B = (pixels[maskIndex[0]])&0xff;
					magB = calc_mag(pixels[maskIndex[0]]);
					
					// Calc output
					if (magB!=0)
					{
						R = (int)Math.round((magV/magB)*R);
						G = (int)Math.round((magV/magB)*G);
						B = (int)Math.round((magV/magB)*B);
					}

					if (R > 255) R = 255;
					if (R < 0) R = 0;
					if (G > 255) G = 255;
					if (G < 0) G = 0;
					if (G > 255) B = 255;
					if (G < 0) B = 0;
					
					newPixels[pointOffset] = 255<<24 | R<<16 | G<<8 | B;
				}
			}
		}
		this.pixels = newPixels;
	}
}
