//
// This class has functions for computing the histogram
// and for equalizing it.
//


import Imager;
import java.awt.*;

class Histogram extends Object
{
  Imager applet;
  HistogramFrame hf;
  int histogram[] = new int[256];
  int inPixels[], width, height;
  int max,mousex = 0;

  public Histogram() {}
  public Histogram(int Pixels[], int w, int h)
  {
	inPixels = new int[Pixels.length];
	inPixels = Pixels;
	width = w;
	height = h;
	update(inPixels);
  }


  // change the histogram according to the new input

  public void update(int Pixels[])
  {
	float factor;
	int numPixels = Pixels.length;
	
	for (int x = 0; x < 256; x++)
		histogram[x] = 0;
		
	for (int x = 0; x < numPixels; x++)
		++histogram[Pixels[x]]; 	
  }


  // Call the histogramFrame class and display the graph

  public void display(String title, int x, int y, Imager applet)
  {
	if (hf == null)
		hf = new HistogramFrame(title,histogram,x,y,applet);
	else
		hf.normalize(histogram);  
  }

  public void destroy()
  {
	hf.dispose();
  }

  
  // Global equalization

  public int[] equalize()
  {
	float equalized[] = new float[256];
	int values[] = new int[256];
	int outPixels[] = new int[inPixels.length];
	float len = (float)inPixels.length;
	outPixels = inPixels;
	
	for (int x = 0; x < 256; x++)
		equalized[x] = (float)histogram[x]/len;
	for (int x = 1; x < 256; x++)
		equalized[x] += equalized[x-1];
	for (int x = 1; x < 256; x++)
		values[x] = (int)(equalized[x]*255.0);	
	
	for (int x = 0; x < len; x++)
		outPixels[x] = values[inPixels[x]];
		
	return outPixels;	
  }  

  
  // The following function equalizes as selected area

  public int[] equalizeArea(int startx, int starty, int endx, int endy)
  {
	float equalized[] = new float[256];
	int values[] = new int[256];
	int outPixels[] = new int[inPixels.length];
	int tempPixels[] = new int[(endx-startx)*(endy-starty)];
	
	outPixels = inPixels;
	
	int z = 0;
	for (int y = starty; y < endy; y++)
		for (int x = startx; x < endx; x++)
		{
			tempPixels[z] = inPixels[y*width+x];
			++z;
		}
		
	update (tempPixels);
	
	float len = (float)tempPixels.length;
	
	for (int x = 0; x < 256; x++)
		equalized[x] = (float)histogram[x]/len;
	for (int x = 1; x < 256; x++)
		equalized[x] += equalized[x-1];
	for (int x = 1; x < 256; x++)
		values[x] = (int)(equalized[x]*255.0);	
		
	for (int y = starty; y < endy; y++)
		for (int x = startx; x < endx; x++)
			outPixels[y*width+x] = values[inPixels[y*width+x]];
		
	return outPixels;	
  }


  // The following function equalizes 4 quarters of the image
  // individually and output the combined image.
  
  public int[] equalize4areas()
  {
	int outPixels[] = new int[inPixels.length];
	int finalPixels[] = new int[inPixels.length];
	
	outPixels = equalizeArea(0,0,width/2,height/2);
		
	for (int y = 0; y < height/2; y++)
		for (int x = 0; x < width/2; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//-----------------------------------------------------------		
	
	outPixels = equalizeArea(width/2,0,width,height/2);
		
	for (int y = 0; y < height/2; y++)
		for (int x = width/2; x < width; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//------------------------------------------------------------------
	
	outPixels = equalizeArea(0,height/2,width/2,height);
		
	for (int y = height/2; y < height; y++)
		for (int x = 0; x < width/2; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//------------------------------------------------------------------
	
	outPixels = equalizeArea(width/2,height/2,width,height);
		
	for (int y = height/2; y < height; y++)
		for (int x = width/2; x < width; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//------------------------------------------------------------------
	
	return outPixels;	
  }

  public int[] equalize16areas()
  {
	int outPixels[] = new int[inPixels.length];
	int finalPixels[] = new int[inPixels.length];
	
	outPixels = equalizeArea(0,0,width/4,height/4);
		
	for (int y = 0; y < height/4; y++)
		for (int x = 0; x < width/4; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//-----------------------------------------------------------		
	
	outPixels = equalizeArea(width/4,0,width/2,height/4);
		
	for (int y = 0; y < height/4; y++)
		for (int x = width/4; x < width/2; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//------------------------------------------------------------------
	
	outPixels = equalizeArea(0,height/4,width/4,height/2);
		
	for (int y = height/4; y < height/2; y++)
		for (int x = 0; x < width/4; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//------------------------------------------------------------------
	
	outPixels = equalizeArea(width/4,height/4,width/2,height/2);
		
	for (int y = height/4; y < height/2; y++)
		for (int x = width/4; x < width/2; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//------------------------------------------------------------------
	
	outPixels = equalizeArea(width/2,0,3*width/4,height/4);
		
	for (int y = 0; y < height/4; y++)
		for (int x = width/2; x < 3*width/4; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//-----------------------------------------------------------		
	
	outPixels = equalizeArea(3*width/4,0,width,height/4);
		
	for (int y = 0; y < height/4; y++)
		for (int x = 3*width/4; x < width; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//------------------------------------------------------------------
	
	outPixels = equalizeArea(width/2,height/4,3*width/4,height/2);
		
	for (int y = height/4; y < height/2; y++)
		for (int x = width/2; x < 3*width/4; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//------------------------------------------------------------------
	
	outPixels = equalizeArea(3*width/4,height/4,width,height/2);
		
	for (int y = height/4; y < height; y++)
		for (int x = 3*width/2; x < width; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//------------------------------------------------------------------
	
	outPixels = equalizeArea(0,height/2,width/4,3*height/4);
		
	for (int y = height/2; y < 3*height/4; y++)
		for (int x = 0; x < width/4; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//-----------------------------------------------------------		
	
	outPixels = equalizeArea(width/4,height/2,width/2,3*height/4);
		
	for (int y = height/2; y < 3*height/4; y++)
		for (int x = width/4; x < width/2; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//------------------------------------------------------------------
	
	outPixels = equalizeArea(0,3*height/4,width/4,height);
		
	for (int y = 3*height/4; y < height; y++)
		for (int x = 0; x < width/4; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//------------------------------------------------------------------
	
	outPixels = equalizeArea(width/4,3*height/4,width/2,height);
		
	for (int y = 3*height/4; y < height; y++)
		for (int x = width/4; x < width/2; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//------------------------------------------------------------------
	
	outPixels = equalizeArea(width/2,height/2,3*width/4,3*height/4);
		
	for (int y = height/2; y < 3*height/4; y++)
		for (int x = width/2; x < 3*width/4; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//-----------------------------------------------------------		
	
	outPixels = equalizeArea(3*width/4,height/2,width,3*height/4);
		
	for (int y = height/2; y < 3*height/4; y++)
		for (int x = 3*width/4; x < width; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//------------------------------------------------------------------
	
	outPixels = equalizeArea(width/2,3*height/4,3*width/4,height);
		
	for (int y = 3*height/4; y < height; y++)
		for (int x = width/2; x < 3*width/4; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//------------------------------------------------------------------
	
	outPixels = equalizeArea(3*width/4,3*height/4,width,height);
		
	for (int y = 3*height/4; y < height; y++)
		for (int x = 3*width/4; x < width; x++)
			finalPixels[y*width+x] = outPixels[y*width+x];
	//------------------------------------------------------------------
	
	return outPixels;	
  }
}
