用Image.Save配合EncoderParameters控制JPEG质量最直接,需显式获取JPEG编码器、设置Quality参数(0–100,long类型),且EncoderParameters只能含一个EncoderParameter,否则可能静默失败。

用 Image.Save 配合 EncoderParameters 控制 JPEG 压缩质量
直接调用 Image.Save 默认会以最高质量保存 JPEG,但实际压缩必须显式传入编码参数。关键不是“缩放尺寸”,而是设置 JPEG 编码器的 Quality 参数(范围 0–100),值越低体积越小、画质损失越明显。
常见错误是只改了 Bitmap.SetResolution 或单纯调整 Width/Height,这属于缩放而非压缩;或者漏掉 EncoderParameters,导致保存结果和原图一样大。
- 必须通过
ImageCodecInfo.GetImageEncoders()找到 JPEG 编码器,不能硬写 MIME 类型 -
Quality参数类型是long,需封装进EncoderParameter,且EncoderParameter的Guid必须是Encoder.Quality - 保存为
.jpg或.jpeg才生效,.png不支持该参数
var encoder = ImageCodecInfo.GetImageEncoders().First(x => x.MimeType == "image/jpeg"); var ep = new EncoderParameters(1); ep.Param[0] = new EncoderParameter(Encoder.Quality, 75L); // 75 是较稳妥的平衡点 img.Save(outputPath, encoder, ep);
批量处理时别用 Bitmap 构造函数加载大图
用 new Bitmap(path) 加载图片会把整张图解码进内存,一张 5000×4000 的 24 位 BMP 就占约 60MB,批量处理十几张就容易触发 OutOfMemoryException。尤其在 Windows Server 或低内存环境更敏感。
正确做法是用 Image.FromFile(只读头信息)+ 按需创建缩略图,或改用流式加载:
- 对仅需压缩不需编辑的场景,优先用
Image.FromStream(new FileStream(...)),并设FileAccess.Read和FileShare.Read - 若要缩放尺寸,用
Graphics.DrawImage绘制到新Bitmap,比Bitmap.GetThumbnailImage更可控(后者质量差、不支持自定义插值) - 每处理完一张图,立刻调用
img.Dispose()和gc.Collect()(仅限批量密集场景,非必需)
保持画质的关键:避免重复压缩和尺寸误判
JPEG 是有损格式,同一张图连续保存两次(哪怕都是 90 质量),画质也会叠加劣化。批量脚本里最容易犯的错是:先用高质保存一次,再读取它二次压缩——这比直接一步压到目标质量更伤画质。
另一个隐形坑是“保持宽高比”逻辑写错,比如用 (int)(origW * scale) 强转丢精度,导致最终尺寸非预期,引发额外插值模糊。
- 始终从原始文件加载,不要链式处理中间文件
- 缩放计算用
Math.Round而非强制截断,例如:(int)Math.Round(origW * 0.8) - 对文字/线条类图片(如截图、UI 界面),质量建议不低于 85;摄影类可下探到 70–75
命令行批量压缩工具用 System.Drawing.Common 需注意运行时依赖
在 .NET Core 3.0+ 或 .NET 5+ 项目中引用 System.Drawing.Common 后,Windows 上默认可用,但 Linux/macOS 必须安装系统级依赖:libgdiplus(Ubuntu/Debian)或 mono-libgdiplus(CentOS/RHEL)。
没装的话运行时抛 DllNotFoundException: libgdiplus.so,而不是编译报错,容易误判为代码问题。
- Docker 镜像需在
Dockerfile中加RUN apt-get install -y libgdiplus - 若部署环境无法装依赖,改用跨平台库如
SixLabors.ImageSharp(纯 C# 实现,无 native 依赖) -
ImageSharp的压缩接口更简洁:encoder.Quality = 75,但 API 风格不同,迁移需重写图像操作部分
真正难的不是怎么压,是怎么压完还看不出区别——多试两组参数,拿原图和压缩图并排放大看边缘文字和天空渐变,比看文件大小更有说服力。


















