87753

Cycle R,G,B vales as HUE?

Question:

I am using SFML and it has a color function that takes values in RGB. example.. (255,0,0). I would like to be able to cycle these numbers though a loop so that the displayed colour cycles though the hue...

So if I am using (76,204,63) the function will adjust those 3 numbers. So I need the function to intake rgb convert to HSV and then return rgb.

Any ideas how I would go about this?

the sfml code I wish to use is...

_sprite.setColor(76,204,63); This will set the sprite to a colour... I ma trying to work out how once that is done with those numbers to cycle the colour though the hue.

Answer1:

With a bit googling I've found <a href="https://stackoverflow.com/a/8510751/1034248" rel="nofollow">this</a> answer and converted the code to C++ with SFML in mind. I'm casting around pretty badly, so feel free to make it better. I guess it should even be possible to replace the 3x3 array.

sf::Uint8 clampAndConvert(float v) { if(v < 0) return 0; if( v > 255) return 255; return static_cast<sf::Uint8>(v); } sf::Color RGBRotate(sf::Color old, float degrees) { float cosA = cos(degrees*3.14159265f/180); float sinA = sin(degrees*3.14159265f/180); float rot = 1.f/3.f * (1.0f - cosA) + sqrt(1.f/3.f) * sinA; float rx = old.r * (cosA + (1.0f - cosA) / 3.0f) + old.g * rot + old.b * rot; float gx = old.r * rot + old.g * (cosA + 1.f/3.f*(1.0f - cosA)) + old.b * rot; float bx = old.r * rot + old.g * rot + old.b * cosA + 1.f/3.f * (1.0f - cosA); return sf::Color(clampAndConvert(rx), clampAndConvert(gx), clampAndConvert(bx), old.a); }

<strong>Edit:</strong> Removed unnecessary casts.

<strong>Edit:</strong> Got rid of the matrix.

<strong>Edit:</strong> As I've noticed the code doesn't really work as wanted, but here's a hardcoded solution that works perfectly, just isn't that compact and nice.

#include <SFML/Graphics.hpp> int main() { sf::RenderWindow Screen (sf::VideoMode (800, 600, 32), "Game", sf::Style::Close); Screen.setFramerateLimit(60); sf::RectangleShape rect(sf::Vector2f(350.f, 350.f)); rect.setPosition(150, 150); int dr = 0; int dg = 0; int db = 0; sf::Uint8 r = 255, g = 0, b = 0; while (Screen.isOpen()) { sf::Event Event; while (Screen.pollEvent (Event)) { if (Event.type == sf::Event::Closed) Screen.close(); } r += dr; g += dg; b += db; if(r == 255 && g == 0 && b == 0) { dr = 0; dg = 1; db = 0; } if(r == 255 && g == 255 && b == 0) { dr = -1; dg = 0; db = 0; } if(r == 0 && g == 255 && b == 0) { dr = 0; dg = 0; db = 1; } if(r == 0 && g == 255 && b == 255) { dr = 0; dg = -1; db = 0; } if(r == 0 && g == 0 && b == 255) { dr = 1; dg = 0; db = 0; } if(r == 255 && g == 0 && b == 255) { dr = 0; dg = 0; db = -1; } rect.setFillColor(sf::Color(r, g, b)); Screen.clear(); Screen.draw(rect); Screen.display(); } return 0; }

Answer2:

Convert <a href="http://www.easyrgb.com/index.php?X=MATH&H=18#text18" rel="nofollow">RGB to HSL</a> or <a href="http://www.easyrgb.com/index.php?X=MATH&H=20#text20" rel="nofollow">HSV</a>, modify the hue, then convert the result <a href="http://www.easyrgb.com/index.php?X=MATH&H=19#text19" rel="nofollow">back to RGB</a>.

Answer3:

Jerry's answer above is one correct way. If you don't care about preserving luminance (which if you do - don't use HSV, either), you can simply rotate your RGB color along the R=G=B axis. This is just a matrix multiply and saves you the conversion to and from HLS or HSV space.

Recommend