RGB HSI HSV HSB HSL

HSI:色相(hue),饱和度(saturation),亮度(Intensity),这种模型完全对应于RGB模型转化而来,转化也有严格的公式推导得到,网上提供了几种转化公式的表示方法:

 

HSV:色相(hue),饱和度(saturation),明度(value),也称HSB(brightness)。

HSL:色相(hue),饱和度(saturation),亮度(luminance)。

上面这两种模型各个意义也不完全一样,它们的意义对应于它们各自的建模方式。其中HSV/HSB来自于Lab建模方式并考虑了人眼的影响之后得到的。

 

通用的RGB转HSV/HSB公式如下:详细的原理还未弄清楚

  R,G,B的取值范围是[0, Cmax],未作归一化的Cmax的值为255。Chigh = max(R,G,B),Clow = min(R,G,B),Crng = Chigh - Clow

饱和度:

  if(Chigh > 0) S = Crng / Chigh else S = 0

明度:

  V = Chigh / Cmax

色调:

  if(Crng == 0)此时饱和度S == 0,为灰度图,色调因此无定义。

  else

  先将各分量归一化:R' = (Chigh - R) / Crng   G' = (Chigh - G) / Crng   B' = (Chigh - B) / Crng

  基于原始颜色分量中的最大值,计算出一个初步的色调H':

    if(R = Chigh) H' = B' - G' ; else if(G = Chigh) H' = R' - B' + 2; else if(B = Chigh) H' = G' - R' + 4;

  由上式可知H'的取值区间为[-1, 5],通过将其归一化到区间[0, 1]得到最终的色调值:

  if(H' < 0) H = 1/6 * (H' + 6) else H = 1/6 * H'

三个分量值都位于区间[0, 1]。

代码如下:来自于JDK java.awt.Color类

    public static float[] RGBtoHSB(int r, int g, int b, float[] hsbvals) {
        float hue, saturation, brightness;
        if (hsbvals == null) {
            hsbvals = new float[3];
        }
        int cmax = (r > g) ? r : g;
        if (b > cmax) cmax = b;
        int cmin = (r < g) ? r : g;
        if (b < cmin) cmin = b;

        brightness = ((float) cmax) / 255.0f;
        if (cmax != 0)
            saturation = ((float) (cmax - cmin)) / ((float) cmax);
        else
            saturation = 0;
        if (saturation == 0)
            hue = 0;
        else {
            float redc = ((float) (cmax - r)) / ((float) (cmax - cmin));
            float greenc = ((float) (cmax - g)) / ((float) (cmax - cmin));
            float bluec = ((float) (cmax - b)) / ((float) (cmax - cmin));
            if (r == cmax)
                hue = bluec - greenc;
            else if (g == cmax)
                hue = 2.0f + redc - bluec;
            else
                hue = 4.0f + greenc - redc;
            hue = hue / 6.0f;
            if (hue < 0)
                hue = hue + 1.0f;
        }
        hsbvals[0] = hue;
        hsbvals[1] = saturation;
        hsbvals[2] = brightness;
        return hsbvals;
    }

 

 

HSB/HSV转RGB的介绍不给出,直接给出java.awt.Color类中的转换代码

  public static int HSBtoRGB(float hue, float saturation, float brightness) {
        int r = 0, g = 0, b = 0;
        if (saturation == 0) {
            r = g = b = (int) (brightness * 255.0f + 0.5f);
        } else {
            float h = (hue - (float)Math.floor(hue)) * 6.0f;
            float f = h - (float)java.lang.Math.floor(h);
            float p = brightness * (1.0f - saturation);
            float q = brightness * (1.0f - saturation * f);
            float t = brightness * (1.0f - (saturation * (1.0f - f)));
            switch ((int) h) {
            case 0:
                r = (int) (brightness * 255.0f + 0.5f);
                g = (int) (t * 255.0f + 0.5f);
                b = (int) (p * 255.0f + 0.5f);
                break;
            case 1:
                r = (int) (q * 255.0f + 0.5f);
                g = (int) (brightness * 255.0f + 0.5f);
                b = (int) (p * 255.0f + 0.5f);
                break;
            case 2:
                r = (int) (p * 255.0f + 0.5f);
                g = (int) (brightness * 255.0f + 0.5f);
                b = (int) (t * 255.0f + 0.5f);
                break;
            case 3:
                r = (int) (p * 255.0f + 0.5f);
                g = (int) (q * 255.0f + 0.5f);
                b = (int) (brightness * 255.0f + 0.5f);
                break;
            case 4:
                r = (int) (t * 255.0f + 0.5f);
                g = (int) (p * 255.0f + 0.5f);
                b = (int) (brightness * 255.0f + 0.5f);
                break;
            case 5:
                r = (int) (brightness * 255.0f + 0.5f);
                g = (int) (p * 255.0f + 0.5f);
                b = (int) (q * 255.0f + 0.5f);
                break;
            }
        }
        return 0xff000000 | (r << 16) | (g << 8) | (b << 0);
    }

 

RGB转HSL

色调:

  同HSV

亮度:

  L = (Chigh + Clow) / 2

饱和度:

  if(L == 0) S = 0; else if( 0<L<=0.5 ) S = 0.5 * Crng / L; else if(0.5 < L < 1) S = 0.5 * Crng / (1 - L); else if(L == 1) S = 0;

	static float[] RGBtoHLS(float R, float G, float B){
		float cHi = Math.max(R, Math.max(G, B));
		float cLo = Math.min(R, Math.min(G, B));
		float cRng = cHi - cLo;
		//计算亮度L
		float L = (cHi + cLo) / 2;
		//计算饱和度S
		float S = 0;
		if(0 < L && L < 1){
			float d = (L <= 0.5f) ? L : (1 - L);
			S = 0.5f * cRng / d;
		}
		
		//计算色调H
		float H = 0;
		if(cRng > 0){
			float rr = (float)((cHi - R) / cRng);
			float gg = (float)((cHi - G) / cRng);
			float bb = (float)((cHi - B) / cRng);
			
			float hh = 0;
			if(R == cHi)hh = bb - gg;
			else if(G == cHi)hh = rr - bb + 2;
			else if(B == cHi)hh = gg - rr + 4;
			if(hh < 0)hh = hh + 6;
			H = hh / 6;
		}
		return new float[]{H, L, S};
	}

 HSL转RGB代码如下:

	static float[] HLStoRGB(float H, float S, float L){
		//假设HSL在[0, 1]区间
		float R = 0;
		float G = 0;
		float B = 0;
		
		if(L <= 0)R = G = B = 0;
		else if(L >= 1) R = G = B = 1;
		else{
			float hh = (6 * H) % 6;
			int c1 = (int)hh;
			float c2 = hh - c1;
			float d = (L <= 0.5f) ? (S * L) : (S * (1 - L));
			float w = L + d;
			float x = L - d;
			float y = w - (w - x) * c2;
			float z = w + (w - x) * c2;
			switch(c1){
			case 0: R = w; G = z; B = x; break;
			case 1: R = y; G = w; B = x; break;
			case 2: R = x; G = w; B = z; break;
			case 3: R = x; G = y; B = w; break;
			case 4:	R = z; G = x; B = w; break;
			case 5: R = w; G = x; B = y; break;
			}
		}
		return new float[]{R, G, B};
	}

 

posted on 2015-07-02 18:47  Matrixin  阅读(1716)  评论(0编辑  收藏  举报

导航