mono / SkiaSharp

SkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Google's Skia Graphics Library. It provides a comprehensive 2D API that can be used across mobile, server and desktop models to render images.
MIT License
4.55k stars 543 forks source link

[BUG] 3.0.0 regression for PNG compression with SKBitmap.Encode #3013

Closed sungaila closed 1 month ago

sungaila commented 2 months ago

Description

Until 2.88.8 you will have a default PNG level of compression when calling SKBitMap.Encode(Stream, SKEncodedImageFormat.Png, int). Starting with 3.0.0 no compression is applied when calling this method.

This is a regression since the previous behavior is broken (suddenly the encoded images are huge) and there is no way to change the compression level in SKBitmap.Encode.

The PNG compression itself seems to work fine though, if tested with SKPixmap.Encode and SKPngEncoderOptions.Default.

Code

using SkiaSharp;
using System.Reflection;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main()
        {
            Console.WriteLine($"{typeof(SKImageInfo).Assembly.GetName().Name}, {typeof(SKImageInfo).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()!.InformationalVersion}");

            // create empty 1000x1000 bitmap
            using var bitmap = new SKBitmap(1000, 1000);

            // encode bitmap with default settings
            using var outputStream = new MemoryStream();
            bitmap.Encode(outputStream, SKEncodedImageFormat.Png, default);
            Console.WriteLine($"SKBitmap.Encode size: {outputStream.Length}");

            // get the pixmap
            using var pixmap = new SKPixmap(bitmap.Info, bitmap.GetPixels());

            // encode it with default SKPngEncoderOptions (that's ZLibLevel 6)
            using var data = pixmap.Encode(SKPngEncoderOptions.Default)!;

            Console.WriteLine($"SKPixmap.Encode size: {data.Size}");
        }
    }
}

Expected Behavior

Calling SKBitmap.Encode for PNGs should use the default compression as below:

SkiaSharp, 2.88.8.0-7af1d0840a381c0ce7ef2877454a88dbb2949686
SKBitmap.Encode size: 3973
SKPixmap.Encode size: 3973

Actual Behavior

In SkiaSharp 3.0.0 calling SKBitmap.Encode for PNGs will result in no compression. Using SKPixmap.Encode still works though.

SkiaSharp, 3.0.0+release-3.0.0-preview.4.f8d5b07f9aa710407097bd4f9321b2da6e269eb3
SKBitmap.Encode size: 4007500
SKPixmap.Encode size: 3973

Version of SkiaSharp

3.x (Alpha)

Last Known Good Version of SkiaSharp

2.88.2 (Previous)

IDE / Editor

Visual Studio (Windows)

Platform / Operating System

Android, Linux, macOS, Windows

Platform / Operating System Version

This regression was observed on Windows, Linux, macOS and Android.

Devices

No response

Relevant Screenshots

No response

Relevant Log Output

No response

Code of Conduct

mattleibow commented 2 months ago

Thanks for reporting this and also the PR. I am having a look.

I think I made a typo when adding the new APIs and I will check all the other instances as well to make sure the other overloads are not broken.