FAQ
Cover
This is the archive Discourse for the Processing (ALPHA) software.
Please visit the new Processing forum for current information.

   Processing 1.0 _ALPHA_
   Programming Questions & Help
   Programs
(Moderators: fry, REAS)
   TomC's fade2anycolour: why is it just greying out?
« Previous topic | Next topic »

Pages: 1 
   Author  Topic: TomC's fade2anycolour: why is it just greying out?  (Read 1985 times)
lunetta

7200475272004752 WWW Email
TomC's fade2anycolour: why is it just greying out?
« on: Nov 28th, 2004, 3:41am »

Hi
 
I was exploring TomC's fade2anycolour sketch, and I have a question about it. My brain suffers from severe bitshiftitis, a rare disease where bit shifting operations are admired but not fully understood.
 
The problem is this:
I'm trying to fade things to white, in a slow rate.
 
Changing the "shift" variable to a higher level makes the screen fade to a gray level and stop; If I set the shift to 6, for an example, it just fade a percentage of the screen, and beyond that point it stays forever.
 
Check my changed code:
 
Quote:

int eliipseX = 0;
int eliipseY = 0;
 
void setup() {
background(255,255,255);
  size(640,480);
  ellipseMode(CENTER_DIAMETER);
  fill(#ff0000);
  stroke(#000000);
}
 
void loop() {
  fadescr(255,255,255);
  ellipse(eliipseX,eliipseY,250,250);
  eliipseX += (mouseX - eliipseX) / 8;
  eliipseY += (mouseY - eliipseY) / 8;
}
 
void fadescr(int r, int g, int b) {  
  int red, green, blue;
  for (int i = 0; i < pixels.length; i++) {
    red = (pixels[i] >> 16) & 0x000000ff;  
    green = (pixels[i] >> & 0x000000ff;  
    blue = pixels[i] & 0x000000ff;  
    int shift = 5;
    pixels[i] = (((red+((r-red)>>shift)) << 16) | ((green+((g-green)>>shift)) << | (blue+((b-blue)>>shift)));
  }  
}  

 
PS: I don't know how to turn off the smileys on the forum...
 
TomC

WWW
Re: TomC's fade2anycolour: why is it just greying
« Reply #1 on: Nov 28th, 2004, 9:23pm »

In summary, the problem arises because it's using integer differences and a large bit-shift.  You'll probably need to modify it if you want a slower fade, or use a different technique.
 
-------  
 
Longer explanation, without covering the binary (see elsewhere on this board for that).
 
A shift of n bits to the rightis the same as integer division by 2 to the power n.
 
That means that shifting a number 1 bit to the right is the same as diving by 2.  It means that shifting a number 5 bits to the right is the same as integer division by 32.
 
The fadedscr code is slightly sloppy (at the benefit of speed), in that because of the integer shifts, it throws away some information.  It works by adding on a certain fraction of the difference between the target colour and the current colour.  If you use a value of 5 for the shift, then when the difference is less than 32, no change will occur.  You could fix this by using 1 if the difference is less than 32 and greater than 0 (but remember the difference could be negative).
 
Try this to see if it helps you understand a bitshift.
 
Code:

 
int a = 255;
 
println(a >> 1);
println(a / int(pow(2,1)));
println(a / 2);
 
println(a >> 2);
println(a / int(pow(2,2)));
println(a / 4);
 
println(a >> 3);
println(a / int(pow(2,3)));
println(a / 8);
 
println(a >> 4);
println(a / int(pow(2,4)));
println(a / 16);
 
println(a >> 5);
println(a / int(pow(2,5)));
println(a / 32);
 

 
Each set of 3 should be the same value.
 
Here's a slightly longer version of the same function, with meaningful variable names.
 
Code:

 
void fadescr(int targetR, int targetG, int targetB) {  
  int currentR, currentG, currentB;
  int diffR, diffG, diffB;
  int changeR, changeG, changeB;
  int newR, newG, newB;
  int shift = 5;
  for (int i = 0; i < pixels.length; i++) {
    // 1. Get colour compnents
    // (same as calling red()/green()/blue(),  
    // but faster if in colorMode(RGB,255), and using ints)
    currentR = (pixels[i] >> 16) & 0x000000ff;  
    currentG = (pixels[i] >> 8) & 0x000000ff;  
    currentB = pixels[i] & 0x000000ff;
    // 2. Get difference between current and target
    diffR = targetR - currentR;
    diffG = targetG - currentG;  
    diffB = targetB - currentB;
    // 3. Calculate change as a fraction of the difference (using the shift value from above)
    changeR = diffR >> shift;
    changeG = diffG >> shift;
    changeB = diffB >> shift;
    // 4. Calculate the new colour
    newR = currentR + changeR;
    newG = currentG + changeG;
    newB = currentB + changeB;
    // 5. Put the components back together again
    // (same as color(newR,newG,newB) in colorMode(RGB,255), but faster with ints
    pixels[i] = (newR << 16) | (newG << 8) | newB;
  }  
}  
 

 
At step 3, for a shift of 5 (division by 32), you might spot that if the difference between the current colour component and the target colour compnent is less than 32, then the change will be 0.  
 
In this case there are a number of things you could try, such as varying the shift size as the current colour approaches the target colour, but all will slow down the function somewhat.
 
« Last Edit: Nov 28th, 2004, 9:26pm by TomC »  
lunetta

7200475272004752 WWW Email
Re: TomC's fade2anycolour: why is it just greying
« Reply #2 on: Nov 28th, 2004, 9:45pm »

very nice, thanks for the feedback.
I'll spend some time exploring this trying to cure my acute bitshiftitis.
 
 
TomC

WWW
Re: TomC's fade2anycolour: why is it just greying
« Reply #3 on: Nov 28th, 2004, 9:49pm »

A potential solution, seems quick enough.
 
Outside the for loop:
 
Code:

  int shift = 5;
  int mindiff = int(pow(2,shift));

 
Change to part 3:
 
Code:

 
    changeR = abs(diffR) >= mindiff ? diffR >> shift : diffR > 0 ? 1 : diffR < 0 ? -1 : 0;
    changeG = abs(diffG) >= mindiff ? diffG >> shift : diffG > 0 ? 1 : diffG < 0 ? -1 : 0;
    changeB = abs(diffB) >= mindiff ? diffB >> shift : diffB > 0 ? 1 : diffB < 0 ? -1 : 0;
 

 
The ternary operator (? and : construct) is just there to keep each calculation on one line.  This code is the long form for the red component and does exactly the same:
 
Code:

 
// changeR = abs(diffR) >= mindiff ? diffR >> shift : diffR > 0 ? 1 : diffR < 0 ? -1 : 0;
 
if (abs(diffR) >= mindiff) {
  changeR = diffR >> shift;
}
else if (diffR > 0) {
  changeR = 1;
}
else if (diffR < 0) {
  changeR = -1;
}
else {
  changeR = -1;
}
 

 
Pages: 1 

« Previous topic | Next topic »