Image.Save(..) throws a GDI+ exception because the memory stream is closed

我有一些二进制数据,我想保存为一个图像。当我尝试保存图像时,如果用于创建图像的内存流在保存之前关闭,它会抛出一个异常。我这样做的原因是因为我是动态创建图像等。.我需要一个记忆流。

this is the code:

[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.
}

是否有任何人有任何建议,如何可以保存一个图像与流关闭?我不能指望开发人员记得在保存图像后关闭流。事实上,开发人员并不知道这个映像是使用内存流生成的(因为它发生在其他一些代码中,在其他地方)。

我真的很困惑:

110170 次浏览

因为它是一个记忆流,所以你真的不能用 需要来关闭流——如果你不这样做,不会发生任何不好的事情,尽管很明显,处理任何一次性的东西都是一个很好的实践。(详情请参阅 这个问题。)

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

您必须保持流的开放,以便 位图的生存期。

I can't find any docs promising to close the stream when you dispose the bitmap, but you should be able to verify that fairly easily.

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

绘制图像时: 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");
}

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

在 GDI + 中发生了一个通用错误。 也可能是由 保存路径不正确造成的! 我花了半天才注意到。 因此,请确保您已经双重检查了路径,以保存图像以及。

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

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

在 GDI + 中发生了一个通用错误。由于图像存储路径的问题,我得到了这个错误,因为我的存储路径太长,我修正了这个问题,首先存储图像在最短的路径,并移动到正确的位置与长路径处理技术。

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

我也有同样的问题,但实际上原因是应用程序没有权限保存 C 上的文件。当我换到 D 的时候。."照片保存完毕。

This error occurred to me when I was trying from Citrix. The image folder was set to C:\ in the server, for which I do not have privilege. Once the image folder was moved to a shared drive, the error was gone.

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

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

C:\Program Files (x86)\some_directory

而且 .exe没有以管理员的身份运行,我希望这能帮助有同样问题的人。

对我来说,下面的代码崩溃与 A generic error occurred in GDI+的行,保存到一个 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);
}
}
}
}

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

Setting an Image element's Source to the bitmap prevents file saving. 即使设置 Source = null 似乎也不会释放该文件。

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

剪辑

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

而不是

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

Use:

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 图像缓存

试试这个代码:

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

我使用图像处理器来调整图像的大小,有一天我得到了“一个通用错误发生在 GDI +”异常。

抬头看了一会儿,我尝试了 回收应用程序池和宾果它的工作。所以我在这里注意到它,希望它能有所帮助;)

干杯

我今天在一台服务器上得到了这个错误,当时同样的代码在本地和我们的 DEV 服务器上工作得很好,但是在 PRODUCTION 上没有。重新启动服务器解决了这个问题。

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