将RGB转换为HSV和HSV转换为RGB的算法,范围为0-255

时间:2010-06-10 20:40:06

标签: c++ c algorithm

我正在寻找从RGB到HSV的色彩空间转换器,特别是两个色彩空间的0到255范围。

15 个答案:

答案 0 :(得分:118)

我已经使用了很长时间了 - 不知道它们来自何处...请注意,输入和输出除了以度为单位的角度外,都在0到1.0之间。

注意:此代码对输入没有真正的健全性检查。谨慎行事!

typedef struct {
    double r;       // a fraction between 0 and 1
    double g;       // a fraction between 0 and 1
    double b;       // a fraction between 0 and 1
} rgb;

typedef struct {
    double h;       // angle in degrees
    double s;       // a fraction between 0 and 1
    double v;       // a fraction between 0 and 1
} hsv;

static hsv   rgb2hsv(rgb in);
static rgb   hsv2rgb(hsv in);

hsv rgb2hsv(rgb in)
{
    hsv         out;
    double      min, max, delta;

    min = in.r < in.g ? in.r : in.g;
    min = min  < in.b ? min  : in.b;

    max = in.r > in.g ? in.r : in.g;
    max = max  > in.b ? max  : in.b;

    out.v = max;                                // v
    delta = max - min;
    if (delta < 0.00001)
    {
        out.s = 0;
        out.h = 0; // undefined, maybe nan?
        return out;
    }
    if( max > 0.0 ) { // NOTE: if Max is == 0, this divide would cause a crash
        out.s = (delta / max);                  // s
    } else {
        // if max is 0, then r = g = b = 0              
        // s = 0, h is undefined
        out.s = 0.0;
        out.h = NAN;                            // its now undefined
        return out;
    }
    if( in.r >= max )                           // > is bogus, just keeps compilor happy
        out.h = ( in.g - in.b ) / delta;        // between yellow & magenta
    else
    if( in.g >= max )
        out.h = 2.0 + ( in.b - in.r ) / delta;  // between cyan & yellow
    else
        out.h = 4.0 + ( in.r - in.g ) / delta;  // between magenta & cyan

    out.h *= 60.0;                              // degrees

    if( out.h < 0.0 )
        out.h += 360.0;

    return out;
}


rgb hsv2rgb(hsv in)
{
    double      hh, p, q, t, ff;
    long        i;
    rgb         out;

    if(in.s <= 0.0) {       // < is bogus, just shuts up warnings
        out.r = in.v;
        out.g = in.v;
        out.b = in.v;
        return out;
    }
    hh = in.h;
    if(hh >= 360.0) hh = 0.0;
    hh /= 60.0;
    i = (long)hh;
    ff = hh - i;
    p = in.v * (1.0 - in.s);
    q = in.v * (1.0 - (in.s * ff));
    t = in.v * (1.0 - (in.s * (1.0 - ff)));

    switch(i) {
    case 0:
        out.r = in.v;
        out.g = t;
        out.b = p;
        break;
    case 1:
        out.r = q;
        out.g = in.v;
        out.b = p;
        break;
    case 2:
        out.r = p;
        out.g = in.v;
        out.b = t;
        break;

    case 3:
        out.r = p;
        out.g = q;
        out.b = in.v;
        break;
    case 4:
        out.r = t;
        out.g = p;
        out.b = in.v;
        break;
    case 5:
    default:
        out.r = in.v;
        out.g = p;
        out.b = q;
        break;
    }
    return out;     
}

答案 1 :(得分:32)

您也可以尝试不使用浮点数(更快但不太准确)的代码:

typedef struct RgbColor
{
    unsigned char r;
    unsigned char g;
    unsigned char b;
} RgbColor;

typedef struct HsvColor
{
    unsigned char h;
    unsigned char s;
    unsigned char v;
} HsvColor;

RgbColor HsvToRgb(HsvColor hsv)
{
    RgbColor rgb;
    unsigned char region, remainder, p, q, t;

    if (hsv.s == 0)
    {
        rgb.r = hsv.v;
        rgb.g = hsv.v;
        rgb.b = hsv.v;
        return rgb;
    }

    region = hsv.h / 43;
    remainder = (hsv.h - (region * 43)) * 6; 

    p = (hsv.v * (255 - hsv.s)) >> 8;
    q = (hsv.v * (255 - ((hsv.s * remainder) >> 8))) >> 8;
    t = (hsv.v * (255 - ((hsv.s * (255 - remainder)) >> 8))) >> 8;

    switch (region)
    {
        case 0:
            rgb.r = hsv.v; rgb.g = t; rgb.b = p;
            break;
        case 1:
            rgb.r = q; rgb.g = hsv.v; rgb.b = p;
            break;
        case 2:
            rgb.r = p; rgb.g = hsv.v; rgb.b = t;
            break;
        case 3:
            rgb.r = p; rgb.g = q; rgb.b = hsv.v;
            break;
        case 4:
            rgb.r = t; rgb.g = p; rgb.b = hsv.v;
            break;
        default:
            rgb.r = hsv.v; rgb.g = p; rgb.b = q;
            break;
    }

    return rgb;
}

HsvColor RgbToHsv(RgbColor rgb)
{
    HsvColor hsv;
    unsigned char rgbMin, rgbMax;

    rgbMin = rgb.r < rgb.g ? (rgb.r < rgb.b ? rgb.r : rgb.b) : (rgb.g < rgb.b ? rgb.g : rgb.b);
    rgbMax = rgb.r > rgb.g ? (rgb.r > rgb.b ? rgb.r : rgb.b) : (rgb.g > rgb.b ? rgb.g : rgb.b);

    hsv.v = rgbMax;
    if (hsv.v == 0)
    {
        hsv.h = 0;
        hsv.s = 0;
        return hsv;
    }

    hsv.s = 255 * long(rgbMax - rgbMin) / hsv.v;
    if (hsv.s == 0)
    {
        hsv.h = 0;
        return hsv;
    }

    if (rgbMax == rgb.r)
        hsv.h = 0 + 43 * (rgb.g - rgb.b) / (rgbMax - rgbMin);
    else if (rgbMax == rgb.g)
        hsv.h = 85 + 43 * (rgb.b - rgb.r) / (rgbMax - rgbMin);
    else
        hsv.h = 171 + 43 * (rgb.r - rgb.g) / (rgbMax - rgbMin);

    return hsv;
}

注意此算法使用0x00 - 0xFF作为其范围( 0-360)。
Source)功能

答案 2 :(得分:22)

我在HLSL中为我们的渲染引擎写了这个,它没有条件:

    float3  HSV2RGB( float3 _HSV )
    {
        _HSV.x = fmod( 100.0 + _HSV.x, 1.0 );                                       // Ensure [0,1[

        float   HueSlice = 6.0 * _HSV.x;                                            // In [0,6[
        float   HueSliceInteger = floor( HueSlice );
        float   HueSliceInterpolant = HueSlice - HueSliceInteger;                   // In [0,1[ for each hue slice

        float3  TempRGB = float3(   _HSV.z * (1.0 - _HSV.y),
                                    _HSV.z * (1.0 - _HSV.y * HueSliceInterpolant),
                                    _HSV.z * (1.0 - _HSV.y * (1.0 - HueSliceInterpolant)) );

        // The idea here to avoid conditions is to notice that the conversion code can be rewritten:
        //    if      ( var_i == 0 ) { R = V         ; G = TempRGB.z ; B = TempRGB.x }
        //    else if ( var_i == 2 ) { R = TempRGB.x ; G = V         ; B = TempRGB.z }
        //    else if ( var_i == 4 ) { R = TempRGB.z ; G = TempRGB.x ; B = V     }
        // 
        //    else if ( var_i == 1 ) { R = TempRGB.y ; G = V         ; B = TempRGB.x }
        //    else if ( var_i == 3 ) { R = TempRGB.x ; G = TempRGB.y ; B = V     }
        //    else if ( var_i == 5 ) { R = V         ; G = TempRGB.x ; B = TempRGB.y }
        //
        // This shows several things:
        //  . A separation between even and odd slices
        //  . If slices (0,2,4) and (1,3,5) can be rewritten as basically being slices (0,1,2) then
        //      the operation simply amounts to performing a "rotate right" on the RGB components
        //  . The base value to rotate is either (V, B, R) for even slices or (G, V, R) for odd slices
        //
        float   IsOddSlice = fmod( HueSliceInteger, 2.0 );                          // 0 if even (slices 0, 2, 4), 1 if odd (slices 1, 3, 5)
        float   ThreeSliceSelector = 0.5 * (HueSliceInteger - IsOddSlice);          // (0, 1, 2) corresponding to slices (0, 2, 4) and (1, 3, 5)

        float3  ScrollingRGBForEvenSlices = float3( _HSV.z, TempRGB.zx );           // (V, Temp Blue, Temp Red) for even slices (0, 2, 4)
        float3  ScrollingRGBForOddSlices = float3( TempRGB.y, _HSV.z, TempRGB.x );  // (Temp Green, V, Temp Red) for odd slices (1, 3, 5)
        float3  ScrollingRGB = lerp( ScrollingRGBForEvenSlices, ScrollingRGBForOddSlices, IsOddSlice );

        float   IsNotFirstSlice = saturate( ThreeSliceSelector );                   // 1 if NOT the first slice (true for slices 1 and 2)
        float   IsNotSecondSlice = saturate( ThreeSliceSelector-1.0 );              // 1 if NOT the first or second slice (true only for slice 2)

        return  lerp( ScrollingRGB.xyz, lerp( ScrollingRGB.zxy, ScrollingRGB.yzx, IsNotSecondSlice ), IsNotFirstSlice );    // Make the RGB rotate right depending on final slice index
    }

答案 3 :(得分:8)

这应该在这里: 无论如何它都有用。与上述相比,它看起来很不错。

hlsl代码

        float3 Hue(float H)
        {
            half R = abs(H * 6 - 3) - 1;
            half G = 2 - abs(H * 6 - 2);
            half B = 2 - abs(H * 6 - 4);
            return saturate(half3(R,G,B));
        }

        half4 HSVtoRGB(in half3 HSV)
        {
            return half4(((Hue(HSV.x) - 1) * HSV.y + 1) * HSV.z,1);
        }

float3是16位精度vector3数据类型,即float3 hue()返回数据类型(x,y,z),例如(r,g,b),半精度相同,8位,float4是(r,g,b,a)4个值。

答案 4 :(得分:5)

这是基于Agoston的 Computer Graphics and Geometric Modeling: Implementation and Algorithms p的C实现。 304, H ∈[0,360]和 S V ∈[0,1]。

X Y * * * /path/to/script1.py && /bin/date '+%Y%m%d%H%M script one ran' >> /home/jrambo/script1.log
X Y * * * /path/to/script2.py && /bin/date '+%Y%m%d%H%M script two ran' >> /home/jrambo/script2.log

答案 5 :(得分:4)

当你将饱和度降低时,@ fins的答案在Arduino上出现溢出问题。这里有一些值转换为int以防止这种情况。

typedef struct RgbColor
{
    unsigned char r;
    unsigned char g;
    unsigned char b;
} RgbColor;

typedef struct HsvColor
{
    unsigned char h;
    unsigned char s;
    unsigned char v;
} HsvColor;

