Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transcoding Support + More Image Format Support (JPEGXL) #3250

Open
wants to merge 37 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
e2a86c6
Add JXL Support.
maxpiva Aug 15, 2024
cb647ad
Make sure if djxl do not exists, continue as usual.
maxpiva Aug 15, 2024
7f6db24
Changed the way conversion happens.
maxpiva Aug 23, 2024
dd0021a
Missing file
maxpiva Aug 23, 2024
efc14ff
Merge branch 'Kareadita:develop' into develop
maxpiva Aug 23, 2024
9d48664
Revert "Changed the way conversion happens."
maxpiva Aug 26, 2024
cf05e5f
Reapply "Changed the way conversion happens."
maxpiva Aug 26, 2024
4902a74
Changed the way conversion happens.
maxpiva Aug 23, 2024
21b4c1b
Merge with Karedita
maxpiva Aug 26, 2024
7d48f6e
Add Documentation
maxpiva Aug 27, 2024
a4a12a1
FIX BOMS
maxpiva Aug 28, 2024
0f98d75
Recode SupportedImageTypesFromRequest removing possible errors.
maxpiva Aug 28, 2024
937f89c
Remove own docker build
maxpiva Aug 28, 2024
a08a795
Shell Call no longer used, since swapped image conversion to Image Ma…
maxpiva Aug 28, 2024
bc8481c
Merge branch 'Kareadita:develop' into JPEG-XL_JPG2000_HEIF
maxpiva Aug 29, 2024
e7f021a
Edit CodeStyle
maxpiva Aug 29, 2024
c624287
Remove custom docker builder
maxpiva Aug 29, 2024
6dbeaf1
Fixed discovered issues.
maxpiva Aug 30, 2024
fead3f6
Merge branch 'Kareadita:develop' into JPEG-XL_JPG2000_HEIF
maxpiva Sep 19, 2024
bf30989
Merge branch 'Kareadita:develop' into JPEG-XL_JPG2000_HEIF
maxpiva Sep 27, 2024
0cc4803
Removed NetVips and ImageSharp (Use only ImageMagick)
maxpiva Sep 28, 2024
10da91c
Remove CropFromDimensions (Geometry will take care)
maxpiva Sep 28, 2024
1541d6a
BOM Changes
maxpiva Sep 28, 2024
23a9aa8
Delete .bak
maxpiva Sep 28, 2024
b6a986a
Bug fixes.
maxpiva Sep 29, 2024
3008ae0
Merge branch 'Kareadita:develop' into RemoveSixLaborsAndNetVips
maxpiva Sep 29, 2024
9bf1fa8
Added SmartCrop (port from smartcrop.js)
maxpiva Oct 1, 2024
170c3b6
Refactor and cleanup.
maxpiva Oct 4, 2024
361c464
BOM Fixes
maxpiva Oct 4, 2024
d6056b8
Update docker-build.sh
maxpiva Oct 4, 2024
92f131a
Fixed Benchmarks
maxpiva Oct 4, 2024
b21ee66
Merge branch 'RemoveSixLaborsAndNetVips' of https://github.com/maxpiv…
maxpiva Oct 4, 2024
4f026e6
Fixed BOM
maxpiva Oct 4, 2024
00ee60b
Requested changes.
maxpiva Oct 10, 2024
fbbbbb8
Removed bak files, fixed EncodeFormat BOM
maxpiva Oct 10, 2024
a0f804b
Removed quality parameter everywhere.
maxpiva Oct 11, 2024
11749bd
Remove quality parameters after refactor.
maxpiva Oct 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions API.Benchmark/API.Benchmark.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,10 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<None Update="Data\comic-normal.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
63 changes: 23 additions & 40 deletions API.Benchmark/ArchiveServiceBenchmark.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
using System;
using System.IO;
using System.IO.Abstractions;
using API.Entities.Enums;
using Microsoft.Extensions.Logging.Abstractions;
using API.Services;
using API.Services.ImageServices;
using API.Services.ImageServices.ImageMagick;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Order;
using EasyCaching.Core;
using NSubstitute;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.Processing;


