Always generate avatar

Even if no avatar is set we should just generate the image. This to not
duplicate the code on all the clients. And only server images from the
avtar endpoint.

Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
This commit is contained in:
Roeland Jago Douma 2017-10-19 16:22:43 +02:00
parent 6097b74970
commit 604596ec16
No known key found for this signature in database
GPG Key ID: F941078878347C0C
1 changed files with 155 additions and 5 deletions

View File

@ -111,6 +111,136 @@ class AvatarController extends Controller {
$this->timeFactory = $timeFactory; $this->timeFactory = $timeFactory;
} }
/**
* @param int $r
* @param int $g
* @param int $b
* @return double[] Array containing h s l in [0, 1] range
*/
private function rgbToHsl($r, $g, $b) {
$r /= 255.0;
$g /= 255.0;
$b /= 255.0;
$max = max($r, $g, $b);
$min = min($r, $g, $b);
$h = ($max + $min) / 2.0;
$l = ($max + $min) / 2.0;
if($max === $min) {
$h = $s = 0; // Achromatic
} else {
$d = $max - $min;
$s = $l > 0.5 ? $d / (2 - $max - $min) : $d / ($max + $min);
switch($max) {
case $r:
$h = ($g - $b) / $d + ($g < $b ? 6 : 0);
break;
case $g:
$h = ($b - $r) / $d + 2.0;
break;
case $b:
$h = ($r - $g) / $d + 4.0;
break;
}
$h /= 6.0;
}
return [$h, $s, $l];
}
/**
* @param string $text
* @return int[] Array containting r g b in the range [0, 255]
*/
private function avatarBackgroundColor($text) {
$hash = preg_replace('/[^0-9a-f]+/', '', $text);
$hash = md5($hash);
$hashChars = str_split($hash);
// Init vars
$result = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'];
$rgb = [0, 0, 0];
$sat = 0.70;
$lum = 0.68;
$modulo = 16;
// Splitting evenly the string
foreach($hashChars as $i => $char) {
$result[$i % $modulo] .= intval($char, 16);
}
// Converting our data into a usable rgb format
// Start at 1 because 16%3=1 but 15%3=0 and makes the repartition even
for($count = 1; $count < $modulo; $count++) {
$rgb[$count%3] += (int)$result[$count];
}
// Reduce values bigger than rgb requirements
$rgb[0] %= 255;
$rgb[1] %= 255;
$rgb[2] %= 255;
$hsl = $this->rgbToHsl($rgb[0], $rgb[1], $rgb[2]);
// Classic formulla to check the brigtness for our eye
// If too bright, lower the sat
$bright = sqrt(0.299 * ($rgb[0] ** 2) + 0.587 * ($rgb[1] ** 2) + 0.114 * ($rgb[2] ** 2));
if ($bright >= 200) {
$sat = 0.60;
}
return $this->hslToRgb($hsl[0], $sat, $lum);
}
/**
* @param double $h Heu in range [0, 1]
* @param double $s Saturation in range [0, 1]
* @param double $l Lightness in range [0, 1]
* @return int[] Array containging r g b in the range [0, 255]
*/
private function hslToRgb($h, $s, $l){
$hue2rgb = function ($p, $q, $t){
if($t < 0) {
$t += 1;
}
if($t > 1) {
$t -= 1;
}
if($t < 1/6) {
return $p + ($q - $p) * 6 * $t;
}
if($t < 1/2) {
return $q;
}
if($t < 2/3) {
return $p + ($q - $p) * (2/3 - $t) * 6;
}
return $p;
};
if($s == 0){
$r = $l;
$g = $l;
$b = $l; // achromatic
}else{
$q = $l < 0.5 ? $l * (1 + $s) : $l + $s - $l * $s;
$p = 2 * $l - $q;
$r = $hue2rgb($p, $q, $h + 1/3);
$g = $hue2rgb($p, $q, $h);
$b = $hue2rgb($p, $q, $h - 1/3);
}
return array(round($r * 255), round($g * 255), round($b * 255));
}
/** /**
* @NoAdminRequired * @NoAdminRequired
* @NoCSRFRequired * @NoCSRFRequired
@ -135,11 +265,31 @@ class AvatarController extends Controller {
['Content-Type' => $avatar->getMimeType()]); ['Content-Type' => $avatar->getMimeType()]);
} catch (NotFoundException $e) { } catch (NotFoundException $e) {
$user = $this->userManager->get($userId); $user = $this->userManager->get($userId);
$resp = new JSONResponse([ $userDisplayName = $user->getDisplayName();
'data' => [ $text = strtoupper(substr($userDisplayName, 0, 1));
'displayname' => $user->getDisplayName(), $backgroundColor = $this->avatarBackgroundColor($userDisplayName);
],
]); $im = imagecreatetruecolor($size, $size);
$background = imagecolorallocate($im, $backgroundColor[0], $backgroundColor[1], $backgroundColor[2]);
$white = imagecolorallocate($im, 255, 255, 255);
imagefilledrectangle($im, 0, 0, $size, $size, $background);
$font = __DIR__ . '/../../core/fonts/OpenSans-Light.woff';
$fontSize = $size * 0.4;
$box = imagettfbbox($fontSize, 0, $font, $text);
$x = ($size - ($box[2] - $box[0])) / 2;
$y = ($size - ($box[1] - $box[7])) / 2;
$y -= $box[7];
imagettftext($im, $fontSize, 0, $x, $y, $white, $font, $text);
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
exit();
} catch (\Exception $e) { } catch (\Exception $e) {
$resp = new JSONResponse([ $resp = new JSONResponse([
'data' => [ 'data' => [