Created
December 18, 2013 10:33
-
-
Save yosko/8020258 to your computer and use it in GitHub Desktop.
Library of color conversion tools in PHP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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 ); | |
} | |
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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