/*
 * This file contains functions for performing
 * Gaussian smoothing
 */


/*
 * Generates a Gaussian mask defined by the 'SIZE' of the
 * mask and the variance 'VAR'. If fills in the global
 * (improc.c) 'g_mask'
 */

void Generate_Gauss()
{

  int i,j;
  
  double sum = 0, unit;

#ifdef DEBUG
  
  if (g_mask != NULL)
      fprintf(db, "Generate_Gauss: mask not null");
  
#endif

  g_mask = (double**)malloc( sizeof(double*)*SIZE);
  for (i=0; i<SIZE; i++)
    g_mask[i] = (double*)malloc( sizeof(double)*SIZE);

  for (i=-G; i<=G; i++)
    for (j=-G; j<=G; j++)
      g_mask[i+(int)G][j+(int)G] = exp( -( (double)(i*i + j*j)/(2*VAR)) );

  /* normalize */
  unit = g_mask[0][0];
  for (i=0; i<SIZE; i++)
    for (j=0; j<SIZE; j++)
      {
	g_mask[i][j] = g_mask[i][j]/unit;
	sum += g_mask[i][j];
      }
  
  for (i=0; i<SIZE; i++)
    for (j=0; j<SIZE; j++)
      g_mask[i][j] = g_mask[i][j]/sum;
     
}


/*
 * Gaussian smooths an area of the image defined by the top left 
 * corner (x1, y1) and bottom right corner (x2,y2)
 */

void Gaussian_Smooth(BYTE * imageIn, BYTE * imageOut, 
		     int x1, int y1, int x2, int y2)
{

  int i,j;
  
  double temp;
  
  if (g_mask == NULL)     // only need to do this once!
    Generate_Gauss();


#ifdef DEBUG
  
  if ( (x1 - G < 0) || (y1 - G < 0) 
       || (x2 + G >= width) || (y2 + G >= height) )
    fprintf(db, "\nPROBLEM: Gaussian smooth working outside image\n");
    
#endif
  
  /* clamp if outside */
  gclamp(&x1, &y1, &x2, &y2);

  for (i=x1; i<=x2; i++)
    for (j=y1; j<=y2; j++)
      {
	temp = smooth_pixel(imageIn, G, i, j);
	imageOut[ j*width + i ] = (BYTE)temp;
      }

}



/*
 * returns the Gaussian smoothed value at pixel (i,j)
 * with a mask size (2*g+1)
 */

double smooth_pixel(BYTE * image, int g, int i, int j)
{

  int a,b;

  double temp = 0;

  for (a=-g; a<=g; a++)
	  for (b=-g; b<=g; b++)
	    temp += g_mask[a+g][b+g]*
		(double)image[ (j+b)*width + (i+a) ];
	
  return(temp);

}


/*
 * Clamps the x and y's so that Gaussian smoothing
 * will not go out of bounds
 */

void gclamp(int *x1, int *y1, int *x2, int *y2)
{

  if ( *x1-G < 0 )
    *x1 = G;
  
  if ( *y1-G < 0 )
    *y1 = G;

  if ( *x2 + G >=width )
    *x2 = width-G-1;

  if (*y2 + G >= height )
    *y2 = height-G-1;

}


/*
 * Smooths the individual areas around the last position
 * of the feature. Overlaping areas are not re-smoothed
 */

void smooth_areas( BYTE *imageIn, BYTE* imageOut)
{

  int done[width*height];

  int i,j,k;

  int x1, y1, x2, y2;

  int s = floor(SEARCH/2);
  
  double temp;

  memset( done, FALSE, width*height*sizeof(int) );
 
  for (k=0; k<XX*YY; k++)

    /*smooth all active and non-active areas */
    if ( ( (motion == TRUE) && (f[k].moving == TRUE) ) 
	 || (motion == FALSE) )
      {
	
	x1 = f[k].x - s;
	y1 = f[k].y - s;  
	x2 = f[k].x + s;
	y2 = f[k].y + s;
	
	gclamp(&x1, &y1, &x2, &y2);
	
	for (i=x1; i<=x2; i++)
	  for (j=y1; j<=y2; j++)
	    {
	      
	      if ( done[j*width+i] != TRUE )
		{
		  temp = smooth_pixel(imageIn, G, i, j);
		  imageOut[ j*width + i ] = (BYTE)temp;
		  done[j*width+i] = TRUE;
		}
	      
	    }
    }
  
}

/*
 * The smoothed pixel of a colour image.
 * 'c' specifies which component:
 *    r = 0
 *    g = 1
 *    b = 2
 */

double smooth_pixel_col(BYTE * image, int g, int i, int j, int c)
{

  int a,b;

  double temp = 0;

  for (a=-g; a<=g; a++)
	  for (b=-g; b<=g; b++)
	    temp += g_mask[a+g][b+g]*
		(double)image[ 3*( (j+b)*width + (i+a) )+c ];
	
  return(temp);

}


