Browse Source

Code review changes for image compress/resize

pull/16632/head
Halil İbrahim Kalkan 3 years ago
parent
commit
8971d03de6
  1. 7
      framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs
  2. 2
      framework/src/Volo.Abp.Http/Volo/Abp/Http/MimeTypes.cs
  3. 5
      framework/src/Volo.Abp.Image.Abstractions/Volo/Abp/Image/IImageCompressor.cs
  4. 14
      framework/src/Volo.Abp.Image.Abstractions/Volo/Abp/Image/IImageCompressorManager.cs
  5. 2
      framework/src/Volo.Abp.Image.Abstractions/Volo/Abp/Image/IImageCompressorSelector.cs
  6. 1
      framework/src/Volo.Abp.Image.Abstractions/Volo/Abp/Image/IImageFormat.cs
  7. 2
      framework/src/Volo.Abp.Image.Abstractions/Volo/Abp/Image/IImageResizeParameter.cs
  8. 6
      framework/src/Volo.Abp.Image.Abstractions/Volo/Abp/Image/IImageResizer.cs
  9. 4
      framework/src/Volo.Abp.Image.Abstractions/Volo/Abp/Image/ImageFormat.cs
  10. 26
      framework/src/Volo.Abp.Image.ImageSharp/Volo/Abp/Image/ImageSharpImageCompressor.cs
  11. 2
      framework/src/Volo.Abp.Image.ImageSharp/Volo/Abp/Image/ImageSharpImageFormatDetector.cs
  12. 2
      framework/src/Volo.Abp.Image.MagickNet/Volo/Abp/Image/MagickImageCompressor.cs
  13. 2
      framework/src/Volo.Abp.Image.MagickNet/Volo/Abp/Image/MagickImageFormatDetector.cs
  14. 2
      framework/src/Volo.Abp.Image.MagickNet/Volo/Abp/Image/MagickImageResizer.cs
  15. 2
      framework/src/Volo.Abp.Image.Web/Volo/Abp/Image/AbpImageCompressAttribute.cs
  16. 1
      framework/src/Volo.Abp.Image.Web/Volo/Abp/Image/AbpImageWebModule.cs
  17. 2
      framework/src/Volo.Abp.Image.Web/Volo/Abp/Image/AbpOriginalImageAttribute.cs
  18. 2
      framework/src/Volo.Abp.Image.Web/Volo/Abp/Image/IFormFileExtensions.cs
  19. 1
      framework/src/Volo.Abp.Image/Volo.Abp.Image.csproj
  20. 19
      framework/src/Volo.Abp.Image/Volo/Abp/Image/ImageResizeArgs.cs
  21. 15
      framework/src/Volo.Abp.Image/Volo/Abp/Image/ImageResizeParameter.cs
  22. 2
      framework/src/Volo.Abp.Image/Volo/Abp/Image/StreamExtensions.cs

7
framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs

@ -37,6 +37,7 @@ public static class AbpStreamExtensions
{ {
stream.Position = 0; stream.Position = 0;
} }
return stream.CopyToAsync( return stream.CopyToAsync(
destination, destination,
81920, //this is already the default value, but needed to set to be able to pass the cancellationToken 81920, //this is already the default value, but needed to set to be able to pass the cancellationToken
@ -50,12 +51,15 @@ public static class AbpStreamExtensions
{ {
stream.Position = 0; stream.Position = 0;
} }
var memoryStream = new MemoryStream(); var memoryStream = new MemoryStream();
await stream.CopyToAsync(memoryStream, cancellationToken); await stream.CopyToAsync(memoryStream, cancellationToken);
if (stream.CanSeek) if (stream.CanSeek)
{ {
stream.Position = 0; stream.Position = 0;
} }
memoryStream.Position = 0; memoryStream.Position = 0;
return memoryStream; return memoryStream;
} }
@ -66,12 +70,15 @@ public static class AbpStreamExtensions
{ {
stream.Position = 0; stream.Position = 0;
} }
var memoryStream = new MemoryStream(); var memoryStream = new MemoryStream();
stream.CopyTo(memoryStream); stream.CopyTo(memoryStream);
if (stream.CanSeek) if (stream.CanSeek)
{ {
stream.Position = 0; stream.Position = 0;
} }
memoryStream.Position = 0; memoryStream.Position = 0;
return memoryStream; return memoryStream;
} }

2
framework/src/Volo.Abp.Http/Volo/Abp/Http/MimeTypes.cs

