All formats

Magick.NET

LanguageC# (.NET 8+, .NET Standard 2.0, .NET Framework 4.6.2+)
LicenseApache 2.0 (ImageMagick: ImageMagick License, permissive)
Repositorygithub.com/dlemstra/Magick.NET
DocumentationMagick.NET docs and samples
Depends onnative ImageMagick, bundled in the NuGet package (Windows, Linux, macOS; x64 and arm64)
Read / writeyes / yes; baseline, progressive, arithmetic, CMYK, 12-bit; Exif, XMP, IPTC, ICC

Magick.NET puts the whole of ImageMagick, with its own copy of libjpeg-turbo, into a NuGet package. For JPEG it exposes everything libjpeg can do: quality, progressive (interlaced) output, sampling factors, Huffman optimization, custom quantization tables, and a size hint that makes the decoder scale down while loading. It also handles PNG, GIF, WebP, HEIC, TIFF, PDF (with Ghostscript) and 100+ other formats.

The native library makes the package large (about 15-30 MB per platform). Pick the Q8 package for 8-bit images like JPEG: it uses half the memory of Q16.

Installation#

Shell
dotnet add package Magick.NET-Q8-AnyCPU

Basic usage: auto-orient, resize and save as JPEG#

C#
using ImageMagick;

using var image = new MagickImage("in.jpg");
Console.WriteLine($"{image.Width} x {image.Height}");

image.AutoOrient();                          // apply the Exif orientation
image.Resize(new MagickGeometry("1200x>"));  // width 1200, only shrink, keep aspect ratio
image.Quality = 85;
image.Write("out.jpg");

How to get JPEG dimensions without decoding#

C#
var info = new MagickImageInfo("in.jpg");
Console.WriteLine($"{info.Width} x {info.Height}, {info.Format}, quality {info.Quality}");

Quality is ImageMagick’s estimate of the quality the file was saved with, computed from its quantization tables.

How to read Exif data#

C#
using ImageMagick;

using var image = new MagickImage("photo.jpg");
IExifProfile? exif = image.GetExifProfile();
if (exif != null)
{
    Console.WriteLine($"Camera: {exif.GetValue(ExifTag.Model)?.Value}");
    Console.WriteLine($"Taken: {exif.GetValue(ExifTag.DateTimeOriginal)?.Value}");
    foreach (IExifValue value in exif.Values)
        Console.WriteLine($"{value.Tag}: {value.GetValue()}");
}

How to write a progressive JPEG with 4:4:4 sampling#

C#
image.Quality = 90;
image.Settings.Interlace = Interlace.Jpeg;   // progressive
image.Write("out.jpg", new JpegWriteDefines
{
    SamplingFactor = JpegSamplingFactor.Ratio444,
    OptimizeCoding = true,
});

How to make thumbnails of large JPEGs quickly#

The jpeg:size hint lets libjpeg decode at ½, ¼ or 1/8 scale, so a 24-megapixel photo loads in a fraction of the time:

C#
var settings = new MagickReadSettings
{
    Defines = new JpegReadDefines { Size = new MagickGeometry(400, 400) },
};
using var image = new MagickImage("big.jpg", settings);
image.AutoOrient();
image.Thumbnail(200, 200);   // resize and strip metadata
image.Write("thumb.jpg");

How to remove metadata#

C#
image.Strip();   // removes Exif, XMP, IPTC, comments and the ICC profile
image.Write("clean.jpg");

To keep the color profile, remove profiles one by one instead: image.RemoveProfile("exif"), image.RemoveProfile("xmp").

Tips#