Solved

RGB to & from HLS coversion alghoritm

Posted on 2000-03-12
21
807 Views
Last Modified: 2008-02-20
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
Comment
Question by:zuppy
  • 11
  • 6
  • 3
  • +1
21 Comments
 

Expert Comment

by:Deathead
ID: 2609921
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
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 2610165
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
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 2610176
But have a look here :

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

Michel
0
 

Author Comment

by:zuppy
ID: 2610389
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
 

Author Comment

by:zuppy
ID: 2610400
BUt for make all easy I need mainly HSB (sorry for HSL but I translated from Italian)
0
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 2610409
I can try to convert it tomorrow if you can wait.

Michel

0
 

Author Comment

by:zuppy
ID: 2610418
Yeah... (for me is just tomorrow here :P)
0
 
LVL 4

Expert Comment

by:brigmar
ID: 2611205
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
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 2611419
Yes, I could see that, but I didn't have the time to remove all the f's and floats ;-)

Michel
0
 

Author Comment

by:zuppy
ID: 2612267
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 4

Expert Comment

by:brigmar
ID: 2613462
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
 

Author Comment

by:zuppy
ID: 2614160
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
 

Author Comment

by:zuppy
ID: 2614172
I'l put the fireplace somewhere and I'll give the link.... so maybe you can see...what I mean.
0
 

Author Comment

by:zuppy
ID: 2615522
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
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 2615680
I could not find that link

Michel
0
 

Author Comment

by:zuppy
ID: 2615957
MMM.....yeah....
Is a strange thing I've just tryed and my DNS tells that it doesn't exist.
Not an nice thing!!
0
 

Author Comment

by:zuppy
ID: 2617815
NOw link should be visible (DN guy maked an error, grrrrrrrrrr!!!)
0
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 2618896
It is up, is the fire supposed to be flickering so much???

Michel
0
 

Author Comment

by:zuppy
ID: 2618982
After doing all color setting I'm going to fix it calibrating it.
0
 
LVL 4

Accepted Solution

by:
brigmar earned 100 total points
ID: 2620601
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
 

Author Comment

by:zuppy
ID: 2675920
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

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

The task A number given should be formatted for easy reading by separating digits into triads. Format must be made inline via JavaScript, i.e., frameworks / functions are not welcome. So let’s take a number like this “12345678.91¿ and format i…
This article demonstrates how to create a simple responsive confirmation dialog with Ok and Cancel buttons using HTML, CSS, jQuery and Promises
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now