Skip to content

jpg.decodedBlock should it release memory after usage? #224

@mhamri

Description

@mhamri

Prerequisites

  • I have written a descriptive issue title
  • I have verified that I am running the latest version of ImageSharp
  • I have verified if the problem exist in both DEBUG and RELEASE mode
  • I have searched open and closed issues to ensure it has not already been reported

Description

I was using imagesharp 1 alpha 4 48 previousely and my app for a normal task took up to 4gb, today I updated to latest version and saw it decreased to 3gb. thanks for the improvement.

I just ran a profiler and saw that the type of decoded block and color block from static type changed to normal property so I got some concern if i'm doing something wrong. I assume that it should release the resources when I call the dispose method or it reach end of the using statement.

I checked almost all of my code, i have using and dispose for every usage. also the class that wrapp the imagesharp is implementing IDisposable.

2017-05-24 18_49_26-pbww imageserver running - microsoft visual studio

Steps to Reproduce

i'm using imagesharp with DI in startup.cs, configServices method:

services.AddTransient<ImageSharpHelper>();

and the imageSharpHelper is like bellow:

using ImageSharp;
using ImageSharp.Formats;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;

namespace namespace1.namespace2.Image
{
    public class ImageSharpHelper : IDisposable
    {
        private readonly ILogger<ImageSharpHelper> _logger;

        public ImageSharpHelper(ILogger<ImageSharpHelper> logger)
        {
            _logger = logger;
        }

        public Image<Rgba32> Client { get; set; }
        public int? CompressRate { get; set; }
        public string Mime { get; set; }
        public ImageOutPutTypes OutPutTypes { get; set; }
        public int? QualityRate { get; set; }

        private Dictionary<ImageOutPutTypes, Func<MemoryStream, string>> SaveImageMapper => new Dictionary<ImageOutPutTypes, Func<MemoryStream, string>>()
        {
            [ImageOutPutTypes.Bmp] = SaveAsBmp,
            [ImageOutPutTypes.Jpg] = SaveAsJpg,
            [ImageOutPutTypes.Png] = SaveAsPng,
            [ImageOutPutTypes.None] = SaveImage
        };

        public void Compress(int compress, int quality)
        {
            CompressRate = compress;
            QualityRate = quality;
        }

        public void Crop(int? x, int? y, int? width, int? height)
        {
            if (x == null || y == null || width == null || height == null)
            {
                throw new NullReferenceException("Crop- Neither Width or height or X or Y can be null");
            }
            _logger.LogDebug($"croping with x:{x} y:{y} width:{width} height:{height}");

            var rectangle = new Rectangle((int)x, (int)y, (int)width, (int)height);
            Client.Crop(rectangle);
        }

        public void Resize(int? width, int? height)
        {
            if (width == null || height == null)
            {
                throw new NullReferenceException("Resize- Neither Width or height can be null");
            }

            _logger.LogDebug($"croping width:{width} - height:{height}");

            Client.Resize((int)width, (int)height);
        }

        public Stream SaveAs()
        {
            var fileStream = new MemoryStream();
            Func<MemoryStream, string> saveOutputMethod;

            if (SaveImageMapper.TryGetValue(OutPutTypes, out saveOutputMethod))
            {
                Mime = saveOutputMethod(fileStream);
            }
            else
            {
                Mime = SaveImage(fileStream);
            }
            return fileStream;
        }

        public void SetImage(Stream file)
        {
            Client?.Dispose();
            Client = ImageSharp.Image.Load<Rgba32>(file);
            Mime = Client.CurrentImageFormat.MimeType;
            OutPutTypes = ImageOutPutTypes.None;
        }
        private string SaveAsBmp(MemoryStream fileStream)
        {
            Client.SaveAsBmp(fileStream);
            return "image/bmp";
        }

        private string SaveAsJpg(MemoryStream fileStream)
        {
            var jpegEncoderOptions = new JpegEncoderOptions()
            {
                IgnoreMetadata = true,
            };

            if (QualityRate != null)
            {
                jpegEncoderOptions.Quality = (int)QualityRate;
            }
            Client.SaveAsJpeg(fileStream, jpegEncoderOptions);
            return "image/jpg";
        }

        private string SaveAsPng(MemoryStream fileStream)
        {
            var pngEncoderOptions = new PngEncoderOptions()
            {
                //Quantizer = new OctreeQuantizer<Color>() {/*Dither = false*/},
                IgnoreMetadata = true
            };

            if (QualityRate != null)
            {
                pngEncoderOptions.Quality = (int)QualityRate;
            }
            if (CompressRate != null)
            {
                pngEncoderOptions.CompressionLevel = (int)CompressRate;
            }
            Client.SaveAsPng(fileStream, pngEncoderOptions);
            return "image/png";
        }

        private string SaveImage(MemoryStream fileStream)
        {
            Client.Save(fileStream);
            return Client.CurrentImageFormat.MimeType;
        }

        public void Dispose()
        {
            Client?.Dispose();
        }
    }
}

and i'm calling the class like bellow:

using (var imageSharpHelper = _serviceProvider.GetService<ImageSharpHelper>())
            {
                imageSharpHelper.SetImage(latestAvailableVersion.Image);
                imageSharpHelper.Resize(x, y);
                return imageSharpHelper.SaveAs();
            }

System Configuration

  • ImageSharp version: 1.0.0-alpha9-00058
  • Other ImageSharp packages and versions:
  • Environment (Operating system, version and so on): windows 10
  • .NET Framework version: asp.net core 1.1.1
  • Additional information:

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions