Jump to content
  • Advertisement
Sign in to follow this  
Eric Coleman

alternative hd color spaces

This topic is 5395 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've been experimenting with generating procdural textures with Lua and I want to be able to perform certain procedures on the image with regards to hue, saturation, lightness, etc, but I can't seem to get a decent color space conversion for my RGB values. It seems that the only HSL, HSV, HSB, HS? spaces only work on the set of normalized RGB values between {0,0,0} and {1,1,1}. For high dynamic range images this is simply unacceptable. Negative values of saturation or lightness generate the wrong effect. I have an idea of how to create a HD HSL/HSV color space, but my high level math skills are lacking in topology. I had considered treating the pure R, G and B values as simple basis vectors and then transformaing into a different coordinate system, but I can't seem to get a decent trasformation other than rotating pi/2 along the Z and then (pi/2 - arctan(1/sqrt(2))) along the X axis. This transformation effectivly puts the RGB color white (1,1,1) at (0,0, sqrt(3)). The value should be normalized of course, so that (0,0,1) is white and (0,0,0) is black. After a conversion to cylindrical coordiantes where r = sqrt(x^2 + y^2) and z = z, this makes the z axis approximate whiteness or brightness or some hybrid concept. The 6 pure colors red, blue, green, cyan, magenta, yellow are all 60 degrees apart when considering their projection on the X,Y plane. The problem is that their Z values are different and that a cross section of the space in the X,Y plane doesn't yield a suitable spread of the spectrum. For example, a plane through R', G', and B' yields an average of their RGB values to create C, M, Y. Simply (R + B) / 2 = M / 2 (linear interpolation) instead of the general (R + B) / 2 = M (angular interpolation). I considered dividing the cylinder into 6 quadrants and then doing a shear along the Z to normalize the transformed R', G', B', C', M', Y' so that their Z values are all the same. However, the result of the points projected onto X,Y results in a hexagon in terms of the transition from color to color and I really don't like that result. I suppose some type of "sphereize" transformation could work, but I'm not so sure if that's the correct way to procede. So, does anyone have any proper suggestion on a high dynamic range HS-ish color space? I'd like something that's elegant and concise instead of requiring a switch case for 6 different areas when doing a shear for each section.

Share this post


Link to post
Share on other sites
Advertisement
Perhaps i'm not the best person to answer this, but I think you could use modified HSI space where intensity component is transformed to contrast space (HSC).

You calculate hue and saturation from normalized values and contrast (and intensity) from unnormalized values of R,G and B.

H=theta, if B <= G
H=360-theta if B > G

theta=arccos((0.5*(R-G)+(R-B)))/(sqrt((R-G)^2+(R-B)*(G-B)))

S=1-3/(R+G+B)*min(R,G,B)

I=1/3(R+G+B)

I don't know the correct transform from intensity to contrast, but it's something like this:
C=a*log(I)

Share this post


Link to post
Share on other sites
Thanks for the reply, but the method you suggest wont work for extreme values. Consider the color (-1 R, -1 G, 0 B). That color should get displayed as black, but since it's high range color you can perform adjustments to it, and if it were to be adjusted to be brighter by adding a say (.5, .5, .5) to it, then the black color would infact be blue.

The power behind high range color spaces is that dark colors maintain color information when out of range of the typical monitor.

Using the traditional HSL conversion you specified results in the hue being inverted instead of maintained.

A specific property that I'm looking for in a high range color transform is that hue be maintained and also be defined for S = 0 and I = 0.

Thanks

Share this post


Link to post
Share on other sites
It seems that the easiest solution would be to normalize your image, perform the calculations, then denormalize it again.

C = (C - MinC) / (MaxC - MinC)
//Do HSL Stuff
C = (C * (MaxC - MinC)) + MinC

Where MinC is the minimum component value in the image and MaxC is the maximum component value. Of course, this would slow things down since you have to scan the whole image to the get the min/max and do two per-pixel scale&offset operations.

If you're doing a per-pixel loop already, you could include the find min & max code and the scale&offset operation at the end of the loop to avoid having a seperate loop, but you still need a seperate loop to do the HSL-space operations and convert back. 2 loops is better than 4+ though =-)

Share this post


Link to post
Share on other sites
Hi,

Normalizing the image is a good idea. Although I would have to reclaculate the min and max for each layer depending on how the LUA script accesses the color information, either a global image or individual components. However, my intentions for the library are to generate the textures once from the source scripts, so the end user would only have to wait once when generating the textures on the first load of the game or possibly during installation.

Although normalizing to the range [0,1] would erase any precision for out-of-range values. I'm not sure if a loss of precision would be detrimental or not.

So I guess no one has heard of a non-RGB HD color space?

Share this post


Link to post
Share on other sites
Hey thanks!

It looks like that stuff is redundant to what I've done already, so I guess that means I'm on the right track. That's definately good to know! :)

As I originally surmised, a shear would probably be needed, so I'll have to take a look at how it's use in that article.

I'll have to do some tests to see if the shear actually works or not. A shear offets everything equally, so from my examination of the progblem I had guessed that 6 seperate shears would be needed. It's easy to assume that if you take a cube of some sort and hold it so that it rests on a single vertex. The R, G, B vertices are coplanar, and the C, M, Y points are coplanar and they obviously alternate, so a single shear, well, it's not so easy to imagine.

I'll try out the shear that the article suggests and post my results here for those that are interested.

Thanks for that article, I guess I'll be spending a quite a bit more time browsing the sgi website for more info.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!