![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Hi again,
at the risk of being nailed to what ever you have handy: Those converter
macros in colors.inc are not ready to use yet, right?
CRGB2HSL(Color) is missing
CHSL2RGB(Color) picks the HSLvalues in the variables R,G and B but works
afterwards with H, S and L. That seems not correct to me.
Is this on someone's ToDo-List already? I couldn't find it being mentioned
anywhere (esp. not in the known issues list).
Marc-Hendrik
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Yes, I think they are under developement.
--
#macro N(D,I)#if(I<6)cylinder{M()#local D[I]=div(D[I],104);M().5,2pigment{
rgb M()}}N(D,(D[I]>99?I:I+1))#end#end#macro M()<mod(D[I],13)-6,mod(div(D[I
],13),8)-3,10>#end blob{N(array[6]{11117333955,
7382340,3358,3900569407,970,4254934330},0)}// - Warp -
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
>
> Yes, I think they are under developement.
Yes, and the person developing them left for college and has never
been heard from again. We may have to scrap them unless someone
else takes over and finishes them.
--
Ken Tyler
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Ken wrote:
>
> Warp wrote:
> >
> > Yes, I think they are under developement.
>
> Yes, and the person developing them left for college and has never
> been heard from again. We may have to scrap them unless someone
> else takes over and finishes them.
I had a quick look at those macros. And I
also skimmed through some of the relevant
sections in this FAQ:
http://www.inforamp.net/~poynton/notes/colour_and_gamma/ColorFAQ.html
I think this section is quite relevant:
http://www.inforamp.net/~poynton/notes/colour_and_gamma/ColorFAQ.html#RTFToC36
It seems to me that the mentioned macros
are far from done...
So I would suggest to scrap them.
=(
Tor Olav
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Tor Olav Kristensen wrote:
>
> Ken wrote:
> >
> > Warp wrote:
> > >
> > > Yes, I think they are under developement.
> >
> > Yes, and the person developing them left for college and has never
> > been heard from again. We may have to scrap them unless someone
> > else takes over and finishes them.
>
> I had a quick look at those macros. And I
> also skimmed through some of the relevant
> sections in this FAQ:
>...
> It seems to me that the mentioned macros
> are far from done...
>
> So I would suggest to scrap them.
Well, I think that I now understand how
the first macro; CHSL2RGB()
(Convert HSL to RGB) was meant to work.
I have rewritten it. But I couldn't get
the .filter and .transmit components to
work (strange things happened).
The macro seems to work OK now, but one
cannot feed it with 4D or 5D color vectors.
Here's my suggestion for it:
#macro CHSL2RGB(vColor)
// Extract Hue, Saturation and Lightness components
#local H = vColor.red;
#local S = vColor.green;
#local L = vColor.blue;
// Construct RGB from Hue
#switch (H)
#range (0/3, 1/3) // H: 0/3 -> 1/3
#local R = (1/3 - H)*6; // R: 2 -> 0
#local G = (H - 0/3)*6; // G: 0 -> 2
#local B = 0; // B: 0 -> 0
#break
#range (1/3, 2/3) // H: 1/3 -> 2/3
#local R = 0; // R: 0 -> 0
#local G = (2/3 - H)*6; // G: 2 -> 0
#local B = (H - 1/3)*6; // B: 0 -> 2
#break
#range (2/3, 3/3) // H: 2/3 -> 3/3
#local R = (H - 2/3)*6; // R: 0 -> 2
#local G = 0; // G: 0 -> 0
#local B = (3/3 - H)*6; // B: 2 -> 0
#break
#else
#error "Error in CHSL2RGB: Value for Hue component is out of
range."
#end // switch
#local vClampedRGB = <min(R, 1), min(G, 1), min(B, 1)>;
// Incorporate saturation and lightness
#local vRGB = ((1 - S)*<1, 1, 1> + S*vClampedRGB)*L;
color rgb <vRGB.red, vRGB.green, vRGB.blue>
#end // macro CHSL2RGB
And here's some examples on how it converts colors:
Red HSL: <0/6, 1, 1> => RGB: <1, 0, 0>
Yellow HSL: <1/6, 1, 1> => RGB: <1, 1, 0>
Green HSL: <2/6, 1, 1> => RGB: <0, 1, 0>
Cyan HSL: <3/6, 1, 1> => RGB: <0, 1, 1>
Blue HSL: <4/6, 1, 1> => RGB: <0, 0, 1>
Magenta HSL: <5/6, 1, 1> => RGB: <1, 0, 1>
Red HSL: < 1, 1, 1> => RGB: <1, 0, 0>
Black HSL: < X, X, 0> => RGB: <0, 0, 0>
White HSL: < X, 0, 1> => RGB: <1, 1, 1>
(X means don't care)
And here's an example that shows how to use it:
#declare HSL_Red = < 0, 1, 1>;
#declare HSL_Yellow = <1/6, 1, 1>;
#declare HSL_Green = <1/3, 1, 1>;
#declare HSL_Cyan = <1/2, 1, 1>;
#declare HSL_Blue = <2/3, 1, 1>;
#declare HSL_Magenta = <5/6, 1, 1>;
#declare HSL_Red = < 1, 1, 1>;
#declare HSL_Black = < 0, 0, 0>;
#declare HSL_White = < 0, 0, 1>;
#declare HSL_Grey = HSL_White/2;
sphere {
<0, 0, 0>, 1
pigment { CHSL2RGB(HSL_Red) }
}
light_source {
100*<-1, 1, -1>
CHSL2RGB(HSL_White)
}
camera {
location <2, 1, -3>
look_at <0, 0, 0>
}
background { CHSL2RGB(HSL_Grey) }
But if I were to write this macro from
scratch, then i would have used an angle
(in degrees) for the Hue component.
I.e. like this:
Red HSL: < 0, 1, 1> => RGB: <1, 0, 0>
Yellow HSL: < 60, 1, 1> => RGB: <1, 1, 0>
Green HSL: <120, 1, 1> => RGB: <0, 1, 0>
Cyan HSL: <180, 1, 1> => RGB: <0, 1, 1>
Blue HSL: <240, 1, 1> => RGB: <0, 0, 1>
Magenta HSL: <300, 1, 1> => RGB: <1, 0, 1>
Black HSL: < X, X, 0> => RGB: <0, 0, 0>
White HSL: < X, 0, 1> => RGB: <1, 1, 1>
// X means don't care
And I would have omitted the color and rgb
keywords before the returned vector.
Then the macro would have looked like this:
#macro ConvertHSLtoRGB(vColor)
// Extract Hue, Saturation and Lightness components
#local H = vColor.x;
#local S = vColor.y;
#local L = vColor.z;
// Construct RGB from Hue
#switch (mod(H, 360))
#range (0, 120)
#local R = (120 - H)/60;
#local G = ( H - 0)/60;
#local B = 0;
#break
#range (120, 240)
#local R = 0;
#local G = (240 - H)/60;
#local B = ( H - 120)/60;
#break
#range (240, 360)
#local R = ( H - 240)/60;
#local G = 0;
#local B = (360 - H)/60;
#break
#end // switch
#local vClampedRGB = <min(R, 1), min(G, 1), min(B, 1)>;
// Incorporate saturation and lightness
(((1 - S)*<1, 1, 1> + S*vClampedRGB)*L)
#end // macro ConvertHSLtoRGB
And some code to show how it works could
look like this:
#declare HSL_Red = < 0, 1, 1>; // or <360, 1, 1> or < 720, 1, 1>
...
#declare HSL_Yellow = < 60, 1, 1>; // or <420, 1, 1> or < 780, 1, 1>
...
#declare HSL_Green = <120, 1, 1>; // or <480, 1, 1> or < 840, 1, 1>
...
#declare HSL_Cyan = <180, 1, 1>; // or <540, 1, 1> or < 900, 1, 1>
...
#declare HSL_Blue = <240, 1, 1>; // or <600, 1, 1> or < 960, 1, 1>
...
#declare HSL_Magenta = <300, 1, 1>; // or <660, 1, 1> or <1020, 1, 1>
...
#declare HSL_Black = < 0, 0, 0>;
#declare HSL_White = < 0, 0, 1>;
#declare HSL_Grey = HSL_White/2;
sphere {
<0, 0, 0>, 1
pigment { color ConvertHSLtoRGB(HSL_Cyan) }
}
light_source {
100*<-1, 1, -1>
color ConvertHSLtoRGB(HSL_White)
}
camera {
location <2, 1, -3>
look_at <0, 0, 0>
}
background { color ConvertHSLtoRGB(HSL_Grey) }
Tor Olav
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
If the macro is written like below, then
it can also handle negative angles for
the Hue component.
Tor Olav
#macro ConvertHSLtoRGB(vColor)
// Extract Hue, Saturation and Lightness components
#local H = vColor.x;
#local S = vColor.y;
#local L = vColor.z;
#local Angle = mod(H, 360) + (H < 0 ? 360 : 0);
// Construct RGB from Hue
#switch (Angle)
#range (0, 120)
#local R = (120 - H)/60;
#local G = ( H - 0)/60;
#local B = 0;
#break
#range (120, 240)
#local R = 0;
#local G = (240 - H)/60;
#local B = ( H - 120)/60;
#break
#range (240, 360)
#local R = ( H - 240)/60;
#local G = 0;
#local B = (360 - H)/60;
#break
#end // switch
#local vClampedRGB = <min(R, 1), min(G, 1), min(B, 1)>;
// Incorporate saturation and lightness
(((1 - S)*<1, 1, 1> + S*vClampedRGB)*L)
#end // macro ConvertHSLtoRGB
Tor Olav Kristensen wrote:
>...
> But if I were to write this macro from
> scratch, then i would have used an angle
> (in degrees) for the Hue component.
>...
> Then the macro would have looked like this:
>
> #macro ConvertHSLtoRGB(vColor)
>
> // Extract Hue, Saturation and Lightness components
> #local H = vColor.x;
> #local S = vColor.y;
> #local L = vColor.z;
>
> // Construct RGB from Hue
> #switch (mod(H, 360))
> #range (0, 120)
> #local R = (120 - H)/60;
> #local G = ( H - 0)/60;
> #local B = 0;
> #break
> #range (120, 240)
> #local R = 0;
> #local G = (240 - H)/60;
> #local B = ( H - 120)/60;
> #break
> #range (240, 360)
> #local R = ( H - 240)/60;
> #local G = 0;
> #local B = (360 - H)/60;
> #break
> #end // switch
>
> #local vClampedRGB = <min(R, 1), min(G, 1), min(B, 1)>;
>
> // Incorporate saturation and lightness
> (((1 - S)*<1, 1, 1> + S*vClampedRGB)*L)
>
> #end // macro ConvertHSLtoRGB
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
I think there's a problem in the basic functionality. If HSL is supposed to
work anything like in regular graphics programs, then this code:
// Incorporate saturation and lightness
(((1 - S)*<1, 1, 1> + S*vClampedRGB)*L)
Should be replaced with this:
// Incorporate saturation and lightness
#switch (L)
#range (0.0, 0.5)
((vClampedRGB*S+<1,1,1>/2*(1-S))*L*2)
#break
#range (0.5, 1.0)
((vClampedRGB*S+<1,1,1>/2*(1-S))*(2-L*2)+<1,1,1>*(L*2-1))
#break
#end
You can use this code to see the difference:
#declare Xm = 50;
#declare Ym = 50;
#declare X = 0;
#while (X<=Xm)
#declare Y = 0;
#while (Y<=Ym)
#declare Xv = (X/Xm);
#declare Yv = (Y/Ym);
sphere {
<Xv,Yv,0>, 0.05
pigment {color ConvertHSLtoRGB(<0,Xv,Yv>)}
finish {ambient 1 diffuse 0}
}
#declare Y=Y+1;
#end
#declare X=X+1;
#end
camera {translate <0.5,0.5,-1>}
background {color rgb 0.5}
I might be wrong though - I would like to hear your opinions on this!
Rune
--
3D images and anims, include files, tutorials and more:
Rune's World: http://rsj.mobilixnet.dk (updated June 26)
POV-Ray Users: http://rsj.mobilixnet.dk/povrayusers/
POV-Ray Webring: http://webring.povray.co.uk
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
I have tested the CHSL2RGB macro and fixed some bugs in it and I've also
coded a CRGB2HSL macro that converts the other way. The conversion back and
forth is perfect at least in the tests I've made. Here are the two macros
and some code that shows that multiple conversions back and forth produce
consistent results.
I will include these macros in colors.inc. The other color formats will be
dropped.
Please feel free to make lots of tests, as there might still be some bugs
left!
#macro CHSL2RGB(Color)
#local Color = color Color;
// Extract Hue, Saturation and Lightness components
#local H = (Color.red);
#local S = (Color.green);
#local L = (Color.blue);
#local H = mod(H, 360);
#local H = (H < 0 ? H+360 : H);
// Construct saturaed RGB from Hue
#switch (H)
#range (0, 120)
#local SR = (120 - H)/60;
#local SG = ( H - 0)/60;
#local SB = 0;
#break
#range (120, 240)
#local SR = 0;
#local SG = (240 - H)/60;
#local SB = ( H - 120)/60;
#break
#range (240, 360)
#local SR = ( H - 240)/60;
#local SG = 0;
#local SB = (360 - H)/60;
#break
#end // switch
#local SaturatedRGB = <min(SR,1), min(SG,1), min(SB,1)>;
// Incorporate saturation and lightness
#switch (L)
#range (0.0, 0.5)
#local RGB = ((SaturatedRGB*S+0.5*(1-S))*L*2);
#break
#range (0.5, 1.0)
#local RGB = ((SaturatedRGB*S+0.5*(1-S))*(2-L*2)+1*(L*2-1));
#break
#end
<RGB.red,RGB.green,RGB.blue,Color.filter,Color.transmit>
#end // macro CHSL2RGB
#macro CRGB2HSL(Color)
#local Color = color Color;
// Extract Red, Green and Blue components
#local R = (Color.red);
#local G = (Color.green);
#local B = (Color.blue);
// Find minimum and maximum component of RGB
#local MIN = min(R,min(G,B));
#local MAX = max(R,max(G,B));
// Find Lightness
#local L = (MAX+MIN)/2;
#if (L<=0|L>=1)
#local HSL = <0,0,min(1,max(0,L))>;
#else
// Find Saturation
#local S = (MAX-MIN) / ( L<0.5 ? (L*2) : (2-L*2) );
#if (S<=0)
#local HSL = <0,0,L>;
#else
// Find fully saturated version of Red, Green and Blue
#local SR = (R-MIN)/(MAX-MIN);
#local SG = (G-MIN)/(MAX-MIN);
#local SB = (B-MIN)/(MAX-MIN);
// Construct Angle from SR, SG and SB
#if (SB=0)
#if (SR=1)
#local Angle = ( SG)*60 ;
#else
#local Angle = (1-SR)*60 + 60;
#end
#end
#if (SR=0)
#if (SG=1)
#local Angle = ( SB)*60 + 120;
#else
#local Angle = (1-SG)*60 + 180;
#end
#end
#if (SG=0)
#if (SB=1)
#local Angle = ( SR)*60 + 240;
#else
#local Angle = (1-SB)*60 + 300;
#end
#end
#local HSL = <Angle,S,L>;
#end
#end
<HSL.x,HSL.y,HSL.z,Color.filter,Color.transmit>
#end // macro CRGB2HSL
#declare Xm = 20;
#declare Ym = 20;
#declare X = 0;
#while (X<=Xm)
#declare Y = 0;
#while (Y<=Ym)
#declare Xv = (X/Xm);
#declare Yv = (Y/Ym);
sphere {
<Xv,Yv,0>-0.6*x, 0.1
pigment {color CHSL2RGB(<0,Xv,Yv>)}
finish {ambient 1 diffuse 0}
}
sphere {
<Xv,Yv,0>+0.6*x, 0.1
pigment {color CHSL2RGB(CRGB2HSL(CHSL2RGB(<0,Xv,Yv>)))}
finish {ambient 1 diffuse 0}
}
#declare Y=Y+1;
#end
#declare X=X+1;
#end
camera {translate <0.5,0.5,-2>}
background {color rgb 0.5}
Rune
--
3D images and anims, include files, tutorials and more:
Rune's World: http://rsj.mobilixnet.dk (updated June 26)
POV-Ray Users: http://rsj.mobilixnet.dk/povrayusers/
POV-Ray Webring: http://webring.povray.co.uk
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Rune,
I have some old HSV <-> RGB macros ... which I've just updated to the
same standard as yours - I think they're right and I've added some
checks, but test them :-)
I include your test code, just changed HSL to HSV, and it seems to work.
Rune wrote:
>
> I have tested the CHSL2RGB macro and fixed some bugs in it and I've also
> coded a CRGB2HSL macro that converts the other way. The conversion back and
> forth is perfect at least in the tests I've made. Here are the two macros
> and some code that shows that multiple conversions back and forth produce
> consistent results.
>
> I will include these macros in colors.inc. The other color formats will be
> dropped.
>
> Please feel free to make lots of tests, as there might still be some bugs
> left!
#macro CRGB2HSV ( Pvec )
#local vec = colour Pvec;
#local V = max(vec.x, max(vec.y, vec.z));
#if (V <= 0.0)
#local R2H_col = colour rgbft <0, 0, 0, vec.filter, vec.transmit>;
#else
#local Vp = min(vec.x, min(vec.y, vec.z));
#local S = (V-Vp)/V;
#if (S <= 0.0)
#local R2H_col = colour rgbft <0, 0, V, vec.filter, vec.transmit>;
#else
#local P = (V-vec)/(V-Vp);
#if (vec.x = V & vec.y = Vp)
#local H = (5 + P.z)/6;
#else
#if (vec.x = V & vec.y != Vp)
#local H = (1 - P.y)/6;
#else
#if (vec.y = V & vec.z = Vp)
#local H = (1 + P.x)/6;
#else
#if (vec.y = V & vec.z != Vp)
#local H = (3 - P.z)/6;
#else
#if (vec.x = V)
#local H = (3 + P.y)/6;
#else
#local H = (5 - P.x)/6;
#end
#end
#end
#end
#end
#local R2H_col = colour rgbft <H, S, V, vec.filter, vec.transmit>;
#end
#end
<R2H_col.x,R2H_col.y,R2H_col.z,R2H_col.filter,R2H_col.transmit>
#end
#macro CHSV2RGB ( Pvec )
#local vec = colour Pvec;
#local H = mod(vec.x*6, 6);
#local H = ((H < 0)? H+6: H);
#local P = floor(H);
#local S = H - P;
#local Y = min(1, max(vec.y, 0));
#local Z = min(1, max(vec.z, 0));
#local A = (1 - Y)*Z;
#local B = (1 - (S*Y))*Z;
#local C = (1 - ((1-S)*Y))*Z;
#switch (P)
#case (0)
#local H2R_col = colour rgbft <Z, C, A, vec.filter, vec.transmit>;
#break
#case (1)
#local H2R_col = colour rgbft <B, Z, A, vec.filter, vec.transmit>;
#break
#case (2)
#local H2R_col = colour rgbft <A, Z, C, vec.filter, vec.transmit>;
#break
#case (3)
#local H2R_col = colour rgbft <A, B, Z, vec.filter, vec.transmit>;
#break
#case (4)
#local H2R_col = colour rgbft <C, A, Z, vec.filter, vec.transmit>;
#break
#case (5)
#local H2R_col = colour rgbft <Z, A, B, vec.filter, vec.transmit>;
#break
#end
<H2R_col.x,H2R_col.y,H2R_col.z,H2R_col.filter,H2R_col.transmit>
#end
#declare Xm = 20;
#declare Ym = 20;
#declare X = 0;
#while (X<=Xm)
#declare Y = 0;
#while (Y<=Ym)
#declare Xv = (X/Xm);
#declare Yv = (Y/Ym);
sphere {
<Xv,Yv,0>-0.6*x, 0.1
pigment {color CHSV2RGB(<0,Xv,Yv>)}
finish {ambient 1 diffuse 0}
}
sphere {
<Xv,Yv,0>+0.6*x, 0.1
pigment {color CHSV2RGB(CRGB2HSV(CHSV2RGB(<0,Xv,Yv>)))}
finish {ambient 1 diffuse 0}
}
#declare Y=Y+1;
#end
#declare X=X+1;
#end
camera {translate <0.5,0.5,-2>}
background {color rgb 0.5}
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Hello again Rune.
It seems that the combination of your modifications
to my macro and your CRGB2HSL() macro makes it
possible to convert back and forth between both RGB
and HSL coded colors.
Right now I have no time to test and study your
modifications thoroughly :(
- So now I only have to hope that you have good
reasons for making these changes.
Below is my suggestion for a somewhat rewritten
(and hopefully simplified) version of your
CRGB2HSL() macro.
There's also a version of my CHSL2RGB() macro that
shows how I would like it to appear with your
modifications.
Please note that I think that both the CRGB2HSL()
macro and the CHSL2RGB() macro has problems with
RGB and HSL color vectors with "out of range
components" (E.g.: Greater than 1 or less than 0).
But I'm not at all sure if it is wise to attempt
to fix this.
Tor Olav
Btw.:
I think that these color conversion macros
should not only be tested with with sphere pairs
with these pigments:
pigment { color CHSL2RGB(<H, S, L>) }
pigment { color CHSL2RGB(CRGB2HSL(CHSL2RGB(<H, S, L>))) }
but also with these pigments:
pigment { color <R, G, B>) }
pigment { color CHSL2RGB(CRGB2HSL(<R, G, B>)) }
#macro CRGB2HSL(Color)
#local RGBFT = color Color;
#local R = (RGBFT.red);
#local G = (RGBFT.green);
#local B = (RGBFT.blue);
#local Min = min(R, min(G, B));
#local Max = max(R, max(G, B));
#local Span = Max - Min;
#local Mid = (Min + Max)/2;
#local H = 0;
#local S = 0;
#if (Mid > 0 & Mid < 1)
#if (Span > 0)
#local H = (
(R = Max ? 0 + (G - B)/Span : 0) +
(G = Max ? 2 + (B - R)/Span : 0) +
(B = Max ? 4 + (R - G)/Span : 0)
)*60;
#end // if
#local S = Span/2/(Mid < 0.5 ? Mid : 1 - Mid);
#end // if
#local L = min(1, max(0, Mid));
<H, S, L, RGBFT.filter, RGBFT.transmit>
#end // macro CRGB2HSL
#macro CHSL2RGB(Color)
#local HSLFT = color Color;
#local H = (HSLFT.red);
#local S = (HSLFT.green);
#local L = (HSLFT.blue);
#local H = mod(H, 360) + (H < 0 ? 360 : 0);
#switch (H)
#range ( 0, 120)
#local SR = (120 - H)/60;
#local SG = ( H - 0)/60;
#local SB = 0;
#break
#range (120, 240)
#local SR = 0;
#local SG = (240 - H)/60;
#local SB = ( H - 120)/60;
#break
#range (240, 360)
#local SR = ( H - 240)/60;
#local SG = 0;
#local SB = (360 - H)/60;
#break
#end // switch
#local SaturatedRGB = <min(SR, 1), min(SG, 1), min(SB, 1)>;
#local Col = 2*S*SaturatedRGB + (1 - S)*<1, 1, 1>;
#switch (L)
#range (0.0, 0.5)
#local RGB = Col*L;
#break
#range (0.5, 1.0)
#local RGB = Col*(1 - L) + (2*L - 1)*<1, 1, 1>;
#break
#end // switch
<RGB.red, RGB.green, RGB.blue, HSLFT.filter, HSLFT.transmit>
#end // macro CHSL2RGB
Rune wrote:
>
> I have tested the CHSL2RGB macro and fixed some bugs in it and I've also
> coded a CRGB2HSL macro that converts the other way. The conversion back and
> forth is perfect at least in the tests I've made. Here are the two macros
> and some code that shows that multiple conversions back and forth produce
> consistent results.
>
> I will include these macros in colors.inc. The other color formats will be
> dropped.
>
> Please feel free to make lots of tests, as there might still be some bugs
> left!
>
> #macro CHSL2RGB(Color)
>
> #local Color = color Color;
>
> // Extract Hue, Saturation and Lightness components
> #local H = (Color.red);
> #local S = (Color.green);
> #local L = (Color.blue);
>
> #local H = mod(H, 360);
> #local H = (H < 0 ? H+360 : H);
>
> // Construct saturaed RGB from Hue
> #switch (H)
> #range (0, 120)
> #local SR = (120 - H)/60;
> #local SG = ( H - 0)/60;
> #local SB = 0;
> #break
> #range (120, 240)
> #local SR = 0;
> #local SG = (240 - H)/60;
> #local SB = ( H - 120)/60;
> #break
> #range (240, 360)
> #local SR = ( H - 240)/60;
> #local SG = 0;
> #local SB = (360 - H)/60;
> #break
> #end // switch
>
> #local SaturatedRGB = <min(SR,1), min(SG,1), min(SB,1)>;
>
> // Incorporate saturation and lightness
> #switch (L)
> #range (0.0, 0.5)
> #local RGB = ((SaturatedRGB*S+0.5*(1-S))*L*2);
> #break
> #range (0.5, 1.0)
> #local RGB = ((SaturatedRGB*S+0.5*(1-S))*(2-L*2)+1*(L*2-1));
> #break
> #end
>
> <RGB.red,RGB.green,RGB.blue,Color.filter,Color.transmit>
>
> #end // macro CHSL2RGB
>
> #macro CRGB2HSL(Color)
>
> #local Color = color Color;
>
> // Extract Red, Green and Blue components
> #local R = (Color.red);
> #local G = (Color.green);
> #local B = (Color.blue);
>
> // Find minimum and maximum component of RGB
> #local MIN = min(R,min(G,B));
> #local MAX = max(R,max(G,B));
>
> // Find Lightness
> #local L = (MAX+MIN)/2;
>
> #if (L<=0|L>=1)
> #local HSL = <0,0,min(1,max(0,L))>;
> #else
>
> // Find Saturation
> #local S = (MAX-MIN) / ( L<0.5 ? (L*2) : (2-L*2) );
>
> #if (S<=0)
> #local HSL = <0,0,L>;
> #else
>
> // Find fully saturated version of Red, Green and Blue
> #local SR = (R-MIN)/(MAX-MIN);
> #local SG = (G-MIN)/(MAX-MIN);
> #local SB = (B-MIN)/(MAX-MIN);
>
> // Construct Angle from SR, SG and SB
> #if (SB=0)
> #if (SR=1)
> #local Angle = ( SG)*60 ;
> #else
> #local Angle = (1-SR)*60 + 60;
> #end
> #end
> #if (SR=0)
> #if (SG=1)
> #local Angle = ( SB)*60 + 120;
> #else
> #local Angle = (1-SG)*60 + 180;
> #end
> #end
> #if (SG=0)
> #if (SB=1)
> #local Angle = ( SR)*60 + 240;
> #else
> #local Angle = (1-SB)*60 + 300;
> #end
> #end
>
> #local HSL = <Angle,S,L>;
>
> #end
>
> #end
>
> <HSL.x,HSL.y,HSL.z,Color.filter,Color.transmit>
>
> #end // macro CRGB2HSL
>
> #declare Xm = 20;
> #declare Ym = 20;
> #declare X = 0;
> #while (X<=Xm)
> #declare Y = 0;
> #while (Y<=Ym)
> #declare Xv = (X/Xm);
> #declare Yv = (Y/Ym);
> sphere {
> <Xv,Yv,0>-0.6*x, 0.1
> pigment {color CHSL2RGB(<0,Xv,Yv>)}
> finish {ambient 1 diffuse 0}
> }
> sphere {
> <Xv,Yv,0>+0.6*x, 0.1
> pigment {color CHSL2RGB(CRGB2HSL(CHSL2RGB(<0,Xv,Yv>)))}
> finish {ambient 1 diffuse 0}
> }
> #declare Y=Y+1;
> #end
> #declare X=X+1;
> #end
> camera {translate <0.5,0.5,-2>}
> background {color rgb 0.5}
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |