c# - 从流中打开的图像与从文件中打开的图像不同

标签 c# gdi+

我有 2 段示例代码,我尝试做同样的事情,将属性项更新回图像并将其保存在不同的文件下。

代码1

        Image image;
        using (FileStream stream = new FileStream(this.fileName, FileMode.Open)) {
            image = Image.FromStream(stream);
            foreach (var property in this.propItems) {
                image.SetPropertyItem(property);
            }
        }

        image.Save(@"D:\Temp\1.jpg");
        image.Dispose();

代码2

        using (Image image = new Bitmap(this.fileName)) {
            foreach (var property in this.propItems) {
                image.SetPropertyItem(property);
            }

            image.Save(@"D:\Temp\1.jpg");
        }

唯一的区别在于我打开文件的方式。如果我运行第一段代码,我会收到异常消息

System.Runtime.InteropServices.ExternalException was unhandled
HResult=-2147467259 Message=A generic error occurred in GDI+.
Source=System.Drawing ErrorCode=-2147467259

我的第二段代码运行良好,我可以获得正确的输出。这里有什么区别?

最佳答案

这是设计使然,MSDN 的 Image.FromStream() 文章对此提出了严厉警告。一旦关闭流,图像就不再可用。尝试像您一样保存它很可能(但不能保证)在尝试从关闭的流中检索像素数据时抛出异常。

Image 类的一个关键属性是它是惰性的,与许多 .NET 类不同,它在必要时不会访问流数据。在实际使用像素数据之前,这是没有必要的,这发生在代码片段中的 Save() 调用中。当它无法再读取时,会出现 Kaboom。

您可以通过将 Save() 调用移至 using 语句内来修复第一个代码片段:

    using (var stream = new FileStream(this.fileName, FileMode.Open)) 
    using (var image = Image.FromStream(stream) {
        foreach (var property in this.propItems) {
            image.SetPropertyItem(property);
        }
        image.Save(@"D:\Temp\1.jpg");
    }

不再使用 FileStream 了。请注意,保存图像的文件不能与从中读取图像的文件相同。有些暗示您试图解决该问题。使用 MemoryStream 是避免文件锁定的常用技术。

另请注意代码中的另一个错误,您使用 .jpg 扩展名保存文件,但它实际上是 PNG。如果您想要 JPEG,则不能省略 ImageFormat 参数。

关于c# - 从流中打开的图像与从文件中打开的图像不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22084813/

相关文章:

c# - 拍摄/选择图片并将其显示在 ImageView 中而不先保存(使用 MvvmCross)

c# - 使用 Visual Studio WPF 编辑器创建不适合 Windows GUI 的 GUI

c# - Nancy 并发请求同步运行

c# - 按 len() 排序,但在 C# 的 linq 中

c++ - 内存中的 GDI+ DC 总是单色

c++ - gdi+ GetWorldTransform() 它在 directx 中的什么位置?

wpf - 将 GDI+ PixelFormat 转换为 WPF PixelFormat

.net - 调整图像大小会在右侧和底部裁剪一个像素

c# - GDI+ 和 WPF 的相对优点

c# - 如何使用 C# 在 IIS 中启用 HTTPS?