Skip to content

Commit

Permalink
Merge pull request #50 from yakatz/feature/autocolor
Browse files Browse the repository at this point in the history
Generate a pseudorandom color based on the user's name
  • Loading branch information
LasseRafn authored Jul 26, 2023
2 parents 1a81fea + 48fe299 commit ffe43d8
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 0 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ $image = $avatar->background('#ff0000')->generate();
$image = $avatar->color('#ff0000')->generate();
````

### Auto Color
````php
// Will choose a background color based on `name` and a contrasting font color. The color for a specific name will always be the same.
$image = $avatar->autoColor()->generate();
````

### Font file - default: /fonts/OpenSans-Regular.ttf
Two fonts with two variants are included:
* /fonts/OpenSans-Regular.ttf
Expand Down
132 changes: 132 additions & 0 deletions src/InitialAvatar.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,26 @@ public function color($color)
return $this;
}

/**
* Automatically set a font and/or background color based on the supplied name.
*
* @param bool $foreground
* @param bool $background
*
* @return $this
*/
public function autoColor(bool $foreground = true, bool $background = true, int $saturation = 85, int $luminance = 60)
{
$hue = (crc32($this->name) % 360) / 360;
$saturation /= 100;
$luminance /= 100;

$this->bgColor = $this->convertHSLtoRGB($hue, $saturation, $luminance);
$this->fontColor = $this->getContrastColor($this->bgColor);

return $this;
}

/**
* Set the font file by path or int (1-5).
*
Expand Down Expand Up @@ -782,4 +802,116 @@ protected function getFontByScript()

return $this->getFontFile();
}

/**
* Convert HSL color value produced by autoColor() to RGB value expected by image driver.
*/
protected function convertHSLtoRGB($h, $s, $l, $toHex = true)
{
assert((0 <= $h) && ($h <= 1));

$red = $l;
$green = $l;
$blue = $l;

$v = ($l <= 0.5) ? ($l * (1.0 + $s)) : ($l + $s - $l * $s);
if ($v > 0) {
$m = $l + $l - $v;
$sv = ($v - $m) / $v;
$h *= 6.0;
$sextant = floor($h);
$fract = $h - $sextant;
$vsf = $v * $sv * $fract;
$mid1 = $m + $vsf;
$mid2 = $v - $vsf;

switch ($sextant) {
case 0:
$red = $v;
$green = $mid1;
$blue = $m;
break;
case 1:
$red = $mid2;
$green = $v;
$blue = $m;
break;
case 2:
$red = $m;
$green = $v;
$blue = $mid1;
break;
case 3:
$red = $m;
$green = $mid2;
$blue = $v;
break;
case 4:
$red = $mid1;
$green = $m;
$blue = $v;
break;
case 5:
$red = $v;
$green = $m;
$blue = $mid2;
break;
}
}

$red = round($red * 255, 0);
$green = round($green * 255, 0);
$blue = round($blue * 255, 0);

if ($toHex) {
$red = ($red < 15) ? '0'.dechex($red) : dechex($red);
$green = ($green < 15) ? '0'.dechex($green) : dechex($green);
$blue = ($blue < 15) ? '0'.dechex($blue) : dechex($blue);

return "#{$red}{$green}{$blue}";
} else {
return ['red' => $red, 'green' => $green, 'blue' => $blue];
}
}

/**
* Get contrasting foreground color for autoColor background.
*/
protected function getContrastColor($hexColor)
{
// hexColor RGB
$R1 = hexdec(substr($hexColor, 1, 2));
$G1 = hexdec(substr($hexColor, 3, 2));
$B1 = hexdec(substr($hexColor, 5, 2));

// Black RGB
$blackColor = '#000000';
$R2BlackColor = hexdec(substr($blackColor, 1, 2));
$G2BlackColor = hexdec(substr($blackColor, 3, 2));
$B2BlackColor = hexdec(substr($blackColor, 5, 2));

// Calc contrast ratio
$L1 = 0.2126 * pow($R1 / 255, 2.2) +
0.7152 * pow($G1 / 255, 2.2) +
0.0722 * pow($B1 / 255, 2.2);

$L2 = 0.2126 * pow($R2BlackColor / 255, 2.2) +
0.7152 * pow($G2BlackColor / 255, 2.2) +
0.0722 * pow($B2BlackColor / 255, 2.2);

$contrastRatio = 0;
if ($L1 > $L2) {
$contrastRatio = (int) (($L1 + 0.05) / ($L2 + 0.05));
} else {
$contrastRatio = (int) (($L2 + 0.05) / ($L1 + 0.05));
}

// If contrast is more than 5, return black color
if ($contrastRatio > 5) {
return '#000000';
} else {
// if not, return white color.
return '#FFFFFF';
}
}
}
29 changes: 29 additions & 0 deletions tests/AutoColorUtilsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

use LasseRafn\InitialAvatarGenerator\InitialAvatar;
use PHPUnit\Framework\TestCase;

class AutoColorUtilsTest extends TestCase
{
/** @test */
public function can_create_all_colors()
{
$avatar = new InitialAvatar();

$avatar->name('A')->autoColor();
$this->assertEquals('#f0a742', $avatar->getBackgroundColor());
$this->assertEquals('#000000', $avatar->getColor());

$avatar->name('B')->autoColor();
$this->assertEquals('#42caf0', $avatar->getBackgroundColor());
$this->assertEquals('#000000', $avatar->getColor());

$avatar->name('C')->autoColor();
$this->assertEquals('#42f085', $avatar->getBackgroundColor());
$this->assertEquals('#000000', $avatar->getColor());

$avatar->name('D')->autoColor();
$this->assertEquals('#f04293', $avatar->getBackgroundColor());
$this->assertEquals('#FFFFFF', $avatar->getColor());
}
}
12 changes: 12 additions & 0 deletions tests/ParameterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,16 @@ public function can_set_auto_font()

$this->assertNotTrue($avatar->getAutoFont());
}

/** @test */
public function can_set_auto_color()
{
$avatar = new InitialAvatar();

$avatar->autoColor();

$this->assertEquals('#eaf042', $avatar->getBackgroundColor());

$this->assertEquals('#000000', $avatar->getColor());
}
}

0 comments on commit ffe43d8

Please sign in to comment.