现在的位置: 首页 > 综合 > 正文

HSV色彩属性

2014年03月02日 ⁄ 综合 ⁄ 共 3917字 ⁄ 字号 评论关闭

HSV色彩属性模式是根据色彩的三个基本属性:色相饱和度明度
确定颜 色的一种方法。

  • 色相(H)是色彩的基本属性,就是平常所说的颜色
    称,如红 色黄色等,依照在右图的标准色轮上的位置,取0-360度的数值。(也有用0
    –100%的方法确定的)。
  • 饱和度(S)是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取0-100%的数值。
  • 明度(V)也叫“亮度”,取0-100%。

这种模式是 1978年 由 Alvy Ray Smith 创立的,它是三原色光模式的一种非线性变换。

算法核心是这样的

Vector3f HSV2RGB(const Vector3f& hsv)
{
    //先根据Hue计算出一个"纯的亮的颜色"
    Vector3f hueColor = GetColorByHue(hsv.h);

    //然后用Sat和Value做两次线性插值,Sat越高颜色越纯,越低会使颜色越靠近灰色,Value控制亮度。 
    return lerp<Vector3f>(0, lerp<Vector3f>(1, hueColor, hsv.s), hsv.v);

// hue应该是属于[0,1),但有时也认为属于[0,1]
// 其实影响不大,我这里统一处理了
Vector3f GetColorByHue(float hue)
{
    Vector3f color;
    hue = max(0.0f, min(hue, 1.0f));
    float hue6 = hue*6.0f;
    int z = min((int)hue6, 5);
    float f = hue6 - z;
    //可以想象一个圆,hue值与圆周上的点一一对应
    //圆周被均分成6段,每段只引起一个RGB分量变化
    switch(int(hue*6.0f))
    {
    case 0:
        color.r = 1.0f;
        color.g = f;
        color.b = 0.0f;
        break;
    case 1:
        color.r = 1.0f - f;
        color.g = 1.0f;
        color.b = 0.0f;
        break;
    case 2:
        color.r = 0.0f;
        color.g = 1.0f;
        color.b = f;
        break;
    case 3:
        color.r = 0.0f;
        color.g = 1.0f - f;
        color.b = 1.0f;
        break;
    case 4:
        color.r = f;
        color.g = 0.0f;
        color.b = 1.0f;
        break;
    case 5:
    default:
        color.r = 1.0f;
        color.g = 0.0f;
        color.b = 1.0f - f;
    }
    return color;
}


#include <iostream>
#include <cmath>
using namespace std;

struct Vector3f
{
    Vector3f(){}
    Vector3f(const Vector3f& v):x(v.x),y(v.y),z(v.z){}
    Vector3f(float f):x(f),y(f),z(f){}
    Vector3f(float x,float y,float z):x(x),y(y),z(z){}

    Vector3f operator + (const Vector3f& v) const
    {
        return Vector3f(x+v.x, y+v.y, z+v.z);
    }

    Vector3f operator - (const Vector3f& v) const
    {
        return Vector3f(x-v.x, y-v.y, z-v.z);
    }

    Vector3f operator * (const Vector3f& v) const
    {
        return Vector3f(x*v.x, y*v.y, z*v.z);
    }

    Vector3f operator / (const Vector3f& v) const
    {
        return Vector3f(x/v.x, y/v.y, z/v.z);
    }

    union{
        struct{float x,y,z;};
        struct{float r,g,b;};
        struct{float h,s,v;};
    };
};

Vector3f operator + (float f, const Vector3f& v){ return Vector3f(f+v.x, f+v.y, f+v.z);}
Vector3f operator - (float f, const Vector3f& v){ return Vector3f(f-v.x, f-v.y, f-v.z);}
Vector3f operator * (float f, const Vector3f& v){ return Vector3f(f*v.x, f*v.y, f*v.z);}
Vector3f operator / (float f, const Vector3f& v){ return Vector3f(f/v.x, f/v.y, f/v.z);}

template <typename T>
T lerp(const T& x, const T& y, const T& s)
{
    return x*(1-s) + y*s;
}

// hue应该是属于[0,1),但有时也认为属于[0,1]
// 其实影响不大,我这里统一处理了
Vector3f GetColorByHue(float hue)
{
    Vector3f color;
    hue = max(0.0f, min(hue, 1.0f));
    float hue6 = hue*6.0f;
    int z = min((int)hue6, 5);
    float f = hue6 - z;
    //可以想象一个圆,hue与圆周上的点一一对应
    
//圆周被均分成6段,每段只引起一个RGB分量变化
    switch(int(hue*6.0f))
    {
    case 0:
        color.r = 1.0f;
        color.g = f;
        color.b = 0.0f;
        break;
    case 1:
        color.r = 1.0f - f;
        color.g = 1.0f;
        color.b = 0.0f;
        break;
    case 2:
        color.r = 0.0f;
        color.g = 1.0f;
        color.b = f;
        break;
    case 3:
        color.r = 0.0f;
        color.g = 1.0f - f;
        color.b = 1.0f;
        break;
    case 4:
        color.r = f;
        color.g = 0.0f;
        color.b = 1.0f;
        break;
    case 5:
    default:
        color.r = 1.0f;
        color.g = 0.0f;
        color.b = 1.0f - f;
    }
    return color;
}

Vector3f HSV2RGB(const Vector3f& hsv)
{
    Vector3f hueColor = GetColorByHue(hsv.h);
    return hsv.v * lerp<Vector3f>(1, hueColor, hsv.s);
    //return lerp<Vector3f>(0, lerp<Vector3f>(1, hueColor, hsv.s), hsv.v);
}

int main()

    printf("HSV<360,256,256>->RGB<256,256,256>\n");
    int h,s,v;
    while(scanf("%d%d%d", &h, &s, &v)!=EOF)
    {
        Vector3f hsv = Vector3f(h/360.0f,s/256.0f,v/256.f);
        Vector3f rgb = HSV2RGB(hsv);
        printf("RGB(%d,%d,%d)\n", (int)(rgb.r*256), (int)(rgb.g*256), (int)(rgb.b*256));
    }
}

抱歉!评论已关闭.