从流打开的图像与从文件打开的图像不同

时间:2014-02-28 02:10:25

标签: 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未处理
  HResult = -2147467259消息= GDI +中发生一般错误   Source = System.Drawing ErrorCode = -2147467259

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

1 个答案:

答案 0 :(得分:2)

这是设计,Image.FromStream()的MSDN文章严厉警告这一点。关闭流后,图像将不再可用。并且尝试像你一样保存它很可能,但不能保证,当它试图从封闭流中检索像素数据时抛出异常。

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

您可以通过使用语句在中移动Save()调用来修复您的第一个代码段:

    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参数。