117

我有一些二进制数据,我想保存为图像。当我尝试保存图像时,如果用于创建图像的内存流在保存之前已关闭,则会引发异常。我这样做的原因是因为我正在动态创建图像,因此..我需要使用内存流。

这是代码:

[TestMethod]
public void TestMethod1()
{
    // Grab the binary data.
    byte[] data = File.ReadAllBytes("Chick.jpg");

    // Read in the data but do not close, before using the stream.
    Stream originalBinaryDataStream = new MemoryStream(data);
    Bitmap image = new Bitmap(originalBinaryDataStream);
    image.Save(@"c:\test.jpg");
    originalBinaryDataStream.Dispose();

    // Now lets use a nice dispose, etc...
    Bitmap2 image2;
    using (Stream originalBinaryDataStream2 = new MemoryStream(data))
    {
        image2 = new Bitmap(originalBinaryDataStream2);
    }

    image2.Save(@"C:\temp\pewpew.jpg"); // This throws the GDI+ exception.
}

有人对我如何在流关闭的情况下保存图像有任何建议吗?我不能依赖开发人员记住在图像保存后关闭流。事实上,开发人员不知道图像是使用内存流生成的(因为它发生在其他一些代码中,其他地方)。

我真的很困惑:(

4

17 回答 17

184

因为它是一个 MemoryStream,所以你真的不需要关闭流——如果你不这样做,不会发生任何不好的事情,尽管很明显,无论如何处理任何一次性的东西都是很好的做法。(有关更多信息,请参阅此问题。)

但是,您应该处理位图 - 这将为您关闭流。基本上,一旦你给 Bitmap 构造函数一个流,它就“拥有”这个流,你不应该关闭它。正如该构造函数的文档所说:

您必须在位图的生命周期内保持流打开。

我找不到任何承诺在您处理位图时关闭流的文档,但您应该能够相当容易地验证这一点。

于 2008-12-03T07:12:05.967 回答
103

GDI+ 中出现一般错误。 也可能是由于保存路径不正确!我花了半天时间才注意到这一点。因此,请确保您已经仔细检查了保存图像的路径。

于 2012-04-03T21:14:35.657 回答
14

或许值得一提的是,如果 C:\Temp 目录不存在,即使你的流仍然存在,它也会抛出这个异常。

于 2011-10-25T22:06:39.600 回答
4

复制位图。您必须在位图的生命周期内保持流打开。

绘制图像时:System.Runtime.InteropServices.ExternalException:GDI 中发生一般错误

    public static Image ToImage(this byte[] bytes)
    {
        using (var stream = new MemoryStream(bytes))
        using (var image = Image.FromStream(stream, false, true))
        {
            return new Bitmap(image);
        }
    }

    [Test]
    public void ShouldCreateImageThatCanBeSavedWithoutOpenStream()
    {
        var imageBytes = File.ReadAllBytes("bitmap.bmp");

        var image = imageBytes.ToImage();

        image.Save("output.bmp");
    }
于 2010-03-31T18:55:04.353 回答
4

我遇到了同样的问题,但实际上原因是应用程序没有在 C 上保存文件的权限。当我更改为“D:\..”时,图片已保存。

于 2014-03-11T21:24:23.017 回答
3

您可以尝试创建另一个位图副本:

using (var memoryStream = new MemoryStream())
{
    // write to memory stream here

    memoryStream.Position = 0;
    using (var bitmap = new Bitmap(memoryStream))
    {
        var bitmap2 = new Bitmap(bitmap);
        return bitmap2;
    }
}
于 2013-11-19T10:59:40.553 回答
2

当我从 Citrix 尝试时,我发生了这个错误。图像文件夹在服务器中设置为 C:\,我没有权限。将图像文件夹移动到共享驱动器后,错误就消失了。

于 2015-01-15T19:40:09.600 回答
1

GDI+ 中出现一般错误。它可能是由于图像存储路径问题而发生的,我收到此错误是因为我的存储路径太长,我通过首先将图像存储在最短路径中并使用长路径处理技术将其移动到正确位置来解决此问题。

于 2014-02-07T08:07:01.273 回答
1

我收到了这个错误,因为我正在执行的自动化测试试图将快照存储到一个不存在的文件夹中。创建文件夹后,错误解决

于 2017-02-07T15:16:05.937 回答
0

一个奇怪的解决方案使我的代码工作。在paint中打开图像并将其另存为具有相同格式(.jpg)的新文件。现在尝试使用这个新文件,它可以工作。它清楚地向您解释了该文件可能以某种方式损坏。仅当您的代码已修复所有其他错误时,这才有帮助

于 2014-02-19T10:33:17.113 回答
0

当我尝试将图像保存到路径中时,它也出现在我身边

C:\Program Files (x86)\some_directory

并且.exe没有以管理员身份运行,我希望这也可以帮助遇到同样问题的人。

于 2017-03-27T15:31:29.223 回答
0

A generic error occurred in GDI+对我来说,下面的代码在Saves to a 的行上崩溃了MemoryStream。该代码在 Web 服务器上运行,我通过停止和启动运行该站点的应用程序池来解决它。

一定是 GDI+ 中的一些内部错误

    private static string GetThumbnailImageAsBase64String(string path)
    {
        if (path == null || !File.Exists(path))
        {
            var log = ContainerResolver.Container.GetInstance<ILog>();
            log.Info($"No file was found at path: {path}");
            return null;
        }

        var width = LibraryItemFileSettings.Instance.ThumbnailImageWidth;

        using (var image = Image.FromFile(path))
        {
            using (var thumbnail = image.GetThumbnailImage(width, width * image.Height / image.Width, null, IntPtr.Zero))
            {
                using (var memoryStream = new MemoryStream())
                {
                    thumbnail.Save(memoryStream, ImageFormat.Png); // <= crash here 
                    var bytes = new byte[memoryStream.Length];
                    memoryStream.Position = 0;
                    memoryStream.Read(bytes, 0, bytes.Length);
                    return Convert.ToBase64String(bytes, 0, bytes.Length);
                }
            }
        }
    }
于 2017-12-22T12:27:35.587 回答
0

当我在 WPF 应用程序中尝试简单的图像编辑时遇到了这个错误。

将 Image 元素的 Source 设置为位图可防止文件保存。即使设置 Source=null 似乎也不会释放文件。

现在我只是从不使用图像作为图像元素的来源,所以我可以在编辑后覆盖!

编辑

在听说 CacheOption 属性(感谢@Nyerguds)后,我找到了解决方案:因此,我必须在设置后设置 Uri,而不是使用 Bitmap 构造函数CacheOption BitmapCacheOption.OnLoad。(Image1下面是 WpfImage元素)

代替

Image1.Source = new BitmapImage(new Uri(filepath));

采用:

var image = new BitmapImage();
image.BeginInit();
image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = new Uri(filepath);
image.EndInit();
Image1.Source = image;

看到这个:WPF图像缓存

于 2018-03-16T08:25:17.883 回答
0

试试这个代码:

static void Main(string[] args)
{
    byte[] data = null;
    string fullPath = @"c:\testimage.jpg";

    using (MemoryStream ms = new MemoryStream())
    using (Bitmap tmp = (Bitmap)Bitmap.FromFile(fullPath))
    using (Bitmap bm = new Bitmap(tmp))
    {
        bm.SetResolution(96, 96);
        using (EncoderParameters eps = new EncoderParameters(1))
        {   
            eps.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
            bm.Save(ms, GetEncoderInfo("image/jpeg"), eps);
        }

        data = ms.ToArray();
    }

    File.WriteAllBytes(fullPath, data);
}

private static ImageCodecInfo GetEncoderInfo(string mimeType)
{
        ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();

        for (int j = 0; j < encoders.Length; ++j)
        {
            if (String.Equals(encoders[j].MimeType, mimeType, StringComparison.InvariantCultureIgnoreCase))
                return encoders[j];
        }
    return null;
}
于 2018-07-30T16:24:59.830 回答
0

我使用图像处理器调整图像大小,有一天我得到“GDI+ 中发生一般错误”异常。

看了一会儿后,我尝试回收应用程序池并宾果游戏它可以工作。所以我在这里注意到它,希望它有帮助;)

干杯

于 2020-02-12T08:10:15.533 回答
0

我今天在服务器上遇到此错误,当时相同的代码在本地和我们的 DEV 服务器上运行良好,但在 PRODUCTION 上却没有。重新启动服务器解决了它。

于 2020-09-25T05:39:15.043 回答
0
public static byte[] SetImageToByte(Image img)
    {
        ImageConverter converter = new ImageConverter();
        return (byte[])converter.ConvertTo(img, typeof(byte[]));
    }
public static Bitmap SetByteToImage(byte[] blob)
    {
        MemoryStream mStream = new MemoryStream();
        byte[] pData = blob;
        mStream.Write(pData, 0, Convert.ToInt32(pData.Length));
        Bitmap bm = new Bitmap(mStream, false);
        mStream.Dispose();
        return bm;
    }
于 2021-03-22T04:17:19.570 回答