How to debug smooth color change in processing?

I have written code in which the stroke color should transition smoothly through red, orange, yellow, green etc. in a loop. The rest of the code works perfectly but I am having issues attaining the color transitions.

It’s expected that the Red value increases by 1 until it reaches 255, where it stays as the Green value does the same. Then the Red value should begin the decrease by 1 whilst the Green remains at 255.

The issue with the code is that the Red and Green values will both increase as necessary, but no matter what I try, I can’t get the Red value to decrease.

Any input will be greatly appreciated. Please note I believe the issues lie in the code block at the end after the line marked //color transitions. I have also posted this question on Stack Overflow here: How to debug smooth color change in processing? - Stack Overflow

float angNoise, radiusNoise;
float xNoise, yNoise;
float angle = -PI/2;
float radius;
int red = 0;
int blue = 0;
int green = 0;
int redValue = 1;
int greenValue = 1;
int blueValue = 1;
int colorMode = 1;

void setup(){
  size(800, 600);
  smooth();
  frameRate(24);
  background(0);
  noFill();
  
  angNoise = random(10);
  radiusNoise = random(10);
  xNoise = random(10);
  yNoise = random(10);
}

void draw(){
  radiusNoise += 0.005;
  radius = (noise(radiusNoise)*550)+1;
  
  angNoise += 0.005;
  angle += (noise(angNoise)*6)-3;
  if(angle > 360){ angle -= 360; }
  if(angle < 0){ angle += 360; }
  
  xNoise += 0.01;
  yNoise += 0.01;
  float centerX = width/2 +(noise(xNoise)*100)-50;
  float centerY = height/2 +(noise(yNoise)*100)-50;
  
  float rad = radians(angle);
  float x1 = centerX + (radius*cos(rad));
  float y1 = centerY + (radius*sin(rad));
  
  float opprad = rad + PI;
  float x2 = centerX + (radius*cos(opprad));
  float y2 = centerY + (radius*sin(opprad));
  
  //color transitions
  stroke(red, green, blue); //60);
  strokeWeight(2);
  ellipse(x1, y1, x2, y2);
  //color mode 1 (red)
  if (colorMode == 1){blueValue = -1;
  if (red == 255 && blue == 0) {colorMode++;}
  if (red == 0) {redValue = +1;}
  red += redValue;}
  //color mode 2 (green)
  if (colorMode == 2){redValue = -1;
  if (green == 255 && red == 0) {colorMode++;}
  if (green == 0) {greenValue = +1;}
  green += greenValue;}
  //color mode 3 (blue)
  if (colorMode == 3){greenValue = -1;
  if (blue == 255 && green == 0) {colorMode++;}
  if (blue == 0) {blueValue = +1;}
  blue += blueValue;}
  if (colorMode > 3) {colorMode =1;}
  }

Hi,

Welcome to the forum! :wink:

If I recap, you want your colors to do this :

red  green  blue
 0     0     0
 |     |     |
 v     v     v
255    0     0
 |     |     |
 v     v     v
255   255    0
 |     |     |
 v     v     v
 0    255    0
 |     |     |
 v     v     v
 0    255   255
 |     |     |
 v     v     v
 0     0    255
 |     |     |
 v     v     v
 0     0     0

So one color increase then another one and they alternate.

So basically every step above can be described as a one if condition like the following :

if (red < 255 && green == 0 && blue == 0) {
  red++;
}

if (red == 255 && green < 255 && blue == 0) {
  green++;
}

if (red > 0 && green == 255 && blue == 0) {
  red--;
}

if (red == 0 && green == 255 && blue < 255) {
  blue++;
}

if (red == 0 && green > 0 && blue == 255) {
  green--;
}

if (red == 0 && green == 0 && blue > 0) {
  blue--;
}

This is maybe not the most elegant way to do this but it works!
So doing this in a loop is going to increase and decrease the colors and repeat infinitely!

If you would plot those colors with vertical lines, you would get this :