namespace API.Benchmark;

Expand All @@ -24,16 +24,16 @@ public class ArchiveServiceBenchmark
private readonly ArchiveService _archiveService;
private readonly IDirectoryService _directoryService;
private readonly IImageService _imageService;
private readonly PngEncoder _pngEncoder = new PngEncoder();
private readonly WebpEncoder _webPEncoder = new WebpEncoder();
private const string SourceImage = "C:/Users/josep/Pictures/obey_by_grrsa-d6llkaa_colored_by_me.png";

private readonly IImageFactory _imageFactory;
private const string SourceImage = "Data/comic-normal.jpg";


public ArchiveServiceBenchmark()
{
_directoryService = new DirectoryService(null, new FileSystem());
_imageService = new ImageService(null, _directoryService, Substitute.For<IEasyCachingProviderFactory>());
_imageService = new ImageService(null, _directoryService, Substitute.For<IEasyCachingProviderFactory>(), Substitute.For<IImageFactory>());
_archiveService = new ArchiveService(new NullLogger<ArchiveService>(), _directoryService, _imageService, Substitute.For<IMediaErrorService>());
_imageFactory = new ImageMagickImageFactory();
}

[Benchmark(Baseline = true)]
Expand Down Expand Up @@ -61,50 +61,33 @@ public void TestGetComicInfo_outside_root()
}

[Benchmark]
public void ImageSharp_ExtractImage_PNG()
public void ImageMagick_ExtractImage_PNG()
{
var outputDirectory = "C:/Users/josep/Pictures/imagesharp/";
var outputDirectory = "Data/ImageMagick";
_directoryService.ExistOrCreate(outputDirectory);

using var stream = new FileStream(SourceImage, FileMode.Open);
using var thumbnail2 = SixLabors.ImageSharp.Image.Load(stream);
thumbnail2.Mutate(x => x.Resize(320, 0));
thumbnail2.Save(_directoryService.FileSystem.Path.Join(outputDirectory, "imagesharp.png"), _pngEncoder);
using var thumbnail2 = _imageFactory.Create(stream);
int width = 320;
int height = (int)(thumbnail2.Height * (width / (double)thumbnail2.Width));
thumbnail2.Thumbnail(width, height);
thumbnail2.Save(_directoryService.FileSystem.Path.Join(outputDirectory, "imagesharp.png"), EncodeFormat.PNG, 100);
}

[Benchmark]
public void ImageSharp_ExtractImage_WebP()
public void ImageMagick_ExtractImage_WebP()
{
var outputDirectory = "C:/Users/josep/Pictures/imagesharp/";
var outputDirectory = "Data/ImageMagick";
_directoryService.ExistOrCreate(outputDirectory);

using var stream = new FileStream(SourceImage, FileMode.Open);
using var thumbnail2 = SixLabors.ImageSharp.Image.Load(stream);
thumbnail2.Mutate(x => x.Resize(320, 0));
thumbnail2.Save(_directoryService.FileSystem.Path.Join(outputDirectory, "imagesharp.webp"), _webPEncoder);
using var thumbnail2 = _imageFactory.Create(stream);
int width = 320;
int height = (int)(thumbnail2.Height * (width / (double)thumbnail2.Width));
thumbnail2.Thumbnail(width, height);
thumbnail2.Save(_directoryService.FileSystem.Path.Join(outputDirectory, "imagesharp.webp"), EncodeFormat.PNG, 100);
}

[Benchmark]
public void NetVips_ExtractImage_PNG()
{
var outputDirectory = "C:/Users/josep/Pictures/netvips/";
_directoryService.ExistOrCreate(outputDirectory);

using var stream = new FileStream(SourceImage, FileMode.Open);
using var thumbnail = NetVips.Image.ThumbnailStream(stream, 320);
thumbnail.WriteToFile(_directoryService.FileSystem.Path.Join(outputDirectory, "netvips.png"));
}

