跳到正文
>sdcb.ai
1.0 新发布latest v1.0.1 · 2026/10/29MITnet10.0NativeAOT

SimdCodecs

纯托管 C# 的图像编解码:JPEG、PNG、TIFF、WebP、GIF、JPEG 2000、JBIG2,外加 EXIF 与 ICC。没有一个原生 DLL,JPEG 解码却比 libjpeg-turbo 还快。

安装
dotnet add package Sdcb.SimdCodecs
JPEG、PNG、WebP、TIFF、JPEG 2000 与 JBIG2 图片拼图,全部由 Sdcb.SimdCodecs 解码
每一格都由这个库解码:JPEG · PNG · WebP · TIFF · JPEG 2000 · JBIG2
0.82×
libjpeg-turbo 的解码用时(446 张语料,单线程)
0 B
每次 JPEG 解码的托管分配
7 + 2
种图像格式,外加 EXIF 与 ICC
0 个
原生依赖:x64 / ARM64 / NativeAOT / WASM

为什么

.NET 读一张图,不该需要原生库

今天在 .NET 里把一个文件变成像素,大致有三条路:

  • System.Drawing
    GDI+,只能在 Windows 上用
  • SkiaSharp · OpenCvSharp · Magick.NET
    每个平台各带一份原生库,体积大,AOT / WASM 都要另想办法
  • ImageSharp
    纯托管,但 JPEG 解码用时是 libjpeg-turbo 的 1.77 倍

SimdCodecs 是第四条:每个编解码器都用 C# 从规范写起,AVX2 / SSE / AdvSimd 手写内核,标量回退兜底。目标不是“能用”,而是每个编码器和解码器都达到或超过对应的原生参考库。

纯 C# 视觉栈 · 全程零原生依赖

三个库吃同一块像素内存:解码直接写进缓冲区,原地增强,直接识别。以前第一步要借 ImageSharp 或 SkiaSharp,现在这一步也是纯 C# 了。

格式

一个包,七种格式

门面 Sdcb.SimdCodecs 按魔数识别格式并分派;每种格式也是独立的包,有更丰富的 API。标着“浏览器打不开”的,可以去实验台亲眼看看。

JPEG

解码编码

基线 / 渐进、任意子采样、CMYK / YCCK、1/2–1/8 缩放解码、零分配 DecodeTo;编码支持优化 Huffman、渐进、EXIF / XMP

Ultra HDR

解码编码

JPEG 增益图读取、组装与 HDR 重建(Ultra HDR / Adobe)

PNG

解码编码

1–16 位全部位深与调色板、Adam7 隔行、文本块、HDR 信令(cICP / mDCV / cLLI)

TIFF

解码编码

多页;8/16/32 位整数与浮点;条带或瓦片;Deflate、LZW、PackBits、CCITT G3/G4 传真

浏览器打不开 → 在实验台看

WebP

解码编码

有损、无损、Alpha、动画与按时间戳跳转;与 libwebp 逐字节一致

GIF

解码编码

87a / 89a、隔行、透明、全部 disposal;编码静图与动画(精确调色板或 Wu 量化 + 抖动)

JPEG 2000

解码编码

Part 1(T.800),用于 PDF 的 /JPXDecode

浏览器打不开 → 在实验台看

JBIG2

解码编码

T.88,用于 PDF 的 /JBIG2Decode 扫描件

浏览器打不开 → 在实验台看

EXIF

解码编码

从 JPEG、TIFF、PNG 读取;ExifWriter 为 JPEG 编码器生成数据块

ICC

解码编码

解码器返回内嵌色彩配置;自带 sRGB v4;可把配置嵌入现有 JPEG

HEIC

下一站

iPhone 默认拍的就是它,Chrome 和 Firefox 都打不开。正在路上——同样纯 C#、同样零原生依赖。

在 GitHub 上 Star 关注进展 →

上手

解码进你自己的内存,任意布局、任意 stride

