Skip to content

Commit

Permalink
Hcl and Oklch color space hue interpolation takes a method argument.
Browse files Browse the repository at this point in the history
  • Loading branch information
kohler committed Nov 5, 2023
1 parent 1e4e645 commit f41caef
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 19 deletions.
61 changes: 53 additions & 8 deletions lib/hclcolor.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,63 @@ function darker($k = null) {
return new HclColor($this->h, $this->c, $this->l - LabColor::K * ($k ?? 1));
}

/** @param float $h1
* @param float $h2
* @param null|'shorter'|'longer'|'increasing'|'decreasing' $method
* @return float */
static function hue_interpolate($h1, $h2, $method = null) {
if (is_float($method)) {
return $method;
}
if (is_nan($h1)) {
$h1 = is_nan($h2) ? 0.0 : $h2;
}
if (is_nan($h2)) {
$h2 = $h1;
}
if ($h1 >= 0 && $h1 < 360) {
$nh1 = $h1;
} else if (($nh1 = fmod($h1, 360.0)) < 0) {
$nh1 += 360.0;
}
if ($h2 >= 0 && $h2 < 360) {
$nh2 = $h2;
} else if (($nh2 = fmod($h2, 360.0)) < 0) {
$nh2 += 360.0;
}
$dinc = $nh2 > $nh1 ? $nh2 - $nh1 : $nh2 + 360.0 - $nh1;
$ddec = $nh1 > $nh2 ? $nh2 - $nh1 : $nh2 - 360.0 - $nh1;
if ($method === null || $method === "shorter") {
if ($dinc < -$ddec || ($dinc === -$ddec && $h1 < $h2)) {
return $dinc;
} else {
return $ddec;
}
} else if ($method === "longer") {
if ($nh1 === $nh2) {
return $h1 <= $h2 ? 360.0 : -360.0;
} else if ($dinc > -$ddec || ($dinc === -$ddec && $h1 < $h2)) {
return $dinc;
} else {
return $ddec;
}
} else if ($method === "increasing") {
return $dinc;
} else {
return $ddec;
}
}

/** @param float $f
* @param HclColor $end
* @param null|float|'shorter'|'longer'|'increasing'|'decreasing' $hue_method
* @return HclColor */
function interpolate($f, $end) {
$d = $end->h - $this->h;
if ($d && $d === $d) {
if ($d > 180 || $d < -180) {
$d -= 360 * round($d / 360);
}
$h = $this->h + $f * $d;
function interpolate($f, $end, $hue_method = null) {
if (is_nan($this->h)) {
$h = $end->h;
} else {
$h = is_nan($this->h) ? $end->h : $this->h;
$dh = is_float($hue_method) ? $hue_method : self::hue_interpolate($this->h, $end->h, $hue_method);
$h = $this->h + $dh * $f;
}

$d = $end->c - $this->c;
Expand Down
5 changes: 3 additions & 2 deletions lib/labcolor.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ function rgb() {

/** @return string */
function hashcolor() {
return sprintf("#%02X%02X%02X", ...$this->rgb());
$rgb = $this->rgb();
return sprintf("#%02X%02X%02X", round($rgb[0]), round($rgb[1]), round($rgb[2]));
}

/** @return HclColor */
Expand All @@ -99,7 +100,7 @@ static function rgb2lrgb($x) {
/** @param float $lx
* @return float */
static function lrgb2rgb($lx) {
return 255 * ($lx <= 0.0031308 ? $lx * 12.92 : 1.055 * pow($lx, 1 / 2.4) - 0.055);
return 255 * ($lx <= 0.0031308 ? max($lx, 0) * 12.92 : 1.055 * pow($lx, 1 / 2.4) - 0.055);
}

/** @param float $t
Expand Down
3 changes: 2 additions & 1 deletion lib/oklabcolor.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ function rgb() {

/** @return string */
function hashcolor() {
return sprintf("#%02X%02X%02X", ...$this->rgb());
$rgb = $this->rgb();
return sprintf("#%02X%02X%02X", round($rgb[0]), round($rgb[1]), round($rgb[2]));
}

/** @return OklchColor */
Expand Down
14 changes: 6 additions & 8 deletions lib/oklchcolor.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,14 @@ function darker($k = null) {

/** @param float $f
* @param OklchColor $end
* @param null|float|'shorter'|'longer'|'increasing'|'decreasing' $hue_method
* @return OklchColor */
function interpolate($f, $end) {
$d = $end->okh - $this->okh;
if ($d && $d === $d) {
if ($d > 180 || $d < -180) {
$d -= 360 * round($d / 360);
}
$h = $this->okh + $f * $d;
function interpolate($f, $end, $hue_method = null) {
if (is_nan($this->okh)) {
$h = $end->okh;
} else {
$h = is_nan($this->okh) ? $end->okh : $this->okh;
$dh = is_float($hue_method) ? $hue_method : HclColor::hue_interpolate($this->okh, $end->okh, $hue_method);
$h = $this->okh + $dh * $f;
}

$d = $end->okc - $this->okc;
Expand Down

0 comments on commit f41caef

Please sign in to comment.