Skip to content

Commit

Permalink
Magick.Net #524
Browse files Browse the repository at this point in the history
  • Loading branch information
Webreaper committed Mar 26, 2024
1 parent 3d5bf28 commit b8af6eb
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 9 deletions.
Binary file modified .DS_Store
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<None Remove="SixLabors.Fonts" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Magick.NET-Q16-AnyCPU" />
<PackageReference Include="SixLabors.ImageSharp" />
<PackageReference Include="SixLabors.Fonts" />
</ItemGroup>
Expand Down
1 change: 0 additions & 1 deletion Damselfly.Core.ImageProcessing/ImageMagickProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ public class ImageMagickProcessor : IImageProcessor

private const string graphicsMagickExe = "gm";

// SkiaSharp doesn't handle .heic files... yet
private static readonly string[] s_imageExtensions = { ".jpg", ".jpeg", ".png", ".heic", ".tif", ".tiff", ".webp", ".arw", ".cr3" };
private static bool imAvailable;
private readonly bool s_useGraphicsMagick = false; // GM doesn't support HEIC yet.
Expand Down
12 changes: 10 additions & 2 deletions Damselfly.Core.ImageProcessing/ImageProcessorFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ public class ImageProcessorFactory : IImageProcessorFactory
private readonly ImageMagickProcessor imProcessor;
private readonly ImageSharpProcessor isharpProcessor;
private readonly SkiaSharpProcessor skiaProcessor;
private readonly MagickNetProcessor magickNetProcessor;

public ImageProcessorFactory()
{
skiaProcessor = new SkiaSharpProcessor();
isharpProcessor = new ImageSharpProcessor();
imProcessor = new ImageMagickProcessor();
magickNetProcessor = new MagickNetProcessor();
}

public void SetContentPath(string path)
Expand Down Expand Up @@ -47,11 +49,17 @@ public IHashProvider GetHashProvider()
if ( ImageSharpProcessor.SupportedFileExtensions.Any(x =>
x.Equals(fileExtension, StringComparison.OrdinalIgnoreCase)) ) return isharpProcessor;

// Magick.Net - As of 12-Aug-2024, it can do thumbs for 100 images in about 45 seconds.
// Main advantage: it can also handle HEIC, and is native
if ( MagickNetProcessor.SupportedFileExtensions.Any(x =>
x.Equals(fileExtension, StringComparison.OrdinalIgnoreCase)) ) return magickNetProcessor;

// ImageMagick last, because of the complexities of spawning a child process.
// As of 12-Aug-2021, it can do thumbs for 100 images in about 33 seconds.
// Main advantage: it can also handle HEIC
if ( ImageMagickProcessor.SupportedFileExtensions.Any(x =>
x.Equals(fileExtension, StringComparison.OrdinalIgnoreCase)) ) return imProcessor;
// Mar 2024 - disable this in preference to Magick.Net
//if ( ImageMagickProcessor.SupportedFileExtensions.Any(x =>
// x.Equals(fileExtension, StringComparison.OrdinalIgnoreCase)) ) return imProcessor;

return null;
}
Expand Down
93 changes: 93 additions & 0 deletions Damselfly.Core.ImageProcessing/MagickNetProcessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
using Damselfly.Core.DbModels.Images;
using Damselfly.Core.Interfaces;
using Damselfly.Core.Utils;
using Damselfly.Shared.Utils;
using ImageMagick;

namespace Damselfly.Core.ImageProcessing;

