|
|
@ -7,6 +7,7 @@ |
|
|
|
|
|
|
|
|
using System; |
|
|
using System; |
|
|
using System.IO; |
|
|
using System.IO; |
|
|
|
|
|
using System.Threading; |
|
|
using System.Threading.Tasks; |
|
|
using System.Threading.Tasks; |
|
|
using SixLabors.ImageSharp; |
|
|
using SixLabors.ImageSharp; |
|
|
using SixLabors.ImageSharp.Formats.Jpeg; |
|
|
using SixLabors.ImageSharp.Formats.Jpeg; |
|
|
@ -19,20 +20,28 @@ namespace Squidex.Infrastructure.Assets.ImageSharp |
|
|
{ |
|
|
{ |
|
|
public sealed class ImageSharpAssetThumbnailGenerator : IAssetThumbnailGenerator |
|
|
public sealed class ImageSharpAssetThumbnailGenerator : IAssetThumbnailGenerator |
|
|
{ |
|
|
{ |
|
|
public Task CreateThumbnailAsync(Stream source, Stream destination, ResizeOptions options) |
|
|
private readonly SemaphoreSlim semaphoreSlim = new SemaphoreSlim(Math.Max(Environment.ProcessorCount / 4, 1)); |
|
|
|
|
|
|
|
|
|
|
|
public async Task CreateThumbnailAsync(Stream source, Stream destination, ResizeOptions options) |
|
|
{ |
|
|
{ |
|
|
|
|
|
Guard.NotNull(source, nameof(source)); |
|
|
|
|
|
Guard.NotNull(destination, nameof(destination)); |
|
|
Guard.NotNull(options, nameof(options)); |
|
|
Guard.NotNull(options, nameof(options)); |
|
|
|
|
|
|
|
|
if (!options.IsValid) |
|
|
if (!options.IsValid) |
|
|
{ |
|
|
{ |
|
|
source.CopyTo(destination); |
|
|
source.CopyTo(destination); |
|
|
|
|
|
|
|
|
return Task.CompletedTask; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
var w = options.Width ?? 0; |
|
|
var w = options.Width ?? 0; |
|
|
var h = options.Height ?? 0; |
|
|
var h = options.Height ?? 0; |
|
|
|
|
|
|
|
|
|
|
|
await semaphoreSlim.WaitAsync(); |
|
|
|
|
|
|
|
|
|
|
|
try |
|
|
|
|
|
{ |
|
|
using (var image = Image.Load(source, out var format)) |
|
|
using (var image = Image.Load(source, out var format)) |
|
|
{ |
|
|
{ |
|
|
var encoder = Configuration.Default.ImageFormatsManager.FindEncoder(format); |
|
|
var encoder = Configuration.Default.ImageFormatsManager.FindEncoder(format); |
|
|
@ -83,12 +92,17 @@ namespace Squidex.Infrastructure.Assets.ImageSharp |
|
|
|
|
|
|
|
|
image.Save(destination, encoder); |
|
|
image.Save(destination, encoder); |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
return Task.CompletedTask; |
|
|
finally |
|
|
|
|
|
{ |
|
|
|
|
|
semaphoreSlim.Release(); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public Task<ImageInfo?> GetImageInfoAsync(Stream source) |
|
|
public Task<ImageInfo?> GetImageInfoAsync(Stream source) |
|
|
{ |
|
|
{ |
|
|
|
|
|
Guard.NotNull(source, nameof(source)); |
|
|
|
|
|
|
|
|
ImageInfo? result = null; |
|
|
ImageInfo? result = null; |
|
|
|
|
|
|
|
|
try |
|
|
try |
|
|
@ -108,7 +122,14 @@ namespace Squidex.Infrastructure.Assets.ImageSharp |
|
|
return Task.FromResult(result); |
|
|
return Task.FromResult(result); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public Task<ImageInfo> FixOrientationAsync(Stream source, Stream destination) |
|
|
public async Task<ImageInfo> FixOrientationAsync(Stream source, Stream destination) |
|
|
|
|
|
{ |
|
|
|
|
|
Guard.NotNull(source, nameof(source)); |
|
|
|
|
|
Guard.NotNull(destination, nameof(destination)); |
|
|
|
|
|
|
|
|
|
|
|
await semaphoreSlim.WaitAsync(); |
|
|
|
|
|
|
|
|
|
|
|
try |
|
|
{ |
|
|
{ |
|
|
using (var image = Image.Load(source, out var format)) |
|
|
using (var image = Image.Load(source, out var format)) |
|
|
{ |
|
|
{ |
|
|
@ -123,7 +144,12 @@ namespace Squidex.Infrastructure.Assets.ImageSharp |
|
|
|
|
|
|
|
|
image.Save(destination, encoder); |
|
|
image.Save(destination, encoder); |
|
|
|
|
|
|
|
|
return Task.FromResult(GetImageInfo(image)); |
|
|
return GetImageInfo(image); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
finally |
|
|
|
|
|
{ |
|
|
|
|
|
semaphoreSlim.Release(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|