【问题标题】:Loading, saving, and then loading an image again throws "A generic error occurred in GDI+"加载、保存然后再次加载图像会引发“GDI+ 中发生一般错误”
【发布时间】:2011-01-12 16:30:40
【问题描述】:

这个seems to be in infamous error。我记得不久前得到了不同的代码,但它回来了,带着复仇,但有一些我似乎无法弄清楚的新代码。
肯定是generic

目标

我正在尝试构建一个允许用户:

  1. 选择一张图片。
  2. 按保存(关闭表单),并将图像保存到byte[] 到数据库中。
  3. 打开表单(从byte[] 加载图像)。
  4. 让他们再次按保存。
  5. 允许他们再次打开表单,显示图像(再次)。

一个非常标准的加载/保存场景。

问题

在加载和保存到 SQL Server 方面一切正常。我遇到的问题是与byte[] 之间反复加载和保存有关,即使我使用的是相同的设置。看看我为演示问题而模拟的这段代码:

static void Main(string[] args)
{
    // Load the image
    var initialImage = (Bitmap)Bitmap.FromFile(@"D:\picture.jpg");

    // Save to a memory stream and get the bytes
    var initialImageBytes = SaveImageToBytes(initialImage);

    // Load again from this saved image
    Bitmap byteLoadedImage = LoadImageFromBytes(initialImageBytes);

    // Save again to bytes, throws "A generic error occurred in GDI+."
    var secondaryImageBytes = SaveImageToBytes(byteLoadedImage);
}

private static byte[] SaveImageToBytes(Bitmap image)
{
    byte[] imageBytes;
    using (MemoryStream imageStream = new MemoryStream())
    {
        image.Save(imageStream, image.RawFormat);
        // "A generic error occurred in GDI+." thrown when saved second time
        imageBytes = imageStream.ToArray();
    }

    return imageBytes;
}

private static Bitmap LoadImageFromBytes(byte[] bytes)
{
    using (MemoryStream imageStream = new MemoryStream(bytes))
    {
        Bitmap image = (Bitmap)Bitmap.FromStream(imageStream);
        return image;
    }
}

第二次将图像再次保存到MemoryStream 时抛出错误A generic error occurred in GDI+.。我通过检查第一次保存之前和第二次保存之前的值来检查这与RawFormat 无关:

1st Save : {b96b3cae-0728-11d3-9d7b-0000f81ef32e}
2nd Save : {b96b3cae-0728-11d3-9d7b-0000f81ef32e}

值相同,因此丢失ImageFormat 信息不会有问题。

谁能帮助调试这个问题?我使用的代码示例是用 JPEG 和you can get it here 测试的。

【问题讨论】:

    标签: c# image gdi+


    【解决方案1】:

    我最近遇到了同样的问题。您需要跳过围绕创建 MemoryStream 的 using 语句。创建位图会保留对创建它的流的引用。您可以在 MSDN 上阅读。

    private static Bitmap LoadImageFromBytes(byte[] bytes)
    {
        var imageStream = new MemoryStream(bytes))
        var image = (Bitmap)Bitmap.FromStream(imageStream);
        return image;
    }
    

    【讨论】:

    • 哦,我的...谢谢你。我找到了您所指的那一点:您不能破坏流。当向 Bitmap 或 Image 类构造函数提供流时,GDI+ 可能会推迟从流中读取,直到稍后。这意味着在销毁 Bitmap 或 Image 对象之前,不得销毁流。如果您在销毁流后尝试使用 Bitmap 或 Image 对象,您可能会收到一条错误消息。应用程序有责任确保在新图像对象的生命周期内可以使用流。
    • 我需要构建一些聪明的流管理,比您的示例提供的更多。不想让那个流在没有被处理的情况下漂浮!
    【解决方案2】:

    永远不要破坏创建 System.Drawing 对象的底层流。保留所有源流,防止它们超出范围。这包括任何字节数组。如果您无法避免丢失原始流的范围,请考虑使用 System.Array.Copy 制作底层字节数组的干净副本,这些副本以后可用于重新组合您的流,从而重新组合您的图像。

    阅读这篇文章:http://support.microsoft.com/kb/814675 (注意症状和原因段落。忽略解决方法段落,它没用。)

    【讨论】:

      【解决方案3】:

      看看:https://support2.microsoft.com/Default.aspx?id=814675 如果流在 Bitmap 对象的生命周期内被销毁,您将无法成功访问基于流的图像。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-09-26
        • 1970-01-01
        • 2015-07-02
        • 2019-01-02
        • 2010-12-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多