Skip to content

PNG Encoder produces too huge images and different sizes in Linux and Windows #1027

@odalet

Description

@odalet

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

When saving an image to PNG I end up with a file that is more than 5x larger than what I would obtain by using System.Drawing (or Paint.NET)
Attached are the images I generated using ImageSharp, and the same one opened/saved with Paint.NET.
I've tried to tweak the CompressionLevel and FilterMethod (not so sure what this one is about)
properties of the encoder, but this changes nearly nothing in the output image size:

  • Compression levels of 1 to 5 give me the same size of 310 KB both in my Windows and WSL tests
  • Compression levels of 6 to 9 give me a size of 289 KB when run on Windows but 102 KB in WSL
  • With FilterMethod set to Adaptive, I obtain slightly better results; however, far from my expected 55 KB

I can see there's a related issue (#702); however, regardless of the different output sizes in Linux vs Windows, I still think my issue stands as a bug as I'd very much like to be able to obtain a ~50 KB image instead of 300 KB.

Steps to Reproduce

Here is the code I used to exhibit this behavior:

using System.IO;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;

namespace ImageSharpCompressionTest
{
    internal sealed class Program
    {
        private static void Main(string[] args)
        {
            var encoder = new PngEncoder
            {
                BitDepth = PngBitDepth.Bit8,
                ColorType = PngColorType.RgbWithAlpha
            };

            // encoder.FilterMethod = PngFilterMethod.Adaptive;

            var w = 3500;
            var h = 3500;
            var rgbaBytes = GetImageBytes(w, h);

            var rootdir = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? @"c:\temp\win" : "/mnt/c/temp/lnx/";
            if (!Directory.Exists(rootdir)) Directory.CreateDirectory(rootdir);

            using (var image = Image.LoadPixelData<Rgba32>(rgbaBytes, w, h))
            {
                for (var level = 1; level <= 9; level++)
                {
                    encoder.CompressionLevel = level;

                    var filename = Path.Combine(rootdir, $"compress-{level}.png");
                    using (var stream = File.Create(filename))
                        image.SaveAsPng(stream, encoder);
                }
            }
        }

        private static byte[] GetImageBytes(int width, int height)
        {
            var bytes = new byte[width * height * 4];
            for (var y = 0; y < height; y++)
            {
                for (var x = 0; x < width * 4; x += 4)
                {
                    bytes[4 * y * width + x] = (byte)((x + y) % 256); // R
                    bytes[4 * y * width + x + 1] = 0; // G
                    bytes[4 * y * width + x + 2] = 0; // B
                    bytes[4 * y * width + x + 3] = 255; // A
                }
            }

            return bytes;
        }
    }
}

Attachments:

  • Running in WSL: lnx.zip
  • Running on Windows: win.zip
  • Opened/Saved by Paint.NET: compress-pdn

System Configuration

  • ImageSharp version: 1.0.0-beta0007
  • Other ImageSharp packages and versions: none explicitly added
  • Environments:
    • Windows 10 Pro 1709 (French)
    • Ubuntu 18.04 WSL
  • .NET Framework versions:
    • Windows .NET Core 3.0.100 (but still running a netcoreapp2.2)
    • Linux .NET Core 2.2.204
  • Additional information:

Metadata

Metadata

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions