Repository navigation
Sdcb.SimdCodecs 1.4.0 adds HEIF / HEIC decoding — the format of modern Android and iPhone photos — as a new, separately installed package, Sdcb.SimdCodecs.Heif. It is pure managed (HEVC intra decoding included), SIMD-accelerated, and faster than libheif.
dotnet add package Sdcb.SimdCodecs.HeifPatent notice. HEVC (H.265) is patent-encumbered.
Sdcb.SimdCodecs.Heifis MIT and conveys no patent licence; evaluate your HEVC patent obligations before deploying it.
New: Sdcb.SimdCodecs.Heif
-
Opt-in, not part of the facade package.
Sdcb.SimdCodecsdoes not reference it. Install it and register it once at start-up; from then on every facade entry point handles HEIF like a built-in format:SimdCodecs.Register(HeifImageDecoder.Registration);
Before registration
SimdCodecs.DetectFormatstill reportsImageFormat.Heif, so an application can tell users what it cannot open, whileIsDecodableand theTry*methods return false. -
What it decodes: HEIC still images, including the tiled
gridimages every phone camera writes; HEVC Main, Main 10 and Main Still Picture (4:2:0, 8 and 10-bit); WPP, sign data hiding, transform skip, deblocking, SAO. -
Display-oriented output:
clap(clean aperture),irotandimirare applied; the ICC profile is passed through;nclx/ VUI colour signalling selects the matrix and range. -
Every facade layout, written straight into your buffer:
TryDecodeIntowrites Rgba32, Bgra32, Rgb24, Bgr24 and Gray8 at any stride, one tile at a time, with no full-size intermediate frame. Gray8 is the stored luma. -
Codec API:
HeifDecoder.ReadInfo(container only),Decode(RGBA8),DecodeTo(your buffer). -
Byte-exact: the decoded Y / Cb / Cr planes equal ffmpeg 8.1.2's on every tile of the test images; the Y′CbCr → RGB conversion is defined in-repo and frozen.
-
Two LINQPad samples ship in the package:
decodeandfacade.
Performance
Ryzen 7 5800X, .NET 10, competitors in the same process on the same bytes (full record).
| Sdcb.SimdCodecs.Heif | vs | |
|---|---|---|
| HEVC decoding, one core | 0.68–0.87× the time | libde265 1.1.1 |
| To RGBA, 8 cores (12.6 MP phone photo: 50 ms vs 196 ms) | 0.20–0.32× the time | libheif 1.23.1 |
| To RGBA, 8 cores | 0.09–0.14× the time | Magick.NET 14.13.1 |
| Peak memory, 12.6 MP photo (48 MB of RGBA) | 75 MB | libheif 80 MB, Magick 220 MB |
| Peak memory, 50 MP photo (192 MB of RGBA) | 230 MB | libheif 373 MB, Magick 940 MB |
AVX2 / Vector128 (SSE, AdvSimd) / scalar kernels for the inverse transform, intra prediction, SAO and colour conversion; grid tiles decode in parallel, and an image without tiles decodes its CTB rows as a WPP wavefront with parallel filter passes.
Verification
- Every vector kernel has a scalar twin; all tiers (Vector256, Vector128, scalar; x64 and arm64) produce identical output, and CI runs the HEIF tests on each.
- Fuzz soak: 300 000 mutated files on the default tier plus 30 000 on each forced lower tier, with no failure; malformed data fails with
InvalidDataException(or false fromTry*). - NativeAOT and Mono AOT (browser-wasm) output matches the JIT.
Facade
SimdCodecs.Register(ImageDecoderRegistration)and the publicImageDecoderRegistrationtype (inSdcb.SimdCodecs.Abstractions) let an application enable a codec the facade does not reference. Registration is idempotent and thread-safe; registered codecs are sniffed after the built-in ones.
Known gaps
- 10-bit sources are output as 8-bit samples in 1.x (16-bit output is planned for 2.0).
- Not decoded: alpha auxiliary images (the colour image decodes, opaque), HDR gain maps, depth maps; Exif in HEIF is not read.
- Not supported: image sequences (
.heics) and the HEVC range-extension profiles (Main 10 Intra, Main 12, 4:4:4) — rejected cleanly. - AVIF is not supported.