


//---- Pattern_Fn_XOR () -> (RGB rgb)

pattern_def( Pattern_Fn_XOR)
{
  pattern_output(PATTERN_RGB, rgb, 0);

  int i, j;
  int c;

  for(j=0; j<256; j++) {
    for(i=0; i<256; i++) {
      c = i^j;

      rgb->buf[j][i][0] = c;
      rgb->buf[j][i][1] = c;
      rgb->buf[j][i][2] = c;
    }
  }
}




//---- Pattern_Fn_Checkers () -> (RGB rgb)

pattern_def( Pattern_Fn_Checkers)
{
  pattern_output(PATTERN_RGB, rgb, 0);

  int i, j;
  int c;

  for(j=0; j<256; j++) {
    for(i=0; i<256; i++) {
      if(i<128) c = j; else c = j-128;
      if(j<128) c -= i;

      rgb->buf[j][i][0] = c;
      rgb->buf[j][i][1] = c;
      rgb->buf[j][i][2] = c;
    }
  }
}



//---- Pattern_Fn_Fade (RGB fade1, RGB fade2, REAL alpha) -> (RGB rgb)

pattern_def( Pattern_Fn_Fade )
{
  pattern_input(PATTERN_RGB , fade1, 0);
  pattern_input(PATTERN_RGB , fade2, 1);
  pattern_input(PATTERN_REAL, alpha, 2);

  pattern_output(PATTERN_RGB, rgb, 0);

  int i, j;

  int a = alpha->value * 255;

  if(a < 0) a = 0;
  if(a > 255) a = 255;

  for(j=0; j<256; j++) {
    for(i=0; i<256; i++) {
      rgb->buf[j][i][0] = (fade1->buf[j][i][0] * (255-a) + fade2->buf[j][i][0] * a) >> 8;
      rgb->buf[j][i][1] = (fade1->buf[j][i][1] * (255-a) + fade2->buf[j][i][1] * a) >> 8;
      rgb->buf[j][i][2] = (fade1->buf[j][i][2] * (255-a) + fade2->buf[j][i][2] * a) >> 8;
    }
  }
}



//---- Pattern_Fn_Lookup (RGB image, ALPHA xlookup, ALPHA ylookup) -> (RGB result)

pattern_def( Pattern_Fn_Lookup )
{
  pattern_input(PATTERN_RGB , image,   0);
  pattern_input(PATTERN_A   , xlookup, 1);
  pattern_input(PATTERN_A   , ylookup, 2);
  
  pattern_output(PATTERN_RGB, result, 0);

  int i, j;
  int x, y;

  for(j=0; j<256; j++) {
    for(i=0; i<256; i++) {
      x = xlookup->buf[j][i];
      y = ylookup->buf[j][i];
      result->buf[j][i][0] = image->buf[y][x][0];
      result->buf[j][i][1] = image->buf[y][x][1];
      result->buf[j][i][2] = image->buf[y][x][2];
    }
  }
}



//---- Pattern_Fn_VStretch (RGB im, REAL time) -> (RGB rgb)

pattern_def( Pattern_Fn_VStretch )
{
  pattern_input(PATTERN_RGB , im, 0);
  pattern_input(PATTERN_REAL, scale, 1);

  pattern_output(PATTERN_RGB, rgb, 0);

  int i, j;
  int y;

  double sc = scale->value;

  for(y=0; y<256; y++)
  {
    j = (y-128) * sc + 128;

    for(i=0; i<256; i++)
    {
      rgb->buf[j][i][0] = im->buf[j][i][0];
      rgb->buf[j][i][1] = im->buf[j][i][1];
      rgb->buf[j][i][2] = im->buf[j][i][2];
    }
  }
}



//---- Pattern_Fn_HStretch (RGB im, REAL time) -> (RGB rgb)

pattern_def( Pattern_Fn_HStretch )
{
  pattern_input(PATTERN_RGB , im, 0);
  pattern_input(PATTERN_REAL, scale, 1);

  pattern_output(PATTERN_RGB, rgb, 0);

  int i, j;
  int x;

  double sc = scale->value;

  for(x=0; x<256; x++)
  {
    i = (x-128) * sc + 128;

    for(j=0; j<256; j++)
    {
      rgb->buf[j][i][0] = im->buf[j][i][0];
      rgb->buf[j][i][1] = im->buf[j][i][1];
      rgb->buf[j][i][2] = im->buf[j][i][2];
    }
  }
}



//---- Pattern_Fn_RGB_BoxBlur

pattern_def( Pattern_Fn_BoxBlur )
{
  pattern_input(PATTERN_RGB , src, 0);
  pattern_input(PATTERN_REAL, rad, 1);

  pattern_output(PATTERN_RGB, dest, 0);

  int b, g, r;
  int i, j;

  int radius = rad->value;

  int diameter = radius*2+1;

  pattern_var(PATTERN_RGB, temp);

  //  Blur horizontally into buffer

  for(j=0; j<256; j++)
  {
    b = g = r = 0;

    for(i=-radius; i<=radius; i++)
    {
      b += src->buf[j][i&255][0];
      g += src->buf[j][i&255][1];
      r += src->buf[j][i&255][2];
    }

    for(i=0; i<255; i++)
    {
      temp->buf[j][i][0] = b/diameter;
      temp->buf[j][i][1] = g/diameter;
      temp->buf[j][i][2] = r/diameter;

      b -= src->buf[j][(i-radius)&255][0];
      g -= src->buf[j][(i-radius)&255][1];
      r -= src->buf[j][(i-radius)&255][2];

      b += src->buf[j][(i+1+radius)&255][0];
      g += src->buf[j][(i+1+radius)&255][1];
      r += src->buf[j][(i+1+radius)&255][2];
    }
  }

  //  Blur vertically

  for(i=0; i<256; i++)
  {
    b = g = r = 0;

    for(j=-radius; j<=radius; j++)
    {
      b += temp->buf[j&255][i][0];
      g += temp->buf[j&255][i][1];
      r += temp->buf[j&255][i][2];
    }

    for(j=0; j<255; j++)
    {
      dest->buf[j][i][0] = b/diameter;
      dest->buf[j][i][1] = g/diameter;
      dest->buf[j][i][2] = r/diameter;

      b -= temp->buf[(j-radius)&255][i][0];
      g -= temp->buf[(j-radius)&255][i][1];
      r -= temp->buf[(j-radius)&255][i][2];

      b += temp->buf[(j+1+radius)&255][i][0];
      g += temp->buf[(j+1+radius)&255][i][1];
      r += temp->buf[(j+1+radius)&255][i][2];
    }
  }

}





