【问题标题】:Cycle R,G,B vales as HUE?循环 R、G、B 值作为 HUE?
【发布时间】:2012-07-12 18:45:04
【问题描述】:

我正在使用 SFML,它有一个颜色函数,可以采用 RGB 值。例如.. (255,0,0)。我希望能够通过循环循环这些数字,以便显示的颜色通过色调循环...

因此,如果我使用 (76,204,63),该函数将调整这 3 个数字。所以我需要将rgb转换为HSV然后返回rgb的函数。

有什么想法可以解决这个问题吗?

我希望使用的 sfml 代码是...

_sprite.setColor(76,204,63);这会将精灵设置为一种颜色...我正在尝试弄清楚如何使用这些数字完成这些数字以通过色调循环颜色。

【问题讨论】:

标签: c++ rgb hsv


【解决方案1】:

通过谷歌搜索,我找到了this 的答案,并将代码转换为 C++,同时考虑到 SFML。 我的选角很糟糕,所以请随时让它变得更好。我想它甚至应该可以替换 3x3 数组。

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);
}

编辑:删除了不必要的演员表。

编辑:摆脱了矩阵。

编辑:我注意到代码并没有真正按预期工作,但这是一个完美运行的硬编码解决方案,只是不是那么紧凑和漂亮。

#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;
}

【讨论】:

    【解决方案2】:

    转换RGB to HSLHSV,修改色调,再转换结果back to RGB

    【讨论】:

      【解决方案3】:

      上面杰里的回答是一种正确的方法。如果您不关心保留亮度(如果您这样做 - 也不要使用 HSV),您可以简单地沿 R=G=B 轴旋转 RGB 颜色。这只是一个矩阵乘法,可以节省您与 HLS 或 HSV 空间之间的转换。

      【讨论】:

      • 您可以将 RGB 值视为由 R 轴、G 轴和 B 轴定义的空间中的 3D 点。然后,您可以围绕任意轴(以及任何方向的无限线,通过原点)旋转该 3D 点。有关如何进行任意旋转的详细信息,请参阅here。最后的矩阵看起来很吓人,但是一旦你计算了几个正弦和余弦,它就变得非常简单。请记住在进行计算之前对向量 进行归一化。
      • 更容易看出这对于大旋转是如何工作的。假设我们从 {50, 100, 150} 开始。我们可以将其旋转到 {150, 50, 150},然后再旋转到 {100, 150, 50}。这种旋转相当于乘以矩阵 {{0,1,0}, {0,0,1}, {1,0,0}}。
      猜你喜欢
      • 1970-01-01
      • 2015-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-30
      • 2018-10-11
      相关资源
      最近更新 更多