[Benchmark]
public void NetVips_ExtractImage_WebP()
{
var outputDirectory = "C:/Users/josep/Pictures/netvips/";
_directoryService.ExistOrCreate(outputDirectory);

using var stream = new FileStream(SourceImage, FileMode.Open);
using var thumbnail = NetVips.Image.ThumbnailStream(stream, 320);
thumbnail.WriteToFile(_directoryService.FileSystem.Path.Join(outputDirectory, "netvips.webp"));
}

// Benchmark to test default GetNumberOfPages from archive
// vs a new method where I try to open the archive and return said stream
Expand Down
Binary file added API.Benchmark/Data/comic-normal.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 12 additions & 5 deletions API.Tests/Services/ArchiveServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
using API.Archive;
using API.Entities.Enums;
using API.Services;
using API.Services.ImageServices;
using API.Services.ImageServices.ImageMagick;
using EasyCaching.Core;
using Microsoft.Extensions.Logging;
using NetVips;
using NSubstitute;
using NSubstitute.Extensions;
using Xunit;
Expand All @@ -29,7 +30,7 @@ public ArchiveServiceTests(ITestOutputHelper testOutputHelper)
{
_testOutputHelper = testOutputHelper;
_archiveService = new ArchiveService(_logger, _directoryService,
new ImageService(Substitute.For<ILogger<ImageService>>(), _directoryService, Substitute.For<IEasyCachingProviderFactory>()),
new ImageService(Substitute.For<ILogger<ImageService>>(), _directoryService, Substitute.For<IEasyCachingProviderFactory>(), Substitute.For<IImageFactory>()),
Substitute.For<IMediaErrorService>());
}

Expand Down Expand Up @@ -167,11 +168,17 @@ public void FindFirstEntry(string[] files, string expected)
public void GetCoverImage_Default_Test(string inputFile, string expectedOutputFile)
{
var ds = Substitute.For<DirectoryService>(_directoryServiceLogger, new FileSystem());
var imageService = new ImageService(Substitute.For<ILogger<ImageService>>(), ds, Substitute.For<IEasyCachingProviderFactory>());
var imageService = new ImageService(Substitute.For<ILogger<ImageService>>(), ds, Substitute.For<IEasyCachingProviderFactory>(), new ImageMagickImageFactory());
var archiveService = Substitute.For<ArchiveService>(_logger, ds, imageService, Substitute.For<IMediaErrorService>());

var testDirectory = Path.GetFullPath(Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/ArchiveService/CoverImages"));
var expectedBytes = Image.Thumbnail(Path.Join(testDirectory, expectedOutputFile), 320).WriteToBuffer(".png");
using var thumbnail = imageService.ImageFactory.Create(Path.Join(testDirectory, expectedOutputFile));
int width = 320;
int height = (int)(thumbnail.Height * (width / (double)thumbnail.Width));
thumbnail.Thumbnail(width, height);
using MemoryStream stream = new MemoryStream();
thumbnail.Save(stream, EncodeFormat.PNG, 100);
var expectedBytes = stream.ToArray();

archiveService.Configure().CanOpen(Path.Join(testDirectory, inputFile)).Returns(ArchiveLibrary.Default);

Expand All @@ -198,7 +205,7 @@ public void GetCoverImage_Default_Test(string inputFile, string expectedOutputFi
[InlineData("sorting.zip", "sorting.expected.png")]
public void GetCoverImage_SharpCompress_Test(string inputFile, string expectedOutputFile)
{
var imageService = new ImageService(Substitute.For<ILogger<ImageService>>(), _directoryService, Substitute.For<IEasyCachingProviderFactory>());
var imageService = new ImageService(Substitute.For<ILogger<ImageService>>(), _directoryService, Substitute.For<IEasyCachingProviderFactory>(), Substitute.For<IImageFactory>());
var archiveService = Substitute.For<ArchiveService>(_logger,
new DirectoryService(_directoryServiceLogger, new FileSystem()), imageService,
Substitute.For<IMediaErrorService>());
Expand Down
3 changes: 2 additions & 1 deletion API.Tests/Services/BookServiceTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.IO;
using System.IO.Abstractions;
using API.Services;
using API.Services.ImageServices;
using EasyCaching.Core;
using Microsoft.Extensions.Logging;
using NSubstitute;
Expand All @@ -17,7 +18,7 @@ public BookServiceTests()
{
var directoryService = new DirectoryService(Substitute.For<ILogger<DirectoryService>>(), new FileSystem());
_bookService = new BookService(_logger, directoryService,
new ImageService(Substitute.For<ILogger<ImageService>>(), directoryService, Substitute.For<IEasyCachingProviderFactory>())
new ImageService(Substitute.For<ILogger<ImageService>>(), directoryService, Substitute.For<IEasyCachingProviderFactory>(), Substitute.For<IImageFactory>())
, Substitute.For<IMediaErrorService>());
}

Expand Down
14 changes: 7 additions & 7 deletions API.Tests/Services/CacheServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ public async Task Ensure_DirectoryAlreadyExists_DontExtractAnything()
new ReadingItemService(Substitute.For<IArchiveService>(),
Substitute.For<IBookService>(),
Substitute.For<IImageService>(), ds, Substitute.For<ILogger<ReadingItemService>>()),
Substitute.For<IBookmarkService>());
Substitute.For<IBookmarkService>(), Substitute.For<IImageService>());

await ResetDB();
var s = new SeriesBuilder("Test").Build();
Expand Down Expand Up @@ -234,7 +234,7 @@ public void CleanupChapters_AllFilesShouldBeDeleted()
var cleanupService = new CacheService(_logger, _unitOfWork, ds,
new ReadingItemService(Substitute.For<IArchiveService>(),
Substitute.For<IBookService>(), Substitute.For<IImageService>(), ds, Substitute.For<ILogger<ReadingItemService>>()),
Substitute.For<IBookmarkService>());
Substitute.For<IBookmarkService>(), Substitute.For<IImageService>());

cleanupService.CleanupChapters(new []{1, 3});
Assert.Empty(ds.GetFiles(CacheDirectory, searchOption:SearchOption.AllDirectories));
Expand All @@ -256,7 +256,7 @@ public void GetCachedEpubFile_ShouldReturnFirstEpub()
var cs = new CacheService(_logger, _unitOfWork, ds,
new ReadingItemService(Substitute.For<IArchiveService>(),
Substitute.For<IBookService>(), Substitute.For<IImageService>(), ds, Substitute.For<ILogger<ReadingItemService>>()),
Substitute.For<IBookmarkService>());
Substitute.For<IBookmarkService>(), Substitute.For<IImageService>());

var c = new ChapterBuilder("1")
.WithFile(new MangaFileBuilder($"{DataDirectory}1.epub", MangaFormat.Epub).Build())
Expand Down Expand Up @@ -297,7 +297,7 @@ public void GetCachedPagePath_ReturnNullIfNoFiles()
var cs = new CacheService(_logger, _unitOfWork, ds,
new ReadingItemService(Substitute.For<IArchiveService>(),
Substitute.For<IBookService>(), Substitute.For<IImageService>(), ds, Substitute.For<ILogger<ReadingItemService>>()),
Substitute.For<IBookmarkService>());
Substitute.For<IBookmarkService>(),Substitute.For<IImageService>());

// Flatten to prepare for how GetFullPath expects
ds.Flatten($"{CacheDirectory}1/");
Expand Down Expand Up @@ -341,7 +341,7 @@ public void GetCachedPagePath_GetFileFromFirstFile()
var cs = new CacheService(_logger, _unitOfWork, ds,
new ReadingItemService(Substitute.For<IArchiveService>(),
Substitute.For<IBookService>(), Substitute.For<IImageService>(), ds, Substitute.For<ILogger<ReadingItemService>>()),
Substitute.For<IBookmarkService>());
Substitute.For<IBookmarkService>(), Substitute.For<IImageService>());

// Flatten to prepare for how GetFullPath expects
ds.Flatten($"{CacheDirectory}1/");
Expand Down Expand Up @@ -382,7 +382,7 @@ public void GetCachedPagePath_GetLastPageFromSingleFile()
var cs = new CacheService(_logger, _unitOfWork, ds,
new ReadingItemService(Substitute.For<IArchiveService>(),
Substitute.For<IBookService>(), Substitute.For<IImageService>(), ds, Substitute.For<ILogger<ReadingItemService>>()),
Substitute.For<IBookmarkService>());
Substitute.For<IBookmarkService>(), Substitute.For<IImageService>());

// Flatten to prepare for how GetFullPath expects
ds.Flatten($"{CacheDirectory}1/");
Expand Down Expand Up @@ -427,7 +427,7 @@ public void GetCachedPagePath_GetFileFromSecondFile()
var cs = new CacheService(_logger, _unitOfWork, ds,
new ReadingItemService(Substitute.For<IArchiveService>(),
Substitute.For<IBookService>(), Substitute.For<IImageService>(), ds, Substitute.For<ILogger<ReadingItemService>>()),
Substitute.For<IBookmarkService>());
Substitute.For<IBookmarkService>(), Substitute.For<IImageService>());

// Flatten to prepare for how GetFullPath expects
ds.Flatten($"{CacheDirectory}1/");
Expand Down
33 changes: 16 additions & 17 deletions API.Tests/Services/ImageServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@
using System.Text;
using API.Entities.Enums;
using API.Services;
using API.Services.ImageServices.ImageMagick;
using EasyCaching.Core;
using Microsoft.Extensions.Logging;
using NetVips;
using NSubstitute;
using Xunit;
using Image = NetVips.Image;

namespace API.Tests.Services;

Expand Down Expand Up @@ -56,21 +55,15 @@ private void GenerateFiles(string outputExtension)
.ToList();

// Step 3: Process each image
ImageMagickImageFactory factory = new ImageMagickImageFactory();
foreach (var imagePath in imageFiles)
{
var fileName = Path.GetFileNameWithoutExtension(imagePath);
var dims = CoverImageSize.Default.GetDimensions();
using var sourceImage = Image.NewFromFile(imagePath, false, Enums.Access.SequentialUnbuffered);

var size = ImageService.GetSizeForDimensions(sourceImage, dims.Width, dims.Height);
var crop = ImageService.GetCropForDimensions(sourceImage, dims.Width, dims.Height);

using var thumbnail = Image.Thumbnail(imagePath, dims.Width, dims.Height,
size: size,
crop: crop);

var thumbnail = factory.Create(imagePath);
thumbnail = ImageService.Thumbnail(thumbnail, dims.Width, dims.Height);
var outputFileName = fileName + outputExtension + ".png";
thumbnail.WriteToFile(Path.Join(_testDirectory, outputFileName));
thumbnail.Save(Path.Join(_testDirectory, outputFileName), EncodeFormat.PNG,100);
}
}

Expand All @@ -80,6 +73,7 @@ private void GenerateHtmlFile()
.Where(file => !file.EndsWith("html"))
.Where(file => !file.Contains(OutputPattern) && !file.Contains(BaselinePattern))
.ToList();
ImageMagickImageFactory factory = new ImageMagickImageFactory();

var htmlBuilder = new StringBuilder();
htmlBuilder.AppendLine("<!DOCTYPE html>");
Expand All @@ -105,7 +99,7 @@ private void GenerateHtmlFile()
var outputPath = Path.Combine(_testDirectory, fileName + "_output.png");
var dims = CoverImageSize.Default.GetDimensions();

