Recently, ImageSharp decided to change their license from Apache to the AGPLv3/Commercial dual license model. The new license will be effective as of release candidate 1, which is expected in Q1 of 2019. In this report we look at the history ImageSharp and reason for the change.

ImageSharp is widely regarded as the most promising graphics library for .NET Core. One of its key benefits is it was actually designed for multi-threaded, server-side environments. To understand why this is important, one has to look at the history of .NET’s System.Drawing.

When .NET was first released, System.Drawing was not envisioned to be the generic graphics API the name suggests. Rather, it is a thin wrapper around GDI+, a Windows OS level library used for displaying images and text on the screen. The GDI+ documentation calls this out explicitly,

GDI+ functions and classes are not supported for use within a Windows service. Attempting to use these functions and classes from a Windows service may produce unexpected problems, such as diminished service performance and run-time exceptions or errors.

Nonetheless, ASP.NET developers needing to generate or manipulate images at runtime needed to use something. And because these warnings were not repeated in the System.Drawing wrapper, developers unwittingly choose this library for the websites.

Fast-forward a decade and a half, and developers start looking to port their code to .NET Core, in part because of the promise of cheaper hosting on Linux machines. But with System.Drawing being ostensibly tied to the Windows OS, and not really appropriate in the first place, an alternative graphics APIs was needed.

ImageSharp Beta 1

After two and a half years of development, Six Labors released the first beta of ImageSharp in September of 2017. This consisted of three libraries:

ImageSharp - Color and image primitives, formats, filters, transforms and other standard algorithms

ImageSharp.Drawing - Image, shape, and line drawing primitives and algorithms

ImageSharp.Web - Extensible middleware for ASP.NET Core projects that allows processing and caching of images

Due to its age and dependency on GDI+, System.Drawing feels more like a C++ API and one specifically designed for .NET. Since ImageSharp isn’t constrained by this, it is able to offer a more modern, LINQ-like syntax. Here is an example of a simple transformation:

using (Image<Rgba32> image = Image.Load("foo.jpg")) { image.Mutate(ctx => ctx .Resize(image.Width / 2, image.Height / 2) .Grayscale()); image.Save("bar.jpg"); // Automatic encoder selected based on extension. }

The first thing you may notice is the using block. In order to reduce memory pressure, some amount of manual memory management is needed. ImageSharp uses ArrayPool<T> to reuse buffers whenever possible. The alternative is to allocate byte arrays in .NET’s Large Object Heap, which is prone to fragmentation and other performance issues.

The next thing to note is the Mutate function, which indicates the operations that succeed it are to be performed on the image itself. If Clone were used instead, the result would be a new image that would likewise need to be placed in an using block.

ImageSharp Beta 4

While beta 3 offered many interesting features, the next really noteworthy release was beta 4 in May of 2018. This was the first time it offered full support for .NET Core 2.1 across all platforms. While still not considered production ready by the Six Labors team, this version has had over 338,000 downloads.

ImageSharp Beta 6

The most recent release, beta 6, focused heavily on performance, both in terms of CPU time and reduced memory utilization. Much of the gains are attributed to the use of the Span<T> class. This is also the last version offered under the Apache license.

New Licensing

The reason for the new licensing scheme is simple: there has been very little support for the project. Though in active development since 2015, as of last week the total contributions are very small relative to the size and complexity of the project. Developer James Jackson-South expresses his frustration with the situation,

We didn't make this decision lightly. In a perfect world we would get corporate sponsorship and continue with the license we have but that simply does not seem to be on the radar. Over the last few years we have been gratefully accepting donations from a generous few totaling up to $3,515.61. I'm sure you would agree that this isn't enough for us to continue to dedicate the time and resources to continue to maintain the library; graphics libraries are a very difficult subject to tackle and require a lot of intensive study to develop and maintain.

Baring sufficient donations or sponsorships, the proposed licensing model will be AGPLv3. When that isn’t appropriate, a commercial license can be obtained. The choices are either an annual subscription, licensed per-developer, or as a perpetual license for unlimited developers. Jackson-South continues,

We will offer free commercial licenses for not-for-profit organizations and cheap licenses for indie developers.

What about forks?

Because beta 6 is offered under the far more liberal Apache license, it is possible for someone to create a fork and continue development under that license. And some developers are planning to do just that.

When asked about it, Jackson-South responded with,

How do I plan on handling Beta6 forks? I find the idea distasteful of course (copying someone’s hard work because for some self entitled reason you don’t them to use their efforts to provide for their families) but there’s nothing I can do to stop them. I’ll be surprised though if they last any time to be honest. In 3+ years we’ve had 66 (I think) contributors; that’s really small considering it’s a well known library with nearly 3K stars. Developing a library of this complexity takes a lot of time, a lot of specific domain knowledge, and a lot of skill. I’ve personally spent 1000s of hours working on the code, burning the candle at both ends, my evenings and weekends dominated all in the while promising my incredibly supportive wife that one day it will be worth it. I’m not all that sure individuals who want to fork it appreciate fully what they are taking on. Beta6 is in great shape but it’s unfinished, we know where the kinks are, others will have to discover them.

Alternatives

The two leading alternatives to ImageSharp are Magick.NET and SkiaSharp.

Magick.NET is a wrapper around ImageMagick. ImageMagick is offered as both a command line tool and a library with bindings offered for most programming languages.

SkiaSharp is a wrapper around Google's Skia Graphics Library. It is noteworthy because Skia “serves as the graphics engine for Google Chrome and Chrome OS, Android, Mozilla Firefox and Firefox OS, and many other products.”