From be8257e012b3c7394288d3859928b2c36f7b0056 Mon Sep 17 00:00:00 2001 From: LD-Reborn Date: Sat, 22 Nov 2025 17:11:00 +0100 Subject: [PATCH] Fixed aspect ratio of user images wrong, added new user default image --- src/Controllers/HomeController.cs | 2 +- src/Controllers/UsersController.cs | 2 +- src/Helpers/ImageHelper.cs | 28 ++++++++++++++++++++++++++++ src/wwwroot/user_default.jpeg | Bin 1209 -> 0 bytes src/wwwroot/user_default.webp | Bin 0 -> 12266 bytes 5 files changed, 30 insertions(+), 2 deletions(-) delete mode 100644 src/wwwroot/user_default.jpeg create mode 100644 src/wwwroot/user_default.webp diff --git a/src/Controllers/HomeController.cs b/src/Controllers/HomeController.cs index 3f4e108..fc3e440 100644 --- a/src/Controllers/HomeController.cs +++ b/src/Controllers/HomeController.cs @@ -102,7 +102,7 @@ public class HomeController : Controller UserModel? user = await _ldap.GetUserByUidAsync(uid, _ldap.UsersAttributes); if (user is null || user.JpegPhoto is null || user.JpegPhoto == "") { - return File("user_default.jpeg", "image/jpeg"); + return File(ImageHelper.GetDefaultUserImage(size ?? 48), "image/webp"); } if (size is null) { diff --git a/src/Controllers/UsersController.cs b/src/Controllers/UsersController.cs index 2391301..5e4fd51 100644 --- a/src/Controllers/UsersController.cs +++ b/src/Controllers/UsersController.cs @@ -75,7 +75,7 @@ public class UsersController : Controller string? title = requestModel.Title; string userPassword = requestModel.UserPassword ?? ""; UserDescription? description = requestModel.Description; - jpegPhoto ??= Convert.ToBase64String(System.IO.File.ReadAllBytes("wwwroot/user_default.jpeg")); // TODO: cleanup - make this a config setting + jpegPhoto ??= ImageHelper.GetDefaultUserImageAsBase64(); string uid = UsersHelper.CreateUsername(requestModel.Cn ?? "", requestModel.Sn ?? ""); title ??= ""; description ??= new() {Address = new(), BirthDate = "", Workplace = "", Groups = []}; diff --git a/src/Helpers/ImageHelper.cs b/src/Helpers/ImageHelper.cs index e0baa08..b230c87 100644 --- a/src/Helpers/ImageHelper.cs +++ b/src/Helpers/ImageHelper.cs @@ -2,6 +2,7 @@ using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats.Webp; using SixLabors.ImageSharp.Formats; using Berufsschule_HAM.Models; +using SixLabors.ImageSharp.Processing; namespace Berufsschule_HAM.Helpers; @@ -30,6 +31,23 @@ public static class ImageHelper using var image = Image.Load(decoderOptions, inputStream); + int minDimension = Math.Min(image.Width, image.Height); + var cropRectangle = new Rectangle( + (image.Width - minDimension) / 2, + (image.Height - minDimension) / 2, + minDimension, + minDimension); + + image.Mutate(x => + { + x.Crop(cropRectangle); + x.Resize(new ResizeOptions + { + Size = new Size(size, size), + Mode = ResizeMode.Crop + }); + }); + using var outputStream = new MemoryStream(); image.Save(outputStream, new WebpEncoder()); result = outputStream.ToArray(); @@ -38,6 +56,16 @@ public static class ImageHelper return result; } + public static byte[] GetDefaultUserImage(int size = 48) + { + return ResizeAndConvertToWebp(GetDefaultUserImageAsBase64(), size); + } + + public static string GetDefaultUserImageAsBase64() + { + return Convert.ToBase64String(File.ReadAllBytes("wwwroot/user_default.webp")); + } + public static async Task PreloadUsers(IEnumerable userModels, UserImagePreloadType? preloadType) { if (preloadType is null || preloadType == UserImagePreloadType.None) return; diff --git a/src/wwwroot/user_default.jpeg b/src/wwwroot/user_default.jpeg deleted file mode 100644 index 0141c99b8976767ef302acbd59b7e4f771e850aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1209 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