using var sourceImage = Image.NewFromFile(imagePath, false, Enums.Access.SequentialUnbuffered);
using var sourceImage = factory.Create(imagePath);
htmlBuilder.AppendLine("<div class=\"image-row\">");
htmlBuilder.AppendLine($"<p>{fileName} ({((double) sourceImage.Width / sourceImage.Height).ToString("F2")}) - {ImageService.WillScaleWell(sourceImage, dims.Width, dims.Height)}</p>");
htmlBuilder.AppendLine($"<img src=\"./{Path.GetFileName(imagePath)}\" alt=\"{fileName}\">");
Expand Down Expand Up @@ -144,11 +138,16 @@ public void TestColorScapes()
.Where(file => !file.Contains(OutputPattern) && !file.Contains(BaselinePattern))
.ToList();

var factory = LoggerFactory.Create(builder => { builder.AddConsole(); });
var logger = factory.CreateLogger<ImageService>();

ImageService service = new ImageService(logger, null, null, new ImageMagickImageFactory());

// Step 3: Process each image
foreach (var imagePath in imageFiles)
{
var fileName = Path.GetFileNameWithoutExtension(imagePath);
var colors = ImageService.CalculateColorScape(imagePath);
var colors = service.CalculateColorScape(imagePath);

// Generate primary color image
GenerateColorImage(colors.Primary, Path.Combine(_testDirectoryColorScapes, $"{fileName}_primary_output.png"));
Expand All @@ -164,10 +163,10 @@ public void TestColorScapes()

private static void GenerateColorImage(string hexColor, string outputPath)
{
ImageMagickImageFactory factory = new ImageMagickImageFactory();
var color = ImageService.HexToRgb(hexColor);
using var colorImage = Image.Black(200, 100);
using var output = colorImage + new[] { color.R / 255.0, color.G / 255.0, color.B / 255.0 };
output.WriteToFile(outputPath);
using var colorImage = factory.Create(200,100,color.R, color.G, color.B);
colorImage.Save(outputPath, EncodeFormat.PNG, 100);
}

private void GenerateHtmlFileForColorScape()
Expand Down
10 changes: 4 additions & 6 deletions API/API.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,19 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="CsvHelper" Version="33.0.1" />
<PackageReference Include="Magick.NET-Q16-HDRI-AnyCPU" Version="13.10.0" />
<PackageReference Include="MailKit" Version="4.7.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="Docnet.Core" Version="2.6.0" />
<PackageReference Include="EasyCaching.InMemory" Version="1.9.2" />
<PackageReference Include="ExCSS" Version="4.2.5" />
<PackageReference Include="Flurl" Version="3.0.7" />
<PackageReference Include="Flurl.Http" Version="3.2.4" />
<PackageReference Include="Flurl" Version="4.0.0" />
<PackageReference Include="Flurl.Http" Version="4.0.2" />
<PackageReference Include="Hangfire" Version="1.8.14" />
<PackageReference Include="Hangfire.InMemory" Version="1.0.0" />
<PackageReference Include="Hangfire.MaximumConcurrentExecutions" Version="1.1.0" />
Expand All @@ -82,8 +83,6 @@
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
<PackageReference Include="MimeTypeMapOfficial" Version="1.0.17" />
<PackageReference Include="Nager.ArticleNumber" Version="1.0.7" />
<PackageReference Include="NetVips" Version="2.4.1" />
<PackageReference Include="NetVips.Native" Version="8.15.3" />
<PackageReference Include="NReco.Logging.File" Version="1.2.1" />
<PackageReference Include="Serilog" Version="4.0.1" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.2" />
Expand All @@ -95,7 +94,6 @@
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.SignalR.Core" Version="0.1.2" />
<PackageReference Include="SharpCompress" Version="0.38.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.32.0.97167">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
Loading