dlemstra / Magick.NET

The .NET library for ImageMagick
Apache License 2.0
3.46k stars 416 forks source link

Since Magick.NET 13.6.0, images resized are much heavier #1620

Closed tranchantl closed 6 months ago

tranchantl commented 6 months ago

Magick.NET version

Magick.NET 13.6.0

Environment (Operating system, version and so on)

.Net Core 6

Description

We were using a previous version of Magick.NET (12.2.2). We decided to upgrade it due to vulnerability issues. We use Magick.NET to resize image to upload it on a storage account on different format and size (small, medium, ...). Recently, we decided to add an additional size between small and medium. When we resized the images with Magick.NET, the size of the medium-small (400 x 400) was about twice bigger than the medium (800 x 800). After some investigations, it appears that same code with Magick.NET 13.5 is working correctly but not Magick.NET 13.6 or 13.7, so it looks like this version has a braking change on resize and I didn't find anything on the documentation. Did I miss something, maybe on settings?

Steps to Reproduce

  1. Resize an image (4OOx4OO) using Magick.NET 13.5
  2. Resize an image (4OOx4OO) using Magick.NET 13.6 or 13.7
  3. Compare the size of both images
dlemstra commented 6 months ago

I don't have enough information to reproduce your issue. And I suspect by heavier you mean that the file size is larger? Can you provide a sample image and tell me the output format you are using?

tranchantl commented 6 months ago

Thanks for your response and sorry for the missing information.

And I suspect by heavier you mean that the file size is larger?

Yes, the size is about 2 or 3x larger with version 13.6 or 13.7 in comparison with version 13.5.

When the user is uploading an image, I save it in different format. Original image is mainly PNG and I save it in Webp with different size (200, 450, 800, ...). To do so, I use the resize method of Magick with the target size.

public void Resize(Stream input, short width, short height, Stream output)
{
  _magickImage = new MagickImage();
  _magickImage.Quality = 100;
  _magickImage.Read(input);
  var small = _magickImage.Clone();
  small.Format = MagickFormat.WebP;
  small.Resize(width, height);
  small.Write(output);
}

Here are some images I tested with, the original one and the result of the resize for the size 450 x 462. Between these two results I only changed the version of Magick from 13.5 to 13.7 (same result as 13.6). The two images have the same dimensions but with version 13.7 its 45KB and 15KB with version 13.5.

images.zip (I cannot upload Webp)

We had the same issue when we tested from Webp to Webp, so it looks like it's not due to the format.

I really need images to be as small as possible. It's not a big issue for now as it's working well with version 13.5, but in the future if we need to upgrade the version, it could be problematic.

dlemstra commented 6 months ago

Are you sure this is not caused by a change in your software? I cannot reproduce your issue with version 13.5. The only way to get that smaller image is by removing _magickImage.Quality = 100.

tranchantl commented 6 months ago

Sorry if it was not clear enough. I have no issue with version 13.5, I got my images with a small size. But when I use the version 13.6 or 13.7, the size of resized Webp is bigger. During my test, I resized the image with the version 13.5 and without any change, I did the same with the version 13.6. I just changed the version of Magick so it looks like it's not due to a change in my software.

dlemstra commented 6 months ago

With your code example and input image using version 13.5 I am not getting an image with the same size. The image I am getting is 47KB. I can only get it to 15KB when I remove _magickImage.Quality = 100;.

tranchantl commented 6 months ago

I used the following code to test both 13.5 and 13.6 version :

var _magickImage = new MagickImage();
_magickImage.Read(baseImage.FileStream);

var mediumSmall = _magickImage.Clone();
mediumSmall.Format = MagickFormat.WebP;
mediumSmall.Resize(MediumSmallSize, 0);
mediumSmall.Write(stream);

var streamQuality = new MemoryStream();
var _magickImageQuality = new MagickImage();
_magickImageQuality.Quality = 100;
_magickImageQuality.Read(baseImage.FileStream);

var mediumSmallQuality = _magickImageQuality.Clone();
mediumSmallQuality.Format = MagickFormat.WebP;
mediumSmallQuality.Resize(MediumSmallSize, 0);
mediumSmallQuality.Write(streamQuality);

Directory.CreateDirectory(Path.GetDirectoryName($"{Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)}/pictures/{guid}/"));

using (var fileStream = File.Create($"{Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)}/pictures/{guid}/medium.webp"))
{
    stream.Position = 0;
    stream.CopyTo(fileStream);
}

using (var fileStream = File.Create($"{Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)}/pictures/{guid}/medium-quality.webp"))
{
    streamQuality.Position = 0;
    streamQuality.CopyTo(fileStream);
}

In the end, I have the solution of my issue, I'll remove the quality setup in new versions. But I'm wondering why I've never had this issue before the version 13.6.

After downgrading from 13.6 to 13.5 I had to rebuild my project as it looks like, VS kept 13.6 in kind of cache.

Here are the results: images.zip

dlemstra commented 6 months ago

I really don't know what environment you are using to test this but I cannot reproduce the situation you claim to have with version 13.5. Your code also doesn't work so it makes me feel like you are using different code to test this.

With this code:

var _magickImage = new MagickImage();
_magickImage.Read(inputFile);

var stream = new MemoryStream();
var mediumSmall = _magickImage.Clone();
mediumSmall.Format = MagickFormat.WebP;
mediumSmall.Resize(400, 0);
mediumSmall.Write(stream);

var streamQuality = new MemoryStream();
var _magickImageQuality = new MagickImage();
_magickImageQuality.Quality = 100;
_magickImageQuality.Read(inputFile);

var mediumSmallQuality = _magickImageQuality.Clone();
mediumSmallQuality.Format = MagickFormat.WebP;
mediumSmallQuality.Resize(400, 0);
mediumSmallQuality.Write(streamQuality);

Console.WriteLine(MagickNET.Version);
Console.WriteLine(MagickNET.ImageMagickVersion);

using (var fileStream = File.Create(outputFile1))
{
    stream.Position = 0;
    stream.CopyTo(fileStream);

    Console.WriteLine(fileStream.Length);
}

using (var fileStream = File.Create(outputFile2))
{
    streamQuality.Position = 0;
    streamQuality.CopyTo(fileStream);

    Console.WriteLine(fileStream.Length);
}

I get the following output

Magick.NET Q8 x64 netstandard21 13.5.0
ImageMagick 7.1.1-22 Q8 x64 f3bacd19f:20231203 https://imagemagick.org
13144
38438

Please create a sample project on GitHub that demonstrates this issue. Even with the old version 12.2.2 that you were using I am getting a difference file size:

Magick.NET Q8 x64 netstandard21 12.2.2
ImageMagick 7.1.0-54 Q8 x64 f5cf5baad:20221210 https://imagemagick.org
13144
38438
tranchantl commented 6 months ago

The sample project: https://github.com/tranchantl/TestMagick

I use these two packages:

As I was telling you, I just have to remove the magickImage.quality line to work with all versions. I still have the strange behavior with version <= 13.5 that the magickImage.quality line does not change anything.

As I will use newer versions, it's not a real issue for me, so I'll close this issue.

Thanks for your time.

dlemstra commented 6 months ago

It looks like Visual Studio was doing some caching because I am now getting a different file size. I suspect a bug was fixed that made .Quality=100 work. It probably did not work in previous versions.