@ -4,7 +4,7 @@ namespace Volo.Abp.Http;
/* Taken from https://gist.github.com/markwhitaker/b29c0142360714688a7cf863ab33e5c9 */ /* Taken from https://gist.github.com/markwhitaker/b29c0142360714688a7cf863ab33e5c9 */
public static class MimeTypes public static class MimeTypes //TODO: Move to Volo.Abp.Core with the same namespace
{ {
public static class Application public static class Application
{ {

5
framework/src/Volo.Abp.Image.Abstractions/Volo/Abp/Image/IImageCompressor.cs

@ -4,9 +4,10 @@ using System.Threading.Tasks;
namespace Volo.Abp.Image; namespace Volo.Abp.Image;
public interface IImageCompressor public interface IImageCompressor // TODO: RENAME: IImageCompressorContributor
{ {
Task<Stream> CompressAsync(Stream stream, CancellationToken cancellationToken = default); //TODO: new extension method that works with byte arrays
Task<Stream> CompressAsync(Stream stream, CancellationToken cancellationToken = default); // TODO: TryCompressAsync & remove CanCompress
Stream Compress(Stream stream); Stream Compress(Stream stream);

14
framework/src/Volo.Abp.Image.Abstractions/Volo/Abp/Image/IImageCompressorManager.cs

@ -0,0 +1,14 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.Image;
public interface IImageCompressorManager // TODO: Rename to IImageCompressor
{
Task<Stream> CompressAsync(
Stream stream,
[CanBeNull] IImageFormat imageFormat = null,
CancellationToken cancellationToken = default);
}

2
framework/src/Volo.Abp.Image.Abstractions/Volo/Abp/Image/IImageCompressorSelector.cs

@ -1,6 +1,6 @@
namespace Volo.Abp.Image; namespace Volo.Abp.Image;
public interface IImageCompressorSelector public interface IImageCompressorSelector //TODO: Remove, merge to IImageCompressorManager
{ {
IImageCompressor FindCompressor(IImageFormat imageFormat); IImageCompressor FindCompressor(IImageFormat imageFormat);
} }

1
framework/src/Volo.Abp.Image.Abstractions/Volo/Abp/Image/IImageFormat.cs

@ -2,6 +2,5 @@
public interface IImageFormat public interface IImageFormat
{ {
string Name { get; }
string MimeType { get; } string MimeType { get; }
} }

2
framework/src/Volo.Abp.Image.Abstractions/Volo/Abp/Image/IImageResizeParameter.cs

@ -1,6 +1,6 @@
namespace Volo.Abp.Image; namespace Volo.Abp.Image;
public interface IImageResizeParameter public interface IImageResizeParameter //TODO: Remove
{ {
int? Width { get; } int? Width { get; }
int? Height { get; } int? Height { get; }

6
framework/src/Volo.Abp.Image.Abstractions/Volo/Abp/Image/IImageResizer.cs

@ -7,9 +7,9 @@ namespace Volo.Abp.Image;
public interface IImageResizer public interface IImageResizer
{ {
Task<Stream> ResizeAsync(Stream stream, IImageResizeParameter resizeParameter, Task<Stream> ResizeAsync(Stream stream, IImageResizeParameter resizeParameter,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default); //TODO: TryResizeAsync...
Stream Resize(Stream stream, IImageResizeParameter resizeParameter); Stream Resize(Stream stream, IImageResizeParameter resizeParameter); //TODO: Remove
bool CanResize(IImageFormat imageFormat); bool CanResize(IImageFormat imageFormat); //TODO: Discard (merge with TryResizeAsync)
} }

4
framework/src/Volo.Abp.Image.Abstractions/Volo/Abp/Image/ImageFormat.cs

@ -2,12 +2,10 @@
public class ImageFormat : IImageFormat public class ImageFormat : IImageFormat
{ {
public ImageFormat(string name, string mimeType) public ImageFormat(string mimeType)
{ {
Name = name;
MimeType = mimeType; MimeType = mimeType;
} }
public string Name { get; }
public string MimeType { get; } public string MimeType { get; }
} }

26
framework/src/Volo.Abp.Image.ImageSharp/Volo/Abp/Image/ImageSharpImageCompressor.cs

@ -14,20 +14,22 @@ public class ImageSharpImageCompressor : IImageCompressor, ITransientDependency
{ {
public async Task<Stream> CompressAsync(Stream stream, CancellationToken cancellationToken = default) public async Task<Stream> CompressAsync(Stream stream, CancellationToken cancellationToken = default)
{ {
var newStream = await stream.CreateMemoryStreamAsync(cancellationToken: cancellationToken); var memoryStream = await stream.CreateMemoryStreamAsync(cancellationToken: cancellationToken);
using var image = await SixLabors.ImageSharp.Image.LoadAsync(newStream, cancellationToken);
newStream.Position = 0; using var image = await SixLabors.ImageSharp.Image.LoadAsync(memoryStream, cancellationToken);
var format = await SixLabors.ImageSharp.Image.DetectFormatAsync(newStream, cancellationToken); memoryStream.Position = 0;
newStream.Position = 0;
var format = await SixLabors.ImageSharp.Image.DetectFormatAsync(memoryStream, cancellationToken);
memoryStream.Position = 0;
var encoder = image.GetConfiguration().ImageFormatsManager.FindEncoder(format); var encoder = image.GetConfiguration().ImageFormatsManager.FindEncoder(format);
switch (encoder) switch (encoder)
{ {
case JpegEncoder jpegEncoder: case JpegEncoder jpegEncoder:
jpegEncoder.Quality = 60; jpegEncoder.Quality = 60;
break; break;
case PngEncoder pngEncoder: case PngEncoder pngEncoder:
pngEncoder.CompressionLevel = PngCompressionLevel.BestCompression; pngEncoder.CompressionLevel = PngCompressionLevel.BestCompression; //TODO: AbpImageSharpOptions (others too)
pngEncoder.IgnoreMetadata = true; pngEncoder.IgnoreMetadata = true;
break; break;
case WebpEncoder webPEncoder: case WebpEncoder webPEncoder:
@ -35,12 +37,13 @@ public class ImageSharpImageCompressor : IImageCompressor, ITransientDependency
webPEncoder.UseAlphaCompression = true; webPEncoder.UseAlphaCompression = true;
break; break;
case null: case null:
throw new NotSupportedException($"No encoder available for provided path: {format.Name}"); throw new NotSupportedException($"No encoder available for the given format: {format.Name}");
} }
await image.SaveAsync(newStream, encoder, cancellationToken: cancellationToken); await image.SaveAsync(memoryStream, encoder, cancellationToken: cancellationToken);
newStream.SetLength(newStream.Position); memoryStream.SetLength(memoryStream.Position);
return newStream;
return memoryStream;
} }
public Stream Compress(Stream stream) public Stream Compress(Stream stream)
@ -77,6 +80,7 @@ public class ImageSharpImageCompressor : IImageCompressor, ITransientDependency
public bool CanCompress(IImageFormat format) public bool CanCompress(IImageFormat format)
{ {
//TODO: Use MimeTypes (after moving it to Volo.Abp.Core)
return format?.MimeType switch { return format?.MimeType switch {
"image/jpeg" => true, "image/jpeg" => true,
"image/png" => true, "image/png" => true,

2
framework/src/Volo.Abp.Image.ImageSharp/Volo/Abp/Image/ImageSharpImageFormatDetector.cs

@ -8,6 +8,6 @@ public class ImageSharpImageFormatDetector : IImageFormatDetector, ITransientDep
public IImageFormat FindFormat(Stream stream) public IImageFormat FindFormat(Stream stream)
{ {
var format = SixLabors.ImageSharp.Image.DetectFormat(stream); var format = SixLabors.ImageSharp.Image.DetectFormat(stream);
return new ImageFormat(format.Name, format.DefaultMimeType); return new ImageFormat(format.DefaultMimeType);
} }
} }

2
framework/src/Volo.Abp.Image.MagickNet/Volo/Abp/Image/MagickImageCompressor.cs

@ -13,7 +13,7 @@ public class MagickImageCompressor : IImageCompressor, ITransientDependency
public async Task<Stream> CompressAsync(Stream stream, CancellationToken cancellationToken = default) public async Task<Stream> CompressAsync(Stream stream, CancellationToken cancellationToken = default)
{ {
var newStream = await stream.CreateMemoryStreamAsync(cancellationToken:cancellationToken); var newStream = await stream.CreateMemoryStreamAsync(cancellationToken:cancellationToken);
try try //TODO: Remove try/catch
{ {
_optimizer.IsSupported(newStream); _optimizer.IsSupported(newStream);
newStream.Position = 0; newStream.Position = 0;

2
framework/src/Volo.Abp.Image.MagickNet/Volo/Abp/Image/MagickImageFormatDetector.cs

@ -10,6 +10,6 @@ public class MagickImageFormatDetector : IImageFormatDetector, ITransientDepende
{ {
using var magickImage = new MagickImage(image); using var magickImage = new MagickImage(image);
var format = magickImage.FormatInfo; var format = magickImage.FormatInfo;
return format == null ? null : new ImageFormat(format.Format.ToString(), format.MimeType ?? string.Empty); return format == null ? null : new ImageFormat(format.MimeType ?? string.Empty);
} }
} }

2
framework/src/Volo.Abp.Image.MagickNet/Volo/Abp/Image/MagickImageResizer.cs

@ -13,7 +13,7 @@ public class MagickImageResizer : IImageResizer, ITransientDependency
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
var newStream = await stream.CreateMemoryStreamAsync(cancellationToken: cancellationToken); var newStream = await stream.CreateMemoryStreamAsync(cancellationToken: cancellationToken);
try try //TODO: Remove try/catch
{ {
using var image = new MagickImage(newStream); using var image = new MagickImage(newStream);
ApplyMode(image, resizeParameter); ApplyMode(image, resizeParameter);

2
framework/src/Volo.Abp.Image.Web/Volo/Abp/Image/AbpImageCompressAttribute.cs

@ -11,6 +11,8 @@ using Volo.Abp.Content;
namespace Volo.Abp.Image; namespace Volo.Abp.Image;
//Rename: CompressImageAttribute
//Also introduce ResizeImageAttribute(...)
public class AbpImageCompressActionFilterAttribute : ActionFilterAttribute public class AbpImageCompressActionFilterAttribute : ActionFilterAttribute
{ {
public string[] Parameters { get; } public string[] Parameters { get; }

1
framework/src/Volo.Abp.Image.Web/Volo/Abp/Image/AbpImageWebModule.cs

@ -5,4 +5,5 @@ namespace Volo.Abp.Image;
[DependsOn(typeof(AbpImageModule))] [DependsOn(typeof(AbpImageModule))]
public class AbpImageWebModule : AbpModule public class AbpImageWebModule : AbpModule
{ {
} }

2
framework/src/Volo.Abp.Image.Web/Volo/Abp/Image/AbpOriginalImageAttribute.cs

@ -3,7 +3,7 @@ using System;
namespace Volo.Abp.Image; namespace Volo.Abp.Image;
[AttributeUsage(AttributeTargets.Parameter)] [AttributeUsage(AttributeTargets.Parameter)]
public class AbpOriginalImageAttribute : Attribute public class AbpOriginalImageAttribute : Attribute //TODO: Remove
{ {
public AbpOriginalImageAttribute(string parameter) public AbpOriginalImageAttribute(string parameter)
{ {

2
framework/src/Volo.Abp.Image.Web/Volo/Abp/Image/IFormFileExtensions.cs

@ -6,7 +6,7 @@ using Microsoft.Extensions.DependencyInjection;
namespace Volo.Abp.Image; namespace Volo.Abp.Image;
public static class IFormFileExtensions public static class IFormFileExtensions //TODO: Remove
{ {
public async static Task<IFormFile> CompressImageAsync( public async static Task<IFormFile> CompressImageAsync(
this IFormFile formFile, this IFormFile formFile,

1
framework/src/Volo.Abp.Image/Volo.Abp.Image.csproj

@ -14,7 +14,6 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Volo.Abp.Core\Volo.Abp.Core.csproj" />
<ProjectReference Include="..\Volo.Abp.Image.Abstractions\Volo.Abp.Image.Abstractions.csproj" /> <ProjectReference Include="..\Volo.Abp.Image.Abstractions\Volo.Abp.Image.Abstractions.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

19
framework/src/Volo.Abp.Image/Volo/Abp/Image/ImageResizeArgs.cs

@ -0,0 +1,19 @@
namespace Volo.Abp.Image;
public class ImageResizeArgs : IImageResizeParameter
{
public int? Width { get; set; }
public int? Height { get; set; }
public ImageResizeMode? Mode { get; set; } //TODO: Set default here
public ImageResizeArgs(int? width = null, int? height = null, ImageResizeMode? mode = null)
{
Mode = mode;
Width = width;
Height = height;
//TODO: Throw exception if width/height is not null and negative
}
}

15
framework/src/Volo.Abp.Image/Volo/Abp/Image/ImageResizeParameter.cs

@ -1,15 +0,0 @@
namespace Volo.Abp.Image;
public class ImageResizeParameter : IImageResizeParameter
{
public ImageResizeParameter(int? width = null, int? height = null, ImageResizeMode? mode = null)
{
Mode = mode;
Width = width;
Height = height;
}
public int? Width { get; set; }
public int? Height { get; set; }
public ImageResizeMode? Mode { get; set; }
}

2
framework/src/Volo.Abp.Image/Volo/Abp/Image/StreamExtensions.cs

@ -6,7 +6,7 @@ using Microsoft.Extensions.DependencyInjection;
namespace Volo.Abp.Image; namespace Volo.Abp.Image;
public static class StreamExtensions public static class StreamExtensions //TODO: Remove
{ {
public static Stream CompressImage(this Stream stream, IImageFormat imageFormat, IImageCompressor imageCompressor) public static Stream CompressImage(this Stream stream, IImageFormat imageFormat, IImageCompressor imageCompressor)
{ {

Loading…
Cancel
Save