public class MagickNetProcessor : IImageProcessor
{
public static ICollection<string> SupportedFileExtensions => SupportedExtensions();

private static ICollection<string> SupportedExtensions()
{
// Interrogate Magick.Net for a list of supported file extensions where we can read and write the image
var formats = MagickNET.SupportedFormats.Where( format => format.SupportsReading && format.SupportsWriting )
.Select( format => $".{format.Format.ToString().ToLower()}").ToList();

return formats;
}

/// <summary>
/// Convert the files to thumbnails using Magick.Net
/// </summary>
/// <param name="source">Source.</param>
/// <param name="sizes">Sizes.</param>
public async Task<IImageProcessResult> CreateThumbs(FileInfo source, IDictionary<FileInfo, IThumbConfig> destFiles)
{
// This processor doesn't support hash creation
IImageProcessResult result = new ImageProcessResult { ThumbsGenerated = false, ImageHash = string.Empty };

using var image = new MagickImage();

var load = new Stopwatch("MagickNetLoad");

await image.ReadAsync(source.FullName);
image.AutoOrient();

load.Stop();

var thumbs = new Stopwatch("MagickNetThumbs");

foreach ( var pair in destFiles )
{
var dest = pair.Key;
var config = pair.Value;

var targetRatio = (decimal)config.width / (decimal)config.height;
var currentRatio = (decimal)image.Width/(decimal)image.Height;

bool widthIsLongest = currentRatio > targetRatio;

var intermediateSize = widthIsLongest
? new MagickGeometry { Width = (int)(config.height * currentRatio), Height = config.height }
: new MagickGeometry { Width = config.width, Height = (int)(config.width / currentRatio) };

Logging.LogTrace("Generating thumbnail for {0}: {1}x{2}", source.Name, config.width, config.height);

image.Resize(intermediateSize);
intermediateSize.IgnoreAspectRatio = false;

if( currentRatio != targetRatio && config.cropToRatio)
{
var size = new MagickGeometry(config.width, config.height);

image.Crop(size, Gravity.Center);
}

await image.WriteAsync(dest.FullName);

result.ThumbsGenerated = true;
}

thumbs.Stop();

return result;
}

public Task TransformDownloadImage(string input, Stream output, IExportSettings config)
{
throw new NotImplementedException();
}

public Task GetCroppedFile(FileInfo source, int x, int y, int width, int height, FileInfo destFile)
{
throw new NotImplementedException();
}

public Task CropImage(FileInfo source, int x, int y, int width, int height, Stream stream)
{
throw new NotImplementedException();
}
}
1 change: 1 addition & 0 deletions Damselfly.Web.Client/Pages/ImagePage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@
CurrentImage = await imageCache.GetCachedImage(imageId);
navContext.CurrentImage = CurrentImage;

// TODO: Fix nullref here
ImageUrl = CurrentImage.ThumbUrl(ThumbSize.Medium);
ImageUrlHighRes = CurrentImage.ThumbUrl(ThumbSize.ExtraLarge);
;
Expand Down
2 changes: 1 addition & 1 deletion Damselfly.Web.Client/wwwroot/version.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
const CACHE_VERSION='4.1.3-20240321104506'
const CACHE_VERSION='4.1.3-20240326071412'
4 changes: 1 addition & 3 deletions Damselfly.Web.Server/Controllers/PeopleController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ namespace Damselfly.Web.Server.Controllers;
[ApiController]
[Route("/api/people")]
public class PeopleController( ImageRecognitionService _aiService,
IPeopleService _peopleService,
ILogger<PeopleController> _logger,
ImageCache _imageCache) : ControllerBase
IPeopleService _peopleService) : ControllerBase
{
[HttpGet("/api/person/{personId}")]
public async Task<Person> GetPerson( int personId )
Expand Down
3 changes: 1 addition & 2 deletions Damselfly.Web.Server/Controllers/StaticDataController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ namespace Damselfly.Web.Server.Controllers;
//[Authorize(Policy = PolicyDefinitions.s_IsLoggedIn)]
[ApiController]
[Route("/api/data")]
public class StaticDataController( ILogger<StaticDataController> _logger,
MetaDataService _metaDataService,
public class StaticDataController( MetaDataService _metaDataService,
ICachedDataService _cachedData,
StatisticsService _stats) : ControllerBase
{
Expand Down
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<PackageVersion Include="FluentValidation" Version="11.9.0" />
<PackageVersion Include="font-awesome" Version="4.7.0" />
<PackageVersion Include="Humanizer" Version="2.14.1" />
<PackageVersion Include="Magick.NET-Q16-AnyCPU" Version="13.6.0" />
<PackageVersion Include="MailKit" Version="4.4.0" />
<PackageVersion Include="Octokit" Version="10.0.0" />
<PackageVersion Include="MetadataExtractor" Version="2.9.0-rc1" />
Expand Down

0 comments on commit b8af6eb

Please sign in to comment.