RgbColor HsvToRgb(HsvColor hsv)
{
    RgbColor rgb;
    unsigned char region, p, q, t;
    unsigned int h, s, v, remainder;

    if (hsv.s == 0)
    {
        rgb.r = hsv.v;
        rgb.g = hsv.v;
        rgb.b = hsv.v;
        return rgb;
    }

    // converting to 16 bit to prevent overflow
    h = hsv.h;
    s = hsv.s;
    v = hsv.v;

    region = h / 43;
    remainder = (h - (region * 43)) * 6; 

    p = (v * (255 - s)) >> 8;
    q = (v * (255 - ((s * remainder) >> 8))) >> 8;
    t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;

    switch (region)
    {
        case 0:
            rgb.r = v;
            rgb.g = t;
            rgb.b = p;
            break;
        case 1:
            rgb.r = q;
            rgb.g = v;
            rgb.b = p;
            break;
        case 2:
            rgb.r = p;
            rgb.g = v;
            rgb.b = t;
            break;
        case 3:
            rgb.r = p;
            rgb.g = q;
            rgb.b = v;
            break;
        case 4:
            rgb.r = t;
            rgb.g = p;
            rgb.b = v;
            break;
        default:
            rgb.r = v;
            rgb.g = p;
            rgb.b = q;
            break;
    }

    return rgb;
}

HsvColor RgbToHsv(RgbColor rgb)
{
    HsvColor hsv;
    unsigned char rgbMin, rgbMax;

    rgbMin = rgb.r < rgb.g ? (rgb.r < rgb.b ? rgb.r : rgb.b) : (rgb.g < rgb.b ? rgb.g : rgb.b);
    rgbMax = rgb.r > rgb.g ? (rgb.r > rgb.b ? rgb.r : rgb.b) : (rgb.g > rgb.b ? rgb.g : rgb.b);

    hsv.v = rgbMax;
    if (hsv.v == 0)
    {
        hsv.h = 0;
        hsv.s = 0;
        return hsv;
    }

    hsv.s = 255 * ((long)(rgbMax - rgbMin)) / hsv.v;
    if (hsv.s == 0)
    {
        hsv.h = 0;
        return hsv;
    }

    if (rgbMax == rgb.r)
        hsv.h = 0 + 43 * (rgb.g - rgb.b) / (rgbMax - rgbMin);
    else if (rgbMax == rgb.g)
        hsv.h = 85 + 43 * (rgb.b - rgb.r) / (rgbMax - rgbMin);
    else
        hsv.h = 171 + 43 * (rgb.r - rgb.g) / (rgbMax - rgbMin);

    return hsv;
}

答案 6 :(得分:4)

这不是C,但它确实有效。我在这里看到的所有其他方法都可以通过将所有方法都包装成六边形的一部分来实现,并且近似于角度&#34;从那以后。相反,从使用余弦的不同方程开始,并求解h s和v,你得到hsv和rgb之间更好的关系,并且补间变得更平滑(代价是它更慢)。

假设一切都是浮点数。如果r g和b从0变为1,则h从0变为2pi,v从0变为4/3,s从0变为2/3。

以下代码是用Lua编写的。它很容易翻译成其他任何东西。

local hsv do
    hsv         ={}
    local atan2 =math.atan2
    local cos   =math.cos
    local sin   =math.sin

    function hsv.fromrgb(r,b,g)
        local c=r+g+b
        if c<1e-4 then
            return 0,2/3,0
        else
            local p=2*(b*b+g*g+r*r-g*r-b*g-b*r)^0.5
            local h=atan2(b-g,(2*r-b-g)/3^0.5)
            local s=p/(c+p)
            local v=(c+p)/3
            return h,s,v
        end
    end

    function hsv.torgb(h,s,v)
        local r=v*(1+s*(cos(h)-1))
        local g=v*(1+s*(cos(h-2.09439)-1))
        local b=v*(1+s*(cos(h+2.09439)-1))
        return r,g,b
    end

    function hsv.tween(h0,s0,v0,h1,s1,v1,t)
        local dh=(h1-h0+3.14159)%6.28318-3.14159
        local h=h0+t*dh
        local s=s0+t*(s1-s0)
        local v=v0+t*(v1-v0)
        return h,s,v
    end
