ImageSharp
| Language | C# (.NET 8 or later) |
|---|---|
| License | Six Labors Split License: Apache 2.0 for open source, non-profits and companies with under $1M annual revenue; commercial license otherwise |
| Repository | github.com/SixLabors/ImageSharp |
| Documentation | docs.sixlabors.com |
| Depends on | nothing (pure managed code) |
| Read / write | yes / yes; baseline and progressive, 4:4:4 / 4:2:2 / 4:2:0, grayscale, CMYK and YCCK decoding; Exif, XMP, ICC, IPTC |
ImageSharp decodes and encodes JPEG in managed C# with SIMD (System.Runtime.Intrinsics), so it runs on every platform .NET runs on with no native libraries to deploy. It also reads PNG, GIF, WebP, TIFF, BMP and more, and has a processing pipeline for resizing, cropping and color adjustments.
Its JPEG decoder is slower than libjpeg-turbo but fast enough for web servers. The encoder writes baseline or progressive files with optimized Huffman tables. Metadata (Exif, XMP, ICC, IPTC) is kept when you load and save. License note: the Six Labors Split License isn’t an OSI license for commercial users above the revenue limit.
Installation#
dotnet add package SixLabors.ImageSharp
Basic usage: resize a photo and save as JPEG#
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Processing;
using Image image = Image.Load("in.jpg");
Console.WriteLine($"{image.Width} x {image.Height}");
image.Mutate(x => x
.AutoOrient() // apply the Exif orientation to the pixels
.Resize(1200, 0)); // 0 = keep the aspect ratio
image.SaveAsJpeg("out.jpg", new JpegEncoder { Quality = 85 });
How to get JPEG dimensions without decoding#
Image.Identify reads only the headers:
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Jpeg;
ImageInfo info = Image.Identify("in.jpg");
JpegMetadata jpeg = info.Metadata.GetJpegMetadata();
Console.WriteLine($"{info.Width} x {info.Height}, {jpeg.ColorType}, progressive: {jpeg.Progressive}");
How to read Exif data (camera, date, orientation)#
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
ImageInfo info = Image.Identify("photo.jpg");
ExifProfile? exif = info.Metadata.ExifProfile;
if (exif != null)
{
if (exif.TryGetValue(ExifTag.Model, out IExifValue<string>? model))
Console.WriteLine($"Camera: {model.Value}");
if (exif.TryGetValue(ExifTag.DateTimeOriginal, out IExifValue<string>? taken))
Console.WriteLine($"Taken: {taken.Value}");
if (exif.TryGetValue(ExifTag.Orientation, out IExifValue<ushort>? orientation))
Console.WriteLine($"Orientation: {orientation.Value}");
foreach (IExifValue value in exif.Values) // every tag
Console.WriteLine($"{value.Tag}: {value.GetValue()}");
}
How to write a progressive JPEG with 4:4:4 subsampling#
var encoder = new JpegEncoder
{
Quality = 90,
Progressive = true,
ColorType = JpegColorType.YCbCrRatio444, // no chroma subsampling
};
image.SaveAsJpeg("out.jpg", encoder);
Other values: YCbCrRatio420 (default), YCbCrRatio422, Luminance (grayscale).
How to remove metadata before saving#
image.Metadata.ExifProfile = null;
image.Metadata.XmpProfile = null;
image.Metadata.IptcProfile = null;
// keep image.Metadata.IccProfile unless you know the image is sRGB
image.SaveAsJpeg("clean.jpg");
How to convert PNG with transparency to JPEG#
JPEG has no alpha channel. Fill transparent areas with a background color first, or they turn black:
using Image image = Image.Load("logo.png");
image.Mutate(x => x.BackgroundColor(Color.White));
image.SaveAsJpeg("logo.jpg", new JpegEncoder { Quality = 90 });
Tips#
- Call
AutoOrient()before resizing phone photos; it also resets the Exif orientation tag to 1. - For thumbnails of big photos, set
DecoderOptions.TargetSizeand pass it toImage.Load(options, path): the JPEG decoder then decodes at a reduced scale, which is much faster. - Use
Image.LoadAsync/SaveAsJpegAsyncin ASP.NET to avoid blocking threads.