首页 > 解决方案 > 将 .bmp 作为 .png 保存到 MemoryStream 时出现 ExternalException

问题描述

我正在将一批 .bmp 转换为 .png。这是代码的相关部分:

foreach (string path in files) {
    using (fs = new FileStream(path, FileMode.Open)) bmp = new Bitmap(fs);

    using (ms = new MemoryStream()) {
        bmp.Save(ms, ImageFormat.Png);
        bmp.Dispose();

        png = Image.FromStream(ms);
    }

    png.Save(path);
}

在该行bmp.Save(ms, ImageFormat.Png);引发以下异常:

System.Runtime.InteropServices.ExternalException:“GDI+ 中发生一般错误。”

根据MSDN的说法,这意味着图像要么以错误的格式保存,要么保存在读取它的相同位置。后者并非如此。但是,我看不出我是如何给出错误格式的:在同一个 MSDN 页面上,给出了一个示例,其中 .bmp 以相同的方式转换为 .gif。

这与我保存到 MemoryStream 有关吗?这样做是为了我可以用转换后的文件覆盖原始文件。(请注意,.bmp 后缀是有意保留的。这应该不是问题,因为在保存最终文件之前出现异常。)

标签: c#imagestream

解决方案


在该Bitmap 构造函数的 MSDN 文档中,它说:

您必须在位图的生命周期内保持流打开。

同样的评论可以在 上找到Image.FromStream

因此,您的代码应该仔细处理它用于每个位图/图像的流的范围和生命周期。

结合所有以下代码正确处理这些流:

foreach (string path in files) {
   using (var ms = new MemoryStream()) //keep stream around
   {
        using (var fs = new FileStream(path, FileMode.Open)) // keep file around
        {
            // create and save bitmap to memorystream
            using(var bmp = new Bitmap(fs))
            {
                bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
            }
        }
        // write the PNG back to the same file from the memorystream
        using(var png = Image.FromStream(ms))
        {
            png.Save(path);
        }
    }
}

推荐阅读