From b4ac10c006f65d2f6293bd9a769c457e8fd2c4c6 Mon Sep 17 00:00:00 2001 From: ju09279 Date: Fri, 16 Aug 2024 00:28:14 +0200 Subject: [PATCH] resizing images ondemand --- backend/Program.cs | 123 ++++++++++++++++----- backend/Properties/launchSettings.json | 9 +- backend/shitweb.csproj | 1 + frontend/src/components/CollectionItem.vue | 8 +- frontend/src/components/NowPlaying.vue | 7 +- frontend/src/components/SongItem.vue | 6 +- frontend/src/stores/userStore.ts | 14 +-- frontend/src/views/CollectionView.vue | 9 +- frontend/src/views/NowPlayingView.vue | 11 +- 9 files changed, 119 insertions(+), 69 deletions(-) diff --git a/backend/Program.cs b/backend/Program.cs index f2a8e2c..26a861c 100644 --- a/backend/Program.cs +++ b/backend/Program.cs @@ -2,20 +2,23 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Hosting; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; var builder = WebApplication.CreateBuilder(args); builder.Services.AddMemoryCache(); -builder.Services.AddCors(options => -{ - options.AddPolicy("AllowAll", - policy => - { - policy.AllowAnyOrigin() - .AllowAnyHeader() - .AllowAnyMethod(); - }); +builder.Services.AddCors(options => +{ + options.AddPolicy("AllowAll", + policy => + { + policy.AllowAnyOrigin() + .AllowAnyHeader() + .AllowAnyMethod(); + }); }); var app = builder.Build(); @@ -28,14 +31,14 @@ app.MapGet("/ping", () => "pong"); app.MapGet("/api/v1/songs/{hash}", (string hash) => { - return Results.Ok(new { hash }); + return Results.Ok(new { hash }); }); app.MapGet("/api/v1/songs/recent", (int? limit, int? offset) => { var limitValue = limit ?? 100; // default to 10 if not provided var offsetValue = offset ?? 0; // default to 0 if not provided - + return Results.Json(Osudb.Instance.GetRecent(limitValue, offsetValue)); }); @@ -54,22 +57,22 @@ app.MapGet("/api/v1/songs/{hash}", (string hash) => app.MapGet("/api/v1/collections/", async (int? limit, int? offset, [FromServices] IMemoryCache cache) => { - const string cacheKey = "collections"; - - if (!cache.TryGetValue(cacheKey, out var collections)) - { - - collections = Osudb.Instance.GetCollections(); - - var cacheEntryOptions = new MemoryCacheEntryOptions() - .SetSlidingExpiration(TimeSpan.FromDays(1)) - .SetAbsoluteExpiration(TimeSpan.FromDays(3)); - - cache.Set(cacheKey, collections, cacheEntryOptions); + const string cacheKey = "collections"; + + if (!cache.TryGetValue(cacheKey, out var collections)) + { + + collections = Osudb.Instance.GetCollections(); + + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetSlidingExpiration(TimeSpan.FromDays(1)) + .SetAbsoluteExpiration(TimeSpan.FromDays(3)); + + cache.Set(cacheKey, collections, cacheEntryOptions); } - return Results.Json(collections); - + return Results.Json(collections); + }); app.MapGet("/api/v1/collection/{index}", (int index) => @@ -103,7 +106,7 @@ app.MapGet("/api/v1/audio/{*fileName}", async (string fileName, HttpContext cont }); -app.MapGet("/api/v1/images/{*filename}", async (string filename) => +app.MapGet("/api/v1/images/{*filename}", async (string filename, int? h, int? w) => { var decodedFileName = Uri.UnescapeDataString(filename); var filePath = Path.Combine(Osudb.osufolder, "Songs", decodedFileName); @@ -124,12 +127,72 @@ app.MapGet("/api/v1/images/{*filename}", async (string filename) => ".webp" => "image/webp", _ => "application/octet-stream", }; - - var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, useAsync: true); + + if (w == null || h == null) + { + var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, useAsync: true); + return Results.Stream(fileStream, contentType, filename); + } + using var originalImage = new Bitmap(filePath); + + + // If resizing is requested, resize the image + Bitmap resizedImage; + if (w.HasValue || h.HasValue) + { + resizedImage = ResizeImage(originalImage, w, h); + } + else + { + resizedImage = new Bitmap(originalImage); // Keep original size + } + + // Convert the resized image to a memory stream + var memoryStream = new MemoryStream(); + resizedImage.Save(memoryStream, GetImageFormat(fileExtension)); + memoryStream.Position = 0; // Reset stream position + + return Results.File(memoryStream, contentType); - return Results.Stream(fileStream, contentType, filename); }); - +static Bitmap ResizeImage(Image originalImage, int? width, int? height) +{ + int newWidth = width ?? originalImage.Width; + int newHeight = height ?? originalImage.Height; + + if (width == null) + { + newWidth = originalImage.Width * newHeight / originalImage.Height; + } + else if (height == null) + { + newHeight = originalImage.Height * newWidth / originalImage.Width; + } + + var resizedImage = new Bitmap(newWidth, newHeight); + using (var graphics = Graphics.FromImage(resizedImage)) + { + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.DrawImage(originalImage, 0, 0, newWidth, newHeight); + } + + return resizedImage; +} + +static ImageFormat GetImageFormat(string extension) +{ + return extension switch + { + ".jpg" or ".jpeg" => ImageFormat.Jpeg, + ".png" => ImageFormat.Png, + ".gif" => ImageFormat.Gif, + ".bmp" => ImageFormat.Bmp, + ".webp" => ImageFormat.Webp, + _ => ImageFormat.Png, + }; +} app.Run(); diff --git a/backend/Properties/launchSettings.json b/backend/Properties/launchSettings.json index ebdcf8c..e81a762 100644 --- a/backend/Properties/launchSettings.json +++ b/backend/Properties/launchSettings.json @@ -12,14 +12,7 @@ "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, - "applicationUrl": "https://localhost:7254;http://localhost:5153", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, + "applicationUrl": "http://localhost:5153", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/backend/shitweb.csproj b/backend/shitweb.csproj index 1d5a263..07f4bfa 100644 --- a/backend/shitweb.csproj +++ b/backend/shitweb.csproj @@ -8,6 +8,7 @@ + diff --git a/frontend/src/components/CollectionItem.vue b/frontend/src/components/CollectionItem.vue index a586825..b2ef669 100644 --- a/frontend/src/components/CollectionItem.vue +++ b/frontend/src/components/CollectionItem.vue @@ -17,7 +17,7 @@ const name = ref('name'); onMounted(async () => { const data = await userStore.fetchCollection(Number(route.params.id)); console.log(data) - + data.songs.forEach(song => { song.previewimage = `${userStore.baseUrl}api/v1/images/${song.previewimage}`; song.url = `${userStore.baseUrl}api/v1/audio/${song.url}`; @@ -47,10 +47,6 @@ onMounted(async () => {
- +
diff --git a/frontend/src/components/NowPlaying.vue b/frontend/src/components/NowPlaying.vue index 08d1cff..75e9f9f 100644 --- a/frontend/src/components/NowPlaying.vue +++ b/frontend/src/components/NowPlaying.vue @@ -11,8 +11,8 @@ const audioStore = useAudioStore();
- Background Image + Background Image