posts - 225, comments - 62, trackbacks - 0, articles - 0
   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

HSV转RGB

Posted on 2010-11-05 23:55 魔のkyo 阅读(1878) 评论(0)  编辑 收藏 引用

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

只有注册用户登录后才能发表评论。