导读:本期聚焦于小伙伴创作的《C#如何转换图片格式?从Bitmap到JPG_PNG_WEBP的完整用法总结》,敬请观看详情。把一张BMP转成JPG看似只要一行Save,实际常遇到透明通道丢失、文件体积暴涨或GDI+报内存不足。底层看,.NET靠System.Drawing的EncoderParameters控制压缩质量与色彩处理,不同格式对应不同GUID编码器。直接Save不加参数时,PNG虽能保透明但体积大,JPG会按默认质量覆盖 alpha 导致黑边。本文整理Bitmap加载、格式枚举映射、带质量参数的JPG导出、PNG与WEBP转换差异,以及用ImageCodecInfo查找可用编码器的实践代码,帮你避开格式互转中的坑。

在C#桌面与后台服务开发中,图片格式转换是高频需求,例如把用户上传的BMP转成体积更小的JPG,或将截图保存为支持透明的PNG。核心类位于System.Drawing命名空间,通过Bitmap和ImageFormat配合编码器完成。理解不同格式的编码器参数,才能避免画质受损或内存异常。

C#如何转换图片格式?从Bitmap到JPG_PNG_WEBP的完整用法总结

一、基础转换:使用Save与ImageFormat

最直观的方式是调用Bitmap的Save方法并指定目标ImageFormat。ImageFormat类提供了静态属性如Jpeg、Png、Bmp、Gif,直接映射系统内置格式。这种方式代码简单,适合对输出质量无精细要求的场景。

下面的示例读取一个BMP文件,将其转换为PNG并保存。注意using语句确保Bitmap资源被释放,否则GDI+对象泄漏会引发后续绘图失败。转换本身不修改原图,而是按目标格式编码新文件。

using System.Drawing;
using System.Drawing.Imaging;

// 加载源图片(BMP格式)
using (Bitmap srcBmp = new Bitmap("source.bmp"))
{
    // 直接以PNG格式保存,保留透明通道
    srcBmp.Save("output.png", ImageFormat.Png);
}

// 转为JPG,使用默认质量
using (Bitmap srcBmp = new Bitmap("source.bmp"))
{
    srcBmp.Save("output.jpg", ImageFormat.Jpeg);
}

这种写法在JPG转换时采用系统默认压缩质量(约70%),若源图含透明度,JPG不支持alpha,区域会被填成黑色。PNG虽无损且支持透明,但体积通常数倍于JPG。因此基础转换只适用于快速导出,生产环境应控制参数。

二、带质量参数的JPG转换

JPG是有损格式,压缩质量直接影响清晰度和文件大小。C#通过ImageCodecInfo定位JPEG编码器,再用EncoderParameters包裹一个EncoderParameter,指定Quality数值(0-100)。该方式能平衡画质与存储。

实践中需先遍历ImageCodecInfo.GetImageEncoders(),匹配MimeType为image/jpeg的编码器。若每次转换都遍历会有微小开销,可缓存编码器实例。以下代码演示如何以85质量保存JPG,并说明参数构造逻辑。

using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;

public static void ConvertToJpgWithQuality(string srcPath, string destPath, long quality)
{
    using (Bitmap bmp = new Bitmap(srcPath))
    {
        ImageCodecInfo jpgEncoder = ImageCodecInfo.GetImageEncoders()
            .First(c => c.MimeType == "image/jpeg");
        EncoderParameters ep = new EncoderParameters(1);
        ep.Param[0] = new EncoderParameter(Encoder.Quality, quality);
        bmp.Save(destPath, jpgEncoder, ep);
    }
}

// 调用:以85质量转换
ConvertToJpgWithQuality("input.bmp", "result.jpg", 85);

质量参数过低(如低于50)会出现明显块状伪影,过高(如100)则文件接近无损、失去压缩意义。一般Web展示用75-85即可。另外,EncoderParameter的Value必须是long类型,传入int会被装箱导致运行时异常,这是常见疏忽。

三、PNG与WEBP等格式的处理差异

PNG属于无损格式,Save时无需质量参数,但可通过EncoderParameters设置压缩级别(Encoder.Compression)。WEBP在旧版.NET Framework中并非原生支持,需借助System.Drawing.Common的扩展或第三方库;.NET Core 3.0后部分平台支持,但仍建议用ImageCodecInfo确认可用性。

下例展示如何检测系统是否支持某格式编码器,避免调用Save时抛出UnsupportedImageFormatException。对于不支持的格式,应提示用户或引入Native库。

using System.Drawing.Imaging;
using System.Linq;

public static bool IsFormatSupported(string mimeType)
{
    return ImageCodecInfo.GetImageEncoders()
        .Any(c => c.MimeType == mimeType);
}

// 检查WEBP
bool webpOk = IsFormatSupported("image/webp");

若环境支持WEBP,其编码器参数可设质量与透明度,体积通常比JPG小30%且支持透明,非常适合前端资源。但在Windows Server无桌面体验包时,System.Drawing常受限,此时应改用ImageSharp等跨平台库,原理类似但API更现代。

四、批量转换与资源释放要点

批量处理图片时,必须对每个Bitmap使用using或显式Dispose,GDI+句柄数量受限,泄漏会触发“内存不足”假异常。建议封装统一转换方法,根据目标后缀选择编码器与参数。

下面的辅助方法通过文件扩展名路由到不同保存逻辑,并统一捕获异常。实际项目中可加入缩放、水印等前置处理,但格式转换应作为最后一步,减少重复编码。

using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;

public static void ConvertByExtension(string src, string dest)
{
    using (Bitmap bmp = new Bitmap(src))
    {
        string ext = Path.GetExtension(dest).ToLower();
        if (ext == ".jpg" || ext == ".jpeg")
        {
            var enc = ImageCodecInfo.GetImageEncoders()
                .First(c => c.MimeType == "image/jpeg");
            var ep = new EncoderParameters(1);
            ep.Param[0] = new EncoderParameter(Encoder.Quality, 80L);
            bmp.Save(dest, enc, ep);
        }
        else if (ext == ".png")
        {
            bmp.Save(dest, ImageFormat.Png);
        }
        else
        {
            bmp.Save(dest, ImageFormat.Bmp);
        }
    }
}

综上,C#转换图片格式并不复杂,关键在选对编码器、设好参数、管好资源。简单场景用ImageFormat直接Save,严谨场景用ImageCodecInfo加EncoderParameters。面对WEBP等新格式,先检测支持度再决定方案,才能写出稳定高效的转换工具。

C#_image_convertSystem_DrawingImageFormat修改时间:2026-08-01 23:39:48

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。