Skip to content

Instantly share code, notes, and snippets.

@yosko
Created Dec 18, 2013
Embed
What would you like to do?
Library of color conversion tools in PHP
<?php
/*
Color lib by Yosko (http://www.yosko.net/)
Licence: WTFPL except for the following
source for HSL algorithm: http://www.easyrgb.com/index.php?X=MATH
*/
//returns a clean 6 digit hex number as a string
function cleanHexColor($hex) {
$hex = strtolower($hex);
//remove the leading "#"
if(strlen($hex) == 7 || strlen($hex) == 4)
$hex = substr($hex, -(strlen($hex)-1));
// $hex like "1a7"
if(preg_match('/^[a-f0-9]{6}$/i', $hex))
return $hex;
// $hex like "162a7b"
elseif(preg_match('/^[a-f0-9]{3}$/i', $hex))
return $hex[0].$hex[0].$hex[1].$hex[1].$hex[2].$hex[2];
//any other format
else
return "000000";
}
//returns an array of 3 [0-255] int
function hex2rgb($hex) {
return array(
hexdec(substr($hex, 0, 2)),
hexdec(substr($hex, 2, 2)),
hexdec(substr($hex, 4, 2)),
);
}
//returns a 6 digit hex number as a string
function rgb2hex($rgb) {
return ""
.substr("00".dechex(ceil($rgb[0])), -2)
.substr("00".dechex(ceil($rgb[1])), -2)
.substr("00".dechex(ceil($rgb[2])), -2)
;
}
//returns a 2 dimensional array of subarrays (HSL: 3 values [0-1] floats)
function variationAround($hsl, $stepSize = 0.2, $constant = "hue") {
if($constant == "hue") {
$i = 1; $j = 2;
} elseif($constant == "sat") {
$i = 0; $j = 2;
}if($constant == "lum") {
$i = 0; $j = 1;
}
$variations = array(); //resulting variations
$hslTemp = array(); //stores current variation
$mod = array(); //stores modulos for h, s & l
$mod[0] = (float)(($hsl[0]*100) % ($stepSize * 100)) / 100;
$mod[1] = (float)(($hsl[1]*100) % ($stepSize * 100)) / 100;
$mod[2] = (float)(($hsl[2]*100) % ($stepSize * 100)) / 100;
$hslTemp = $hsl;
$hslTemp[$i] = $mod[$i];
while($hslTemp[$i] <= 1) {
$row = array();
$hslTemp[$j] = $mod[$j];
while($hslTemp[$j] <= 1) {
$row[(string)$hslTemp[$j]] = array($hslTemp[0], $hslTemp[1], $hslTemp[2]);
$hslTemp[$j] = (float)($hslTemp[$j] + $stepSize);
}
$variations[(string)$hslTemp[$i]] = $row;
$hslTemp[$i] = (float)($hslTemp[$i] + $stepSize);
}
return $variations;
}
function rgb2hsl($rgb) {
//work with range [0-1] for RGB values
$r = $rgb[0] / 255;
$g = $rgb[1] / 255;
$b = $rgb[2] / 255;
//get min and max from RGB
$min = min($r, $g, $b);
$max = max($r, $g, $b);
$delta = $max-$min;
//luminance
$l = ($max + $min) / 2;
//saturation & hue
if($min == $max) {
//grayscale
$s = 0;
$h = 0;
} else {
//saturation
if($l < 0.5) $s = $delta/($max+$min);
else $s = $delta/(2-$max-$min);
//hue
if($r == $max) $h = ($g-$b)/(6*$delta);
elseif($g == $max) $h = 1/3 + ($b-$r)/(6*$delta);
elseif($b == $max) $h = 2/3 + ($r-$g)/(6*$delta);
//keep hue in the range [0,1]
if ($h < 0) $h++;
if ($h > 1) $h--;
}
return array($h, $s, $l);
}
function hsl2rgb($hsl) {
$h = $hsl[0];
$s = $hsl[1];
$l = $hsl[2];
//no saturation: grayscale
if($s == 0) {
$r = $g = $b = round($l * 255);
} else {
if($l < 0.5) $var2 = $l * (1 + $s);
else $var2 = ($l + $s) - ($s * $l);
$var1 = 2 * $l - $var2;
$r = 255 * hue2rgb($var1, $var2, $h + 1/3);
$g = 255 * hue2rgb($var1, $var2, $h);
$b = 255 * hue2rgb($var1, $var2, $h - 1/3);
}
return array($r, $g, $b);
}
function hue2rgb($v1, $v2, $vH)
{
if ( $vH < 0 ) $vH += 1;
if ( $vH > 1 ) $vH -= 1;
if ( $vH < 1/6 ) return $v1 + ( $v2 - $v1 ) * 6 * $vH;
elseif ( $vH < 1/2 ) return $v2;
elseif ( $vH < 2/3 ) return $v1 + ( $v2 - $v1 ) * ( 2/3 - $vH ) * 6;
else return ( $v1 );
}
?>
<?php
/*
Color lib by Yosko (http://www.yosko.net/)
Licence: WTFPL except for the following
source for HSL algorithm: http://www.easyrgb.com/index.php?X=MATH
*/
require_once ('color.lib.php');
//step size between 0 and 1
define("STEP_SIZE", (float)0.2);
if(isset($_GET['color'])) {
$sourceColor = $_GET['color'];
} else {
$sourceColor = "b7ff00";
}
$color = cleanHexColor($sourceColor);
$rgb = hex2rgb($color);
$hsl = rgb2hsl($rgb);
$samplesConstHue = variationAround($hsl, STEP_SIZE, "hue");
$samplesConstSat = variationAround($hsl, STEP_SIZE, "sat");
$samplesConstLum = variationAround($hsl, STEP_SIZE, "lum");
?><!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title>HSL Color Sampler</title>
<style>
table { border-collapse: collapse; border: 2px solid black; text-align:center; }
td, .preview { width:70px; height:50px; }
th { border: 1px solid black; }
.preview { display:table-cell; vertical-align:middle; text-align:center; color:#fff; font-weight: bold; }
</style>
</head>
<body>
<h1>HSL Color Sampler</h1>
<h2>Source color</h2>
<form method="get">
<input type="text" name="color" value="<?php echo $sourceColor; ?>">
<button type="send">
Sample
</button>
</form>
<div>6 digit hexadecimal number</div>
<div>Configuration: <?php echo STEP_SIZE; ?> step variations</div>
<div>Interpreted color : <span class="preview" style="background:#<?php echo $color; ?>;">#<?php echo $color; ?></span></div>
<div>
Note: the chosen color is supposed to appear in each (white text), but due to some rounded numbers, it may slightly differ (ex: 162417 instead of 162517).
</div>
<h2>Saturation/Luminance variation for a constant Hue</h2>
<div>Hue : <?php echo round($hsl[0],2); ?></div>
<table><?php
$firsRow = array_keys(array_shift(array_values($samplesConstHue)));
echo "<tr><th>sat \ lum</th>";
for($i = 0; $i < count($firsRow); $i++) {
echo "<th>".$firsRow[$i]."</th>";
}
echo "</tr>";
foreach($samplesConstHue as $sat => $row) {
$thisRow = (round($hsl[1],1) == round($sat,1));
echo "\n\t\t<tr><th>".$sat."</th>";
foreach($row as $lum => $value) {
$thisLine = (round($hsl[2],1) == round($lum,1));
$rgb = hsl2rgb($value);
$html = "#".rgb2hex($rgb);
if($thisRow && $thisLine)
echo "<td class=\"preview\" style=\"background:".$html.";\">".$html."</td>";
else
echo "<td style=\"background:".$html.";\">".$html."</td>";
}
echo "</tr>";
}
?>
</table>
<h2>Hue/Luminance variation for a constant Saturation</h2>
<div>Saturation : <?php echo round($hsl[1],2); ?></div>
<table><?php
$firsRow = array_keys(array_shift(array_values($samplesConstSat)));
echo "<tr><th>sat \ lum</th>";
for($i = 0; $i < count($firsRow); $i++) {
echo "<th>".$firsRow[$i]."</th>";
}
echo "</tr>";
foreach($samplesConstSat as $hue => $row) {
$thisRow = (round($hsl[0],1) == round($hue,1));
echo "\n\t\t<tr><th>".$hue."</th>";
foreach($row as $lum => $value) {
$thisLine = (round($hsl[2],1) == round($lum,1));
$rgb = hsl2rgb($value);
$html = "#".rgb2hex($rgb);
if($thisRow && $thisLine)
echo "<td class=\"preview\" style=\"background:".$html.";\">".$html."</td>";
else
echo "<td style=\"background:".$html.";\">".$html."</td>";
}
echo "</tr>";
}
?>
</table>
<h2>Hue/Saturation variation for a constant Luminance</h2>
<div>Luminance : <?php echo round($hsl[2],2); ?></div>
<table><?php
$firsRow = array_keys(array_shift(array_values($samplesConstLum)));
echo "<tr><th>sat \ lum</th>";
for($i = 0; $i < count($firsRow); $i++) {
echo "<th>".$firsRow[$i]."</th>";
}
echo "</tr>";
foreach($samplesConstLum as $hue => $row) {
$thisRow = (round($hsl[0],1) == round($hue,1));
echo "\n\t\t<tr><th>".$hue."</th>";
foreach($row as $sat => $value) {
$thisLine = (round($hsl[1],1) == round($sat,1));
$rgb = hsl2rgb($value);
$html = "#".rgb2hex($rgb);
if($thisRow && $thisLine)
echo "<td class=\"preview\" style=\"background:".$html.";\">".$html."</td>";
else
echo "<td style=\"background:".$html.";\">".$html."</td>";
}
echo "</tr>";
}
?>
</table>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment