본문으로 바로가기

RGB to HSV and HSV to RGB

category 개발언어/c++ 2016. 6. 13. 16:12

    

Algorithm to convert RGB to HSV and HSV to RGB in range 0-255 for both (하단소스 참조)

 

HSV(HSB) 공간 색을 표현하는 하나의 방법이자, 방법에 따라 색을 배치하는 방식이다색상(Hue), 채도(Saturation), 명도(Brightness, Value) 좌표 써서
특정한 
지정한다.HSB 불리는 경우도 있다. 비슷한 것으로 HSL(Lightness), HSI(Intensity) 등이 있다

HSV 공간 모형

 

HSV 공간 모형은 원기둥 또는 거꾸로  원뿔 모양의 입체 도형이다.

원기둥 모형

 

 

NI Graph로 평면적으로 HUE를 나열 했을 때

 

HSV 공간 원기둥 모형

구성요소의 정의에 따라 HSV 공간은 그림과 같은 원기둥으로 표현할 있다. 원기둥의 표면과 내부의 점은 하나의 색을 나타낸다.

 

남색

남색 예로 원기둥 모형을 설명하면 남색은 파랑 같은 색상을 지닌 어두운 색이다.

HSV 공간 원뿔 모형

원뿔모형은 원기둥 모형을 보다 현실적으로 수정한 것이다. 명도 0% 오직 검정 의미하기 때문에 하나의 점으로 표현되며 원뿔의 꼭짓점에 해당한다. 또한 실제 색상은 어두워질수록 채도값의 변화에 따른 색상 변화가 크지 않기 때문에 높은 명도에 비해 채도값이 나타내는 폭은 줄어든다. 이와 같은 사실을 원기둥 모형에 반영한 것이 원뿔모형이다. 오른쪽 그림을 보면 높은 명도에서는 넓은 폭의 채도 변화를 보이고 어두워질수록 채도 변화가 크지 않은 것을 확인할 있다.

[[[[[   소스  ]]]]

// Color.cpp: implementation of the CColor class.

//

//////////////////////////////////////////////////////////////////////

 

#include "stdafx.h"

#include "APL_UI.h"

#include "Color.h"

 

#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[]=__FILE__;

#define new DEBUG_NEW

#endif

 

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

 

CColor::CColor()

{

 

}

 

CColor::~CColor()

{

 

}

 

HSV CColor::RGBtoHSV(COLORREF rgb)

{

    BYTE r = (BYTE)GetRValue(rgb);

    BYTE g = (BYTE)GetGValue(rgb);

    BYTE b = (BYTE)GetBValue(rgb);

 

    float r_percent = ((float)r)/255;

    float g_percent = ((float)g)/255;

    float b_percent = ((float)b)/255;

 

    float max_color = 0;

    if((r_percent >= g_percent) && (r_percent >= b_percent))

    {

        max_color = r_percent;

    }

    if((g_percent >= r_percent) && (g_percent >= b_percent))

        max_color = g_percent;

    if((b_percent >= r_percent) && (b_percent >= g_percent))

        max_color = b_percent;

 

    float min_color = 0;

    if((r_percent <= g_percent) && (r_percent <= b_percent))

        min_color = r_percent;

    if((g_percent <= r_percent) && (g_percent <= b_percent))

        min_color = g_percent;

    if((b_percent <= r_percent) && (b_percent <= g_percent))

        min_color = b_percent;

 

    float L = 0;

    float S = 0;

    float H = 0;

 

    L = (max_color + min_color)/2;

 

    if(max_color == min_color)

    {

        S = 0;

        H = 0;

    }

    else

    {

        if(L < .50)

        {

            S = (max_color - min_color)/(max_color + min_color);

        }

        else

        {

            S = (max_color - min_color)/(2 - max_color - min_color);

        }

        if(max_color == r_percent)

        {

            H = (g_percent - b_percent)/(max_color - min_color);

        }

        if(max_color == g_percent)

        {

            H = 2 + (b_percent - r_percent)/(max_color - min_color);

        }

        if(max_color == b_percent)

        {

            H = 4 + (r_percent - g_percent)/(max_color - min_color);

        }

    }

    H = H*60;

    if(H < 0)H += 360;

    return HSV((BYTE)H,(BYTE)(S*100),(BYTE)(L*100));

}

 

COLORREF CColor::HSVtoRGB(HSV in)

{

BYTE r = 0;

    BYTE g = 0;

    BYTE b = 0;

 

    float L = ((float)in.v)/100;

    float S = ((float)in.s)/100;

    float H = ((float)in.h)/360;

 

    if(in.s == 0)

    {

        r = in.v;

        g = in.v;

        b = in.v;

    }

    else

    {

        float temp1 = 0;

        if(L < .50)

        {

            temp1 = L*(1 + S);

        }

        else

        {

            temp1 = L + S - (L*S);

        }

 

        float temp2 = 2*L - temp1;

 

        float temp3 = 0;

        for(int i = 0 ; i < 3 ; i++)

        {

            switch(i)

            {

            case 0: // red

                {

                    temp3 = H + .33333f;

                    if(temp3 > 1)

                        temp3 -= 1;

                    HSLtoRGB_Subfunction(r,temp1,temp2,temp3);

                    break;

                }

            case 1: // green

                {

                    temp3 = H;

                    HSLtoRGB_Subfunction(g,temp1,temp2,temp3);

                    break;

                }

            case 2: // blue

                {

                    temp3 = H - .33333f;

                    if(temp3 < 0)

                        temp3 += 1;

                    HSLtoRGB_Subfunction(b,temp1,temp2,temp3);

                    break;

                }

            default:

                {

 

                }

            }

        }

    }

    r = (BYTE)((((float)r)/100)*255);

    g = (BYTE)((((float)g)/100)*255);

    b = (BYTE)((((float)b)/100)*255);

    return RGB(r,g,b);

 

}

 

// This is a subfunction of HSLtoRGB

void CColor::HSLtoRGB_Subfunction(BYTE& c, const float& temp1, const float& temp2, const float& temp3)

{

    if((temp3 * 6) < 1)

        c = (BYTE)((temp2 + (temp1 - temp2)*6*temp3)*100);

    else

        if((temp3 * 2) < 1)

            c = (BYTE)(temp1*100);

        else

            if((temp3 * 3) < 2)

                c = (BYTE)((temp2 + (temp1 - temp2)*(.66666 - temp3)*6)*100);

            else

                c = (BYTE)(temp2*100);

    return;

}

 

 

// This function extracts the hue, saturation, and luminance from "color"

// and places these values in h, s, and l respectively.

 

 

// This function converts the "color" object to the equivalent RGB values of

// the hue, saturation, and luminance passed as h, s, and l respectively

 

 

COLORREF CColor::BrightenColor(COLORREF color,BYTE amount)

{

    HSV hsv;

    hsv=RGBtoHSV(color);

    hsv.v+=amount;    

    hsv.v =min(hsv.v, 100);    

    return HSVtoRGB(hsv);

}

COLORREF CColor::DarkenColor(COLORREF color,int amount)

{

HSV hsv;

    hsv=RGBtoHSV(color);

    if ( amount >= hsv.v )

        hsv.v = 0;    

    else    

        hsv.v -=amount;    

    return HSVtoRGB(hsv);

}