0; $i--) { // 3 2 1 $t = $num % $width; $num /= $width; $c[$i] = $t * (256 / $width) + $t * floor(16 / $width); } return $c; case 'keyword': $name = $value[1]; if (isset(Constants::CSS_COLORS[$name])) { $rgba = explode(',', Constants::CSS_COLORS[$name]); if (isset($rgba[3])) return ['color', $rgba[0], $rgba[1], $rgba[2], $rgba[3]]; return ['color', $rgba[0], $rgba[1], $rgba[2]]; } return null; } return null; } /** * Calculate the perceptual brightness of a color object */ public static function toLuma(array $color): float { [, $r, $g, $b] = Color::coerceColor($color); $r = $r / 255; $g = $g / 255; $b = $b / 255; $r = ($r <= 0.03928) ? $r / 12.92 : (($r + 0.055) / 1.055) ** 2.4; $g = ($g <= 0.03928) ? $g / 12.92 : (($g + 0.055) / 1.055) ** 2.4; $b = ($b <= 0.03928) ? $b / 12.92 : (($b + 0.055) / 1.055) ** 2.4; return (0.2126 * $r) + (0.7152 * $g) + (0.0722 * $b); } /** * Convert a color to HSL color space */ public static function toHSL(array $color): array { if ($color[0] == 'hsl') return $color; $r = $color[1] / 255; $g = $color[2] / 255; $b = $color[3] / 255; $min = min($r, $g, $b); $max = max($r, $g, $b); $L = ($min + $max) / 2; if ($min == $max) { $S = $H = 0; } else { if ($L < 0.5) { $S = ($max - $min) / ($max + $min); } else { $S = ($max - $min) / (2.0 - $max - $min); } if ($r == $max) { $H = ($g - $b) / ($max - $min); } elseif ($g == $max) { $H = 2.0 + ($b - $r) / ($max - $min); } elseif ($b == $max) { $H = 4.0 + ($r - $g) / ($max - $min); } else { $H = 0; } } $out = [ 'hsl', ($H < 0 ? $H + 6 : $H) * 60, $S * 100, $L * 100, ]; if (count($color) > 4) $out[] = $color[4]; // copy alpha return $out; } /** * Converts a hsl array into a color value in rgb. * Expects H to be in range of 0 to 360, S and L in 0 to 100 */ public static function toRGB(array $color): array { if ($color[0] == 'color') return $color; $H = $color[1] / 360; $S = $color[2] / 100; $L = $color[3] / 100; if ($S == 0) { $r = $g = $b = $L; } else { $temp2 = $L < 0.5 ? $L * (1.0 + $S) : $L + $S - $L * $S; $temp1 = 2.0 * $L - $temp2; $r = self::calculateRGBComponent($H + 1 / 3, $temp1, $temp2); $g = self::calculateRGBComponent($H, $temp1, $temp2); $b = self::calculateRGBComponent($H - 1 / 3, $temp1, $temp2); } // $out = array('color', round($r*255), round($g*255), round($b*255)); $out = ['color', $r * 255, $g * 255, $b * 255]; if (count($color) > 4) $out[] = $color[4]; // copy alpha return $out; } /** * make sure a color's components don't go out of bounds */ public static function fixColor(array $c): array { foreach (range(1, 3) as $i) { if ($c[$i] < 0) $c[$i] = 0; if ($c[$i] > 255) $c[$i] = 255; } return $c; } /** * Helper function for the HSL to RGB conversion process. * * This function normalizes the input component of the HSL color and determines the RGB * value based on the HSL values. * * @param float $comp The component of the HSL color to be normalized and converted. * @param float $temp1 The first temporary variable used in the conversion process * @param float $temp2 The second temporary variable used in the conversion process * * @return float The calculated RGB value as percentage of the maximum value (255) */ protected static function calculateRGBComponent(float $comp, float $temp1, float $temp2): float { // Normalize the component value to be within the range [0, 1] if ($comp < 0) $comp += 1.0; elseif ($comp > 1) $comp -= 1.0; // Determine the return value based on the value of the component if (6 * $comp < 1) return $temp1 + ($temp2 - $temp1) * 6 * $comp; if (2 * $comp < 1) return $temp2; if (3 * $comp < 2) return $temp1 + ($temp2 - $temp1) * ((2 / 3) - $comp) * 6; // Fallback return value, represents the case where the saturation of the color is zero return $temp1; } }