end

答案 7 :(得分:2)

基于Patapoms的GLSL Shader版本回答:

vec3 HSV2RGB( vec3 hsv )
{
    hsv.x = mod( 100.0 + hsv.x, 1.0 ); // Ensure [0,1[
    float   HueSlice = 6.0 * hsv.x; // In [0,6[
    float   HueSliceInteger = floor( HueSlice );
    float   HueSliceInterpolant = HueSlice - HueSliceInteger; // In [0,1[ for each hue slice
    vec3  TempRGB = vec3(   hsv.z * (1.0 - hsv.y), hsv.z * (1.0 - hsv.y * HueSliceInterpolant), hsv.z * (1.0 - hsv.y * (1.0 - HueSliceInterpolant)) );
    float   IsOddSlice = mod( HueSliceInteger, 2.0 ); // 0 if even (slices 0, 2, 4), 1 if odd (slices 1, 3, 5)
    float   ThreeSliceSelector = 0.5 * (HueSliceInteger - IsOddSlice); // (0, 1, 2) corresponding to slices (0, 2, 4) and (1, 3, 5)
    vec3  ScrollingRGBForEvenSlices = vec3( hsv.z, TempRGB.zx );           // (V, Temp Blue, Temp Red) for even slices (0, 2, 4)
    vec3  ScrollingRGBForOddSlices = vec3( TempRGB.y, hsv.z, TempRGB.x );  // (Temp Green, V, Temp Red) for odd slices (1, 3, 5)
    vec3  ScrollingRGB = mix( ScrollingRGBForEvenSlices, ScrollingRGBForOddSlices, IsOddSlice );
    float   IsNotFirstSlice = clamp( ThreeSliceSelector, 0.0,1.0 );                   // 1 if NOT the first slice (true for slices 1 and 2)
    float   IsNotSecondSlice = clamp( ThreeSliceSelector-1.0, 0.0,1. );              // 1 if NOT the first or second slice (true only for slice 2)
    return  mix( ScrollingRGB.xyz, mix( ScrollingRGB.zxy, ScrollingRGB.yzx, IsNotSecondSlice ), IsNotFirstSlice );    // Make the RGB rotate right depending on final slice index
}

答案 8 :(得分:0)

This link包含您想要的公式。如果你想快速的话,那就是性能问题(数值技术)。

答案 9 :(得分:0)

这是我今天早上写的基于与上面几乎相同的数学的那个:

/* math adapted from: http://www.rapidtables.com/convert/color/rgb-to-hsl.htm
 * reasonably optimized for speed, without going crazy */
void rgb_to_hsv (int r, int g, int b, float *r_h, float *r_s, float *r_v) {
  float rp, gp, bp, cmax, cmin, delta, l;
  int cmaxwhich, cminwhich;

  rp = ((float) r) / 255;
  gp = ((float) g) / 255;
  bp = ((float) b) / 255;

  //debug ("rgb=%d,%d,%d rgbprime=%f,%f,%f", r, g, b, rp, gp, bp);

  cmax = rp;
  cmaxwhich = 0; /* faster comparison afterwards */
  if (gp > cmax) { cmax = gp; cmaxwhich = 1; }
  if (bp > cmax) { cmax = bp; cmaxwhich = 2; }
  cmin = rp;
  cminwhich = 0;
  if (gp < cmin) { cmin = gp; cminwhich = 1; }
  if (bp < cmin) { cmin = bp; cminwhich = 2; }

  //debug ("cmin=%f,cmax=%f", cmin, cmax);
  delta = cmax - cmin;

  /* HUE */
  if (delta == 0) {
    *r_h = 0;
  } else {
    switch (cmaxwhich) {
      case 0: /* cmax == rp */
        *r_h = HUE_ANGLE * (fmod ((gp - bp) / delta, 6));
      break;

      case 1: /* cmax == gp */
        *r_h = HUE_ANGLE * (((bp - rp) / delta) + 2);
      break;

      case 2: /* cmax == bp */
        *r_h = HUE_ANGLE * (((rp - gp) / delta) + 4);
      break;
    }
    if (*r_h < 0)
      *r_h += 360;
  }

  /* LIGHTNESS/VALUE */
  //l = (cmax + cmin) / 2;
  *r_v = cmax;

  /* SATURATION */
  /*if (delta == 0) {
    *r_s = 0;
  } else {
    *r_s = delta / (1 - fabs (1 - (2 * (l - 1))));
  }*/
  if (cmax == 0) {
    *r_s = 0;
  } else {
    *r_s = delta / cmax;
  }
  //debug ("rgb=%d,%d,%d ---> hsv=%f,%f,%f", r, g, b, *r_h, *r_s, *r_v);
}


