![知乎周源微信](https://i-blog.csdnimg.cn/blog_migrate/684d70b4bff5a7f389db8032b8d9d05f.png)
知乎周源微信
I got a nice little Yellow Screen of Death (YSOD) error on some code running under IIS that worked fine when running on the VS Developer Web Server. The error was "A generic error occurred in GDI+" and you know that if an error is generic, it's sure in the heck not specific.
我在IIS下运行的某些代码上出现了一个小小的死亡黄屏(YSOD)错误,该代码在VS Developer Web服务器上运行时效果很好。 错误是“ GDI +中发生了一般性错误”,您知道,如果是一般性错误,则可以肯定地确定该错误。
My little application takes an overhead map that's stored in a local file, does some calculations from user input and draws an X on the map, then returns the resulting dynamically generated image.
我的小应用程序获取一个存储在本地文件中的俯视图,根据用户输入进行一些计算,并在该图上绘制X,然后返回生成的动态生成的图像。
There's basically three ways to do images on the server side. Use Native APIs and Interop, which only works in full trust, use System.Drawing, which "isn't supported" or use WPF on the server side, which also, ahem, isn't officially supported. I'm still trying to figure out why, but just to be clear, I used System.Drawing in extremely high traffic sites with no problems. As long as paid close attention to my unmanaged resources, I have never had a problem. I've heard anecdotally of people having trouble with GDI+ (System.Drawing) and switching over to WPF and having no problem with that. As with all things, test what you're doing. There's even some ASP.NET Controls on CodePlex that might help.
基本上有三种在服务器端进行映像的方法。 使用本机API和Interop(仅在完全信任的情况下才能使用),使用System.Drawing (不支持)或在服务器端使用WPF(这也确实不受官方支持)。 我仍在尝试找出原因,但为了清楚起见,我在流量非常高的站点中使用System.Draw没有问题。 只要密切注意我不受管理的资源,我就不会遇到任何问题。 我听说过有人在使用GDI +(System.Drawing)并切换到WPF时遇到问题,对此没有任何问题。 与所有事物一样,测试您在做什么。 在CodePlex上甚至还有一些ASP.NET控件可能会有所帮助。
Now this post can't answer ALL reasons you're getting "a generic error occurred in GDI+" but it can answer mine. In my particular case (and I think this is the most common mistake) I was saving the composited image as a PNG.
现在,这篇文章无法回答您收到“ GDI +中发生一般错误”的所有原因,但可以回答我的问题。 在我的特殊情况下(我认为这是最常见的错误),我将合成图像另存为PNG。
First, I'll show you a little chunk of a code from 5 years ago that took two images and built a single image from them.
首先,我将向您展示5年前的一小段代码,该代码拍摄了两个图像并从中构建了一个图像。
public class SomeCheckImageHandler : IHttpHandler
{
//some stuff snipped
public SomeCheckImageHandler(){}
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "image/jpg";
//some stuff snipped
GetCheckImageRequest req = new GetCheckImageRequest();
//some stuff snipped, get the params from the QueryString
GetCheckImageResponse res = banking.GetCheckImage(req);
//some stuff snipped
if (res.ImageBack != null)
{
//merge them into one image
using(MemoryStream m = new MemoryStream(res.BackImageBytes))
using(Image backImage = System.Drawing.Image.FromStream(m))
using(MemoryStream m2 = new MemoryStream(res.BrontImageBytes))
using(Image frontImage = System.Drawing.Image.FromStream(m2))
using(Bitmap compositeImage = new Bitmap(frontImage.Width,frontImage.Height+backImage.Height))
using(Graphics compositeGraphics = Graphics.FromImage(compositeImage))
{
compositeGraphics.CompositingMode = CompositingMode.SourceCopy;
compositeGraphics.DrawImageUnscaled(frontImage,0,0);
compositeGraphics.DrawImageUnscaled(backImage,0,frontImage.Height);
compositeImage.Save(context.Response.OutputStream, ImageFormat.Jpeg);
}
}
else //just show the front, we've got no back
{
using(MemoryStream m = new MemoryStream(frontImageBytes))
using(Image image = System.Drawing.Image.FromStream(m))
{
image.Save(context.Response.OutputStream, ImageFormat.Jpeg);
}
}
}
}
This code generated a JPEG. No problems, runs fine even today. Now, the code I was working on created a PNG and when you create a PNG you need a seekable stream. This little sample uses the BaseHttpHandler Phil and I made.
这段代码生成了JPEG。 没问题,即使今天运行良好。 现在,我正在处理的代码创建了一个PNG,当您创建PNG时,您需要一个可搜索的流。 这个小样本使用的是我和BaseHttpHandler Phil。
Note the highlighted lines in this sample. (You'll see the highlights if you view this post on my blog directly, rather than from RSS.)
请注意此示例中突出显示的行。 (如果您直接在我的博客上而不是从RSS上查看此帖子,则会看到亮点。)
The Trick for making PNGs: Without the extra intermediate MemoryStream to save to, you won't be able to make PNGs. You can't image.Save() a PNG directly to Response.OutputStream.
制作PNG的窍门:如果没有多余的中间MemoryStream要保存,您将无法制作PNG。 您不能image.Save()直接将PNG保存到Response.OutputStream。
namespace FooFoo
{
public class MapHandler : BaseHttpHandler
public override void HandleRequest(HttpContext context)
{
string filename = context.Server.MapPath(".") + @"\images\newmap2000.jpg";
using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
using (System.Drawing.Image image = System.Drawing.Image.FromStream(fs))
{
using (Graphics g = Graphics.FromImage(image))
{
BrickFinderDrawing drawer = new BrickFinderDrawing(...somedata...);
drawer.DrawBrick(g);
drawer.DrawName(g);
using (MemoryStream stream = new MemoryStream())
{
image.Save(stream, ImageFormat.Png);
stream.WriteTo(context.Response.OutputStream);
}
}
}
}
}
public override bool RequiresAuthentication
{
get { return false; }
}
public override string ContentMimeType
{
get { return "image/png"; }
}
public override bool ValidateParameters(HttpContext context)
{
return true;
}
}
}
Just a little something I wish I remembered when I hit the YSOD. Sure glad I have a blog to put this kind of stuff on! ;)
我希望我记得《 YSOD》时的一些回忆。 我很高兴我有一个博客可以发布这种内容! ;)
Related Links
相关链接
ASP.NET Futures - Generating Dynamic Images with HttpHandlers gets Easier
Compositing two images into one from the ASP.NET Server Side
What InterpolationMode and CompositingQuality to use when generating thumbnails via System.Drawing
通过System.Drawing生成缩略图时使用什么InterpolationMode和CompositingQuality
Resizing images from the server using WPF/WIC instead of GDI+
Gamma Correction and Color Correction - PNG is still too hard
知乎周源微信