Magick.NET
| Language | C# (.NET 10 and .NET Standard 2.0, so also .NET Framework and older .NET) |
|---|---|
| License | Apache-2.0 (ImageMagick license for the native library) |
| Repository | github.com/dlemstra/Magick.NET |
| Documentation | Magick.NET docs |
| Depends on | bundled native ImageMagick with OpenJPEG (Windows, Linux, macOS; x64 and arm64) |
| Read / write | yes / yes; JP2, J2K, J2C, JPC, JPT (decoding through OpenJPEG) |
Magick.NET is the .NET binding of ImageMagick. The NuGet packages contain the native ImageMagick library built with OpenJPEG, so JPEG 2000 works without installing anything else. You get the same image as any other format, as a MagickImage, and can resize, convert color spaces and save to any format ImageMagick supports.
JPEG 2000-specific options are set with Jp2ReadDefines and Jp2WriteDefines. Packages come in quantum depths Q8 and Q16 (bits per channel internally); pick Q16 for 12-bit and 16-bit JPEG 2000 images.
Installation#
Shell
dotnet add package Magick.NET-Q16-AnyCPU
# or Magick.NET-Q8-AnyCPU for 8-bit images and less memory
Basic usage: convert JPEG 2000 to PNG and back#
C#
using ImageMagick;
using var image = new MagickImage("in.jp2");
Console.WriteLine($"{image.Width} x {image.Height}, depth {image.Depth}, {image.ColorSpace}");
image.Write("out.png");
using var png = new MagickImage("out.png");
png.Quality = 40; // lossy; 100 (or unset) = lossless
png.Write("roundtrip.jp2", MagickFormat.Jp2);
Use MagickFormat.J2k to write a raw codestream instead of a JP2 file.
How to decode at reduced resolution#
Discarding resolution levels makes thumbnails of large JPEG 2000 images fast:
C#
using ImageMagick;
using ImageMagick.Formats;
var settings = new MagickReadSettings
{
Defines = new Jp2ReadDefines
{
ReduceFactor = 2, // 1/4 width and height
QualityLayers = 1, // decode only the first quality layer
},
};
using var thumb = new MagickImage("big.jp2", settings);
thumb.Write("thumb.png");
How to write with compression ratios and quality layers#
C#
using ImageMagick;
using ImageMagick.Formats;
using var image = new MagickImage("in.tif");
image.Settings.SetDefines(new Jp2WriteDefines
{
Rate = new float[] { 40, 20, 10 }, // 3 quality layers at 40:1, 20:1, 10:1
NumberResolutions = 6,
ProgressionOrder = Jp2ProgressionOrder.RLCP,
});
image.Write("out.jp2", MagickFormat.Jp2);
How to read image info without decoding#
MagickImageInfo reads only the header:
C#
using ImageMagick;
var info = new MagickImageInfo("in.jp2");
Console.WriteLine($"{info.Format}: {info.Width} x {info.Height}");
Tips#
- Check that your build supports JPEG 2000 with
MagickNET.SupportedFormats.Any(f => f.Format == MagickFormat.Jp2). - Set
MagickNET.SetTempDirectoryand resource limits (ResourceLimits.Memory) when you process very large satellite or scanned images.