Xiaolin Wu line algorithm for antialiasing

On my hard way to implement antialiasing, I found this algorithm from Xaolin Wu, but the problem is on the alpha value gestion, it’s very weird. when I put the value alpha it’s transparency and when I multiply by the alpha rang of my sketch it’s like the is no anti-alias.
You can try the both option to see my problem.

If anybody have an idea…that’s can be great.

void plot(PImage img, double x, double y, double alpha) {
  //float a = (float)alpha;
  // float a = (float)alpha *g.colorModeA *.1;
  int col = color(255,0,0,a);
  img.loadPixels();
  int rank = (int)x + (int)y * img.width;
  img.pixels[rank] = col;
  img.updatePixels();
}

original source
there is an other but it’s very buggy

my full sketch

void setup() {
  size(350,300);
}

void draw() {
  background(255);
  wuline(g,width/2,height/2,mouseX,mouseY);
}

int ipart(double x) {
  return (int) x;
}
 
double fpart(double x) {
  return x - Math.floor(x);
}
 
double rfpart(double x) {
  return 1.0 - fpart(x);
}

void wuline(PImage img, double x_0, double y_0, double x_1, double y_1) {
  boolean steep = Math.abs(y_1 - y_0) > Math.abs(x_1 - x_0);
  double t;
  if (steep) {
    t = y_0; 
    y_0 = x_0; 
    x_0 = t;
    t = y_1; 
    y_1 = x_1; 
    x_1 = t;
  }
  
  if (x_0 > x_1) {
    t = x_0; 
    x_0 = x_1; 
    x_1 = t;
    t = y_0; 
    y_0 = y_1; 
    y_1 = t;
  }

  double dx = x_1 - x_0;
  double dy = y_1 - y_0;
  double gradient = dy / dx;

  // handle first endpoint
  int x_end_0 = (int)Math.round(x_0);
  double y_end_0 = y_0 + gradient * (x_end_0 - x_0);
  double x_gap_0 = rfpart(x_0 + 0.5);
  pixel_wu(img, steep, x_end_0, y_end_0, x_gap_0);

  // handle second endpoint
  int x_end_1 = (int)Math.round(x_1);
  double y_end_1 = y_1 + gradient * (x_end_1 - x_1);
  double x_gap_1 = fpart(x_1 + 0.5);
  pixel_wu(img, steep, x_end_1, y_end_1, x_gap_1);

  // main loop
    // first y-intersection for the main loop
  double intery = y_end_0 + gradient;
  for (int x = x_end_0 ; x <= x_end_1 ; x++) {
    double gap = 1.0;
    pixel_wu(img, steep, x, intery, gap);
    intery += gradient;
  }
}

void pixel_wu(PImage img, boolean steep, int x, double intery, double gap) {
  double alpha = g.colorModeA;
  if (steep) {
    alpha = rfpart(intery) * gap;
    plot(img, ipart(intery) + 0, x, alpha);
    alpha = fpart(intery) * gap;
    plot(img, ipart(intery) + 1, x, alpha);
  } else {
    alpha = rfpart(intery) * gap;
    plot(img, x, ipart(intery) + 0, alpha);
    alpha = fpart(intery) * gap;
    plot(img, x, ipart(intery) + 1, alpha);
  }
}

void plot(PImage img, double x, double y, double alpha) {
 //  float a = (float)alpha;
  float a = (float)alpha *g.colorModeA;
  int col = color(255,0,0,a);
  img.loadPixels();
  int rank = (int)x + (int)y * img.width;
  img.pixels[rank] = col;
  img.updatePixels();
}
1 Like

Ok I found the problem, is from the pixel refresh.
The solution is here

int ipart(double x) {
  return (int) x;
}
 
double fpart(double x) {
  return x - Math.floor(x);
}
 
double rfpart(double x) {
  return 1.0 - fpart(x);
}
 
void draw_line_aa_wu(PImage img, double x_0, double y_0, double x_1, double y_1) {
  img.loadPixels();
  boolean steep = Math.abs(y_1 - y_0) > Math.abs(x_1 - x_0);
  double buffer;
  if (steep) {
    buffer = y_0;
    y_0 = x_0; 
    x_0 = buffer;
    buffer = y_1; 
    y_1 = x_1; 
    x_1 = buffer;
  }
  
  if (x_0 > x_1) {
    buffer = x_0; 
    x_0 = x_1; 
    x_1 = buffer;
    buffer = y_0; 
    y_0 = y_1; 
    y_1 = buffer;
  }

  double dx = x_1 - x_0;
  double dy = y_1 - y_0;
  double gradient = dy / dx;

  // handle first endpoint
  int x_end_0 = (int)Math.round(x_0);
  double y_end_0 = y_0 + gradient * (x_end_0 - x_0);
  double x_gap_0 = rfpart(x_0 + 0.5);
  pixel_wu(img, steep, x_end_0, y_end_0, x_gap_0);

  // handle second endpoint
  int x_end_1 = (int)Math.round(x_1);
  double y_end_1 = y_1 + gradient * (x_end_1 - x_1);
  double x_gap_1 = fpart(x_1 + 0.5);
  pixel_wu(img, steep, x_end_1, y_end_1, x_gap_1);

  // main loop
    // first y-intersection for the main loop
  double intery = y_end_0 + gradient;
  for (int x = x_end_0 ; x <= x_end_1 ; x++) {
    double gap = 1.0;
    pixel_wu(img, steep, x, intery, gap);
    intery += gradient;
  }
  img.updatePixels();
}

void pixel_wu(PImage img, boolean steep, int x, double intery, double gap) {
  double alpha = 0;
  if (steep) {
    alpha = rfpart(intery) * gap;
    plot(img, ipart(intery) + 0, x, alpha);
    alpha = fpart(intery) * gap;
    plot(img, ipart(intery) + 1, x, alpha);
  } else {
    alpha = rfpart(intery) * gap;
    plot(img, x, ipart(intery) + 0, alpha);
    alpha = fpart(intery) * gap;
    plot(img, x, ipart(intery) + 1, alpha);
  }
}

void plot(PImage img, double x, double y, double alpha) {
  float a = (float)alpha;
  int px = (int)x;
  int py = (int)y;
  int bg = get(px,py);
int colour = color(255,0,0);
  int col = mixer(bg,colour,a);
  int rank = (int)x + (int)y * img.width;
  g.pixels[rank] = col;  
}

method mixer

int mixer(int o, int d, float threshold) {
  if(g.colorMode == 1) {
    float x = gradient_value(red(o),red(d),threshold);
    float y = gradient_value(green(o),green(d),threshold);
    float z = gradient_value(blue(o),blue(d),threshold);
    return color(x,y,z);
  } else {
    float x = gradient_value(hue(o),hue(d),threshold);
    float y = gradient_value(saturation(o),saturation(d),threshold);
    float z = gradient_value(brightness(o),brightness(d),threshold);
    return color(x,y,z);
  }
}

float gradient_value(float origin, float destination, float threshold) {
  float gradient = origin;
  float range = origin - destination;
  float power = range * threshold;
  return gradient - power;
}
3 Likes