sassのlighten, darken, saturate, desaturateをphpで再現する

sassの彩度・明度の調整をphpで再現しました。
下記サイトの計算式を参考にしています。
http://www.peko-step.com/tool/hslrgb.html

```ColorChanger.php
<?php
class ColorChanger
{
    private $_r = 0, $_g = 0, $_b = 0, $_h = 0, $_s = 0, $_l = 0;

    public function lighten ($color, $lightness)
    {
        $this->setColor($color);
        $l = $this->_l;
        $l += $lightness;
        $this->_l = (100 < $l)?100:$l;
        $this->_getRgb();
        return $this->_decHex($this->_r) .  $this->_decHex($this->_g) .  $this->_decHex($this->_b);
    }

    public function darken ($color, $darkness)
    {
        $this->setColor($color);
        $l = $this->_l;
        $l -= $darkness;
        $this->_l = (0 > $l)?0:$l;
        $this->_getRgb();
        return $this->_decHex($this->_r) .  $this->_decHex($this->_g) .  $this->_decHex($this->_b);
    }

    public function saturate ($color, $per)
    {
        $this->setColor($color);
        $s = $this->_s;
        $s += $per;
        $this->_s = (100 < $s)?100:$s;
        $this->_getRgb();
        return $this->_decHex($this->_r) .  $this->_decHex($this->_g) .  $this->_decHex($this->_b);
    }

    public function desaturate ($color, $per)
    {
        $this->setColor($color);
        $s = $this->_s;
        $s -= $per;
        $this->_s = (0 > $s)?0:$s;
        $this->_getRgb();
        return $this->_decHex($this->_r) .  $this->_decHex($this->_g) .  $this->_decHex($this->_b);
    }

    public function _decHex ($dec)
    {
        return sprintf('%02s', dechex($dec));
    }

    private function setColor ($color)
    {
        $this->_r = hexdec(substr($color, 0, 2));
        $this->_g = hexdec(substr($color, 2, 2));
        $this->_b = hexdec(substr($color, 4, 2));
        $this->_maxRgb = max($this->_r, $this->_g, $this->_b);
        $this->_minRgb = min($this->_r, $this->_g, $this->_b);
        $this->_getHue();
        $this->_getSaturation();
        $this->_getLuminance();
    }

    private function _getHue ()
    {
        $r = $this->_r;
        $g = $this->_g;
        $b = $this->_b;
        $max = $this->_maxRgb;
        $min = $this->_minRgb;
        if ($r === $g && $r === $b) {
            $h = 0;
        } else {
            $mm = $max - $min;
            switch ($max) {
            case $r :
                $h = 60 * ($mm?($g - $b) / $mm:0);
                break;
            case $g :
                $h = 60 * ($mm?($b - $r) / $mm:0) + 120;
                break;
            case $b :
                $h = 60 * ($mm?($r - $g) / $mm:0) + 240;
                break;
            }
            if (0 > $h) {
                $h += 360;
            }
        }
        $this->_h = $h;
    }

    private function _getSaturation ()
    {
        $max = $this->_maxRgb;
        $min = $this->_minRgb;
        $cnt = round(($max + $min) / 2);
        if (127 >= $cnt) {
            $tmp = ($max + $min);
            $s = $tmp?($max - $min) / $tmp:0;
        } else {
            $tmp = (510 - $max - $min);
            $s = ($tmp)?(($max - $min) / $tmp):0;
        }
        $this->_s = $s * 100;
    }

    private function _getLuminance ()
    {
        $max = $this->_maxRgb;
        $min = $this->_minRgb;
        $this->_l = ($max + $min) / 2 / 255 * 100;
    }

    private function _getMaxMinHsl ()
    {
        $s = $this->_s;
        $l = $this->_l;
        if (49 >= $l) {
            $max = 2.55 * ($l + $l * ($s / 100));
            $min = 2.55 * ($l - $l * ($s / 100));
        } else {
            $max = 2.55 * ($l + (100 - $l) * ($s / 100));
            $min = 2.55 * ($l - (100 - $l) * ($s / 100));
        }
        $this->_maxHsl = $max;
        $this->_minHsl = $min;
    }

    private function _getRGB ()
    {
        $this->_getMaxMinHsl();
        $h = $this->_h;
        $s = $this->_s;
        $l = $this->_l;
        $max = $this->_maxHsl;
        $min = $this->_minHsl;
        if (60 >= $h) {
            $r = $max;
            $g = ($h / 60) * ($max - $min) + $min;
            $b = $min;
        } else if (120 >= $h) {
            $r = ((120 - $h) / 60) * ($max - $min) + $min;
            $g = $max;
            $b = $min;
        } else if (180 >= $h) {
            $r = $min;
            $g = $max;
            $b = (($h - 120) / 60) * ($max - $min) + $min;
        } else if (240 >= $h) {
            $r = $min;
            $g = ((240 - $h) / 60) * ($max - $min) + $min;
            $b = $max;
        } else if (300 >= $h) {
            $r = (($h - 240) / 60) * ($max - $min) + $min;
            $g = $min;
            $b = $max;
        } else {
            $r = $max;
            $g = $min;
            $b = ((360 - $h) / 60) * ($max - $min) + $min;
        }
        $this->_r = round($r);
        $this->_g = round($g);
        $this->_b = round($b);
    }
}
```

* 使い方

```test.php
<?php
include('plugins/NjcCommon/Lib/Color/ColorChanger.php');

$colorChanger = new ColorChanger();
$color = 'ff7700';
$val = 10;
echo "sass の lighten(#{$color}, {$val}%); -> " . $colorChanger->lighten($color, $val) . "\n";
echo "sass の darken(#{$color}, {$val}%); -> " . $colorChanger->darken($color, $val) . "\n";

$val = 50;
$color = 'bf7b40';
echo "sass の saturate(#{$color}, {$val}%); -> " . $colorChanger->saturate($color, $val) . "\n";
$color = 'ff7700';
echo "sass の desaturate(#{$color}, {$val}%); -> " . $colorChanger->desaturate($color, $val) . "\n";
```

* 実行結果

```
$ php -f test.php 
sass の lighten(#ff7700, 10%); -> ff9233
sass の darken(#ff7700, 10%); -> cc5f00
sass の saturate(#bf7b40, 50%); -> ff7600
sass の desaturate(#ff7700, 50%); -> bf7b40
```