Color - changing RGB values when in HSB colorMode

I have produced this crude and simple sketch to get and change a RGB value when I am in HSB colorMode. Later I will use bit shifting instead of green() and so on.

But before I build on this, is this the best way to do this?

noStroke();
colorMode(HSB, 360, 100, 100);
color blah = color(204, 100, 100);
background(blah);
println(hue(blah) +", "+ saturation(blah) +", "+ brightness(blah)); // 204.2353, 100.0, 100.0
println(red(blah) +", "+ green(blah) +", "+ blue(blah)); // 0.0, 59.607845, 100.0

//can I change green()? yes.

// get the RGB value when in HSB mode then change it
float greenValue = green(blah);  
println(greenValue);  // 59.607845
greenValue = greenValue + 10;
println(greenValue);  // 69.607845

// switch to RGB to change the green (G)
colorMode(RGB, 255, 100, 100); // is 255 correct?

// Use 'greenValue' in new fill
fill(0, greenValue, 0);  
rect(50, 20, 35, 60);

// return to HSB
colorMode(HSB, 360, 100, 100);
1 Like

Hello,

References:
https://processing.org/tutorials/color/
https://processing.org/reference/color_.html
https://processing.org/reference/colorMode_.html

Update: Added below to be thorough and for those that glean through the forums for information.

The references also have a “color” section:
https://processing.org/reference/


:slight_smile:

1 Like

Maybe you should take a look at this :
https://processing.org/reference/pushStyle_.html

If i understood you correctly, then this does pretty much what you want… i think… unless it‘s about specifically changing RGB colors without switching to RGB Mode?

1 Like

Thanks @glv and @Lexyth
Yes, I do want to change RGB values without switching to RGB mode. pushStyle() might well be the way to go but first I wanted to analyse my current method. One or two interesting observations.

I started in HSB and used values of (211, 76, 81). Strangely, when I do this and look at the RGB values the Blue value is exactly the same as the Brightness value (80.78432). Is this just some very unlikely coincidence?

size(200,100);
colorMode(HSB, 360, 100, 100);
color blah = color(211, 76, 81);
background(blah);
println(hue(blah) +", "+ saturation(blah) +", "+ brightness(blah)); // 210.95541, 76.21359, 80.78432
println(red(blah) +", "+ green(blah) +", "+ blue(blah)); // 69.176476, 49.019608, 80.78432 (50, 126, 206)

float redValue = red(blah);  
float greenValue = green(blah);  
float blueValue = blue(blah);  

colorMode(RGB, 255, 255, 255);
/*
does not matter what I have here if I use red(blah)
then red(blah) will be correct in the fill
if I use redValue, etc. I need to remap to values of colorMode RGB
*/

  
fill((redValue/360)*255,(greenValue/100)*255,(blueValue/100)*255);
rect(35, 20, 40, 60);// left

fill(redValue,greenValue,blueValue);
rect(80, 20, 40, 60);// centre

fill(red(blah),green(blah),blue(blah));
rect(125, 20, 40, 60);// right

// return to HSB
colorMode(HSB, 360, 100, 100); 

// save the image
//save("blue_image.jpg");

You can see that it is a very unlikely coincidence by changing the Hue. I changed it from 211 to 359 and the brightness wasn‘t equal to blue() anymore. It seems that a Hue of 211 causes the calculation of brightness() and blue() to have the same result (although i don‘t know the exact formula.

As for how the Color class works, it has a value of -1 to ~ -16 million and the red() is calculated from this number. So while red() accesses this number to calculate the value, redValue does not. It has basically the same effect as remapping redValue, that‘s also why the first and 3rd rects are equal in color.

Yes, but perhaps it is not so unlikely. I used a for loop to test for all hues between 0° and 360° and the brightness () equals the blue () from 180 to 300. This is so for brightness values other than 81.


size(200,100);
colorMode(HSB, 360, 100, 100);
for (int i = 180; i <= 300; i++) {
  color blah = color(i, 76, 60);

background(blah);
println(hue(blah) +", "+ saturation(blah) +", "+ brightness(blah)); // 60.000004
println(red(blah) +", "+ green(blah) +", "+ blue(blah)); // 60.000004

}

If you really don’t want to use pushStyle / popStyle, then bit-shifting is definitely the way to go – in both directions (extracting the color value, and building the fill value). If you want to use red() it is scaled to match current colorMode, and fill() accepts arguments in the current colorMode – so just bypass both. Then you can leave your sketch in HSB colorMode the entire time.

colorMode() doesn’t change the underlying data in the pixels array, only the way it is interpreted by helper methods. Since your goal is to copy color information from this, skipping the mode entirely:

AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB

To, for example, a color channel:

FFFFFFFFRRRRRRRR0000000000000000

Here is an example:

/** RGB in HSB mode
 *  2019-11-11 Processing 3.4
 *  Display the red channel of any pixel, while in HSB colorMode.
 */

int maxH = 360;
PImage img;
void setup(){
  size(200,200);
  img = loadImage("https://processing.org/img/processing3-logo.png");
  img.resize(200,200);
  colorMode(HSB, maxH, 100, 100);  // set HSB colormode
}

void draw() {
  image(img, 0, 0);
  int rval = int(red(get(mouseX, mouseY)) *  255 / float(maxH));  // retrieve scaled r value
  int rcolor = (255 << 24) + (rval << 16);  // alpha + r channel  // build r channel value
  fill(rcolor);
  rect(0, 0, 50, 50);
}

Edit

Oops, sorry, meant to also include the version showing an alternative to red() with bit shifting:

/** RGB in HSB mode
 *  2019-11-11 Processing 3.4
 *  Display the red channel of any pixel, while in HSB colorMode.
 */
PImage img;
void setup(){
  size(200,200);
  img = loadImage("https://processing.org/img/processing3-logo.png");
  img.resize(200,200);
  colorMode(HSB, 360, 100, 100);
}

void draw() {
  image(img, 0, 0);
  // int rval = int(red(get(mouseX, mouseY)) *  255 / g.colorModeX);  // retrieve scaled r value and rescale to 255
  int rval = get(mouseX, mouseY) >> 16 & 0xFF;  // retrieve direct 8-bit (255) r value,
  int rcolor = (255 << 24) + (rval << 16);  // alpha + r channel  // build r channel value
  fill(rcolor);
  rect(0, 0, 50, 50);
}

I have also included a commented out lined demonstrating scaling red() using g.colorModeX – thanks @Lexyth.

2 Likes

add comment: ( please correct me if wrong )

processing JAVA can use

red(c), green(c),blue(c), hue(c),saturation(c),brightness(c)

and it does not matter if color mode RGB or HSB

recently i try that with p5.js and failed.

Yes, it works. I used it in my latest topic.

2 Likes

It works because color is always stored in 32-bit and the colors are just calculated from those bits. Like @jeremydouglass posted, the bits are in 4 parts, for Alpha,Red,Green and Blue.

So green() would just take the 16th to 24th bit, while hue () does some calculation with all the 8bit (32bits / 4parts) Parts and gives out the correct value. So the current colorMode doesn‘t affect anything in this case. It just affects how you set and get the complete color, but not specific parts.

2 Likes

yes, i should have said like " only the number range and thinking change?"


isn’t it sad that you can not ask what mode / range is active?

Just some things I learned from my latest work.
You really need to push and pop, because it’s easy to get an error with the range. The same range is applied from one mode to the other.
Also using convertion with red() etc. will sometimes give a (very slight) difference from the original color.

You should actually be able to, if i didn‘t get that wrong. Try using

int colormode = this.g.colorMode;
float redHue = this.g.colorModeX; //these are the range
float greenSaturation = this.g.colorModeY;
float blueValue = this.g.colorModeZ; // i assume value means brightness...
float alpha = this.g.colorModeA;

This should work.

Edit :
colormode is the colorMode represented as int.
colormodeX is the Range of red/hue depending on the current colormode you‘re in.
colormodeY is the range for green/saturation.
colorModeZ is the range for blue/brightness.
colorModeA is the alpha range.

3 Likes

Printing

println(g.colorModeX);
println(g.colorModeY);
println(g.colorModeZ);
println(g.colorModeA);

gives the ranges for both modes.
red, green, blue, alpha or hue saturation, brightness alpha.
I could not find anything to get the actual mode hsb or rgb. Any idea?

EDIT It seems that println(g.colorMode); gives 1 for RGB and 3 for HSB.

1 Like

Yes, you can find RGB (=1) ARGB (=2) and HSB (=3) defined in PConstants.

https://processing.github.io/processing-javadocs/core/constant-values.html#processing.core.PConstants.ALPHA

So you can test and then execute depending on the current colorMode with:

if(g.colorMode == HSB){
  // do this ...
}

or

switch(g.colorMode) {
  case RGB: 
    println("red green blue!");
    break;
  case ARGB: 
    println("alpha red green blue!");
    break;
  case HSB: 
    println("hue saturation brightness!");
    break;
  default:
    println("warning: octarine mode!");  
}
4 Likes

Thank you all. The code and the advice are super helpful. Before I start to use both I have two questions (one small and one big).

@jeremydouglass says, “colorMode() doesn’t change the underlying data in the pixels array, only the way it is interpreted by helper methods.” And @Lexyth says, “hue() does some calculation with all the 8bit (32bits / 4parts) Parts and gives out the correct value.”

So, small question, does it make more sense to work in RGB mode and find the value of H, S, and B when I need to (rather than work in HSB mode and find the value of R, G, or B when needs be)?

Then, large question, as there are methods for calculating Hue(), Saturation(), and Brightness() from the underlying ARGB, are there also methods for the calculation of other values such as Chroma?

My reason for asking is that I am trying to make a tool that will analyse colours using different colour spaces (Hue-Chroma-Lightness, etc.) and display the analysis in an accessible way.

1 Like

Hi @noel, what was your latest topic? It would be interesting to see.

There are several colorspace libraries for Processing (& Java).

For one example, check out Chroma: https://github.com/neilpanchal/Chroma – see also Colorblindness https://ixora.io/projects/colorblindness/ – and also this CIELAB color space sketch.

Regarding bit-shifting etc., you are trying to make a tool (instead of doing this as a leraning exercise) then I’m wondering why not use the existing API – red(), brightness() etc. all work as intended, and you can use pushStyle() / popStyle() to reconfigure the colorMode (and thus, the return values on those methods) during each phase of analysis. Is something running slowly so that you feel the need to optimize further?

The methods for calculating HSB in Processing are in its source code – you can just copy them out and fiddle with them, if you like. Here is hue():

…which is actually using a method from import java.awt.Color; – you could use that method to, or look at it’s source code (or the OpenJDK equivalent) and use it to write your own.

1 Like

It’s a Color Picker for Processing Android. I have chosen a HSB model because I think it is more intuitive. But Android doesn’t except HSB. It can handle HSV, but the normal way is RGB… you can find it here.

1 Like

Thanks (I will explore), Is there a typo here: “Using color converting between HSB and ROB”?