#include <stdio.h>
#include <sys/types.h>
#include <tiffio.h>

int outside,rorb;


uint32 *tiff_read2raster(char filename[], uint32 *nrow, uint32 *ncol);
int tiff_raster2file(char filename[], uint32 *raster, uint32 nrow, uint32 ncol);

int getalpha(uint32 pixel);
int getred(uint32 pixel);
int getgreen(uint32 pixel);
int getblue(uint32 pixel);
void inttouint(int *outarray,uint32 *image,uint32 rows, uint32 cols);
int lookupandback(int *outarray,int i, int j, uint32 rows, uint32 cols);
int lookdownandright(int *outarray, int i, int j, uint32 rows, uint32 cols); 
void setcolor (uint32 *image,int i, int j,uint32 rows, uint32 cols, int red, int green, int blue);
void PassTwice(uint32 *image, uint32 rows, uint32 cols);
int condition(int r, int g, int b);

int getalpha(uint32 pixel)
{
  return(((pixel) & 0xFF000000) >>24);
}

int getblue(uint32 pixel)
{
  return(((pixel) & 0x00FF0000) >>16);
}

int getgreen(uint32 pixel)
{
  return(((pixel) & 0x0000FF00) >>8);
}

int getred(uint32 pixel)
{
  return(((pixel) & 0x000000FF));
}

void inttouint(int *outarray, uint32 *image, uint32 rows, uint32 cols)
{    
  int i,j;
  for (i=0;i<rows;i++){
    for (j=0;j<cols;j++){
      setcolor(image,i,j,rows, cols,outarray[i*cols+j],outarray[i*cols+j],outarray[i*cols+j]);
    }
  }
}
void setcolor(uint32 *image,int i, int j,uint32 rows, uint32 cols, int red, int green, int blue)
{
    image[i*cols+j] =  blue*256*256 + green *256 + red; 
}

int lookupandback(int *outarray,int i, int j, uint32 rows, uint32 cols)
{
 int min;

 //Wrong if edge pixel is within 255 pixels of an object, but will be corrected
 //in second pass
 printf("outside=%d\n",outside);
 if (i==0 || j==0) return(outside);
 min = outarray[i*cols+j -1];
 if (outarray[(i-1)*cols + j]< min) min =  outarray[(i-1)*cols + j];
 return min;
}

int lookdownandright(int *outarray, int i, int j, uint32 rows, uint32 cols)
{  
  int min;
  // remember will not be used unless its smaller than current value
  if (i==rows-1 || j==cols-1) return(outside);
  min = outarray[i*cols+j +1];
  if (outarray[(i+1)*cols + j]< min) min =  outarray[(i+1)*cols + j];
  return min;
}


void PassTwice(uint32 *image,uint32 rows,uint32 cols)
{
  int outarray[rows*cols];
  int i,j,r,g,b,min;

  for(i=0;i<rows;i++) {
    for(j=0;j<cols;j++) {
      r = getred(image[i*cols + j]);
      g = getgreen(image[i*cols + j]);
      b = getblue(image[i*cols + j]);
      if (condition(r, g, b)==0) outarray[i*cols + j] = 0;
      else outarray[i*cols+j] = lookupandback(outarray,i,j,rows,cols) + 1;
      if (outarray[i*cols+j] > 255) outarray[i*cols+j] = 255;	
    }
  }
  
    for(i=rows-1;i>=0;i--) {
      for(j=cols-1;j>=0;j--) {
	r = getred(image[i*cols + j]);
	g = getgreen(image[i*cols + j]);
	b = getblue(image[i*cols + j]);
	if (condition(r, g, b)==1){
	  if (lookdownandright(outarray,i,j,rows,cols)<outarray[i*cols+j]) outarray[i*cols+j] = lookdownandright(outarray,i,j,rows,cols)+1;
	}
      }
    }
    inttouint(outarray,image,rows,cols);
}

int condition(int r, int g, int b)
{
  if (rorb ==0)
    {
      if (r+g+b==0) return 1;
      else return 0;
    }
  else {
    if (r+g+b!=0) return 1;
      else return 0;
  }
}

main(int argc, char *argv[]) {
  uint32 *image;
  uint32 rows, cols;
  int i,j,r,g,b, min;
  if(strcmp(argv[3], "zero\0")==0)
    outside = 0;
  else if(strcmp(argv[3], "inf\0")==0)
    outside=255;
  else {
    printf("Wrong input for border value.  Border set to 255.\n");
    outside=255;
  }
  
  if(strcmp(argv[4], "plus\0")==0)
    rorb=1;
  else if(strcmp(argv[4], "minus\0")==0)
    rorb=0;
  else{
    printf("Wrong input for region value. Setting to red.\n");
    rorb=1;
  }
 
  printf("rorb = %d\n",rorb);
  
  printf("Beginning process\n");

  image = tiff_read2raster(argv[1], &rows, &cols);

  printf("Image is %d rows by %d columns\n", rows, cols);
 
  PassTwice(image,rows,cols);
  
  printf("Starting write process\n");
  
  tiff_raster2file(argv[2],image, rows, cols);
  
  printf("Exiting\n");
  
  printf("outside= %d\n",outside);
  

}