Sdcb.SimdCodecs.Jpeg2000
1.2.0
Prefix Reserved
dotnet add package Sdcb.SimdCodecs.Jpeg2000 --version 1.2.0
NuGet\Install-Package Sdcb.SimdCodecs.Jpeg2000 -Version 1.2.0
<PackageReference Include="Sdcb.SimdCodecs.Jpeg2000" Version="1.2.0" />
<PackageVersion Include="Sdcb.SimdCodecs.Jpeg2000" Version="1.2.0" />
<PackageReference Include="Sdcb.SimdCodecs.Jpeg2000" />
paket add Sdcb.SimdCodecs.Jpeg2000 --version 1.2.0
#r "nuget: Sdcb.SimdCodecs.Jpeg2000, 1.2.0"
#:package Sdcb.SimdCodecs.Jpeg2000@1.2.0
#addin nuget:?package=Sdcb.SimdCodecs.Jpeg2000&version=1.2.0
#tool nuget:?package=Sdcb.SimdCodecs.Jpeg2000&version=1.2.0
<img src="https://raw.githubusercontent.com/sdcb/SimdCodecs/main/assets/icon.png" width="64" align="right" alt="Sdcb.SimdCodecs icon">
Sdcb.SimdCodecs

English | 简体中文
Pure-managed image codecs for .NET 10: JPEG, PNG, TIFF, WebP, GIF, BMP, ICO / CUR, QOI, Netpbm (PBM / PGM / PPM / PAM / PFM), JPEG 2000 and JBIG2, plus EXIF and ICC. No native dependencies, NativeAOT-compatible, and SIMD-accelerated (AVX2, SSE, AdvSimd) with a scalar fallback. The JPEG decoder is faster than libjpeg-turbo on the benchmark corpus.
<sub>Every tile above was decoded by this library; the files are the LINQPad samples' images (how they were made).</sub>
Quick start
dotnet add package Sdcb.SimdCodecs
using Sdcb.SimdCodecs;
using Sdcb.SimdCodecs.Abstractions;
using Sdcb.SimdCodecs.Jpeg;
byte[] file = File.ReadAllBytes("photo.webp"); // JPEG, PNG, TIFF, WebP, GIF, BMP, ICO, CUR, QOI, Netpbm, JPEG 2000 or JBIG2
// The facade sniffs the format from the magic bytes and decodes into a buffer you own (R G B A).
if (!SimdCodecs.TryReadInfo(file, out ImageInfo info)) throw new InvalidDataException("Not a supported image");
byte[] rgba = new byte[info.Width * info.Height * 4];
SimdCodecs.TryDecodeIntoRgba8(file, rgba);
// Encode it as a JPEG: SIMD, baseline / optimised Huffman / progressive, 4:2:0 or 4:4:4.
byte[] jpeg = JpegEncoder.Encode(rgba, info.Width, info.Height, channels: 4, new JpegEncodeOptions { Quality = 90 });
File.WriteAllBytes("photo.jpg", jpeg);
The rest of the facade:
SimdCodecs.TryDecodeInto(file, buffer, stride, format)— BGRA (Windows / WPF / Skia), RGB, BGR (OpenCV) or grey (OCR) straight into your buffer, at any row stride. JPEG and PNG write these natively, with no RGBA frame in between; a colour JPEG's grey is its Y plane.SimdCodecs.TryDecode(file, out image)— the native layout: channel count (grey JPEG 1, colour JPEG 3), 8/16-bit or float samples, ICC profile.SimdCodecs.TryReadInfo(file, out info)— from the headers alone: format, stored bit depth, EXIF orientation (reported, never applied), frame or page count.SimdCodecs.DetectFormat(file)— also names formats it recognises but does not decode (HEIF, AVIF, JPEG XL, …);SimdCodecs.IsDecodable(format)tells the two apart.SimdCodecs.TryOpenFrames(file, out reader)— every frame, by index, in any layout: animated WebP / GIF frames with durations, multi-page TIFF pages, the images of an icon (any other image is one frame).reader.EnumerateFramesInto(buffer, stride, format)plays them in order through one buffer.
Each format is also its own package with a richer API: scaled JPEG decoding, TIFF segment reads, WebP animation seeking by timestamp, Ultra HDR, and more.
Formats
| Format | Decode | Encode | Highlights |
|---|---|---|---|
| JPEG | ✅ | ✅ | Decodes baseline and progressive DCT JPEG, any subsampling, CMYK / YCCK, scaled 1/2–1/8, zero-allocation DecodeTo; the separate LosslessJpeg.FromMemory API handles SOF3; encodes baseline / optimised Huffman / progressive with EXIF, XMP and ICC |
| Ultra HDR JPEG | ✅ | ✅ | Gain-map read, assemble and HDR reconstruction (Ultra HDR / Adobe) |
| PNG | ✅ | ✅ | All bit depths (1–16, indexed); text chunks; HDR signalling (cICP, mDCV, cLLI) |
| TIFF | ✅ | ✅ | Multi-page; 8/16/32-bit integer and float; strips or tiles; reads Deflate, LZW, PackBits, CCITT G3/G4 and single tiles; writes Deflate |
| WebP | ✅ | — | Lossy, lossless, alpha; animation with seeking; byte-exact with libwebp |
| GIF | ✅ | ✅ | 87a / 89a: interlacing, transparency, every disposal method; animation with seeking; encodes stills and animations (exact palette, or Wu quantization + dithering) |
| BMP | ✅ | ✅ | Every Windows and OS/2 variant: core to V5 headers, 1–32 bits, any channel masks, RLE4 / RLE8 / RLE24, OS/2 Huffman 1D, embedded PNG, ICC; SIMD rows into your buffer with no allocation; encodes palettes (exact or quantized), RLE, 555 / 565, 24 / 32-bit |
| ICO / CUR | ✅ | ✅ | Every image of an icon or cursor, PNG or DIB with its AND mask, hotspots; multi-size encoding |
| QOI | ✅ | ✅ | RGB and RGBA, from the specification; decodes into your buffer with no allocation; encodes to an array or a stream |
| Netpbm | ✅ | ✅ | PBM, PGM, PPM plain and raw at any maximum up to 65535, PAM with 1–4 channels, PFM float; native 8/16-bit or float samples, or any layout into your buffer with no allocation; encodes every variant |
| JPEG 2000 | ✅ | — | Part 1 (T.800), for PDF /JPXDecode |
| JBIG2 | ✅ | — | T.88, for PDF /JBIG2Decode |
| EXIF | ✅ | ✅ | From JPEG, TIFF, PNG and WebP; ExifWriter builds a block for the JPEG encoder |
| ICC profiles | ✅ | ✅ | Decoders return embedded profiles; IccProfiles.Describe names one; bundled sRGB v4 profile; splice a profile into an existing JPEG |
The table describes the individual format packages. The Sdcb.SimdCodecs facade intentionally exposes a narrower dispatch/display contract; for example, the separate LosslessJpeg.FromMemory API supports SOF3 directly, while JpegDecoder and the facade reject it. The other facade-specific limits are listed in docs/known-gaps.md (in Chinese).
Performance
Single-threaded, AMD Ryzen 7 5800X, .NET 10. Time relative to the native library (lower is faster):
| JPEG decode to RGBA, 446 files | Time | Managed allocation per decode |
|---|---|---|
| libjpeg-turbo 3.2.0 (native) | 1.00× | — |
| Sdcb.SimdCodecs | 0.82× | 0 B |
| ImageSharp 3.1.12 | 1.77× | about 16 KiB, plus its own image |
| WebP decode to RGBA, 1920×1080 | lossy | lossy + alpha | lossless |
|---|---|---|---|
| libwebp 1.6.0 (native) | 1.00× | 1.00× | 1.00× |
| Sdcb.SimdCodecs | 0.88× | 0.53× | 0.72× |
| JPEG 2000 decode, 1600×1200 | lossless (5/3) | lossy (9/7, q=40) | PSNR vs native |
|---|---|---|---|
| libopenjp2 2.5.4 (native) | 1.00× (221 ms) | 1.00× (49 ms) | baseline |
| Sdcb.SimdCodecs | 1.96× (433 ms) | 2.03× (99 ms) | Lossless Exact / Lossy 84 dB |
| BMP, 1920×1080, geometric mean | decode (22 layouts) | encode 24/32-bit to a stream (4) |
|---|---|---|
| WIC (Windows' native codec) | 1.00× | 1.00× |
| Sdcb.SimdCodecs | 0.20× | 0.08× from RGBA, 0.05× from BGR(A) |
| ImageSharp 3.1.12 | 1.62× | 0.06× |
BMP decoding writes into your buffer in any layout with no allocation and is pixel-for-pixel identical to WIC (apart from the documented decisions); every RLE, palette and mask layout decodes faster than both WIC and ImageSharp, and 5-6-5 and palette encoding are 2–6× faster than ImageSharp.
| 1920×1080, geometric mean vs. ImageSharp 3.1.12 | decode | encode to a stream |
|---|---|---|
| QOI (RGB, RGBA) | 0.29× | 0.49× |
| Netpbm (P1–P7, 8 and 16-bit, plain) | 0.23× | 0.54× |
QOI and Netpbm decode into your buffer with no allocation; both match ImageMagick exactly, both ways.
The JPEG decoder is also at least as accurate as libjpeg-turbo's default (about 1 dB higher RGB PSNR against an exact reference where chroma is upsampled), and its output is bit-identical on AVX2, SSE, AdvSimd, scalar and NativeAOT. WebP output is byte-identical to libwebp. JPEG 2000 lossless decode is bit-identical to libopenjp2, and lossy decode achieves >84 dB PSNR. Full tables, corpora and methodology: JPEG, WebP, and JPEG 2000, BMP / ICO, QOI / Netpbm (on photo-like opaque lossy files WebP is on par: 0.87–1.13×; JPEG 2000 pure managed single-threaded decode is currently about 2× of libopenjp2).
Packages
All packages ship in lockstep under one version.
<details> <summary>Feature details per package</summary>
- Jpeg — T.81 decoder: baseline, progressive, restart intervals, any subsampling, grey / YCbCr / RGB / CMYK / YCCK, scaled 1/2–1/8 decode, lossless (SOF3). SIMD encoder: baseline, optimised Huffman or progressive; 4:4:4 / 4:2:0 / grey; embeds EXIF (APP1), XMP and an ICC profile (APP2).
- Png — every standard bit depth (including 1/2/4-bit grey and indexed), tEXt / zTXt / iTXt text chunks, PNG-3 cICP / mDCV / cLLI HDR signalling.
- Tiff — multi-page; 8/16/32-bit integer and float; Deflate / LZW (+ PackBits read); strips or tiles; chunky or planar; on-demand single strip or tile reads; reads 1/2/4-bit pages (expanded to 8-bit), CCITT fax (Group 3 1D/2D, Group 4, Modified Huffman) and the floating-point predictor.
- Webp — RFC 6386 / RFC 9649: VP8 lossy, VP8L lossless, ALPH, animation with seek, ICC / EXIF / XMP.
The facade's
TryDecodereturns a still or frame 0 of an animation,TryOpenFramesevery frame;WebpAnimationDecoderadds seeking by timestamp and the frame rectangles. - Gif — GIF89a: global / local colour tables, interlacing, transparency, all disposal methods, NETSCAPE2.0 loop count; composited frames with seek. The decisions the spec leaves open are listed in the package README. Encoder: stills and animations, exact palettes or Wu quantization with optional Floyd–Steinberg dithering, changed-rectangle frames for opaque animations.
- Bmp — the Windows DIB and OS/2 bitmap: core, OS/2 2.x, 40-byte, V2–V5 headers; 1/2/4/8-bit palettes and
16/24/32-bit;
BI_BITFIELDS/BI_ALPHABITFIELDS; RLE4 / RLE8 with deltas, OS/2 RLE24 and Huffman 1D;BI_PNG; top-down rows; V5 ICC; packed DIBs (clipboard, icon images). Decodes into anyImagePixelFormatwithout allocating; checked pixel for pixel against WIC. The decisions the documentation leaves open are listed in the package README. - Ico — icons and cursors over Bmp and Png: every image, the largest and deepest by default, hotspots; encodes multi-size icons and cursors, each image PNG or a 1/4/8/24/32-bit DIB.
- Qoi — the QOI specification: 3- and 4-channel images, the colour space reported (a linear one as a linear
transfer); decodes into any
ImagePixelFormatwithout allocating; encodes from RGBA, BGRA, RGB, BGR or grey. - Pnm — Netpbm: P1–P6 plain and raw at any maximum up to 65535 (16-bit samples above 255), PAM (P7) with 1–4
channels, PFM (
Pf/PF) as float samples; only a file's first image. Encodes every format; plain output keeps lines within 70 characters. The decisions the format pages leave open are listed in the package README. - Exif — reads JPEG, TIFF, PNG and WebP;
ExifWriterbuilds a blob forJpegEncodeOptions.Exif.
</details>
<details> <summary>Dependency graph</summary>
Sdcb.SimdCodecs (facade)
├─ Abstractions
├─ Png ──────────┬─ Color.Icc ─ Abstractions
│ └─ Abstractions
├─ Tiff ─────────┬─ Png
│ └─ Abstractions
├─ Jpeg ─────────── Abstractions
├─ Jpeg.GainMap ─┬─ Jpeg
│ ├─ Color.Icc
│ └─ Abstractions
├─ Jbig2 ────────── Abstractions
├─ Jpeg2000 ─────── Abstractions
├─ Webp ─────────── Abstractions
├─ Gif ──────────── Abstractions
├─ Bmp ──────────┬─ Png
│ └─ Abstractions
├─ Ico ──────────┬─ Bmp
│ ├─ Png
│ └─ Abstractions
├─ Qoi ──────────── Abstractions
└─ Pnm ──────────── Abstractions
Exif ─ Tiff Jpeg.IccInjector (no dependencies)
The MQ arithmetic decoder (JBIG2, JPEG 2000), the T.4 fax code tables (JBIG2, TIFF, BMP), Wu's palette
quantizer (GIF, BMP), the stream and array writers (QOI, Netpbm) and the EXIF orientation reader (JPEG, PNG, WebP) are shared as source (src/Shared),
compiled into each package that uses them: no package uses another's internals.
</details>
LINQPad samples
Each package ships runnable samples in linqpad-samples/, which LINQPad lists in its NuGet browser
(source: src/<package>/linqpad-samples/):
| Package | Samples |
|---|---|
Sdcb.SimdCodecs |
quick-start, all-formats, skiasharp, opencvsharp |
Sdcb.SimdCodecs.Jpeg |
encode (quality, subsampling, progressive, EXIF/XMP), scaled-decode |
Sdcb.SimdCodecs.Jpeg.GainMap |
ultrahdr (write and read an Ultra HDR JPEG) |
Sdcb.SimdCodecs.Png |
read-write |
Sdcb.SimdCodecs.Tiff |
multi-page (incl. CCITT Group 4), float-and-tiles, write |
Sdcb.SimdCodecs.Exif |
read-exif |
Sdcb.SimdCodecs.Webp |
decode, animation |
Sdcb.SimdCodecs.Gif |
decode, encode |
Sdcb.SimdCodecs.Bmp |
bmp (every layout written, read back and compared) |
Sdcb.SimdCodecs.Ico |
icons (a multi-size icon and a cursor, written and read back) |
Sdcb.SimdCodecs.Qoi |
qoi (QOI against PNG on size and speed, decoding into a padded BGRA buffer) |
Sdcb.SimdCodecs.Pnm |
netpbm (P1–P7 plain and raw, a hand-written PPM, 16-bit PGM, PFM) |
They download their images from https://cv-public.sdcb.ai/simdcodecs/samples/v1/; how those were
made and where they come from is in tools/sample-assets.
Build and test
dotnet build SimdCodecs.slnx -c Release
dotnet test SimdCodecs.slnx -c Release
Oracle-backed tests skip when their reference tool is missing; set REQUIRE_ORACLES=1 to make a
missing oracle fail instead (CI does). How to get each oracle is in AGENTS.md, which
also holds the clean-room rules every contribution follows. Benchmarks are built on their own, by
path: see benchmarks/README.md. Releasing: RELEASING.md.
Contact
If the WeChat group is full or the QR code has expired, join the QQ group C#/.NET Computer Vision 579060605.
License
MIT — see LICENSE. Derived from SharpAstro/Codecs (released under the Unlicense).
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Sdcb.SimdCodecs.Abstractions (>= 1.2.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Sdcb.SimdCodecs.Jpeg2000:
| Package | Downloads |
|---|---|
|
Sdcb.SimdCodecs
Image-codec facade over the Sdcb.SimdCodecs family: sniff a byte stream's format by its magic-byte signature and dispatch to the matching decoder (PNG, JPEG, TIFF, JBIG2, JPEG 2000, WebP, GIF, BMP, ICO, CUR, QOI, PBM / PGM / PPM / PAM, PFM), returning a codec-neutral IDecodedImage (fidelity tier: native bit depth + ColorEncoding colour signalling, with a ToFloats() RGBA float32 view) or decoding zero-copy into a caller-provided 8-bit RGBA buffer (display tier, integer-sample formats). AOT-compatible. |
GitHub repositories
This package is not used by any popular GitHub repositories.