filter.c 8.07 KB

#include "graphic.h"

#define abs(x) (((x)<0)?(-(x)):(x))
#define max(x,y) (((x)>(y))?(x):(y))
#define min(x,y) (((x)<(y))?(x):(y))

static signed char *filter;
static int *shadow;
static int xsize, ysize;

/*-----------------------------------------*/
create_filter( sx, sy)
  int sx, sy;
{
  filter = (signed char *)malloc( sx*sy);
  shadow = (int *)malloc( 4*sx*sy);
  xsize = sx;
  ysize = sy;
  clear_filter();
}
/*-----------------------------------------*/
clear_filter()
{
  int x, y;
  signed char *pf = filter;
  for (y=0; y<ysize; y++)
    for (x=0; x<xsize; x++) {
      *pf++ = 7;
    }
}
/*-----------------------------------------*/
copy_shadow()
{
  int x, y, color;
  int *pf = shadow;
  for (y=0; y<ysize; y++)
    for (x=0; x<xsize; x++) {
      get_pixel(x, y, &color);
      *pf++ = color;
    }
}
/*-----------------------------------------*/
put_filter( x, y, cvg)
  int x, y, cvg;
{
  *(filter + y * xsize + x) = cvg;
}	
/*-----------------------------------------*/
get_filter( x, y, cvg)
  int x, y, *cvg;
{
  /*
  if (x<0) x=0;
  if (x>=xsize) x=xsize-1;
  if (y<0) y=0;
  if (y>=ysize) y=ysize-1;
  */
  if ((x<0) || (x>=xsize) || (y<0) || (y>=ysize))
    *cvg = 7;
  else
    *cvg = *(filter + y * xsize + x);
}	
/*-----------------------------------------*/
get_shadow( x, y, color)
  int x, y, *color;
{
  if (x<0) x=0;
  if (x>=xsize) x=xsize-1;
  if (y<0) y=0;
  if (y>=ysize) y=ysize-1;
  /*
     if ((x<0) || (x>=xsize) || (y<0) || (y>=ysize))
     *color = 0;
     else
     */
  *color = *(shadow + y * xsize + x);
}	
/*-----------------------------------------*/
filter_image()
{
  int x, y;
  int i, j;
  int cvg[15];
  int red[15];
  int grn[15];
  int blu[15];
  int depth, color, w, temp, cnt;
  int maxred, maxgrn, maxblu;
  int minred, mingrn, minblu;
  int outputred, outputgrn, outputblu;
  copy_shadow();
  for (y=0; y<ysize; y++) {
    get_filter(-2, y-1, &cvg[1]);
    get_shadow(-2, y-1, &color);
    unpack_color(color, red[1], grn[1], blu[1]);
    get_filter(-1, y-1, &cvg[2]);
    get_shadow(-1, y-1, &color);
    unpack_color(color, red[2], grn[2], blu[2]);
    get_filter( 0, y-1, &cvg[3]);
    get_shadow( 0, y-1, &color);
    unpack_color(color, red[3], grn[3], blu[3]);
    get_filter( 1, y-1, &cvg[4]);
    get_shadow( 1, y-1, &color);
    unpack_color(color, red[4], grn[4], blu[4]);
    get_filter(-2, y+0, &cvg[6]);
    get_shadow(-2, y+0, &color);
    unpack_color(color, red[6], grn[6], blu[6]);
    get_filter(-1, y+0, &cvg[7]);
    get_shadow(-1, y+0, &color);
    unpack_color(color, red[7], grn[7], blu[7]);
    get_filter( 0, y+0, &cvg[8]);
    get_shadow( 0, y+0, &color);
    unpack_color(color, red[8], grn[8], blu[8]);
    get_filter( 1, y+0, &cvg[9]);
    get_shadow( 1, y+0, &color);
    unpack_color(color, red[9], grn[9], blu[9]);
    get_filter(-2, y+1, &cvg[11]);
    get_shadow(-2, y+1, &color);
    unpack_color(color, red[11], grn[11], blu[11]);
    get_filter(-1, y+1, &cvg[12]);
    get_shadow(-1, y+1, &color);
    unpack_color(color, red[12], grn[12], blu[12]);
    get_filter( 0, y+1, &cvg[13]);
    get_shadow( 0, y+1, &color);
    unpack_color(color, red[13], grn[13], blu[13]);
    get_filter( 1, y+1, &cvg[14]);
    get_shadow( 1, y+1, &color);
    unpack_color(color, red[14], grn[14], blu[14]);
    for (x=0; x<xsize; x++) {
      cvg[0] = cvg[1];
      cvg[1] = cvg[2];
      cvg[2] = cvg[3];
      cvg[3] = cvg[4];
      red[0] = red[1];
      red[1] = red[2];
      red[2] = red[3];
      red[3] = red[4];
      grn[0] = grn[1];
      grn[1] = grn[2];
      grn[2] = grn[3];
      grn[3] = grn[4];
      blu[0] = blu[1];
      blu[1] = blu[2];
      blu[2] = blu[3];
      blu[3] = blu[4];
      get_filter(x+2, y-1, &cvg[4]);
      get_shadow(x+2, y-1, &color);
      unpack_color(color, red[4], grn[4], blu[4]);
      cvg[5] = cvg[6];
      cvg[6] = cvg[7];
      cvg[7] = cvg[8];
      cvg[8] = cvg[9];
      red[5] = red[6];
      red[6] = red[7];
      red[7] = red[8];
      red[8] = red[9];
      grn[5] = grn[6];
      grn[6] = grn[7];
      grn[7] = grn[8];
      grn[8] = grn[9];
      blu[5] = blu[6];
      blu[6] = blu[7];
      blu[7] = blu[8];
      blu[8] = blu[9];
      get_filter(x+2, y+0, &cvg[9]);
      get_shadow(x+2, y+0, &color);
      unpack_color(color, red[9], grn[9], blu[9]);
      cvg[10] = cvg[11];
      cvg[11] = cvg[12];
      cvg[12] = cvg[13];
      cvg[13] = cvg[14];
      red[10] = red[11];
      red[11] = red[12];
      red[12] = red[13];
      red[13] = red[14];
      grn[10] = grn[11];
      grn[11] = grn[12];
      grn[12] = grn[13];
      grn[13] = grn[14];
      blu[10] = blu[11];
      blu[11] = blu[12];
      blu[12] = blu[13];
      blu[13] = blu[14];
      get_filter(x+2, y+1, &cvg[14]);
      get_shadow(x+2, y+1, &color);
      unpack_color(color, red[14], grn[14], blu[14]);
      /* Tests for z and coverage: */
      /*
	 get_zbuffer( x, y, &depth);
	 put_pixel( x, y,(depth>>10)&0x0000FF00);
	 continue;
	 */
      /*
         if ( cvg[7]    >7) put_pixel(x,y,255);
	 if ((cvg[7]&7)==7) put_pixel(x,y,255<<8);
	 if ((cvg[7]&7) <7) put_pixel(x,y,255<<16);
	 continue;
	 */
      /*
	 put_pixel(x,y,(7&cvg[7])<<5);
	 continue;
	 */
      maxred = minred = red[7];
      maxgrn = mingrn = grn[7];
      maxblu = minblu = blu[7];
      if (cvg[7] != 7) {
	for (i=1; i<15; i+=2) {
	  if (cvg[i] != 7) continue;
	  if (red[i] > maxred)
	    for (j=1; j<15; j+=2)
	      if ((i != j) && (red[i] <= red[j]) && (cvg[j] == 7))
		maxred = red[i];
	  if (grn[i] > maxgrn)
	    for (j=1; j<15; j+=2)
	      if ((i != j) && (grn[i] <= grn[j]) && (cvg[j] == 7))
		maxgrn = grn[i];
	  if (blu[i] > maxblu)
	    for (j=1; j<15; j+=2)
	      if ((i != j) && (blu[i] <= blu[j]) && (cvg[j] == 7))
		maxblu = blu[i];
	  if (red[i] < minred)
	    for (j=1; j<15; j+=2)
	      if ((i != j) && (red[i] >= red[j]) && (cvg[j] == 7))
		minred = red[i];
	  if (grn[i] < mingrn)
	    for (j=1; j<15; j+=2)
	      if ((i != j) && (grn[i] >= grn[j]) && (cvg[j] == 7))
		mingrn = grn[i];
	  if (blu[i] < minblu)
	    for (j=1; j<15; j+=2)
	      if ((i != j) && (blu[i] >= blu[j]) && (cvg[j] == 7))
		minblu = blu[i];
	}
	w = 7 - cvg[7];
	outputred = red[7] + ((maxred + minred - (red[7] << 1))*w + 4 >> 3);
	outputgrn = grn[7] + ((maxgrn + mingrn - (grn[7] << 1))*w + 4 >> 3);
	outputblu = blu[7] + ((maxblu + minblu - (blu[7] << 1))*w + 4 >> 3);
	put_pixel( x, y, pack_color( outputred, outputgrn, outputblu));
      }
    }
  }
  if (en_divot) {
    copy_shadow();
    for (y=0; y<ysize; y++) {
      get_filter(-1, y, &cvg[1]);
      get_shadow(-1, y, &color);
      unpack_color(color, red[1], grn[1], blu[1]);
      get_filter(0, y, &cvg[2]);
      get_shadow(0, y, &color);
      for (x=0; x<xsize; x++) {
	cvg[0] = cvg[1];
	cvg[1] = cvg[2];
	red[0] = red[1];
	red[1] = red[2];
	grn[0] = grn[1];
	grn[1] = grn[2];
	blu[0] = blu[1];
	blu[1] = blu[2];
	get_filter(x+1, y, &cvg[2]);
	get_shadow(x+1, y, &color);
	unpack_color(color, red[2], grn[2], blu[2]);
	/* Tests for z and coverage: */
	/*
	   get_zbuffer( x, y, &depth);
	   put_pixel( x, y,(depth>>10)&0x0000FF00);
	   continue;
	   */
	/*
	   if ( cvg[7]    >7) put_pixel(x,y,255);
	   if ((cvg[7]&7)==7) put_pixel(x,y,255<<8);
	   if ((cvg[7]&7) <7) put_pixel(x,y,255<<16);
	   continue;
	   */
	/*
	   put_pixel(x,y,(7&cvg[7])<<5);
	   continue;
	   */
	if ((cvg[0] != 7) || (cvg[1] != 7) || (cvg[2] != 7)) {
	  if (red[0] > red[1]) {
	    maxred = red[0];
	    minred = red[1];
	  } else {
	    maxred = red[1];
	    minred = red[0];
	  }
	  if (red[2] > minred) minred = red[2];
	  if (maxred > minred)
	    outputred = minred;
	  else
	    outputred = maxred;
	  
	  if (grn[0] > grn[1]) {
	    maxgrn = grn[0];
	    mingrn = grn[1];
	  } else {
	    maxgrn = grn[1];
	    mingrn = grn[0];
	  }
	  if (grn[2] > mingrn) mingrn = grn[2];
	  if (maxgrn > mingrn)
	    outputgrn = mingrn;
	  else
	    outputgrn = maxgrn;
	  
	  if (blu[0] > blu[1]) {
	    maxblu = blu[0];
	    minblu = blu[1];
	  } else {
	    maxblu = blu[1];
	    minblu = blu[0];
	  }
	  if (blu[2] > minblu) minblu = blu[2];
	  if (maxblu > minblu)
	    outputblu = minblu;
	  else
	    outputblu = maxblu;
	  put_pixel( x, y, pack_color( outputred, outputgrn, outputblu));
	}
      }
    }
  }
}