Search code examples
c#asp.net-coreimage-resizing

What is the decent approach to resizing images in ASP.NET Core?


It's my first time resizing images in ASP.NET Core, so after a bit of research I found this approach to be the easiest and most efficient and I implemented it as shown below.

However, I am not sure if that approach is the most efficient one since there are two issues with it that go as follows

  1. Images lose a lot of their quality
  2. I get this 'warning' in Visual Studio that is fine as long as I am the only one who develops it, however that will not always be the case if someone else does -

This call site is reachable on all platforms. 'Bitmap' is only supported on windows.

Therefore I wonder what are other approaches more decent that exist and I can implement to at least fix the first of both issues.

public async Task<IActionResult> Add(AddCardFormModel card, List<IFormFile> ImageFile)
{
    // ...

    foreach (var image in ImageFile)
    {
        if (image.Length > 0 || image.Length <= (2 * 1024 * 1024))
        {
            var imagesToBeResized = Image.FromStream(image.OpenReadStream());
            var resized = new Bitmap(imagesToBeResized, new Size(250, 350));

            using (var stream = new MemoryStream())
            {
                resized.Save(stream, ImageFormat.Jpeg);

                var cardData = new Card
                        {
                            Title = card.Title,
                            Description = card.Description,
                            ImageUrl = card.ImageUrl,
                            CategoryId = card.CategoryId,
                            ConditionId = card.ConditionId,
                            Price = card.Price,
                            DealerId = dealerId,
                            Image = stream.ToArray()
                        };

                this.data.Cards.Add(cardData);
                this.data.SaveChanges();
            }
        }
    }

    // ...
}

Solution

  • The System.Drawing.Common package is only supported on Windows.

    If you want your application to work cross-platform then Microsoft suggests to migrate to one of the following libraries:

    https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/6.0/system-drawing-common-windows-only#recommended-action

    You should first decide which image processing library you will use in your project and after that look for the best algorithm for resizing images using that specific library.

    SkiaSharp example:

    using SkiaSharp;
    
    public static byte[] ScaleImage(byte[] imageBytes, int maxWidth, int maxHeight)
    {
        SKBitmap image = SKBitmap.Decode(imageBytes);
    
        var ratioX = (double)maxWidth / image.Width;
        var ratioY = (double)maxHeight / image.Height;
        var ratio = Math.Min(ratioX, ratioY);
    
        var newWidth = (int)(image.Width * ratio);
        var newHeight = (int)(image.Height * ratio);
    
        var info = new SKImageInfo(newWidth, newHeight);
        image = image.Resize(info, SKFilterQuality.High);
    
        using var ms = new MemoryStream();
        image.Encode(ms, SKEncodedImageFormat.Png, 100);
        return ms.ToArray();
    }
    

    ImageSharp example:

    using SixLabors.ImageSharp;
    using SixLabors.ImageSharp.Formats.Png;
    using SixLabors.ImageSharp.Processing;
    
    public static byte[] ScaleImage(byte[] imageBytes, int maxWidth, int maxHeight)
    {
        Image image = Image.Load(imageBytes);   
    
        var ratioX = (double)maxWidth / image.Width;
        var ratioY = (double)maxHeight / image.Height;
        var ratio = Math.Min(ratioX, ratioY);
    
        var newWidth = (int)(image.Width * ratio);
        var newHeight = (int)(image.Height * ratio);
    
        image.Mutate(x => x.Resize(newWidth, newHeight));
    
        using var ms = new MemoryStream();
        image.Save(ms, new PngEncoder());
        return ms.ToArray();
    }