Program.cs
using Sdcb.SimdCodecs;
using Sdcb.SimdCodecs.Abstractions;

byte[] file = File.ReadAllBytes("photo.webp");   // JPEG, PNG, TIFF, WebP, GIF, JPEG 2000, JBIG2

// 按魔数识别格式,只读文件头
if (!SimdCodecs.TryReadInfo(file, out ImageInfo info)) throw new InvalidDataException();
Console.WriteLine($"{info.Width}×{info.Height}, {info.BitDepth}-bit, {info.FrameCount} frame(s), {info.Orientation}");

// 解码到你自己的缓冲区(R G B A)
byte[] rgba = new byte[info.Width * info.Height * 4];
SimdCodecs.TryDecodeIntoRgba8(file, rgba);

每个包都带可直接运行的 LINQPad 样例(在 LINQPad 的 NuGet 浏览器里就能看到),覆盖 SkiaSharp、OpenCvSharp、Ultra HDR、多页 TIFF 等。

性能

对手是原生库本身

单线程,AMD Ryzen 7 5800X,.NET 10。用时相对原生库,越短越快。

JPEG 解码到 RGBA · 446 张

libjpeg-turbo 3.2.0 · native1.00×
Sdcb.SimdCodecs0.82×
ImageSharp 3.1.121.77×

每次解码 0 B 托管分配(ImageSharp 约 16 KiB 外加它自己的图像对象)。精度至少与 libjpeg-turbo 默认相当(色度上采样处 RGB PSNR 高约 1 dB),在 AVX2、SSE、AdvSimd、标量与 NativeAOT 上逐位一致。完整报告

WebP 解码到 RGBA · 1920×1080

有损0.88×
有损 + Alpha0.53×
无损0.72×
libwebp 1.6.0 · nativeSdcb.SimdCodecs

输出与 libwebp 逐字节一致。照片类不透明有损文件上两者持平(0.87–1.13×)。完整报告

实验台

同一套 C#,在你的浏览器里

打开实验台

编译成 WebAssembly,图片不离开你的电脑。只做浏览器自己做不到的三件事:

NuGet

13 个包,同一个版本号

依赖关系
Sdcb.SimdCodecs (facade)
 ├─ Abstractions
 ├─ Png ──────────┬─ Color.Icc ─ Abstractions
 │                └─ Abstractions
 ├─ Tiff ─────────┬─ Png
 │                └─ Abstractions
 ├─ Jpeg ─────────── Abstractions
 ├─ Jpeg.GainMap ─┬─ Jpeg
 │                └─ Abstractions
 ├─ Jbig2 ────────── Abstractions
 ├─ Jpeg2000 ─────── Abstractions
 ├─ Webp ─────────── Abstractions
 └─ Gif ──────────── Abstractions

Exif ─ Tiff        Jpeg.IccInjector (no dependencies)

所有包同步发布、版本一致。包之间从不使用彼此的 internal:两个包要共用的代码以源码形式编进各自的程序集。

洁净室

只从规范写,只拿原生库当黑盒

  • 算法只来自 ITU-T / ISO 规范(T.81、T.88、T.800…)、PNG 规范、RFC 6386 / 9649 的正文与表格、论文与 CPU 手册
  • 从不阅读 libjpeg-turbo、libpng、libwebp、ImageSharp 或任何 GPL 代码,每个文件都是一手 MIT
  • 原生库只作为黑盒参照:CI 里逐张对比输出(REQUIRE_ORACLES=1)
  • 对恶意输入加固:JBIG2 段头、EXIF IFD、循环的 TIFF IFD 链

致谢

派生自 SharpAstro/Codecs(Unlicense);JPEG 的标记与熵编码层移植自公有领域的 stb_image。

已知的限制按编解码器逐条列在 docs/known-gaps.md。

MIT 许可,可放心商用。

计算机视觉微信群二维码

C#/.NET 计算机视觉技术交流

扫码加入微信群;二维码每周更新,如已过期,请先加 QQ 群 579060605。