[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 823
  • Last Modified:

RGB to & from HLS coversion alghoritm

I must work with colors.
I need the alghoritm that makes conversion RGB <-> HLS

For ex. if I have RGB color 125-160-233 I want to know the corrispondent in HLS and viceversa.
Hoping someone can help me :D

0
zuppy
Asked:
zuppy
  • 11
  • 6
  • 3
  • +1
1 Solution
 
DeatheadCommented:
I have been doing this for 4 years and this is my first time hearing HLS.. please explain and I would love to help you
~X. Deathead
0
 
Michel PlungjanIT ExpertCommented:
Hue, saturation, Lightness ;-)

HSB is more likely.

Here is a java one.

I do alas not have time to convert it to javascript


/**
     * Converts the components of a color, as specified by the HSB
     * model, to an equivalent set of values for the default RGB model.
     * <p>
     * The integer that is returned by <code>HSBtoRGB</code> encodes the
     * value of a color in bits 0&endash;23 of an integer value, the same
     * format used by the method <code>getRGB</code>. This integer can be
     * supplied as an argument to the <code>Color</code> constructor that
     * takes a single integer argument.
     * @param     hue   the hue component of the color.
     * @param     saturation   the saturation of the color.
     * @param     brightness   the brightness of the color.
     * @return    the RGB value of the color with the indicated hue,
     *                            saturation, and brightness.
     * @see       java.awt.Color#getRGB()
     * @see       java.awt.Color#Color(int)
     * @see       java.awt.image.ColorModel#getRGBdefault()
     * @since     JDK1.0
     */
    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);
    }

    /**
     * Converts the components of a color, as specified by the default RGB
     * model, to an equivalent set of values for hue, saturation, and
     * brightness, the three components of the HSB model.
     * <p>
     * If the <code>hsbvals</code> argument is <code>null</code>, then a
     * new array is allocated to return the result. Otherwise, the method
     * returns the array <code>hsbvals</code>, with the values put into
     * that array.
     * @param     r   the red component of the color.
     * @param     g   the green component of the color.
     * @param     b   the blue component of the color.
     * @param     hsbvals  the array to be used to return the
     *                     three HSB values, or <code>null</code>.
     * @return    an array of three elements containing the hue, saturation,
     *                     and brightness (in that order), of the color with
     *                     the indicated red, green, and blue components.
     * @see       java.awt.Color#getRGB()
     * @see       java.awt.Color#Color(int)
     * @see       java.awt.image.ColorModel#getRGBdefault()
     * @since     JDK1.0
     */
    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;
    }
0
 
Michel PlungjanIT ExpertCommented:
But have a look here :

http://www.nebulus.org/freebies/coders/palette/

Michel
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
zuppyAuthor Commented:
Yeah, interesting but I have a bit difficulty because I've never worked in Java :(
 (I had not idea that the alghoritm was so complicated)
0
 
zuppyAuthor Commented:
BUt for make all easy I need mainly HSB (sorry for HSL but I translated from Italian)
0
 
Michel PlungjanIT ExpertCommented:
I can try to convert it tomorrow if you can wait.

Michel

0
 
zuppyAuthor Commented:
Yeah... (for me is just tomorrow here :P)
0
 
brigmarCommented:
I used to work on Optical Spectrum Analysers, and have the formulae for RGB/HSB & HSB/RGB conversion here.

As you can see, the javascript is actually a slight part simpler than the java, because of the loose typing of the language.

By the way, the most widely used acronym for the HSB colour space is actually HLS. It also goes under the acronym HSI.

 HLS = Hue, Luminance, Saturation
 HSB = Hue, Saturation, Brightness
 HSI = Hue, Saturation, Intensity

Luminance = Saturation = Intensity.

Here ya go:
--
<html>
 <head>
  <script language="javascript"> <!--

function HSBtoRGB( hue, sat, bri ) {
 var r,g,b;
 var x1,x2,x3,x4,x5;
 var b2 = bri * 255;
 var b3 = Math.round( b2 );

 if( sat == 0 ) {
  r = g = b = b3;
 }
 else {
  var x1 = (hue - Math.floor(hue)) * 6;
  var x2 = x1 - Math.floor(x1);
  var x3 = Math.round( b2 * ( 1 - sat ) );
  var x4 = Math.round( b2 * ( 1 - sat * x2 ) );
  var x5 = Math.round( b2 * ( 1 - sat * ( 1 - x2 )) );

  switch( parseInt(x1, 10) ) {
   case 0: r = b3; g = x5; b = x3; break;
   case 1: r = x4; g = b3; b = x3; break;
   case 2: r = x3; g = b3; b = x5; break;
   case 3: r = x3; g = x4; b = b3; break;
   case 4: r = x5; g = x3; b = b3; break;
   case 5: r = b3; g = x3; b = x4; break;
  }
 }
 return new Array(r,g,b);
}

