Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
2ba59d8
refactor(image): modernize/cleanup GD Image class
joshtrichards Jun 28, 2026
cbb511a
test(ldap): correct loadFromBase64 mock return type in UserTest
joshtrichards Jun 29, 2026
3295ebe
chore(image): add $filePath import to closure
joshtrichards Jun 30, 2026
efe93d8
docs(image): clarity IImage crop / cropCopy entries
joshtrichards Jun 30, 2026
80958f7
docs(image): clarity Image cropNew entry
joshtrichards Jun 30, 2026
69ca991
refactor(theming): use public IImage API for background color extraction
joshtrichards Jun 30, 2026
6c04fdf
refactor(theming): use public IImage loading API for background image…
joshtrichards Jun 30, 2026
1bd921d
refactor(settings): use public Image loading API for avatar importing
joshtrichards Jun 30, 2026
21a2e2d
chore(theming): BackgroundService needs both Image+IImage
joshtrichards Jun 30, 2026
d767364
refactor(TextToImage): use public Image loading API output image gene…
joshtrichards Jun 30, 2026
2ed2c49
refactor(preview): use public Image loading API for Imaginary thumnbn…
joshtrichards Jun 30, 2026
b96c28f
refactor(ldap): use public public Image loading API for avatar handling
joshtrichards Jun 30, 2026
d50cf81
refactor(avatar): use public Image API for loading avatar in resource…
joshtrichards Jun 30, 2026
7920e68
docs(image): clarify IImage::loadFromData() entry
joshtrichards Jun 30, 2026
caa9e7a
chore(settings): fixup import() refactor
joshtrichards Jun 30, 2026
acb1789
chore(Image): fixup conditional for WEBP from refactor in loadFromFile
joshtrichards Jun 30, 2026
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
6 changes: 4 additions & 2 deletions apps/settings/lib/UserMigration/AccountMigrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,11 @@ public function import(IUser $user, IImportSource $importSource, OutputInterface
$importPath = AccountMigrator::PATH_ROOT . reset($avatarFiles);

$output->writeln('Importing avatar from ' . $importPath . '…');
$stream = $importSource->getFileAsStream($importPath);
$data = $importSource->getFileContents($importPath);
$image = new Image();
$image->loadFromFileHandle($stream);
if ($image->loadFromData($data) === false) {
throw new AccountMigratorException('Failed to load avatar');
}

try {
$avatar = $this->avatarManager->getAvatar($user->getUID());
Expand Down
30 changes: 19 additions & 11 deletions apps/theming/lib/Service/BackgroundService.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use OCP\IAppConfig;
use OCP\IConfig;
use OCP\Image;
use OCP\IImage;
use OCP\Lock\LockedException;
use OCP\PreConditionNotMetException;
use RuntimeException;
Expand Down Expand Up @@ -252,8 +253,8 @@ public function recalculateMeanColor(?string $userId = null): void {
$userId = $userId ?? $this->getUserId();

$image = new Image();
$handle = $this->getAppDataFolder($userId)->getFile('background.jpg')->read();
if ($handle === false || $image->loadFromFileHandle($handle) === false) {
$data = $this->getAppDataFolder($userId)->getFile('background.jpg')->getContent();
if ($image->loadFromData($data) === false) {
throw new InvalidArgumentException('Invalid image file');
}

Expand Down Expand Up @@ -322,23 +323,27 @@ public function getBackground(?string $userId = null): ?ISimpleFile {
*/
public function setGlobalBackground($path): ?string {
$image = new Image();
$handle = is_resource($path) ? $path : fopen($path, 'rb');

if ($handle && $image->loadFromFileHandle($handle) !== false) {
$rawImageData = is_resource($path)
? stream_get_contents($path)
: file_get_contents($path);

if ($rawImageData !== false && $image->loadFromData($rawImageData) !== false) {
$meanColor = $this->calculateMeanColor($image);
if ($meanColor !== false) {
$this->appConfig->setValueString(Application::APP_ID, 'background_color', $meanColor);
return $meanColor;
}
}

return null;
}

/**
* Calculate mean color of an given image
* Calculate mean color of a 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(Image $image): false|string {
private function calculateMeanColor(IImage $image): false|string {
/**
* Small helper to ensure one channel is returned as 8byte hex
*/
Expand All @@ -352,15 +357,18 @@ function toHex(int $channel): string {
};
}

$tempImage = new 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) {
$tempImage = $image->cropCopy(
0,
0,
$image->width(),
min(max(50, (int)($image->height() * 0.125)), $image->height()),
);

if (!$tempImage->valid()) {
return false;
}

$tempImage->setResource($resource);
if (!$tempImage->preciseResize(100, 7)) {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion apps/user_ldap/lib/User/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ public function updateAvatar(bool $force = false): bool {
return false;
}

if (!$this->image->loadFromBase64(base64_encode($avatarImage))) {
if (!$this->image->loadFromData($avatarImage)) {
return false;
}

Expand Down
8 changes: 4 additions & 4 deletions apps/user_ldap/tests/User/UserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ public function XtestUpdateAvatarJpegPhotoProvided() {

$this->image->expects($this->once())
->method('loadFromBase64')
->willReturn('imageResource');
->willReturn(imagecreatetruecolor(1, 1));
$this->image->expects($this->once())
->method('valid')
->willReturn(true);
Expand Down Expand Up @@ -531,7 +531,7 @@ public function testUpdateAvatarKnownJpegPhotoProvided(): void {

$this->image->expects($this->once())
->method('loadFromBase64')
->willReturn('imageResource');
->willReturn(imagecreatetruecolor(1, 1));
$this->image->expects($this->never())
->method('valid');
$this->image->expects($this->never())
Expand Down Expand Up @@ -590,7 +590,7 @@ public function XtestUpdateAvatarThumbnailPhotoProvided() {

$this->image->expects($this->once())
->method('loadFromBase64')
->willReturn('imageResource');
->willReturn(imagecreatetruecolor(1, 1));
$this->image->expects($this->once())
->method('valid')
->willReturn(true);
Expand Down Expand Up @@ -697,7 +697,7 @@ public function XtestUpdateAvatarUnsupportedThumbnailPhotoProvided() {

$this->image->expects($this->once())
->method('loadFromBase64')
->willReturn('imageResource');
->willReturn(imagecreatetruecolor(1, 1));
$this->image->expects($this->once())
->method('valid')
->willReturn(true);
Expand Down
5 changes: 4 additions & 1 deletion lib/private/Avatar/UserAvatar.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ private function getAvatarImage($data): IImage {
) {
$img->setResource($data);
} elseif (is_resource($data)) {
$img->loadFromFileHandle($data);
$contents = stream_get_contents($data);
if ($contents !== false) {
$img->loadFromData($contents);
}
} else {
try {
// detect if it is a path or maybe the images as string
Expand Down
Loading
Loading