#include <stdio.h>
#include "util.h"

// the following are flags, not RGB value (actually reverse of RGB)
#define BG 255   
#define NOT_BG 0

/*-------------------------------------*
 * detect moment
 *------------------------------------*/
// intensity based
void null_bg(unsigned char *bg, unsigned char *img, int fsize) {

  int i,j, pix;
  double img_i, bg_i;  //intensity

  for(i=0; i<fsize; i+=4) {
    
    // from input image, skipping blue
    img_i = (img[i]+img[i+1]+img[i+2])/3.0;

    // from background
    bg_i = (bg[i]+bg[i+1]+bg[i+2])/3.0;


    if(ABS(img_i - bg_i) < 8) {
      //img[i] = img[i+1] = img[i+2] = 0;
      img[i+3] = BG;
    }
    else img[i+3] = NOT_BG;
  }
  
  // clean up backup a little more to get rid of light flickers
  for(i=1; i<Xsize-1; i++) {
    for(j=1; j<Ysize-1; j++) {
      pix = (Xsize*4)*j+(i*4);
      
      if(img[pix+3] == NOT_BG) {
	if(((img[pix+7] == BG) && (img[pix+(Xsize*4)+3] == BG)) ||
	   ((img[pix+(Xsize*4)-1] == BG) && (img[pix+(Xsize*4)+7] == BG))){
	  //img[pix] = img[pix+1] = img[pix+2] = 0;
	  img[pix+3] = BG;
	}
      }
    }
  }
}

/*-------------------------------------
 * make other pixel black except for skin
 * ------------------------------------*/

void isolate_skin(unsigned char *img, int fsize){
  
  int i,j, pix;
  double chrom_g, chrom_r, sum;
  for(i=0; i<fsize; i+=4) {
    
    if(img[i+3] == NOT_BG) { 
      
      sum = img[i] + img[i+1] + img[i+2];
      chrom_r = (double)img[i+2] / (double)sum;
      chrom_g = (double)img[i+1] / (double)sum;
      
      if(chrom_r >= 0.35 && chrom_r <=0.55 && chrom_g >= 0.28 && chrom_g <=0.35) {
	//img[i] = img[i+1] = img[i+2] = 255;
	img[i+3] = NOT_BG;
      }
      else {
	//img[i] = img[i+1] = img[i+2] = 0;
	img[i+3] = BG;
      }
    }
  }

  
  // clean up image a bit
  for(i=1; i<Xsize-1; i++) {
    for(j=1; j<Ysize-1; j++) {
      pix = (Xsize*4)*j+(i*4);
      if(pix == BG) {
	if(((img[pix+7] != BG) && (img[pix+(Xsize*4)+3] != BG)) ||
	   ((img[pix-1] != BG) && (img[pix-(Xsize*4)+3] != BG))) {
	  
	  //img[pix] = img[pix+1] = img[pix+2] = 255;
	  img[pix+3] = NOT_BG;
	} 
	else {
	  //img[pix] = img[pix+1] = img[pix+2] = 0;
	  img[pix+3] = BG;
	}
      }
    }
  }
}


/*----------------------------------------------------
 * convert Ximage to binimage for 2-pass segmentation
 *---------------------------------------------------*/

void ConvertToBinary(unsigned char *img, int fsize, unsigned char *bin) {
  
  int i, j;
  for(i=0, j=0; i<fsize; i+=4, j++) {
    if(img[i+3] == BG) 
      bin[j] = 0;
    else
      bin[j]=255;
  }
}

/*---------------------------------------------
 * show bounding box on Ximage 
 *-----------------------------------------*/
void show_box(unsigned char *img, Box_t *bbox, int x, int y, int nRegions) {
  int i,j, width, height;

  int cols = x * 4;

  for(i=0;i<nRegions;i++){
    
    width = ABS(bbox[i][3] - bbox[i][1]);
    height = ABS(bbox[i][2] - bbox[i][0]);
    
    for(j=0;j<height;j++) {
      img[cols*bbox[i][0] + bbox[i][1]*4+j*cols+2] = 255;   //left border in red
      img[cols*bbox[i][0] + bbox[i][3]*4+j*cols+2] = 255;   //right border in red
    }

    for(j=0;j<width;j++) {
      img[bbox[i][0]*cols + bbox[i][1]*4+(j*4)+2] = 255;    //top border of bbox
      img[bbox[i][2]*cols + bbox[i][3]*4-(j*4)+2] = 255;    //bottom border of bbox

    }
  }
}

/*----------------------------------------
 * update background periodically
 *------------------------------------*/
int check_bg(unsigned char *pre,  unsigned char *curr, int fsize) {
  
  int temp;
  int i;
  long pix;
  double pre_i, curr_i;  //intensity

  pix = 0;
  temp = 0;

  for(i=0; i<fsize; i+=4) {
    
    // from previous image, skipping blue
    pre_i = (pre[i]+pre[i+1]+pre[i+2])/3.0;

    // from curr image,
    curr_i = (curr[i]+curr[i+1]+curr[i+2])/3.0;

    if(ABS(pre_i - curr_i) < 8) 
      pix++;
  }
  //printf("pix matched: %ld\n", pix);

  if( pix > 65280 )  //above 85% of pixels matched
    temp=1;
  return(temp);
}

/*--------------------------
 * get bbox for heads only, ignore limbs 
 *----------------------------*/
int get_heads(Box_t *bbox, Box_t *headbox, long *size, int nRegions) {

  int heads=0;
  int i,j, k;
  double ratio;
  double h, w;
  double boxfilled;

  for(i=0, k=0; i<nRegions; i++) {
   
    //printf("box %i\n", i);

    h = ABS((double)bbox[i][0] - (double)bbox[i][2]);
    w = ABS((double)bbox[i][1] - (double)bbox[i][3]);


    boxfilled = (double)size[i] / (h * w);

    if(boxfilled >= 0.60) {
      
      //printf("ratio: %g\n", ratio);
      
      ratio = w / h;
      
      if(ratio >= 0.4 && ratio <= 1.25) {
	heads++;
	for(j=0; j<4; j++)
	  headbox[k][j] = bbox[k][j];
	k++;
      }
    }
  }    

  return(heads);
}

   

