You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用Bitmap.Save保存位图时触发GDI+一般性错误问题咨询

错误产生原因
  • 核心诱因:Bitmap接收流作为构造参数时,不会将流内的图像数据完整复制到独立内存中,在Bitmap的整个生命周期内,都要求绑定的源流保持可访问状态。你的代码中用using块包裹MemoryStream,在Bitmap创建完成后就立刻释放了内存流,后续调用Save方法时,Bitmap无法读取底层依赖的流数据,就会抛出GDI+一般性错误。
  • 其他可能触发相同错误的场景:程序对目标保存路径无写入权限、目标路径下的同名文件正被其他进程占用。
修复方案

方案1:对齐流与Bitmap的生命周期(推荐)

不要提前释放内存流,将MemoryStream和Bitmap的释放时机延后到保存操作完成之后,代码实现如下:

var picture = _webcamStreaming.LastPngFrame;
string fileName = "screenshot.jpeg";
// 两个资源都在using块内,等保存完成后统一释放
using (var ms = new MemoryStream(picture))
using (var bmp = new Bitmap(ms))
{
    // 如果遇到权限问题,可替换为明确的可写路径,例如:
    // string savePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
    bmp.Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg);
}

方案2:创建独立Bitmap脱离流依赖

如果你需要提前释放内存流,可以基于流加载的临时位图,新建一个独立的位图对象并完成数据拷贝,新的Bitmap不依赖原始流,后续操作不会受流释放影响:

var picture = _webcamStreaming.LastPngFrame;
Bitmap bmp;
using (var ms = new MemoryStream(picture))
using (var tempBmp = new Bitmap(ms))
{
    // 创建同尺寸的独立位图
    bmp = new Bitmap(tempBmp.Width, tempBmp.Height);
    // 将临时位图的内容绘制到新位图上,完成数据全量拷贝
    using (var g = Graphics.FromImage(bmp))
    {
        g.DrawImage(tempBmp, 0, 0, tempBmp.Width, tempBmp.Height);
    }
}
string fileName = "screenshot.jpeg";
bmp.Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg);
bmp.Dispose();

排查提示:如果调整流生命周期后仍报错,优先检查两项配置:

  1. 不要将文件保存到系统权限受限目录(如C盘根目录、Program Files目录),优先选择程序运行目录、用户文档目录等有权限的路径
  2. 检查目标路径下是否存在被其他进程锁定的同名文件,必要时可在保存前做文件存在性校验

内容的提问来源于stack exchange,提问作者nik4298

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 13:03:21