diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index 6dc31787b5..2a2c73e3e8 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -354,27 +354,20 @@ App::get('/v1/avatars/initials') ->param('name', '', new Text(128), 'Full Name. When empty, current user name or email will be used. Max length: 128 chars.', true) ->param('width', 500, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('height', 500, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true) - ->param('color', '', new HexColor(), 'Changes text color. By default a random color will be picked and stay will persistent to the given name.', true) ->param('background', '', new HexColor(), 'Changes background color. By default a random color will be picked and stay will persistent to the given name.', true) ->inject('response') ->inject('user') - ->action(function (string $name, int $width, int $height, string $color, string $background, Response $response, Document $user) { + ->action(function (string $name, int $width, int $height, string $background, Response $response, Document $user) { $themes = [ - ['color' => '#27005e', 'background' => '#e1d2f6'], // VIOLET - ['color' => '#5e2700', 'background' => '#f3d9c6'], // ORANGE - ['color' => '#006128', 'background' => '#c9f3c6'], // GREEN - ['color' => '#580061', 'background' => '#f2d1f5'], // FUSCHIA - ['color' => '#00365d', 'background' => '#c6e1f3'], // BLUE - ['color' => '#00075c', 'background' => '#d2d5f6'], // INDIGO - ['color' => '#610038', 'background' => '#f5d1e6'], // PINK - ['color' => '#386100', 'background' => '#dcf1bd'], // LIME - ['color' => '#615800', 'background' => '#f1ecba'], // YELLOW - ['color' => '#610008', 'background' => '#f6d2d5'], // RED + ['background' => '#F2F2F8'], // Default + ['background' => '#FDC584'], // Orange + ['background' => '#94DBD1'], // Green + ['background' => '#A1C4FF'], // Blue + ['background' => '#FFA1CE'], // Pink + ['background' => '#CBB1FC'] // Purple ]; - $rand = \rand(0, \count($themes) - 1); - $name = (!empty($name)) ? $name : $user->getAttribute('name', $user->getAttribute('email', '')); $words = \explode(' ', \strtoupper($name)); // if there is no space, try to split by `_` underscore @@ -393,25 +386,34 @@ App::get('/v1/avatars/initials') } $rand = \substr($code, -1); + + // Wrap rand value to avoid out of range + $rand = ($rand > \count($themes) - 1) ? $rand % \count($themes) : $rand; + $background = (!empty($background)) ? '#' . $background : $themes[$rand]['background']; - $color = (!empty($color)) ? '#' . $color : $themes[$rand]['color']; $image = new \Imagick(); + $punch = new \Imagick(); $draw = new \ImagickDraw(); $fontSize = \min($width, $height) / 2; + $punch->newImage($width, $height, 'transparent'); + $draw->setFont(__DIR__ . "/../../../public/fonts/poppins-v9-latin-500.ttf"); $image->setFont(__DIR__ . "/../../../public/fonts/poppins-v9-latin-500.ttf"); - $draw->setFillColor(new \ImagickPixel($color)); + $draw->setFillColor(new ImagickPixel('black')); $draw->setFontSize($fontSize); $draw->setTextAlignment(\Imagick::ALIGN_CENTER); $draw->annotation($width / 1.97, ($height / 2) + ($fontSize / 3), $initials); + $punch->drawImage($draw); + $punch->negateImage(true, Imagick::CHANNEL_ALPHA); + $image->newImage($width, $height, $background); $image->setImageFormat("png"); - $image->drawImage($draw); + $image->compositeImage($punch, Imagick::COMPOSITE_COPYOPACITY, 0, 0); //$image->setImageCompressionQuality(9 - round(($quality / 100) * 9)); diff --git a/tests/e2e/Services/Avatars/AvatarsBase.php b/tests/e2e/Services/Avatars/AvatarsBase.php index e631fd4391..e2ddc1a863 100644 --- a/tests/e2e/Services/Avatars/AvatarsBase.php +++ b/tests/e2e/Services/Avatars/AvatarsBase.php @@ -491,7 +491,6 @@ trait AvatarsBase 'name' => 'W W', 'width' => 200, 'height' => 200, - 'color' => 'ffffff', 'background' => '000000', ]); @@ -508,34 +507,33 @@ trait AvatarsBase 'name' => 'W W', 'width' => 200000, 'height' => 200, - 'color' => 'ffffff', 'background' => '000000', ]); $this->assertEquals(400, $response['headers']['status-code']); - - $response = $this->client->call(Client::METHOD_GET, '/avatars/initials', [ - 'x-appwrite-project' => $this->getProject()['$id'], - ], [ - 'name' => 'W W', - 'width' => 200, - 'height' => 200, - 'color' => 'white', - 'background' => '000000', - ]); - - $this->assertEquals(400, $response['headers']['status-code']); - - $response = $this->client->call(Client::METHOD_GET, '/avatars/initials', [ - 'x-appwrite-project' => $this->getProject()['$id'], - ], [ - 'name' => 'W W', - 'width' => 200, - 'height' => 200, - 'color' => 'ffffff', - 'background' => 'black', - ]); - - $this->assertEquals(400, $response['headers']['status-code']); + } + + public function testInitialImage() + { + $response = $this->client->call(Client::METHOD_GET, '/avatars/initials', [ + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'name' => 'W W', + 'width' => 200, + 'height' => 200, + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('image/png', $response['headers']['content-type']); + $this->assertNotEmpty($response['body']); + + $image = new \Imagick(); + $image->readImageBlob($response['body']); + $original = new \Imagick(__DIR__ . '/../../../resources/initials.png'); + + $this->assertEquals($image->getImageWidth(), $original->getImageWidth()); + $this->assertEquals($image->getImageHeight(), $original->getImageHeight()); + $this->assertEquals('PNG', $image->getImageFormat()); + $this->assertEquals(strlen(\file_get_contents(__DIR__ . '/../../../resources/initials.png')), strlen($response['body'])); } } diff --git a/tests/resources/initials.png b/tests/resources/initials.png new file mode 100644 index 0000000000..08a61594c6 Binary files /dev/null and b/tests/resources/initials.png differ