Which is pretty cool! :grinning: (note that it’s fading to black here so it’s not a real color spectrum but it’s what you wanted)


Bonus, here is another technique to generate rainbow colors with RGB values : :rainbow: :rainbow_flag:

// The array of colors (here red, green, blue)
int[] colors = {255, 0, 255};

// The index of the current color
int currentColorIndex = 0;

// We start decreasing the previous color
boolean decreasePrev = true;
boolean increaseNext = false;

void colorStep() {
  if (decreasePrev) {
    int prevIndex = currentColorIndex - 1;
    if (prevIndex < 0) prevIndex = colors.length - 1;

    colors[prevIndex]--;

    // Finished decreasing color
    if (colors[prevIndex] == 0) {
      decreasePrev = false;
      increaseNext = true;
    }
  } else if (increaseNext) {
    // Increase next color, wrap index if necessary
    int nextIndex = (currentColorIndex + 1) % colors.length;
    colors[nextIndex]++;

    // Finished increasing next
    if (colors[nextIndex] == 255) {
      increaseNext = false;
      decreasePrev = true;

      // Go to next color
      currentColorIndex = nextIndex;
    }
  }
}

void setup() {
  // The width is 6 * 255 which is the number of steps
  size(1530, 200);

  for (int i = 0; i < width; i++) {
    stroke(color(colors[0], colors[1], colors[2]));
    line(i, 0, i, height);
    
    colorStep();
  }

  noLoop();
}

In this case it goes from purple to purple and can be generalized to a larger array of values :wink:

(Note that for this it would be easier to use HSV values and change the hue parameter but the challenge was fun!)

my version



float angNoise, radiusNoise;
float xNoise, yNoise;
float angle = -PI/2;
float radius;

int red = 0;
int blue = 0;
int green = 0;

int redValue = 1;
int greenValue = 1;
int blueValue = 1;

int colorMode = 1;

void setup() {
  size(800, 600);
  smooth();
  frameRate(24);
  background(0);
  noFill();

  angNoise = random(10);
  radiusNoise = random(10);
  xNoise = random(10);
  yNoise = random(10);
}

void draw() {
  radiusNoise += 0.005;
  radius = (noise(radiusNoise)*550)+1;

  angNoise += 0.005;
  angle += (noise(angNoise)*6)-3;
  if (angle > 360) { 
    angle -= 360;
  }
  if (angle < 0) { 
    angle += 360;
  }

  xNoise += 0.01;
  yNoise += 0.01;
  float centerX = width/2 +(noise(xNoise)*100)-50;
  float centerY = height/2 +(noise(yNoise)*100)-50;

  float rad = radians(angle);
  float x1 = centerX + (radius*cos(rad));
  float y1 = centerY + (radius*sin(rad));

  float opprad = rad + PI;
  float x2 = centerX + (radius*cos(opprad));
  float y2 = centerY + (radius*sin(opprad));

  //color transitions
  stroke(red, green, blue); //60);
  strokeWeight(2);
  ellipse(x1, y1, x2, y2);

  //color mode 1 (red)
  if (colorMode == 1) {
    blueValue = -1;
    if (red == 255) {
      colorMode++;
      println("go 2");
      red=0; // ?????
    }
    if (red == 0) {
      redValue = +1;
    }
    if (colorMode == 1)
      red += redValue;
  }
  //color mode 2 (green)
  else if (colorMode == 2) {
    redValue = -1;
    if (green == 255) {
      println("go 3"); 
      colorMode++;
      green=0; // ?????
    }
    //if (green == 0) {
    greenValue = +1;
    //}
    green += greenValue;
  }
  //color mode 3 (blue)
  else if (colorMode == 3) {
    greenValue = -1;
    if (blue == 255) {
      colorMode++;
      println("go 4");
      blue = 0;
    }
    //if (blue == 0) {
    blueValue = +1;
    //}
    blue += blueValue;
  } else if (colorMode > 3) {
    colorMode = 1;//reset
  }
}
//