代码之家  ›  专栏  ›  技术社区  ›  Codesleuth

加载、保存然后再次加载图像会引发“gdi+中发生一般性错误”

  •  2
  • Codesleuth  · 技术社区  · 15 年前

    这个 seems to be in infamous error . 我记得有一段时间我得到了不同的代码,但是 它回来了 复仇,但有一些新的代码,我似乎想不出来。
    这绝对是 generic 当然!

    目标

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

    1. 选择图像。
    2. 按保存(关闭窗体),然后将图像保存到 byte[] 进入数据库。
    3. 打开窗体(从 字节[] )
    4. 允许他们再次按“保存”。
    5. 允许他们再次打开表单,显示图像(再次)。

    相当标准的加载/保存场景。

    问题

    加载和保存到SQL Server时,一切正常。我遇到的问题是重复加载和保存 字节[] 即使我使用相同的设置。请看我模拟的代码,以演示问题:

    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;
        }
    }
    

    误差 A generic error occurred in GDI+. 当图像再次保存到 MemoryStream 第二轮。我查过这和 RawFormat 通过检查第一次保存之前和第二次保存之前的值:

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

    这些值是相同的,因此它不可能是丢失 ImageFormat 信息。

    有人能帮忙调试这个问题吗?我使用的代码示例是用jpeg测试的,并且 you can get it here .

    3 回复  |  直到 9 年前
        1
  •  2
  •   Jake Pearson    15 年前

    我最近也遇到了同样的问题。您需要在创建内存流时跳过using语句。创建位图将保留对创建它的流的引用。你可以在上面读到 MSDN .

    private static Bitmap LoadImageFromBytes(byte[] bytes)
    {
        var imageStream = new MemoryStream(bytes))
        var image = (Bitmap)Bitmap.FromStream(imageStream);
        return image;
    }
    
        2
  •  1
  •   bebopPete    13 年前

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

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

        3
  •  0
  •   Samir    9 年前

    看一看: https://support2.microsoft.com/Default.aspx?id=814675 如果流在位图对象的生命周期内被破坏,则无法成功访问基于流的图像。