SixLabors / ImageSharp

:camera: A modern, cross-platform, 2D Graphics library for .NET
https://sixlabors.com/products/imagesharp/
Other
7.35k stars 850 forks source link

Expose non-nullable configuration to remove AOT limiting null check #2514

Closed JimBobSquarePants closed 11 months ago

JimBobSquarePants commented 1 year ago

Prerequisites

Description

Fixes #2486

As discussed in the linked issue AdvancedImageExtensions.GetConfiguration() causes the AOT compiler to include all image unused formats due to the null check and assignment of Configuration.Default.

Since that null check is unavoidable without an API change, I decided to make it by making IConfigurationProvider public and exposing the property directly.

While developers should be careful to not edit the configuration singleton, I do not consider accessing the configuration an advanced scenario since we already provide means to construct and pass custom configuration to our types.

JimBobSquarePants commented 11 months ago

@MichalStrehovsky I finally bit the bullet and installed the .NET 8 RC so I could use Sizoscope. With these changes and a tweak to the calling code from the sample project in #2486 we achieve much better results.

/// <summary>
/// Saves the given buffer using the filename extension as format.
/// </summary>
/// <param name="filename">The full pathname for the filename being written</param>
/// <param name="buffer">The image data stored as RGB buffer.</param>
/// <param name="width">The image width in pixels.</param>
/// <param name="height">The image height in pixels.</param>
public static void SaveImage(string filename, ReadOnlySpan<byte> buffer, int width, int height)
{
    // Pass custom Configuration to avoid loading all default formats.
    using var image = Image.LoadPixelData<Rgb24>(new(), buffer, width, height);
    using var stream = new FileStream(filename, FileMode.Create);
    var pngEncoder = new PngEncoder()
    {
        ColorType = PngColorType.Rgb
    };

    image.SaveAsPng(stream, pngEncoder);
}
image

We could probably drop the size by another 40-45kb if we refactored the way the quantizer is loaded in the png encoder, for some reason the compiler cannot trim out the construction of that type but that's beyond the scope of this PR.

MichalStrehovsky commented 11 months ago

@MichalStrehovsky I finally bit the bullet and installed the .NET 8 RC so I could use Sizoscope. With these changes and a tweak to the calling code from the sample project in https://github.com/SixLabors/ImageSharp/issues/2486 we achieve much better results.

Nice! How big is the resulting sample project? I'm guessing this is a ~30% size reduction? IIRC this app was about 5 MB before.

JimBobSquarePants commented 11 months ago

Nice! How big is the resulting sample project? I'm guessing this is a ~30% size reduction? IIRC this app was about 5 MB before.

The executable? Less than half if I'm following the Twitter thread correctly.

image
MichalStrehovsky commented 11 months ago

Nice! How big is the resulting sample project? I'm guessing this is a ~30% size reduction? IIRC this app was about 5 MB before.

The executable? Less than half if I'm following the Twitter thread correctly.

image

Better than expected! Looks like C#/.NET matches the Go size now!

JimBobSquarePants commented 11 months ago

Fantastic stuff! I'll be looking at Sizoscope a lot for v4 to see if we can design the library internals to be as trimmable as possible. 😁