tags:

views:

368

answers:

4

Does anyone know of a way to get HSL from an linearRGB color (not an sRGB color)? I've seen a lot of sRGB<->HSL conversions, but nothing for linearRGB<->HSL. Not sure if it is fundementally the same conversion with minor tweaks, but I'd appreciate any insight someone may have on this.

Linear RGB is not the same as linearizing sRGB (which is taking [0,255] and making it [0,1]). Linear RGB transformation from/to sRGB is at http://en.wikipedia.org/wiki/SRGB. In VBA, this would be expressed (taking in linearized sRGB values [0,1]):

Public Function sRGB_to_linearRGB(value As Double)
   If value < 0# Then
      sRGB_to_linearRGB = 0#
      Exit Function
   End If
   If value <= 0.04045 Then
      sRGB_to_linearRGB = value / 12.92
      Exit Function
   End If
   If value <= 1# Then
      sRGB_to_linearRGB = ((value + 0.055) / 1.055) ^ 2.4
      Exit Function
   End If
   sRGB_to_linearRGB = 1#
End Function

Public Function linearRGB_to_sRGB(value As Double)
   If value < 0# Then
      linearRGB_to_sRGB = 0#
      Exit Function
   End If
   If value <= 0.0031308 Then
      linearRGB_to_sRGB = value * 12.92
      Exit Function
   End If
   If value < 1# Then
      linearRGB_to_sRGB = 1.055 * (value ^ (1# / 2.4)) - 0.055
      Exit Function
   End If
   linearRGB_to_sRGB = 1#
End Function

I have tried sending in Linear RGB values to standard RGB_to_HSL routines and back out from HSL_to_RGB, but it does not work. Maybe because current HSL<->RGB algorithms account for gamma correction and Linear RGB is not gamma corrected - I don't know exactly. I have seen almost no references that this can be done, except for two:

  1. A reference on http://en.wikipedia.org/wiki/HSL_and_HSV#cite_note-9 (numbered item 10).
  2. A reference on an open source project Grafx2 @ http://code.google.com/p/grafx2/issues/detail?id=63#c22 in which the contributor states that he has done Linear RGB <-> HSL conversion and provides some C code in an attachment to his comment in a .diff file (which I can't really read :( )

My intent is to:

  1. send from sRGB (for example, FF99FF (R=255, G=153, B=255)) to Linear RGB (R=1.0, G=0.318546778125092, B=1.0)
    • using the code above (for example, the G=153 would be obtained in Linear RGB from sRGB_to_linearRGB(153 / 255))
  2. to HSL
  3. modify/modulate the Saturation by 350%
  4. send back from HSL->Linear RGB->sRGB, the result would be FF19FF (R=255, G=25, B=255).

Using available functions from .NET, such as .getHue from a System.Drawing.Color does not work in any sRGB space above 100% modulation of any HSL value, hence the need for Linear RGB to be sent in instead of sRGB.

+1  A: 

The System.Windows.Media.Color class lets you get or set scRGB via ScA,ScR,ScG,ScB properties, or RGB via A,R,G,B properties.

So you could convert RGB to HSL, manipulate that, then convert back to RGB and store in a Color instance. You can then read out the converted scRGB properties.

Not ideal, and might involve some information loss. But it's an option!

Paul Dixon
Thanks. I've looked at this possibility a bit and the main issue is that I lose a bit of color every time I got to RGB and then back again as I'll be doing multiple calculations on on top of calculations. For example, I'll need to set the brightness to a new brightness, then change the saturation based on an input variable then tint a color with white. Going in and out of RGB I find that I lose exact values.
Otaku
+1  A: 

Based on your comment here, your issue isn't doing the conversion incorrectly; it's that you are performing successive conversions on quantized values. In other words, you are taking the result of sRGB=>RGB=>HSL=>HSL=>RGB=>sRGB and using that in subsequent color operations. The most straightforward way to maintain precision is to always keep around the original RGB value and accumulate the changes in HSL space you want to apply. That way, you are always applying the HSL space operations to the original color and you don't have to worry about repeatedly processing quantized values.

MSN
Thanks for the thoughts, but no, scRGB is not what I'm looking for here. Secondarily, System.Windows.Media.Color does not have any HSL conversion from/to methods.
Otaku
@Otaku, that's not my point. My point is that if you are going to perform additional conversions from sRGB to HSL and back, you need to either keep the intermediate results in a higher precision format (Short, Int, Single, Double, etc.) or apply all the transformations in HSL space at once.
MSN
I guess I'm not entirely following you. Linear RGB is a Double (as per the code above), that is where the data will be kept between HSL and sRGB. I'm not sure what I'm misunderstanding here though.
Otaku
@Otaku, you mentioned in the other comment "Going in and out of RGB I find that I lose exact values". I am assuming that you go from Linear RGB (as Double) to sRGB (as Byte). If you do that and then go back to Linear RGB, you will lose precision.
MSN
Sorry, that was over 6 months ago and the thread has been edited significantly since then. You can view the history of the thread to see some of the differences. You should use the question as it is now to provide any possible solution.
Otaku
+2  A: 

It doesn't make much sense to convert to linear RGB, since HSL is defined in terms of gamma encoded values. Instead, write your own function convert sRGB to HSL, modulate the saturation with those values (allowing potentially out-of-gamut saturation values), and then convert back to sRGB, clamping intensities that are out of sRGB range (or disallowing saturation changes that can't be encoded in sRGB).

ergosys
Hmmm...you may be on to something, I hadn't thought of this at all. Let me give it a shot and I'll come back with results.
Otaku
Single pass tests are working with this idea! Great! Testing multiple pass now.
Otaku
Well, this did the trick - thanks so much ergosys!
Otaku
+1  A: 

Does this help? There are a lot of interesting links in that question, maybe something that works in your case, too...

mafutrct
There are some good links here, one I'm going to bookmark, but unforutnately, not a lot of explanation as to what I'm after.
Otaku