locked
How to resize image before upload to varbinary column? RRS feed

  • Question

  • User991566988 posted

    Hi

    I'm uploading an image to a varbinary column in the database successfully. But I want to resize it before uploading.

    So this is what I tried:

    Guests model:

    public byte[] Image { get; set; }

    public string ContentType { get; set; }

    ImageExtentions Class to resize the image:

    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.IO;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace System.Drawing
    {
        public static class ImageExtentions
        {
            public static Image Resize(this Image current, int maxWidth, int maxHeight)
            {
                int width, height;
    
                if (current.Width > current.Height)
                {
                    width = maxWidth;
                    height = Convert.ToInt32(current.Height * maxHeight / (double)current.Width);
                }
                else
                {
                    width = Convert.ToInt32(current.Width * maxWidth / (double)current.Height);
                    height = maxHeight;
                }
    
                var canvas = new Bitmap(width, height);
    
                using (var graphics = Graphics.FromImage(canvas))
                {
                    graphics.CompositingQuality = CompositingQuality.HighSpeed;
                    graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    graphics.CompositingMode = CompositingMode.SourceCopy;
                    graphics.DrawImage(current, 0, 0, width, height);
                }
    
                return canvas;
            }
    
            public static byte[] ToByteArray(this Image current)
            {
                using (var stream = new MemoryStream())
                {
                    current.Save(stream, current.RawFormat);
                    return stream.ToArray();
                }
            }
        }
    }
    

    GuestsController:

    //using a lot
    using System.Drawing;
    namespace Proj.Controllers
    {
    public class GuestsController : Controller
    {
    private readonly ApplicationDbContext _context; public GuestsController(ApplicationDbContext context) { _context = context; } //Some code [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create([Bind("Id,Name,DoB")] Guests guest, List<IFormFile> Image) { IFormFile uploadedImage = Image.FirstOrDefault(); if (ModelState.IsValid) { foreach (var item in Image) { if (item.Length > 0) { using (var stream = new MemoryStream()) { using (Image img = Image.FromStream(uploadedImage.OpenReadStream())) { Stream ms = new MemoryStream(img.Resize(900, 1000).ToByteArray()); FileStreamResult fsr = new FileStreamResult(ms, "image/jpg"); uploadedImage.OpenReadStream().CopyTo(stream); guest.Image = stream.ToArray(); guest.ContentType = uploadedImage.ContentType; } } } } } _context.Add(guest); await _context.SaveChangesAsync();
    }

    But this scenario gives me this error:

    List<IFormFile> does not contain a definition for 'FromStream' and no accessible extension method  'FromStream' accepting a first argument of type List<IFormFile> could be found.

    How to perform this task please?

    Tuesday, April 7, 2020 6:35 AM

All replies

  • User439975351 posted

    Hi there,

    I have found these two solutions work very well, might be worth a look:

    https://www.imageflow.io/

    https://imageresizing.net/

    Jus

    Tuesday, April 7, 2020 8:20 AM
  • User991566988 posted

    I've found this solution on Stack overflow:

    using (Image<Rgba32> image = Image.Load("foo.jpg"))
    {
        image.Mutate(x => x
             .Resize(image.Width / 2, image.Height / 2)
             .Grayscale());
        image.Save("bar.jpg"); // Automatic encoder selected based on extension.
    }

    but 'Load' gives me this error:

    No overload for method Load takes 1 argument.

    and I don't know to implement it in my scenario. Any help please?

    Wednesday, April 8, 2020 7:05 AM
  • User711641945 posted

    Hi musbah7,

    Your received parameter named Image is the same as Image.FromStream which is in `System.Drawing`.You need to specify the namespace like below:

    ImageExtension:

    public static class ImageExtentions
    {
        public static Image Resize(this Image current, int maxWidth, int maxHeight)
        {
            int width, height;
    
            if (current.Width > current.Height)
            {
                width = maxWidth;
                height = Convert.ToInt32(current.Height * maxHeight / (double)current.Width);
            }
            else
            {
                width = Convert.ToInt32(current.Width * maxWidth / (double)current.Height);
                height = maxHeight;
            }
    
            var canvas = new Bitmap(width, height);
    
            using (var graphics = Graphics.FromImage(canvas))
            {
                graphics.CompositingQuality = CompositingQuality.HighSpeed;
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.CompositingMode = CompositingMode.SourceCopy;
                graphics.DrawImage(current, 0, 0, width, height);
            }
    
            return canvas;
        }
    
        public static byte[] ToByteArray(this Image current)
        {
            ImageConverter _imageConverter = new ImageConverter();
            byte[] xByte = (byte[])_imageConverter.ConvertTo(current, typeof(byte[]));
            return xByte;
        }
    }

    Controller:

    [HttpPost]
    //[ValidateAntiForgeryToken]
    public async Task<IActionResult> Create([Bind("Id,Name,DoB")] Guests guest, List<IFormFile> Image)
    {
        IFormFile uploadedImage = Image.FirstOrDefault();
        if (ModelState.IsValid)
        {
            foreach (var item in Image)
            {
                if (item.Length > 0)
                {
                    using (var stream = new MemoryStream())
                    {
                        using (System.Drawing.Image img = System.Drawing.Image.FromStream(uploadedImage.OpenReadStream()))
                        {
                            Stream ms = new MemoryStream(img.Resize(900, 1000).ToByteArray());
                            FileStreamResult fsr = new FileStreamResult(ms, "image/jpg");
                            uploadedImage.OpenReadStream().CopyTo(stream);
                            guest.Image = stream.ToArray();
                            guest.ContentType = uploadedImage.ContentType;
                        }
    
                    }
    
                }
            }
        }
                
        _context.Add(guest);
        await _context.SaveChangesAsync();
        return View(guest);
    }

    Best Regards,

    Rena

    Wednesday, April 8, 2020 9:14 AM
  • User991566988 posted

    Thanks.

    I performed your suggestion but it gives me this error:

    with this red color line of code in the error also:

    Stream ms = new MemoryStream(img.Resize(266, 200).ToByteArray());

    Why? and How to solve please?

    Sunday, April 12, 2020 7:56 AM
  • User711641945 posted

    Hi musbah7@hotmail.com,

    The code I provided could work well on my project.Did you change anything?And did you change the code?Besides,what is your version of system.drawing and asp.net core?

    Best Regards,

    Rena

    Friday, April 24, 2020 9:22 AM
  • User991566988 posted

    I'm using core 2.1 and SixLabors.ImageSharp 1.0.0-beta0007 package.

    Thursday, May 14, 2020 7:46 AM