void hsv_to_rgb (float h, float s, float v, int *r_r, int *r_g, int *r_b) {
  if (h > 360)
    h -= 360;
  if (h < 0)
    h += 360;
  h = CLAMP (h, 0, 360);
  s = CLAMP (s, 0, 1);
  v = CLAMP (v, 0, 1);
  float c = v * s;
  float x = c * (1 - fabsf (fmod ((h / HUE_ANGLE), 2) - 1));
  float m = v - c;
  float rp, gp, bp;
  int a = h / 60;

  //debug ("h=%f, a=%d", h, a);

  switch (a) {
    case 0:
      rp = c;
      gp = x;
      bp = 0;
    break;

    case 1:
      rp = x;
      gp = c;
      bp = 0;
    break;

    case 2:
      rp = 0;
      gp = c;
      bp = x;
    break;

    case 3:
      rp = 0;
      gp = x;
      bp = c;
    break;

    case 4:
      rp = x;
      gp = 0;
      bp = c;
    break;

    default: // case 5:
      rp = c;
      gp = 0;
      bp = x;
    break;
  }

  *r_r = (rp + m) * 255;
  *r_g = (gp + m) * 255;
  *r_b = (bp + m) * 255;

  //debug ("hsv=%f,%f,%f, ---> rgb=%d,%d,%d", h, s, v, *r_r, *r_g, *r_b);
}

答案 10 :(得分:0)

我创建了一个可能更快的实现,使用0-1范围用于RGBS和V和0-6范围用于Hue(避免除法),并将案例分为两类:

coll/doc

对于0-255范围,只需* 255.0f + 0.5f并将其分配给无符号字符(或除以255.0以获得相反的结果)。

答案 11 :(得分:0)

我不是C ++开发人员,所以我将不提供代码。但是,我可以提供目前发现的简单 hsv2rgb 算法(rgb2hsv here)-我用描述HSVHLS更新Wiki。主要的改进是,我仔细观察了r,g,b作为色调函数,并引入了更简单的形状函数来描述它们(不失精确性)。 算法-输入时,我们有:h(0-255),s(0-255),v(0-255)

r = 255*f(5),   g = 255*f(3),   b = 255*f(1)

我们使用如下所述的函数f

f(n) = v/255 - (v/255)*(s/255)*max(min(k,4-k,1),0)

其中(mod可以返回小数部分; k是浮点数)

k = (n+h*360/(255*60)) mod 6;

以下是JS中的摘要/ PoV:HSVHSL

答案 12 :(得分:0)

// This pair of functions convert HSL to RGB and vice-versa.
// It's pretty optimized for execution speed

typedef unsigned char       BYTE
typedef struct _RGB
{
    BYTE R;
    BYTE G;
    BYTE B;
} RGB, *pRGB;
typedef struct _HSL
{
    float   H;  // color Hue (0.0 to 360.0 degrees)
    float   S;  // color Saturation (0.0 to 1.0)
    float   L;  // Luminance (0.0 to 1.0)
    float   V;  // Value (0.0 to 1.0)
} HSL, *pHSL;

