Complementary colors, hue shift (RGB<->HSV conversion)

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
ent1ty
Competition winner
Posts: 1106
Joined: Sun Nov 08, 2009 11:09 am

Complementary colors, hue shift (RGB<->HSV conversion)

Post by ent1ty »

Code: Select all

 
/*
Copyright (c) 2014 Adam 'entity' Krupicka
Released under the zlib license (http://zlib.net/zlib_license.html).
*/
 
/** Converts an RGB color to it's HSV representation
 *  @param rgb RGB color to convert
 *  @return The HSV encoded color, as an irr::core::vector3df where X is Hue [0, 360); Y is Saturation [0, 1]; Z is Value [0, 1].
 */
inline core::vector3df RGBftoHSV(video::SColorf rgb)
{
    core::vector3df hsv;
 
    f32 M = max_(max_(rgb.getRed(), rgb.getGreen()), max_(rgb.getGreen(), rgb.getBlue()));
    f32 m = min_(min_(rgb.getRed(), rgb.getGreen()), min_(rgb.getGreen(), rgb.getBlue()));
    f32 C = M - m;
 
    if (C == 0)
        hsv.X = 0;
    else if (M <= rgb.getRed())
        hsv.X = ((rgb.getGreen() - rgb.getBlue()) / C);
    else if (M <= rgb.getGreen())
        hsv.X = ((rgb.getBlue() - rgb.getRed()) / C) + 2;
    else if (M <= rgb.getBlue())
        hsv.X = ((rgb.getRed() - rgb.getGreen()) / C) + 4;
 
    hsv.X *= 60;
    if (hsv.X < 0)
        hsv.X += 360;
 
    hsv.Y = M;
 
    if (hsv.Y == 0)
        hsv.Z = 0;
    else
        hsv.Z = C / hsv.Y;
 
    return hsv;
}
 
inline core::vector3df RGBtoHSV(video::SColor rgb)
{
    return RGBftoHSV(video::SColorf(rgb));
}
 
inline video::SColorf HSVtoRGBf(core::vector3df hsv)
{
    video::SColorf rgb;
 
    f32 C = hsv.Z * hsv.Y;
    f32 H = hsv.X / 60;
    f32 Hmod = H - (2 * (int(H) / 2)); // same as H = fmod(H, 2)
    f32 X = C * (1 - abs_(Hmod - 1));
 
    if (H < 1)
        rgb = video::SColorf(C, X, 0);
    else if (H < 2)
        rgb = video::SColorf(X, C, 0);
    else if (H < 3)
        rgb = video::SColorf(0, C, X);
    else if (H < 4)
        rgb = video::SColorf(0, X, C);
    else if (H < 5)
        rgb = video::SColorf(X, 0, C);
    else if (H < 6)
        rgb = video::SColorf(C, 0, X);
 
    f32 m = hsv.Z - C;
    rgb.r += m;
    rgb.g += m;
    rgb.b += m;
 
    return rgb;
}
 
inline video::SColor HSVtoRGB(core::vector3df hsv)
{
    return HSVtoRGBf(hsv).toSColor();
}
 
inline video::SColorf hueShift(video::SColorf col, f32 shift)
{
    f32 a = col.a;
 
    core::vector3df hsvCol = RGBftoHSV(col);
    hsvCol.X += shift;
    while (hsvCol.X >= 360)
        hsvCol.X -= 360;
    while (hsvCol.X < 0)
        hsvCol.X += 360;
 
    video::SColorf comp = HSVtoRGBf(hsvCol);
    comp.a = a;
    return comp;
}
 
inline video::SColor hueShift(video::SColor col, f32 shift)
{
    return hueShift(video::SColorf(col), shift).toSColor();
}
 
^ is functions to convert between the RGB and HSV representaion of a color, can be used to find complementary colors, for example:

Code: Select all

 
// complementary in the RGB/HSV model
video::SColor red(255, 0, 0, 255);
video::SColor cyan = hueShift(red, 180);
video::SColor red2 = hueShift(cyan, 180);
 
// to get "real life" complementary, hue shift by 240
video::SColor red(255, 0, 0, 255);
video::SColor green = hueShift(red, 240);
video::SColor red2 = hueShift(green, -240);
 
irrRenderer 1.0
Height2Normal v. 2.1 - convert height maps to normal maps

Step back! I have a void pointer, and I'm not afraid to use it!
Post Reply