在绘图时把image保存为PNG格式时出理的gdi+ general error
最近在做图片缩放时遇到的一个问题,当我把缩放之后的图片另存为png格式时,出现gdi+ general error,详细的异常描述如下:
A generic error occurred in GDI+.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.Exception Details: System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI+.
Source Error:
Line 42: catch (Exception ex) |
这个异常什么消息都没提供给我,莫名其妙,ex.InnerException为null,看来MS对我们隐藏了具体的异常。
我的代码:
1 ...........
2 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
3 g.DrawImage(bitmap, 0, 0, originWidth, originHeight);
4
5 try
6 {
7 bitmap.Save(stream, ImageFormat.Png);
8 }
9 catch (Exception ex)
10 {
11 throw ex;
12 }
13 finally
14 {
15 bitmap.Dispose();
16 g.Dispose();
17 originImg.Dispose();
18 }
由于我是在一个handler中直接把输出图片至outputstream(这个是问题产生的根本原因)。题外话:刚开始还以为是bitmap锁住的原因导致不能保存,于是采用一个临时bitmap来过渡一下。看具体代码:
Bitmap tempBitmap = new Bitmap(originImage);
Bitmap bitmap = new Bitmap(tempBitmap );
//释放临时bitmap后,再save
tempBitmap .Dispose();
bitmap.Save(bitmap ,0,0,width,height)
这个方法不起效,我还想到是不是权限的问题,结果也被排除了!
既然不然保存为PNG,不妨试试其它的格式,当然换在Jpeg格式时,发现可以正常输出图片。这肯定有图片跟图片格式有关系了,搜索到一些东西:
Png's are a special case. Their encoder requires a bi-directional stream. The solution is to stream to a memory stream first and write the contents of that memory stream to OutputStream afterwards.
大概意思是对PNG解码器需要一个双向流,解决方法是先把数据写入memeory stream,然后再把memory stream写入至outputstream。
我们知道Response.OutputStream是一个单向流,无法向回读取数据(MS他的CanSeek属性为false),可能是png在解码的时候还需要往回写数据,由于CanSeek属性为false,所有不能往回写数据,导致这个问题吧。
用MemoryStream来中转一下
using (MemoryStream ms =new MemoryStream())
{
bitmap.Save(ms,ImageFormat.Png);
ms.WriteTo(stream);
}
等比缩放代码:
private Size GetNewSize(int originWidth, int originHeight, int toWidth, int toHeight)
{
int w, h;
if ((double)originWidth / (double)toWidth < (double)originHeight / (double)toHeight)
{
h = toHeight;
w = originWidth * toHeight / originHeight;
}
else
{
w = toWidth;
h = originHeight * toWidth / originWidth ;
}
return new Size(w, h);
}
解决问题一定要一步一步来定位问题,然后再去尝试解决!
From: http://repository.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。