function RGBtoHSB( r, g, b ) {
 var mx = Math.max( r, Math.max(g, b) );
 var mn = Math.min( r, Math.min(g, b) );
 var cd = mx-mn;
 var bri = mx / 255;
 var sat = (mx == 0) ? 0 : (cd / mx);
 var hue;

 if( sat == 0 )
  hue = 0;
 else {
  var rc = (mx-r) / cd;
  var gc = (mx-g) / cd;
  var bc = (mx-b) / cd;

  if( r == mx )
   hue = bc - gc;
  else if( g == mx)
   hue = 2 + rc - bc;
  else
   hue = 4 + gc - rc;

  hue /= 6;
  if( hue < 0)
   hue += 1;
 }
 return new Array( hue, sat, bri);
}

// Example follows :

rr = 25; gg = 50; bb = 75;

rgb1 = new Array( rr, gg, bb );
hsb1 = RGBtoHSB( rr, gg, bb );
hh = hsb1[0]; ss = hsb1[1]; br = hsb1[2];
rgb2 = HSBtoRGB( hh, ss, br );

dw = "started with RGB of (" + rgb1 + ")<br>";
dw = dw + "converted to HSB of (" + hsb1 + ")<br>";
dw = dw + "back to RGB of (" + rgb2 + ")";

document.write( dw );
// -->
</script>
</head>
</html>
--

For each function, you pass the triplet of values, and you are returned an array of the triplet values you required.

Brian
0
 
Michel PlungjanIT ExpertCommented:
Yes, I could see that, but I didn't have the time to remove all the f's and floats ;-)

Michel
0
 
zuppyAuthor Commented:
Mumble mumble....
I've tried you function but seems work fine only with (0,0,bri)

Try this exemple code (tried under NN but it shoul work fine under IE):

a make a continuous cicle from 0 to 100 to change Brightness of two 100x100 trasparent gifs.

this is what i expected

black --> gray   (from darkner to lighter)   ->white
black --> yellow (from darkner to lighter)   ->white


But , as you can see the yellow one stop becoming white.

Maybe I mispelled something?

I think your function range values must be 0 to 1.

My need was to have al kind of yellow (or other color) fixed H and S and working with B.


<html>
<head>
<STYLE>
..tipo4 {
font-family:    times;
font-size:      48px;
color:          #ffffff;
position:       absolute;
top:            140px;
left:           10px;
width:          100px;
height:         100px;
visibility:     visible;
z-index:        1;
}

..tipo5 {
font-family:    times;
font-size:      48px;
color:          #ffffff;
position:       absolute;
top:            140px;
left:           110px;
width:          100px;
height:         100px;
visibility:     visible;
z-index:        1;
}
</STYLE>

<SCRIPT>

luminosity=0;

function HSBtoRGB( hue, sat, bri ) {

var r,g,b;
var x1,x2,x3,x4,x5;
var b2 = bri * 255;
var b3 = Math.round( b2 );

if( sat == 0 ) { r = g = b = b3; }
else {
   var x1 = (hue - Math.floor(hue)) * 6;
   var x2 = x1 - Math.floor(x1);
   var x3 = Math.round( b2 * ( 1 - sat ) );
   var x4 = Math.round( b2 * ( 1 - sat * x2 ) );
   var x5 = Math.round( b2 * ( 1 - sat * ( 1 - x2 )) );

      switch( parseInt(x1, 10) ) {
          case 0: r = b3; g = x5; b = x3; break;
          case 1: r = x4; g = b3; b = x3; break;
          case 2: r = x3; g = b3; b = x5; break;
          case 3: r = x3; g = x4; b = b3; break;
          case 4: r = x5; g = x3; b = b3; break;
          case 5: r = b3; g = x3; b = x4; break;
         }
    }

r = r.toString(16);
if (r.length == 1) r = '0' + r;
g = g.toString(16);
if (g.length == 1) g = '0' + g;
b = b.toString(16);
if (b.length == 1) b = '0' + b;

rgb="#"+r+g+b;

//here conversion to #RRGGBB base 16

return rgb;
 }


function dec2virg(value)
{
quantity=value/100;
return quantity;
}


function colore()
{
var isNS = (navigator.appName == "Netscape" && parseInt(navigator.appVersion) >= 4);
var trasp = (isNS) ? document.trasp : document.all.trasp.style;
var trasp2 = (isNS) ? document.trasp2 : document.all.trasp2.style;

luminosity++;
if (luminosity >100){luminosity=0;}


if (isNS)
      {
      trasp.bgColor=HSBtoRGB(.125,.9058,dec2virg(luminosity));
      trasp2.bgColor=HSBtoRGB(0,0,dec2virg(luminosity));
      }
      else
      {
      trasp.backgroundColor=HSBtoRGB(.125,.9058,dec2virg(luminosity));
      trasp2.backgroundColor=HSBtoRGB(0,0,dec2virg(luminosity));
      }
      return ;
}

function Animate()
{
setInterval("colore()",10);
}

</SCRIPT>
</head>
<body text="#FFFFFF" bgcolor="#FFFFFF" onload="Animate();">
<DIV ID = "trasp" CLASS = "tipo4"><img src="trasp.gif"></DIV>
<DIV ID = "trasp2" CLASS = "tipo5"><img src="trasp.gif"></DIV>
</body>
</html>  
0
 
