我正在为各种文档类型构建类库。其中一种类型是图像,它包含我们处理图像的自定义业务逻辑,包括转换为PDF。我遇到了许多文章中描述的问题,例如在这里和这里,System.Drawing.Image.Save
构造函数抛出了一个System.Runtime.InteropServices.ExternalException
异常,并带有"GDI+中发生了一个通用错误"。
我看到的答案是,输入流需要在Image
的整个生命周期中保持打开。我明白了。我遇到的问题是,我的类库不能控制输入流,甚至不能控制是否使用输入流,因为我有两个构造函数。这里有一些代码:
public sealed class MyImage
{
private System.Drawing.Image _wrappedImage;
public MyImage(System.IO.Stream input)
{
_wrappedImage = System.Drawing.Image.FromStream(input);
}
public MyImage(System.Drawing.Image input)
{
_wrappedImage = input;
}
public MyPdf ConvertToPdf()
{
//no 'using' block because ms needs to be kept open due
// to third-party PDF conversion technology.
var ms = new System.IO.MemoryStream();
//System.Runtime.InteropServices.ExternalException occurs here:
//"A generic error occurred in GDI+"
_wrappedImage.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
return MyPdf.CreateFromImage(ms);
}
}
public sealed class MyPdf
{
internal static MyPdf CreateFromImage(System.IO.Stream input)
{
//implementation details not important.
return null;
}
}
我的问题是:我是否应该保留输入流的副本,以避免客户端在保存我的图像之前关闭流?也就是说,我可以把这个添加到我的类中:
private System.IO.Stream _streamCopy = new System.IO.MemoryStream();
并将构造函数更改为:
public MyImage(System.IO.Stream input)
{
input.CopyTo(_streamCopy);
_wrappedImage = System.Drawing.Image.FromStream(_streamCopy);
}
这当然会增加复制流的开销,这并不理想。有更好的方法吗?
您可以创建另一个Bitmap
实例:
public MyImage(System.IO.Stream input)
{
var image = System.Drawing.Image.FromStream(input);
_wrappedImage = new System.Drawing.Bitmap(image);
// input stream may now be closed
}