jpeg 不支持真正无损压缩,image.save 默认质量约80且不可控;真正无损只能选png或webp(lossless=true),而jpeg调至quality=100仍会进行ycbcr转换和量化等有损操作。

为什么 Image.Save 默认压缩不是“无损”
很多人以为调用 Image.Save 保存为 JPEG 就是“压缩”,其实它默认用的是中等质量(约 80),既非无损,也非可控。JPEG 本身不支持真正无损压缩(那是 PNG 或 WebP 无损模式的领域),所谓“无损压缩 JPEG”在 C# 中实际是指:不引入新失真、保留原始像素级一致 —— 这只有在**不经过 JPEG 编码重采样**的前提下才可能。
常见错误现象:Image.Save("out.jpg", ImageFormat.Jpeg) 后图片变模糊、色块明显、尺寸反而更大;或用不同 .NET 版本保存同一张图,哈希值不一致。
- 真正无损的路径只有两个:
PNG(无压缩或Deflate无损)或WebP(启用Lossless = true) -
JPEG的EncoderParameters只能调质量(0–100),100也不等于无损 —— 它仍会做 YCbCr 转换、量化表应用、DCT 近似 - .NET 6+ 的
System.Drawing.Common在 Linux/macOS 上依赖 libgdiplus,对高质量 JPEG 支持不稳定,容易静默降级到75
用 WebP 实现可配置的无损压缩(.NET 6+)
这是目前最实用的折中方案:体积比 PNG 小 25–30%,解码快,且 C# 原生支持无损编码。关键在正确设置 EncoderValue 和绕过默认的有损 fallback。
使用场景:需要小体积 + 像素完全一致 + 兼容现代浏览器/移动端显示
- 必须引用
System.Drawing.Common并确保运行时有libwebp(Windows 自带;Linux 需apt install libwebp-dev) - 不要用
ImageCodecInfo.GetImageEncoders()查找 WebP 编码器 —— 它在某些 .NET 版本下返回 null,直接 newWebPEncoder更可靠 - 核心参数:
WebPEncoderOptions.Lossless = true,WebPEncoderOptions.Quality = 100(此时 Quality 仅影响压缩速度,不影响像素)
using var img = Image.FromFile("input.png");
using var fs = File.Create("output.webp");
img.Save(fs, new WebPEncoderOptions { Lossless = true }); // 不用设 Quality,100 是默认
PNG 是唯一真正无损的选择,但要注意这三点
如果你必须 100% 保证每个字节和原始一致(比如医学图像、算法输入校验),PNG 是唯一安全选项。但它不是“零成本”——体积、内存、加载行为都有隐性代价。
-
Image.Save(..., ImageFormat.Png)默认用Compression.Level = -1(自动),但实际压缩率取决于底层 zlib 实现,不同平台结果可能不同 - 若原始图是 32 位带 Alpha,保存 PNG 时别漏掉
PixelFormat.Format32bppArgb—— 否则Graphics.FromImage可能触发半透明像素预乘,导致 Alpha 值偏移 - 大图(>4000px)用
System.Drawing保存 PNG 可能 OOM,因为整个图像要载入内存再压缩;此时应切块处理或改用ImageSharp
别碰 System.Drawing 的 EncoderParameters JPEG 质量陷阱
网上大量示例教你怎么传 EncoderParameters 给 Save 来“提高 JPEG 质量”,但这个 API 在 .NET Core/.NET 5+ 中已被标记为 obsolete,且行为不可靠。
错误现象:EncoderParameter 设置 Quality = 100 后,生成的 JPEG 文件大小反而比 80 还小;用 exiftool 查看发现实际 Quantization Table 已被简化。
- 根本原因:
System.Drawing.Common在非 Windows 平台走 libgdiplus → libjpeg-turbo,默认启用TURBOJPEG模式,会忽略部分参数 - 即使 Windows 下,
EncoderParameters对于 Chroma Subsampling(如4:2:0)无法关闭 —— 这本身就是有损环节 - 替代方案:真要 JPEG,用
ImageSharp库,它暴露JpegEncodeOptions.Subsample = JpegSubsample.None,才能逼近视觉无损(但仍非数学无损)
事情说清了就结束:无损是严格概念,JPEG 天然不满足;选 WebP 或 PNG 是务实做法,而试图“调高 JPEG 质量”只是在管理失真程度,不是消除它。











