Stop Using System.Drawing: Modern Image Manipulation in .NET
If you've been a .NET developer for a while, you probably have a muscle memory for using System.Drawing whenever you need to resize a profile picture, generate a thumbnail, or stamp a watermark onto an image.
// The old, deprecated way
using System.Drawing;
using var image = Image.FromFile("user.jpg");
// ...
But if you’ve tried to deploy that code to a Linux Docker container recently, you were probably greeted with a nasty PlatformNotSupportedException.
Why Did Microsoft Kill System.Drawing?
System.Drawing was essentially a wrapper around GDI+, a graphics API deeply integrated into the Windows operating system. For years, the Mono project maintained libgdiplus to make it work on Linux and macOS, but it was incredibly buggy, leaked memory, and was a nightmare to maintain.
Microsoft finally pulled the plug. Starting in .NET 6, System.Drawing.Common officially only supports Windows. If you try to use it on Linux, it crashes by design.
So, what do we use now?
The King: SixLabors.ImageSharp
If you need a robust, fully managed, cross-platform image processing library, ImageSharp is the gold standard. It is written completely in C#, requires no native dependencies, and runs perfectly inside Alpine Linux containers, AWS Lambdas, and anywhere else .NET runs.
Need to resize a user-uploaded avatar and save it as a highly-compressed WebP? It’s trivial:
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Formats.Webp;
public async Task ProcessAvatarAsync(Stream inputStream, string outputPath)
{
// Load the image
using var image = await Image.LoadAsync(inputStream);
// Resize, keeping aspect ratio, cropping to a 200x200 square
image.Mutate(x => x.Resize(new ResizeOptions
{
Size = new Size(200, 200),
Mode = ResizeMode.Crop
}));
// Save as WebP with 80% quality
var encoder = new WebpEncoder { Quality = 80 };
await image.SaveAsync(outputPath, encoder);
}
The Catch with ImageSharp: ImageSharp recently changed its licensing. It is dual-licensed: open-source for non-commercial projects, but if you are a commercial entity with over $1M in revenue, you need to purchase a commercial license. For many enterprises, this is perfectly fine, but if you are an indie dev pushing the limit, you need to be aware of it.
The High-Performance Alternative: SkiaSharp
If you are balking at ImageSharp's licensing, or if you need hardware-accelerated 2D graphics rendering (like drawing complex charts or generating PDFs), SkiaSharp is your best bet.
SkiaSharp is a .NET wrapper around Google's Skia Graphics Engine (the same C++ engine that powers Google Chrome and Android).
using SkiaSharp;
public void CreateRedSquare()
{
var info = new SKImageInfo(200, 200);
using var surface = SKSurface.Create(info);
var canvas = surface.Canvas;
canvas.Clear(SKColors.White);
// Draw a red square
using var paint = new SKPaint
{
Color = SKColors.Red,
IsAntialias = true,
Style = SKPaintStyle.Fill
};
canvas.DrawRect(50, 50, 100, 100, paint);
// Encode to PNG
using var image = surface.Snapshot();
using var data = image.Encode(SKEncodedImageFormat.Png, 100);
using var stream = File.OpenWrite("square.png");
data.SaveTo(stream);
}
The Catch with SkiaSharp:
Because it relies on native C++ binaries, you have to ensure the correct native assets are deployed with your app. On Windows, it usually "just works." On Linux Docker containers, you often have to run apt-get install libfontconfig1 in your Dockerfile to ensure Skia can render text properly.
Conclusion
Stop using System.Drawing. If you are building modern cloud-native apps on Linux, it is a dead end.
If you need pure image manipulation (cropping, resizing, converting formats), use ImageSharp (if licensing permits). If you need complex 2D drawing or a fully free alternative, use SkiaSharp. Both are vastly superior to what we had a decade ago.