
$echelle = 31;
$xmin = 1;
$ymin = 1;
$zmin = 1;
$smin = 1;
$hmin = 1;
$lmin = 1;
$amin = 1;
$bmin = 1;
$lamin = 1;
$umin = 1;
$vmin = 1;
$lumin = 1;

for ($re=0;$re<=$echelle;$re++)
{
    $red = $re / $echelle;
    for ($bl=0;$bl<=$echelle;$bl++)
    {
        $blu = $bl / $echelle;
        for ($gr=0;$gr<=$echelle;$gr++)
        {
            $gre = $gr / $echelle;
            ($h,$s,$l) = rgb_hsl($red, $gre, $blu);
            ($x,$y,$z) = rgb_xyz($red, $gre, $blu);
            ($la,$a,$b) = xyz_lab($x, $y, $z);
            ($lu,$u,$v) = xyz_luv($x, $y, $z);

if ($x > $xmax) { $xmax = $x };
if ($y > $ymax) { $ymax = $y };
if ($z > $zmax) { $zmax = $z };
if ($x < $xmin) { $xmin = $x };
if ($y < $ymin) { $ymin = $y };
if ($z < $zmin) { $zmin = $z };

if ($h > $hmax) { $hmax = $h };
if ($s > $smax) { $smax = $s };
if ($l > $lmax) { $lmax = $l };
if ($h < $hmin) { $hmin = $h };
if ($s < $smin) { $smin = $s };
if ($l < $lmin) { $lmin = $l };

if ($la > $lamax) { $lamax = $la };
if ($a  > $amax ) { $amax  = $a  };
if ($b  > $bmax ) { $bmax  = $b  };
if ($la < $lamin) { $lamin = $la };
if ($a  < $amin ) { $amin  = $a  };
if ($b  < $bmin ) { $bmin  = $b  };

if ($lu > $lumax) { $lumax = $lu };
if ($u  > $umax ) { $umax  = $u  };
if ($v  > $vmax ) { $vmax  = $v  };
if ($lu < $lumin) { $lumin = $lu };
if ($u  < $umin ) { $umin  = $u  };
if ($v  < $vmin ) { $vmin  = $v  };

        }
    }
}
print "Xmax: $xmax, Ymax: $ymax, Zmax: $zmax\n";
print "Xmin: $xmin, Ymin: $ymin, Zmin: $zmin\n";
print "\n";
print "Hmax: $hmax, Smax: $smax, Lmax: $lmax\n";
print "Hmin: $hmin, Smin: $smin, Lmin: $lmin\n";
print "\n";
print "Lmax: $lamax, Amax: $amax, Bmax: $bmax\n";
print "Lmin: $lamin, Amin: $amin, Bmin: $bmin\n";
print "\n";
print "Lmax: $lumax, Umax: $umax, Vmax: $vmax\n";
print "Lmin: $lumin, Umin: $umin, Vmin: $vmin\n";

sub zarbi
{
    ($k) = @_;
    if ($k > 0.008856)
    {
        $out = ( $k ** 0.333333333333 );
    } else {
        $out = ( 7.787 * $k + 0.16);
    };
    return($out);
}

sub cbrt
{
    ($k) = @_;
    return( $k ** 0.333333333333 );
}

sub xyz_lab
{
    ($xr, $yr, $zr) = @_;

    $fx = cbrt($xr);
    $fy = cbrt($yr);
    $fz = cbrt($zr);

    $la = $fy;
    $a  = 1.611 * ($fx - $fy) + 0.413;
    $b  = ($fy - $fz) / 1.555 + 0.4987;

    return($la, $a, $b);
}

sub xyz_luv
{
    ($xr, $yr, $zr) = @_;
           
    $lu = cbrt($yr);

    if ( $xr+$yr+$zr == 0)
    {
        $u = 0;
        $v = 0;
    } else {
        $up = 4*$xr / ($xr + 15 * $yr + 3 * $zr);
        $vp = 9*$yr / ($xr + 15 * $yr + 3 * $zr);
    }

    $u = 2.8575 * $lu * $up;
    $v = 1.766 * $lu * $vp;

    return($lu, $u, $v);
}

sub rgb_xyz ($red, $gre, $blu)
{
    $x = 0.488718  * $red + 0.310680  * $gre + 0.200602  * $blu;
    $y = 0.176204  * $red + 0.812985  * $gre + 0.0108109 * $blu;
    $z = 0.000000  * $red + 0.0102048 * $gre + 0.989795  * $blu;

#    $x = 0.488718  * $red + 0.176204  * $gre + 0.000000  * $blu;
#    $y = 0.310680  * $red + 0.812985  * $gre + 0.0102048 * $blu;
#    $z = 0.200602  * $red + 0.0108109 * $gre + 0.989795  * $blu;
    return ($x, $y, $z);
}

sub rgb_hsl
{
    ($r, $g, $b) = @_;

    if ($r > $g)
    {
        if ($r > $b)
        {
            $max = $r;
        } else {
            $max = $b;
        }
    } else {
        if ($g > $b)
        {
            $max = $g;
        } else {
            $max = $b;
        }
    }

    if ($r < $g)
    {
        if ($b < $r)
        {
            $min = $b;
        } else {
            $min = $r;
        }
    } else {
        if ($b < $g)
        {
            $min = $b;
        } else {
            $min = $g;
        }
    }

    $l = ($max + $min)/2;

    if ($min == $max) { return (0,0,$l); };

    if ($l < 0.5) {
        $s = ($max-$min)/($max+$min);
    } else {
        $s = ($max-$min)/(2-$max-$min);
    };

    if ($r == $max) { $h = ($g-$b)/($max-$min); }
    if ($g == $max) { $h = 2 + ($b-$r)/($max-$min); }
    if ($b == $max) { $h = 4 + ($r-$g)/($max-$min); }

    $h = $h / 6;
    if ( $h < 0 ) { $h = $h + 1 };

#    $h = $h * $echelle;
#    $s = $s * $echelle;
#    $l = $l * $echelle;

    return ($h,$s,$l);
}