float   *fMin       (float *a, float *b)
{
    return *a <= *b?  a : b;
}

float   *fMax       (float *a, float *b)
{
    return *a >= *b? a : b;
}

void    RGBtoHSL    (pRGB rgb, pHSL hsl)
{
// See https://en.wikipedia.org/wiki/HSL_and_HSV
// rgb->R, rgb->G, rgb->B: [0 to 255]
    float r =       (float) rgb->R / 255;
    float g =       (float) rgb->G / 255;
    float b =       (float) rgb->B / 255;
    float *min =    fMin(fMin(&r, &g), &b);
    float *max =    fMax(fMax(&r, &g), &b);
    float delta =   *max - *min;

// L, V [0.0 to 1.0]
    hsl->L = (*max + *min)/2;
    hsl->V = *max;
// Special case for H and S
    if (delta == 0)
    {
        hsl->H = 0.0f;
        hsl->S = 0.0f;
    }
    else
    {
// Special case for S
        if((*max == 0) || (*min == 1))
            hsl->S = 0;
        else
// S [0.0 to 1.0]
            hsl->S = (2 * *max - 2*hsl->L)/(1 - fabsf(2*hsl->L - 1));
// H [0.0 to 360.0]
        if      (max == &r)     hsl->H = fmod((g - b)/delta, 6);    // max is R
        else if (max == &g)     hsl->H = (b - r)/delta + 2;         // max is G
        else                    hsl->H = (r - g)/delta + 4;         // max is B
        hsl->H *= 60;
    }
}

void    HSLtoRGB    (pHSL hsl, pRGB rgb)
{
// See https://en.wikipedia.org/wiki/HSL_and_HSV
    float a, k, fm1, fp1, f1, f2, *f3;
// L, V, S: [0.0 to 1.0]
// rgb->R, rgb->G, rgb->B: [0 to 255]
    fm1 = -1;
    fp1 = 1;
    f1 = 1-hsl->L;
    a = hsl->S * *fMin(&hsl->L, &f1);
    k = fmod(0 + hsl->H/30, 12);
    f1 = k - 3;
    f2 = 9 - k;
    f3 = fMin(fMin(&f1, &f2), &fp1) ;
    rgb->R = (BYTE) (255 * (hsl->L - a * *fMax(f3, &fm1)));

    k = fmod(8 + hsl->H/30, 12);
    f1 = k - 3;
    f2 = 9 - k;
    f3 = fMin(fMin(&f1, &f2), &fp1) ;
    rgb->G = (BYTE) (255 * (hsl->L - a * *fMax(f3, &fm1)));

    k = fmod(4 + hsl->H/30, 12);
    f1 = k - 3;
    f2 = 9 - k;
    f3 = fMin(fMin(&f1, &f2), &fp1) ;
    rgb->B = (BYTE) (255 * (hsl->L - a * *fMax(f3, &fm1)));
}

答案 13 :(得分:0)

这里是online converter,其中包含解释了所有颜色转换算法的文章。

您可能希望使用现成的C版本,但是应用起来应该不会太久,它可以帮助其他尝试使用另一种语言或另一种色彩空间进行相同操作的人。

答案 14 :(得分:-1)

How is this algorithm-

void RGB_to_HSV(float R, float G, float B){
    float H, S, V;
    float Max, Min;
    Max = max(R, G, B);
    Min= min(R, G, B);
    V= Max;

if(Max == 0){
  s=0;
}
else{
  s= Max-Min/Max;
}
if(s==0){
  H = undefined;
}
else{
  if(R == Max){
  H = (G-B)*60/Max-Min;
  if(H<0)
   H+ = 360;
}
elseif(G==Max){
    H = (B-R)*(60+120)/Max-Min;
}
else{
   H = (R-G)*(60+240)/Max-Min;
}
}
  printf('H S V');
}