Processing: Repeatedly painting 'transparent white' does not result in full white

Created on 15 Nov 2016  路  4Comments  路  Source: processing/processing

The same thing with 'transparent black'
How black or white the repainted section becomes is a function of the transparency of the fill color.

If you do the the same with transparent red, blue, green, the repeated painting eventually converges to full red, blue, green.

Processing 3.2.3, Windows 8, AMD A8, Acer E15.

The following sketch will demonstrate the problem.

void setup() {
  size(500,300,P3D); 
  fill(255);
  rect(0,0,250,300);
  fill(0);
  rect(250,0,250,300);
}

void draw() {
  noStroke();
  rectMode(CENTER);
  if(mouseX > 250) {
    fill(255,5);
    rect(mouseX,mouseY,50,50);
  } else {
    fill(0,5);
    rect(mouseX,mouseY,50,50);
  }
  rectMode(CORNER);
  for(int i = 0; i <= 480; i+=5) {
   int gray = (int)map(i, 0, 480, 0, 255);
   noStroke();
   fill(gray);
   rect(i, 0, 20,40);
  }
}

Most helpful comment

You shoud use blendMode(ADD) if you want additive blending. Default blending mixes the two colors as follows: result = dest * (1 - srcAlpha) + src * (srcAlpha) (where colors are mapped form 0-255 to 0.0-1.0).

All 4 comments

Isn't this _expected_ due to Zeno's Paradox + rounding?

Pixels are repeatedly washed with a low alpha -- each time getting 2% of the way closer to the target color. Initially that 2% step is 5, then 4, 3, 2, 1... The pixels never reach 100% value because, at a certain distance, the next step is so small that it drops below the rounding error. In this case that value is ~25 -- (25/255)*0.02 = .00019, so the color never gets darker than 25. Same math applied in the opposite direction means never getting whiter than 230 (255-25). If the alpha was a different value, change would converge and stop at a different distance.

Whether this is expected or not, here is a simple inspector based on your code. It stops and prints the result once repeated applications of the color no longer have an effect. Trying changing "alpha" to change the convergence point.

// Repeat Transparent Color Convergence
// https:// github.com/processing/processing/issues/4743
// blacker and whiter squares stall out at (25,25,25) and (230,230,230)
color c1, c2;
color prev1, prev2;
int alpha = 5;

void setup() {
  size(400,200); 
  noStroke();
  textAlign(CENTER,CENTER);
  frameRate(15);
  background(128);
}
void draw() {
  // wash blacker
  fill(0,alpha);
  rect(0,0,width/2,height);
  // wash whiter
  fill(255,alpha);
  // reference strip
  rect(width/2,0,width,height);
  for(int i = 0; i <= 480; i+=5) {
    int gray = (int)map(i, 0, 480, 0, 255);
    noStroke();
    fill(gray);
    rect(i, 0, 20,40);
  }
  // console inspector
  c1 = get(width/4,height/2);
  c2 = get(3*width/4, height/2);
  println(red(c1),green(c1),blue(c1),"  |  ", red(c2),green(c2),blue(c2));
  // stop when no longer changing
  if(prev1 == c1 && prev2 == c2){
    fill(255);
    text(red(c1)+" "+green(c1)+" "+blue(c1),width/4,height/2);
    fill(0);
    text(red(c2)+" "+green(c2)+" "+blue(c2),3*width/4, height/2);
    noLoop();
  }
  prev1 = c1;
  prev2 = c2;
}

transparentcolorconvergence

If you do the the same with transparent red, blue, green, the repeated painting eventually converges to full red, blue, green.

By the way, this would be an inconsistency if it was true, but it not true. Just change the test sketch to fill(255,0,0,alpha) -- you'll see that the red channel converges on (230,25,25).

By the way, this would be an inconsistency if it was true, but it not true. Just change the test sketch to fill(255,0,0,alpha) -- you'll see that the red channel converges on (230,25,25).

Ah! You are right. I thought for sure I confirmed that it did converge to full red/green/blue! Sorry about that.

Isn't this expected due to Xeno's Paradox + rounding?

Hmmm. I thought painting with 5/255 alpha means you add 5/255 over and over, until you hit the 255 ceiling.
What is the repeated operation that is happening on that initial transparent white that takes it from 130 to 230 and stay at 230? (reading from your print outs)

You shoud use blendMode(ADD) if you want additive blending. Default blending mixes the two colors as follows: result = dest * (1 - srcAlpha) + src * (srcAlpha) (where colors are mapped form 0-255 to 0.0-1.0).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

TheErrorScript picture TheErrorScript  路  5Comments

sjaustirni picture sjaustirni  路  5Comments

sk0028 picture sk0028  路  4Comments

GoldenQubicle picture GoldenQubicle  路  8Comments

danieltorrer picture danieltorrer  路  10Comments