I thought I needed a RGB to HSL (Hue, Saturation, Lightness) converter, but Android SDK only provides RGB to HSV value, which has some similarity but different.
Based on the above Wikipedia article, I wrote the Java code to convert between RGB and HSL. Hopefully this can be useful to your project.
- rgb is an int (with alpha ignored) 0xrrggbb
- hsl is an array of 3 floats:
- [0] is hue, 0..360
- [1] is saturation, 0..1
- [2] is lightness, 0..1
public static void rgbToHsl(int rgb, float[] hsl) {
float r = ((0x00ff0000 & rgb) >> 16) / 255.f;
float g = ((0x0000ff00 & rgb) >> 8) / 255.f;
float b = ((0x000000ff & rgb)) / 255.f;
float max = Math.max(Math.max(r, g), b);
float min = Math.min(Math.min(r, g), b);
float c = max - min;
float h_ = 0.f;
if (c == 0) {
h_ = 0;
} else if (max == r) {
h_ = (float)(g-b) / c;
if (h_ < 0) h_ += 6.f;
} else if (max == g) {
h_ = (float)(b-r) / c + 2.f;
} else if (max == b) {
h_ = (float)(r-g) / c + 4.f;
}
float h = 60.f * h_;
float l = (max + min) * 0.5f;
float s;
if (c == 0) {
s = 0.f;
} else {
s = c / (1 - Math.abs(2.f * l - 1.f));
}
hsl[0] = h;
hsl[1] = s;
hsl[2] = l;
}
public static int hslToRgb(float[] hsl) {
float h = hsl[0];
float s = hsl[1];
float l = hsl[2];
float c = (1 - Math.abs(2.f * l - 1.f)) * s;
float h_ = h / 60.f;
float h_mod2 = h_;
if (h_mod2 >= 4.f) h_mod2 -= 4.f;
else if (h_mod2 >= 2.f) h_mod2 -= 2.f;
float x = c * (1 - Math.abs(h_mod2 - 1));
float r_, g_, b_;
if (h_ < 1) { r_ = c; g_ = x; b_ = 0; }
else if (h_ < 2) { r_ = x; g_ = c; b_ = 0; }
else if (h_ < 3) { r_ = 0; g_ = c; b_ = x; }
else if (h_ < 4) { r_ = 0; g_ = x; b_ = c; }
else if (h_ < 5) { r_ = x; g_ = 0; b_ = c; }
else { r_ = c; g_ = 0; b_ = x; }
float m = l - (0.5f * c);
int r = (int)((r_ + m) * (255.f) + 0.5f);
int g = (int)((g_ + m) * (255.f) + 0.5f);
int b = (int)((b_ + m) * (255.f) + 0.5f);
return r << 16 | g << 8 | b;
}
> if (h_ < 0) h_ += 6.f;
ReplyDeleteThat line is only in the first case of rgbToHsl - is it supposed to be like that, or should it be for every case?
Only the first case. Because when max==r, h_ can range between -1.0 to +1.0, but we want to normalize (-1.0 to 0.0) to (+5.0 to +6.0).
ReplyDeleteThis code do not work for me (Eclipse Juno, JDK 1.7). I changed the lines
ReplyDeletefloat r = ((0x00ff0000 & rgb) >> 16) / 255.f;
float g = ((0x0000ff00 & rgb) >> 8) / 255.f;
loat b = ((0x000000ff & rgb)) / 255.f;
with :
int ir = ( rgb >> 24 ) & 0xFF;
int ig = ( rgb >> 16 ) & 0xFF;
int ib = ( rgb >> 8 ) & 0xFF;
float r = (float)ir / 255.f;
float g = (float)ig / 255.f;
float b = (float)ib / 255.f;
code does not work either
ReplyDeletethe / 60.f makes all color the same