最近在做图片缩放时遇到的一个问题,当我把缩放之后的图片另存为png格式时,出现gdi+ general 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);
}
解决问题一定要一步一步来定位问题,然后再去尝试解决!