POV-Ray : Newsgroups : povray.beta-test : Colors.inc-macros incomplete Server Time
19 Apr 2024 04:10:57 EDT (-0400)
  Colors.inc-macros incomplete (Message 1 to 10 of 11)  
Goto Latest 10 Messages Next 1 Messages >>>
From: Marc-Hendrik Bremer
Subject: Colors.inc-macros incomplete
Date: 9 Sep 2001 12:21:29
Message: <3b9b9709@news.povray.org>
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

From: Warp
Subject: Re: Colors.inc-macros incomplete
Date: 10 Sep 2001 06:49:45
Message: <3b9c9ac9@news.povray.org>
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

From: Ken
Subject: Re: Colors.inc-macros incomplete
Date: 10 Sep 2001 06:52:30
Message: <3B9C9C59.15A109E2@pacbell.net>
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

From: Tor Olav Kristensen
Subject: Re: Colors.inc-macros incomplete
Date: 10 Sep 2001 17:17:40
Message: <3B9D2DB3.7E55E0BA@hotmail.com>
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

From: Tor Olav Kristensen
Subject: Re: Colors.inc-macros incomplete
Date: 10 Sep 2001 21:13:41
Message: <3B9D6505.101CB65F@hotmail.com>
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

From: Tor Olav Kristensen
Subject: Re: Colors.inc-macros incomplete
Date: 10 Sep 2001 22:01:27
Message: <3B9D7039.80799D1A@hotmail.com>
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

From: Rune
Subject: Re: Colors.inc-macros incomplete
Date: 11 Sep 2001 04:25:56
Message: <3b9dca94$1@news.povray.org>
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

From: Rune
Subject: Re: Colors.inc-macros incomplete
Date: 11 Sep 2001 08:15:06
Message: <3b9e004a@news.povray.org>
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

From: Michael Andrews
Subject: Re: Colors.inc-macros incomplete
Date: 11 Sep 2001 09:26:44
Message: <3B9E12AB.3B0CDA0@reading.ac.uk>
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

From: Tor Olav Kristensen
Subject: Re: Colors.inc-macros incomplete
Date: 11 Sep 2001 21:34:45
Message: <3B9EBB7A.98563AFE@hotmail.com>
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

Goto Latest 10 Messages Next 1 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.