1

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.

aJynks
  • 677
  • 2
  • 14
  • 27
  • possible duplicate of [Shift hue of an RGB Color](http://stackoverflow.com/questions/8507885/shift-hue-of-an-rgb-color) – MasterHD Sep 15 '15 at 10:52

3 Answers3

2

Convert RGB to HSL or HSV, modify the hue, then convert the result back to RGB.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
2

With a bit googling I've found this 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);
}

Edit: Removed unnecessary casts.

Edit: Got rid of the matrix.

Edit: 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;
}
Community
  • 1
  • 1
Lukas
  • 2,461
  • 2
  • 19
  • 32
1

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.

user1118321
  • 25,567
  • 4
  • 55
  • 86
  • You can think of an RGB value as a 3D point in a space defined by the R-axis, the G-axis, and the B-axis. You can then rotate that 3D point around an arbitrary axis (and infinite line of any orientation, passing through the origin). See [here](http://inside.mines.edu/~gmurray/ArbitraryAxisRotation/) for details of how to do an arbitrary rotation. The matrix at the end looks scary, but once you calculate a few sines and cosines once, it becomes pretty simple. Just remember to normalize the vector <1,1,1> before doing the calculation. – user1118321 Jul 12 '12 at 19:44
  • It's easier to see how this works for big rotations. Say we start with {50, 100, 150}. We can rotate this to {150, 50, 150} and then to {100, 150, 50}. This rotation is equivalent to multiplying by the matrix {{0,1,0}, {0,0,1}, {1,0,0}}. – MSalters Jul 13 '12 at 08:26