summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJake Mannens <jake@asger.xyz>2023-08-29 15:47:37 +1000
committerJake Mannens <jake@asger.xyz>2023-08-29 15:47:37 +1000
commitcb8c17917d0363f09eeaa3c379617dc213b2dacf (patch)
tree9c3c1c15cb6925b31fb9ef3eb93b66fb9e02a5ac
parentd3b8abea30cda6127e9318f7762df175d5f6d459 (diff)
Moved thumbnail generation from media controller to media service
-rw-r--r--Controllers/MediaController.cs40
-rw-r--r--Exception.cs14
-rw-r--r--Pages/Gallery.razor5
-rw-r--r--Services/MediaService.cs37
-rw-r--r--Todo.md4
-rw-r--r--wwwroot/styles/global.css4
6 files changed, 68 insertions, 36 deletions
diff --git a/Controllers/MediaController.cs b/Controllers/MediaController.cs
index 674b406..85dfc65 100644
--- a/Controllers/MediaController.cs
+++ b/Controllers/MediaController.cs
@@ -38,39 +38,17 @@ public class MediaController : Controller {
[HttpGet("thumb/{mediaId}")]
public IActionResult Thumbnail(
[FromRoute] Guid mediaId,
- [FromQuery] int? w,
- [FromQuery] int? h) {
+ [FromQuery(Name = "w")] int? width,
+ [FromQuery(Name = "h")] int? height) {
- var media = db.Media.First(m => m.Guid == mediaId);
- if(media is null)
- return NotFound();
-
- if(media.MimeType.Split("/")[0] != "image")
- return BadRequest("Media object not an image");
-
- using var image = new MagickImage(mediaService.GetPath(media));
-
- if(w is null && h is null)
- return BadRequest("Both width and height cannot be null!");
-
- if(w > image.Width || h > image.Height)
- return BadRequest("Requested thumbnail size is larger than original media");
-
- #pragma warning disable CS8629
- int width = (int)(w is not null ? w : image.Width * h / image.Height);
- int height = (int)(h is not null ? h : image.Height * w / image.Width);
- #pragma warning restore CS8629
-
- var thumbPath = mediaService.GetPath(media, width, height);
-
- if(!System.IO.File.Exists(thumbPath)) {
- image.Resize(width, height);
- image.Write(thumbPath);
+ try {
+ var thumb = mediaService.GetThumbnail(mediaId, width, height);
+ return new FileStreamResult(thumb, "image/jpeg");
+ } catch(ThumbnailException e) {
+ return BadRequest(e.Message);
+ } catch(ObjectNotFoundException e) {
+ return NotFound(e.Message);
}
-
- var fs = System.IO.File.OpenRead(thumbPath);
-
- return new FileStreamResult(fs, "image/jpeg");
}
[HttpDelete("{mediaId}")]
diff --git a/Exception.cs b/Exception.cs
index 528be52..2005b1a 100644
--- a/Exception.cs
+++ b/Exception.cs
@@ -9,6 +9,13 @@ public class HBException : Exception {
: base(message, inner) {}
}
+public class ObjectNotFoundException : HBException {
+ public Guid Guid { get; set; }
+
+ public ObjectNotFoundException(Guid guid)
+ : base($"Object not found: {guid}") {}
+}
+
public class MediaException : HBException {
public Media? Media { get; set; }
@@ -20,6 +27,9 @@ public class MediaException : HBException {
public class MediaCreateException : MediaException {
public MediaCreateException(string message)
: base(message) {}
- public MediaCreateException(string message, Media media)
- : base(message, media) {}
+}
+
+public class ThumbnailException : MediaException {
+ public ThumbnailException(string message, Media media)
+ :base(message, media) {}
}
diff --git a/Pages/Gallery.razor b/Pages/Gallery.razor
index e5b1e7b..a582c02 100644
--- a/Pages/Gallery.razor
+++ b/Pages/Gallery.razor
@@ -11,8 +11,11 @@
<link rel="stylesheet" href="@(nameof(HyperBooru)).styles.css"/>
@foreach(var media in Media) {
+ // Precalculate thumbnail size to help the browser
+ // lay out the images during initial page load
+ int width = media.Width * 200 / media.Height;
<a href="/ViewMedia?m=@(media.Guid)">
- <img src="/media/thumb/@(media.Guid)?h=200" />
+ <img src="/media/thumb/@(media.Guid)?h=200" width=@width height="200"/>
</a>
}
diff --git a/Services/MediaService.cs b/Services/MediaService.cs
index 8c2a5e0..ccee027 100644
--- a/Services/MediaService.cs
+++ b/Services/MediaService.cs
@@ -24,6 +24,8 @@ public interface IMediaService {
public void Delete(Guid media);
public void Delete(Media media);
+ public Stream GetThumbnail(Guid media, int? width, int? height);
+ public Stream GetThumbnail(Media media, int? width, int? height);
public string GetPath(Media media);
public string GetPath(Media media, int width, int height);
@@ -206,6 +208,41 @@ public class MediaService : IMediaService {
public void Delete(Media media) =>
Delete(media.Guid);
+ public Stream GetThumbnail(Guid media, int? width, int? height) {
+ using var db = dbFactory.CreateDbContext();
+ var m = db.Media.First(m => m.Guid == media);
+ if(m is null)
+ throw new ObjectNotFoundException(media);
+
+ if(m.MimeType.Split("/")[0] != "image")
+ throw new ThumbnailException("Media object not an image", m);
+
+ using var image = new MagickImage(GetPath(m));
+
+ if(width is null && height is null)
+ throw new ThumbnailException("Both width and height cannot be null!", m);
+
+ if(width > image.Width || height > image.Height)
+ throw new ThumbnailException("Requested thumbnail size is larger than original media", m);
+
+ #pragma warning disable CS8629
+ int w = (int) (width is not null ? width : image.Width * height / image.Height);
+ int h = (int) (height is not null ? height : image.Height * width / image.Width);
+ #pragma warning restore CS8629
+
+ var thumbPath = GetPath(m, w, h);
+
+ if(!System.IO.File.Exists(thumbPath)) {
+ image.Resize(w, h);
+ image.Write(thumbPath);
+ }
+
+ return System.IO.File.OpenRead(thumbPath);
+ }
+
+ public Stream GetThumbnail(Media media, int? width, int? height) =>
+ GetThumbnail(media.Guid, width, height);
+
public string GetPath(Media media) {
var fileInfo = new FileInfo(
Path.Join(
diff --git a/Todo.md b/Todo.md
index ee1aad3..89dc6db 100644
--- a/Todo.md
+++ b/Todo.md
@@ -8,14 +8,14 @@
# Short-term Features
- Store original filesize as part of uploaded files
- Progressive page loading
- - Media metadata (width, height, etc)
- Proper thumbnail generation
- Deleting media also deletes thumbnails
- Video support
- User/security support
- - About page
#Long-term Features
+ - Search engine includes implicit tags
+ - Periodic thumbnail scrubbing
- Search tags from ViewMedia page
- Loading animations
- Keyboard shortcuts
diff --git a/wwwroot/styles/global.css b/wwwroot/styles/global.css
index 2757d09..de0a0ac 100644
--- a/wwwroot/styles/global.css
+++ b/wwwroot/styles/global.css
@@ -23,6 +23,10 @@
--col-switch-bg-hl: var(--col-accent-pri);
}
+::selection {
+ background: var(--col-accent-pri);
+}
+
body {
background: var(--col-bg);
color: white;