brigmarCommented:
All HLS/HSB values are from 0 to 1.

Hue :
 0.0000 (0/6) = Red
 0.1667 (1/6) = Yellow
 0.3333 (2/6) = Green
 0.5000 (3/6) = Cyan
 0.6667 (4/6) = Blue
 0.8333 (5/6) = Magenta
 1.0000 (6/6) = Red (again)

Your 'yellow' has an orange tinge, because you are using 0.125, instead of 0.16667.

Then, you are ONLY cycling the luminosity. To cycle out from yellow to white, you'd need to 'unsaturate'. Your yellow is 91% saturation.
White is 0% saturation @ 100% Luminance.
Black is any saturation @ 0% Luminance.

If you want to cycle black->yellow-> white, you can :
a) Split the cycle into two parts. Black to Yellow(increasing luminosity), and then Yellow to White(decreasing saturation).
b) decrease the saturation AS you increase the luminance (though you'll never see a bright yellow).

Here's solution a:
--
// Created these vars
var yellow = 1/6; // Hue for Yellow
var ysat   = 1; // 100% saturation
var ylum   = 0; // 0% luminance (black)

var grey   = 0; // Hue for Red
var gsat   = 0; // 0% saturation (white)
var glum   = 0; // 0% luminance (black)

function colore() {
  var isNS = (navigator.appName == "Netscape" && parseInt(navigator.appVersion) >= 4);
  var trasp = (isNS) ? document.trasp : document.all.trasp.style;
  var trasp2 = (isNS) ? document.trasp2 : document.all.trasp2.style;

  // Increase the luminance of the
  // yellow twice as fast as the grey
  ylum += 1
  glum += 0.5

  // When full luminance of the yellow
  // is achieved, unsaturate it (fade to
  // white)
  if( ylum > 100 ) {
   ysat -= 0.01
   ylum = 100;
  }

  // When full luminance of the grey
  // is achieved, reset the cycle.
  if( glum > 100 ) {
    glum = 0;
    ylum = 0;
    ysat = 1;
  }  

  // pure yellow
  var rgb1 = HSBtoRGB( yellow, ysat, dec2virg( ylum ) );
  // 0% saturation = greyscale
  var rgb2 = HSBtoRGB( grey, gsat, dec2virg( glum ) );

  if (isNS) {
    trasp.bgColor = rgb1;
    trasp2.bgColor = rgb2;
  }
  else {
    trasp.backgroundColor = rgb1;
    trasp2.backgroundColor = rgb2;
  }
  return;
}

--

Brian
0
 
zuppyAuthor Commented:
I'll try tonight....
But...maybe I've made a starting error.
Infact..... now I explain my need.

I must animate a fireplace..... so I must use color piked  randomly for a color and work with it (a different color for every part of fireplace).
For example i must animate fire usig yellow from darker to lighter (yellow-white)....in some point of figure (trasparents).
I started working using RGB but it was so difficult...so, playing with Paintbrush (windows) I noticed that the color change changing Brightness (Luminosity) from 0 to 240.
I thoungt it was simple...a function that convert from HSB to RGB and voila....playing with only a component (B).
I start thinking it is a bad idea.... :(
Hoping you can understand.
0
 
zuppyAuthor Commented:
I'l put the fireplace somewhere and I'll give the link.... so maybe you can see...what I mean.
0
 
zuppyAuthor Commented:
NOw here the link

http://www.ilcaminetto.com/mio/cappa13.html

As you can seen (images are not the end one...we ae working on them).... you have 6 lyers:

3 trasparent
3 with object

every trasparent is behind an object...and its background change color

black -> gray for  fireplace backround
(black) ->yellow ->white (should) for fire
orange to dark ornage for the 2 object (I dont kno translation into English)
Hoping you can better understand
0
 
Michel PlungjanIT ExpertCommented:
I could not find that link

Michel
0
 
zuppyAuthor Commented:
MMM.....yeah....
Is a strange thing I've just tryed and my DNS tells that it doesn't exist.
Not an nice thing!!
0
 
zuppyAuthor Commented:
NOw link should be visible (DN guy maked an error, grrrrrrrrrr!!!)
0
 
Michel PlungjanIT ExpertCommented:
It is up, is the fire supposed to be flickering so much???

Michel
0
 
zuppyAuthor Commented:
After doing all color setting I'm going to fix it calibrating it.
0
 
brigmarCommented:
I like the idea of what you're attempting, zuppy.

I would achieve the calibration you require is by loading an array with the h,s,b values you want for each component, then convert to rgb, and then move along the array like a path. This would lighten the computation so that the RGB values for each HSB triplet would only need to be calculated once.

What is the problem with the page you present ? The background to the fire ?

Brian
0
 
zuppyAuthor Commented:
Thanks for help to everybody, all were interesting answers and I've learned a lot :D
But I must give point to someone....just only one ...so.... but mindlly they are for all.

0

Featured Post

Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

  • 11
  • 6
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now