Skip to content

Sdcb.SimdCodecs 1.0.1

Choose a tag to compare

@sdcb sdcb released this 29 Oct 10:49
· 10 commits to main since this release

The first stable release of Sdcb.SimdCodecs: pure-managed image codecs for .NET 10. There are no native dependencies, the libraries are NativeAOT- and browser-wasm-compatible, and the kernels are SIMD-accelerated (AVX2, SSE, AdvSimd, WebAssembly SIMD) with a bit-identical scalar fallback.

dotnet add package Sdcb.SimdCodecs
using Sdcb.SimdCodecs;
using Sdcb.SimdCodecs.Abstractions;

byte[] file = File.ReadAllBytes("photo.webp");   // JPEG, PNG, TIFF, WebP, GIF, JPEG 2000 or JBIG2
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);

Formats

Format Decode Encode Notes
JPEG ✅ ✅ Baseline and progressive, any subsampling, CMYK / YCCK, 1/2–1/8 scaled decode, zero-allocation DecodeTo; the encoder writes baseline, optimised Huffman or progressive streams with EXIF, XMP and ICC
Ultra HDR JPEG ✅ ✅ Gain-map read, assembly and HDR reconstruction
PNG ✅ ✅ Every bit depth, indexed colour, text chunks, HDR signalling (cICP, mDCV, cLLI)
TIFF ✅ ✅ Multi-page; 8/16/32-bit integer and float samples; strips or tiles; reads Deflate, LZW, PackBits and CCITT G3/G4
WebP ✅ — Lossy, lossless, alpha and animation with seeking; output is byte-exact with libwebp
GIF ✅ ✅ Stills and animations, every disposal method; quantising encoder
JPEG 2000 ✅ — Part 1 (T.800), for PDF /JPXDecode
JBIG2 ✅ — T.88, for PDF /JBIG2Decode
EXIF ✅ ✅ Read from JPEG, TIFF, PNG and WebP; ExifWriter builds the block the JPEG encoder embeds
ICC ✅ ✅ Decoders return embedded profiles; IccProfiles.Describe gives a profile's name and TryGetPrimaries its gamut; bundled sRGB v4 profile

The facade

A single Sdcb.SimdCodecs reference brings in the whole family, which ships in lockstep under one version, and exposes these entry points:

  • DetectFormat: identifies a file by its signature. It also recognises formats it does not decode (HEIF, AVIF, JPEG XL, BMP, …), and IsDecodable tells the two kinds apart.
  • TryReadInfo: reads dimensions, channels, bit depth, format, EXIF orientation and frame count from the headers alone.
  • TryDecode: returns the native layout (8/16-bit or float samples) together with the ICC profile and an H.273 colour description.
  • TryDecodeInto: writes RGBA, BGRA, RGB, BGR or grey straight into your buffer, at any row stride.
  • TryOpenFrames: decodes frame by frame, covering animated WebP and GIF frames and multi-page TIFF.
  • PixelConverter.StretchToRgba8: makes float and HDR rasters viewable, with optional sRGB encoding for linear light.

Every Try* call on untrusted input returns false instead of throwing, hanging or allocating without bound.

Performance

Measured single-threaded on an AMD Ryzen 7 5800X with .NET 10. Each time is relative to the native library, so lower is faster:

Time
JPEG decode to RGBA (446 files), vs. libjpeg-turbo 3.2.0 0.82×, with no managed allocation per decode
WebP decode, 1920×1080, vs. libwebp 1.6.0 0.88× lossy, 0.53× lossy + alpha, 0.72× lossless

The JPEG decoder is at least as accurate as libjpeg-turbo's default mode. Its output is bit-identical on AVX2, SSE, AdvSimd, scalar, NativeAOT and Mono AOT; CI checks every one of these paths on each push. The full methodology is in the README.

Packages

Sdcb.SimdCodecs (facade), .Abstractions, .Jpeg, .Jpeg.GainMap, .Jpeg.IccInjector, .Png, .Tiff, .Webp, .Gif, .Jpeg2000, .Jbig2, .Exif, .Color.Icc. All 13 are on NuGet and MIT-licensed.

Known limits, such as APNG frames, BigTIFF and 12-bit JPEG, are listed in docs/known-gaps.md (in Chinese).