经过追查离奇GDI +错误的几天里,我经历了这个小宝石偶然在MSDN :
System.Drawing命名空间中的类不支持Windows或ASP.NET服务中使用。 尝试使用这些类从这些应用程序类型之一中可能会产生意想不到的问题,如降低服务性能和运行时异常。
我不知道“ASP.NET服务”是否意味着在这方面“Web应用程序”,而是“减少服务绩效”肯定似乎涵盖的“发生在GDI +一般性错误”和“内存不足”的错误随机搭配我的应用程序抛出 - 间歇性的,非重复性的错误读取和写入JPEG图像 - 在许多情况下 - 在首位System.Drawing.Imaging实际上创建。
所以-如果GDI +无法读取和写入JPEG在Web应用程序文件的可靠的,我应该怎么使用呢?
我希望用户能够上传图片(JPEG要求,其他格式不错的到了),他们重新取样可靠 ,如果有什么不顺心显示有用的错误消息。 有任何想法吗? 从WPF的System.Media命名空间值得考虑的?
编辑:是的,我知道GDI +作品“大部分时间”。 这还不够好,因为当它失败时,它的方式,是不可能孤立或从正常恢复这样做。 我不感兴趣的GDI +代码,你的作品的例子:我正在寻找替代库,用于图像处理。
Answer 1:
有一位优秀的博客文章,包括有关使用C#代码ImageMagick的图形库,通过互操作过的TOPTEN软件博客 。 这特别与运行于下单的Linux ASP.net后的交易; 然而,C#代码应该是完美的复制粘贴,能,你需要改变的唯一的事情是,如果你引用一个窗口二进制文件(DLL)在Windows下运行的互操作属性。
ImageMagick®是一个软件套件来创建,编辑,撰写,或转换成位图图像。 它可以读取和各种格式的图像写入(超过100),包括DPX,EXR,GIF,JPEG,JPEG-2000,PDF,PhotoCD的,PNG,后记,SVG和TIFF。 使用ImageMagick的调整大小,翻转,镜像,旋转,扭曲,剪切和变换图像,调整图像颜色,应用各种特殊效果,或绘制文本,线,多边形,椭圆形和Bézier曲线。
还有一个ImageMagick的.Net开发项目在CodePlex上,它包装起来为你的一切。 不过,这并不表明积极发展自2009年以来,所以它可能落后于当前ImageMagick库的版本了。 对于一个小的琐碎日常调整大小,我可能会坚持使用互操作。 你只需要仔细看你实现你自己的内存泄漏或未发布的资源(图书馆本身很好的测试,并通过社区审核)。
图书馆是免费和开源。 在Apache 2许可证似乎与个人和商业用途兼容。 请参阅ImageMagick的许可证页 。
该库是完全跨平台并实现未在GDI +中(或下单未实现)许多功能强大的图像处理和转换例程并具有良好的信誉为ASP.net图像处理的替代方案。
更新:看起来像有一个.NET包装的更新版本在这里: http://magick.codeplex.com/
Answer 2:
是的,使用WPF System.Windows.Media
类。 得到充分管理他们不遭受同样的问题,因为GDI的东西。
下面是一些MVC代码,我用它来呈现渐变的摘录,给你一个想法是如何从一个WPF来获得Visual
为PNG:
using System;
using System.IO;
using System.Web.Mvc;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace MyMvcWebApp.Controllers
{
public class ImageGenController : Controller
{
// GET: ~/ImageGen/Gradient?color1=red&color2=pink
[OutputCache(CacheProfile = "Image")]
public ActionResult Gradient(Color color1, Color color2, int width = 1, int height = 30, double angle = 90)
{
var visual = new DrawingVisual();
using (DrawingContext dc = visual.RenderOpen())
{
Brush brush = new LinearGradientBrush(color1, color2, angle);
dc.DrawRectangle(brush, null, new Rect(0, 0, width, height));
}
return new FileStreamResult(renderPng(visual, width, height), "image/png");
}
static Stream renderPng(Visual visual, int width, int height)
{
var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Default);
rtb.Render(visual);
var frame = BitmapFrame.Create(rtb);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(frame);
var stream = new MemoryStream();
encoder.Save(stream);
stream.Position = 0;
return stream;
}
}
}
Answer 3:
你可以找到一个微软员工在这里很好的文章: 使用WPF / WIC,而不是GDI +服务器调整图像大小是建议使用WPF,而不是GDI +。 它更多的是缩略但它的总体相同的问题。
总之,在最后它指出这一点:
我联系了WPF团队对此是否支持一锤定音。 不幸的是,它不是,该文档被相应地更新。 我很抱歉,这个可能造成的混乱。 我们正在寻找办法,使这个故事在未来更可以接受的。
因此,WPF也是Web应用程序不支持的,现在仍然是,我相信:-S
Answer 4:
ImageSharp
ImageSharp是一个开源的跨平台2D图形库。 它是用C#编写的新的.NET标准之上,对任何特定的操作系统的API不存在依赖关系。
这是目前仍然在MyGet预发布版(你必须添加软件包源在VS选项或NuGet.config文件),但我们已经在使用它了一些非常积极的成果。
Answer 5:
大多数的问题,我看了一下涉及到未正确配置资源。
我已经使用这个代码的时间和与Web应用程序没有任何问题一次又一次的变体:
public void GenerateThumbNail(HttpPostedFile fil, string sPhysicalPath,
string sOrgFileName,string sThumbNailFileName,
System.Drawing.Imaging.ImageFormat oFormat, int rez)
{
try
{
System.Drawing.Image oImg = System.Drawing.Image.FromStream(fil.InputStream);
decimal pixtosubstract = 0;
decimal percentage;
//default
Size ThumbNailSizeToUse = new Size();
if (ThumbNailSize.Width < oImg.Size.Width || ThumbNailSize.Height < oImg.Size.Height)
{
if (oImg.Size.Width > oImg.Size.Height)
{
percentage = (((decimal)oImg.Size.Width - (decimal)ThumbNailSize.Width) / (decimal)oImg.Size.Width);
pixtosubstract = percentage * oImg.Size.Height;
ThumbNailSizeToUse.Width = ThumbNailSize.Width;
ThumbNailSizeToUse.Height = oImg.Size.Height - (int)pixtosubstract;
}
else
{
percentage = (((decimal)oImg.Size.Height - (decimal)ThumbNailSize.Height) / (decimal)oImg.Size.Height);
pixtosubstract = percentage * (decimal)oImg.Size.Width;
ThumbNailSizeToUse.Height = ThumbNailSize.Height;
ThumbNailSizeToUse.Width = oImg.Size.Width - (int)pixtosubstract;
}
}
else
{
ThumbNailSizeToUse.Width = oImg.Size.Width;
ThumbNailSizeToUse.Height = oImg.Size.Height;
}
Bitmap bmp = new Bitmap(ThumbNailSizeToUse.Width, ThumbNailSizeToUse.Height);
bmp.SetResolution(rez, rez);
System.Drawing.Image oThumbNail = bmp;
bmp = null;
Graphics oGraphic = Graphics.FromImage(oThumbNail);
oGraphic.CompositingQuality = CompositingQuality.HighQuality;
oGraphic.SmoothingMode = SmoothingMode.HighQuality;
oGraphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
Rectangle oRectangle = new Rectangle(0, 0, ThumbNailSizeToUse.Width, ThumbNailSizeToUse.Height);
oGraphic.DrawImage(oImg, oRectangle);
oThumbNail.Save(sPhysicalPath + sThumbNailFileName, oFormat);
oImg.Dispose();
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}
Answer 6:
你可以看看http://gd-sharp.sourceforge.net/这是GD库的包装。 我没有测试它,但它看起来很有希望。
Answer 7:
我从开罗库(http://www.cairographics.org)在ASP.Net Web服务器环境有良好的行为。 其实,我搬到了从开罗WPF由于对基于Web的东西WPF的穷人内存使用模式。
WPF实际上往往会运行工作进程的内存不足。 WPF的对象都没有实现IDisposable
,其中许多人引用非托管记忆体的角色只能通过一个终结释放。 大量使用WPF的(特别是如果你的服务器显著为CPU征税),最终会因为你的终结队列中获得饱和运行你的内存不足。 当我剖析我的应用程序,例如,终结队列对其有向上50,000对象,很多他们持有非托管内存的引用。 开罗已经表现要好得多对我来说,和它的内存使用模式已经比WPF的更具可预测性。
如果您有兴趣使用开罗,抢的GTK +网站的库。 他们有一个x86以及x64的二进制文件集。
唯一的缺点是,开罗无法读取本地/写JPG; 然而,你可以很容易地/ WPF适应的东西才能读写JPG,做重采样/缩放/制图/任何其他人使用开罗。
文章来源: Alternatives to System.Drawing for use with ASP.NET?