Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
fix(theming): Also set default background color ("primary") for custo…
…m images

Signed-off-by: Ferdinand Thiessen <[email protected]>
  • Loading branch information
susnux committed May 21, 2024
commit 0211feb94647a0e329030b66bc4c5b4304d10a0f
66 changes: 65 additions & 1 deletion apps/theming/lib/Service/BackgroundService.php
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,6 @@ public function setDefaultBackground(): void {
* @throws NoUserException
*/
public function setFileBackground($path): void {
$this->config->setUserValue($this->userId, Application::APP_ID, 'background_image', self::BACKGROUND_CUSTOM);
$userFolder = $this->rootFolder->getUserFolder($this->userId);

/** @var File $file */
Expand All @@ -224,7 +223,13 @@ public function setFileBackground($path): void {
throw new InvalidArgumentException('Invalid image file');
}

$meanColor = $this->calculateMeanColor($image);
if ($meanColor !== false) {
$this->setColorBackground($meanColor);
}

$this->getAppDataFolder()->newFile('background.jpg', $file->fopen('r'));
$this->config->setUserValue($this->userId, Application::APP_ID, 'background_image', self::BACKGROUND_CUSTOM);
}

public function setShippedBackground($fileName): void {
Expand All @@ -235,6 +240,9 @@ public function setShippedBackground($fileName): void {
$this->setColorBackground(self::SHIPPED_BACKGROUNDS[$fileName]['primary_color']);
}

/**
* Set the background to color only
*/
public function setColorBackground(string $color): void {
if (!preg_match('/^#([0-9a-f]{3}|[0-9a-f]{6})$/i', $color)) {
throw new InvalidArgumentException('The given color is invalid');
Expand Down Expand Up @@ -276,4 +284,60 @@ private function getAppDataFolder(): ISimpleFolder {
return $rootFolder->newFolder($this->userId);
}
}

/**
* Calculate mean color of an given image
* It only takes the upper part into account so that a matching text color can be derived for the app menu
*/
private function calculateMeanColor(\OCP\Image $image): false|string {
/**
* Small helper to ensure one channel is returned as 8byte hex
*/
function toHex(int $channel) {
$hex = dechex($channel);
return match (strlen($hex)) {
0 => '00',
1 => '0'.$hex,
2 => $hex,
default => 'ff',
};
}

$tempImage = new \OCP\Image();

// Crop to only analyze top bar
$resource = $image->cropNew(0, 0, $image->width(), min(max(50, (int)($image->height() * 0.125)), $image->height()));
if ($resource === false) {
return false;
}

$tempImage->setResource($resource);
if (!$tempImage->preciseResize(100, 7)) {
return false;
}

$resource = $tempImage->resource();
if ($resource === false) {
return false;
}

$reds = [];
$greens = [];
$blues = [];
for ($y = 0; $y < 7; $y++) {
for ($x = 0; $x < 100; $x++) {
$value = imagecolorat($resource, $x, $y);
if ($value === false) {
continue;
}
$reds[] = ($value >> 16) & 0xFF;
$greens[] = ($value >> 8) & 0xFF;
$blues[] = $value & 0xFF;
}
}
$meanColor = '#' . toHex((int)(array_sum($reds) / count($reds)));
$meanColor .= toHex((int)(array_sum($greens) / count($greens)));
$meanColor .= toHex((int)(array_sum($blues) / count($blues)));
return $meanColor;
}
}
3 changes: 2 additions & 1 deletion apps/theming/lib/Themes/CommonThemeTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ protected function generateUserBackgroundVariables(): array {
$cacheBuster = substr(sha1($user->getUID() . '_' . $currentVersion), 0, 8);
return [
'--image-background' => "url('" . $this->urlGenerator->linkToRouteAbsolute('theming.userTheme.getBackground') . "?v=$cacheBuster')",
'--color-background-plain' => $this->primaryColor,
'--color-background-plain' => $this->themingDefaults->getColorPrimary(),
'--background-image-invert-if-bright' => $isPrimaryBright ? 'invert(100%)' : 'no',
];
}

Expand Down