【问题标题】:GDI+ exception saving a Bitmap to a MemoryStream将位图保存到 MemoryStream 的 GDI+ 异常
【发布时间】:2009-02-06 19:57:08
【问题描述】:

我在 Windows 窗体应用程序中遇到问题,当我保存到 MemoryStream 时,Bitmap.Save 失败。该问题似乎仅在一台机器上间歇性发生(到目前为止),而坏消息是在客户站点上。我无法在机器上调试,但我得到了一个堆栈跟踪,将问题缩小到一行代码。

这是我的代码的精简版:

byte[] ConvertPixelsToBytes()
{
    // imagine a picture class that creates a 24 bbp image, and has
    // a method to get an unmanaged pixel buffer.
    // imagine it also has methods for getting the width,
    // height, pitch 

    // I suppose this line could return a bad address, but 
    // I would have expected that the Bitmap constructor would have 
    // failed if it was
    System.IntPtr pPixels = picture.GetPixelData();

    System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(
            picture.width(),
            picture.height(),
            picture.pitch(),
            System.Drawing.Imaging.PixelFormat.Format24bppRgb,
            pPixels );

    // This line doesn't actually free the memory, but it could be freed in a 
    // background thread
    // (2)
    picture.releasePixelData(pPixels);

    System.IO.MemoryStream memStream = new System.IO.MemoryStream();
    try
    {
        // I don't see how this line could fail, but it does
        // (3)
        bmp.Save(memStream, System.Drawing.Imaging.ImageFormat.Bmp);
        return memStream.ToArray();
    }
   catch(System.Runtime.InteropServices.ExternalException e)
   {
       // e.Message is the very helpful " A generic error occurred in GDI+."
   }
   finally
   {
       memStream.Dispose();
   }
   return new byte[0];
}

知道会发生什么吗?我很确定我的像素缓冲区是正确的,它始终可以在我们的开发/测试机器和其他客户站点上运行。

我对失败的可能原因的看法是

一个。位图构造函数不会复制像素数据,而是保留对它的引用,由于内存被释放,保存失败。我没有找到 MSDN 文档明确这一点,但我假设位图复制像素数据而不是假设它被锁定。

b.像素数据无效,导致 Save 方法失败。我对此表示怀疑,因为我的像素数据是每像素 24 位,所以据我所知它不应该是无效的。

c。 .NET 框架有问题。

如果对其他可能的失败原因有任何想法,我将不胜感激,这样我就可以在我的应用程序中添加额外的检查和日志记录信息,这样我就可以向现场发送一些东西。

【问题讨论】:

  • 有什么特殊的例外吗?或者它是那些“发生了通用 GDI+ 错误”的异常之一?
  • 这是“通用 GDI+”例外之一。

标签: c# .net winforms gdi+


【解决方案1】:

该位图构造函数的 MSDN 文档毫无疑问:

备注 调用者负责分配和释放由scan0参数指定的内存块,但是,在释放相关的Bitmap之前不应释放内存。

【讨论】:

  • 谢谢。这实际上并没有记录在 Visual Studio 2005 的 MSDN 库中(下次我也会查看在线文档)。
  • 我遇到了一个与此非常相似的问题,也使用 bmp.Save(memStream,... etc 虽然文档提到您所说的似乎是真的,但它似乎是指到 bmp 的构造函数中使用的内存流 - 现在这是有道理的,但更难接受的是位图保存到的内存流必须保持最新 - 我一直在写入 png,它只会在生产机器上出错,而​​且问题是间歇性的,只有在应用程序池被回收后才能解决。之前已经工作了 10 年没有问题。但是感谢您提供信息!
【解决方案2】:

你试过搬家吗

   picture.releasePixelData(pPixels);

   finally
   {
       memStream.Dispose();
       picture.releasePixelData(pPixels);
   }

这听起来绝对像是一个线程问题(特别是因为您声明 releasePixelData 可能发生在后台线程上)。线程问题总是只发生在一台机器上,而且总是在客户端机器上(可能是因为他们只有 256Megs 的内存或者一些荒谬的东西,垃圾收集器很早就开始了,或者机器有四核而你的开发机器是双核什么的)。

【讨论】:

    猜你喜欢
    • 2012-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多