< Summary

Information
Class: Anichron.Worker.Ingestion.Proxy.ImageSharpProcessor
Assembly: Anichron.Worker
File(s): /home/runner/work/anichron/anichron/src/Anichron.Worker/Ingestion/Proxy/ImageProcessor.cs
Tag: 228_36821334185
Line coverage
0%
Covered lines: 0
Uncovered lines: 23
Coverable lines: 23
Total lines: 62
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 2
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
CreateThumbnailAsync()100%210%
CreateFullPreviewAsync()0%620%
ComputeBlurhashAsync(...)100%210%

File(s)

/home/runner/work/anichron/anichron/src/Anichron.Worker/Ingestion/Proxy/ImageProcessor.cs

#LineLine coverage
 1using Anichron.Worker.Settings;
 2using Blurhash.ImageSharp;
 3using Microsoft.Extensions.Options;
 4using SixLabors.ImageSharp;
 5using SixLabors.ImageSharp.Formats.Jpeg;
 6using SixLabors.ImageSharp.PixelFormats;
 7using SixLabors.ImageSharp.Processing;
 8
 9namespace Anichron.Worker.Ingestion.Proxy;
 10
 11internal interface IImageProcessor
 12{
 13    Task<byte[]> CreateThumbnailAsync(Image<Rgba32> image, CancellationToken ct);
 14    Task<byte[]> CreateFullPreviewAsync(Image<Rgba32> image, CancellationToken ct);
 15    Task<string> ComputeBlurhashAsync(Image<Rgba32> image, CancellationToken ct);
 16}
 17
 018internal sealed class ImageSharpProcessor(IOptions<WorkerSettings> options) : IImageProcessor
 19{
 020    private readonly WorkerSettings settings = options.Value;
 21
 22    public async Task<byte[]> CreateThumbnailAsync(Image<Rgba32> image, CancellationToken ct)
 023    {
 24        image.Mutate(x => x.Resize(new ResizeOptions
 25        {
 26            Size = new Size(settings.ThumbnailMaxWidth, 0),
 27            Mode = ResizeMode.Max,
 28        }));
 29
 030        await using var ms = new MemoryStream();
 031        await image.SaveAsJpegAsync(ms, new JpegEncoder { Quality = settings.ThumbnailJpegQuality }, ct);
 032        return ms.ToArray();
 033    }
 34
 35    public async Task<byte[]> CreateFullPreviewAsync(Image<Rgba32> image, CancellationToken ct)
 036    {
 037        if (image.Width > settings.PreviewMaxWidth)
 038        {
 39            image.Mutate(x => x.Resize(new ResizeOptions
 40            {
 41                Size = new Size(settings.PreviewMaxWidth, 0),
 42                Mode = ResizeMode.Max,
 43            }));
 044        }
 45
 046        await using var ms = new MemoryStream();
 047        await image.SaveAsJpegAsync(ms, new JpegEncoder { Quality = settings.PreviewJpegQuality }, ct);
 048        return ms.ToArray();
 049    }
 50
 51    public Task<string> ComputeBlurhashAsync(Image<Rgba32> image, CancellationToken ct)
 052    {
 053        image.Mutate(x => x.Resize(new ResizeOptions
 054        {
 055            Size = new Size(settings.BlurhashSampleWidth, 0),
 056            Mode = ResizeMode.Max,
 057        }));
 58
 59        // Blurhasher.Encode is CPU-bound and synchronous; no overload accepts a CancellationToken.
 060        return Task.FromResult(Blurhasher.Encode(image, 4, 3));
 061    }
 62}