Search code examples
c#asp.net-core.net-coreimagesharp

How use ImageSharp(Web) to compress / mutate stream with images(IFormFile)


I am trying to compress image(usually around 5-30) quality / size with ImageSharp.Web() library, and I cant really understand how can I do that or what I am missing here.

  • Can I reuse the same memory stream / IFormFile object to save the mutated image? Or do I need to create a new Image from current image object?
  • To work with a memory Stream do I also need to use specific JpegDecoder() ?
  • Not sure if this line is correct item.SaveAsJpeg(memoryStream);.
  • Maybe someone can help me out with the logic or any tips or tricks would be really helpful. Thanks!

Simple code example:

private byte[] ConvertImageToByteArray(IFormFile inputImage)
{
    byte[] result = null;

    // filestream
    using (var fileStream = inputImage.OpenReadStream()) // IFormFile inputImage

    // memory stream
    using (var memoryStream = new MemoryStream())
    {
        fileStream.CopyTo(memoryStream);
        memoryStream.Position = 0; // The position needs to be reset.

        var before = memoryStream.Length;

        using (var item = Image.Load(memoryStream)) // do I need to use here JpegDecoder?
        {
            var beforeMutations = item.Size();

            // dummy resize options
            int width = 50;
            int height = 100;
            IResampler sampler = KnownResamplers.Lanczos3;
            bool compand = true;
            ResizeMode mode = ResizeMode.Stretch;

            // init resize object
            var resizeOptions = new ResizeOptions
            {
                Size = new Size(width, height),
                Sampler = sampler,
                Compand = compand,
                Mode = mode
            };

            // mutate image
            item.Mutate(x => x
                 .Resize(resizeOptions)
                 .Rotate(35));

            var afterMutations = item.Size();

            // try to save mutated image back to memory stream / overwrite
            // this is not overwriting memory stream
            item.SaveAsJpeg(memoryStream);

            // prepare result to byte[]
            result = memoryStream.ToArray();
        }

        var after = fileStream.Length; // kind of not needed.
        }

Solution

  • I know this post is a bit old, and I'm sure that you have fixed your issue, but hopefully, it'll help some else out in the future.

    Can I reuse the same memory stream / IFormFile object to save the mutated image? Or do I need to create a new Image from current image object?

    You have two streams going on here, you can use one for the image from IFormFile and you can manipulate everything here, and then use your MemoryStream to save to

    To work with a memory Stream do I also need to use specific JpegDecoder()?

    You can save your image to the Memory Stream with .SaveAsJpeg(memoryStream)

    Not sure if this line is correct item.SaveAsJpeg(memoryStream);.

    You are on the right track

    Maybe someone can help me out with the logic or any tips or tricks would be really helpful. Thanks!

    Here is my rewrite based on what you have: Hope this helps. I'm sure there are some things that can be simplified, I tried to keep it close to OPs format

        private byte[] ConvertImageToByteArray(IFormFile inputImage)
        {
            byte[] result = null;
    
            // memory stream
            using (var memoryStream = new MemoryStream())
            // filestream
            using (var image = Image.Load(inputImage.OpenReadStream())) // IFormFile inputImage
            {
                //var before = memoryStream.Length; Removed this, assuming you are using for debugging?
                var beforeMutations = image.Size();
    
                // dummy resize options
                int width = 50;
                int height = 100;
                IResampler sampler = KnownResamplers.Lanczos3;
                bool compand = true;
                ResizeMode mode = ResizeMode.Stretch;
    
                // init resize object
                var resizeOptions = new ResizeOptions
                {
                    Size = new Size(width, height),
                    Sampler = sampler,
                    Compand = compand,
                    Mode = mode
                };
    
                // mutate image
                image.Mutate(x => x
                     .Resize(resizeOptions)
                     .Rotate(35));
    
                var afterMutations = image.Size();
    
                //Encode here for quality
                var encoder = new JpegEncoder()
                {
                    Quality = 30 //Use variable to set between 5-30 based on your requirements
                };
    
                //This saves to the memoryStream with encoder
                image.Save(memoryStream, encoder);
                memoryStream.Position = 0; // The position needs to be reset.
    
                // prepare result to byte[]
                result = memoryStream.ToArray();
    
                var after = memoryStream.Length; // kind of not needed.
            }
        }