Graphics.DrawImage:内存不足异常

时间:2013-04-17 08:52:52

标签: c# asp.net system.drawing

我只是不能为我的生活弄清楚为什么我在这里得到一个内存不足的例外,即使经过对各种网站和论坛的大量研究。有人能够在这段代码中阐明所有邪恶的根源吗?调用Graphics.DrawImage()方法第79行引发异常。

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult EditImage(FileModel model)
    {
        var fileData = new MySite.Models.File(model.FileID, model.ClientID, ConfigurationManager.ConnectionStrings["MySite"].ConnectionString).Data;
        Image image = null;

        using (var memStream = new MemoryStream())
        {
            memStream.Write(fileData, 0, fileData.Length);
            image = Image.FromStream(memStream);
        }

        using (var graphics = Graphics.FromImage(image))
        {
            graphics.DrawImage(image, model.x1, model.y1, (model.x2 - model.x1), (model.y2 - model.y1));
            graphics.Save();
        }

        using (var memStream = new MemoryStream())
        {
            image.Save(memStream, System.Drawing.Imaging.ImageFormat.Jpeg);
            return File(memStream.ToArray(), "image/jpeg");
        }
    }

堆栈追踪:

[OutOfMemoryException: Out of memory.]
System.Drawing.Graphics.CheckErrorStatus(Int32 status) +1143476
System.Drawing.Graphics.DrawImage(Image image, Int32 x, Int32 y, Int32 width, Int32 height) +141
ProPilot.Controllers.DocumentsController.EditImage(FileModel model) in C:\DEV\Web\Controllers\DocumentsController.cs:79
lambda_method(Closure , ControllerBase , Object[] ) +104
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +14
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +211
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +27
System.Web.Mvc.Async.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41() +28
System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +10
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +57
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +48
System.Web.Mvc.Async.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33() +57
System.Web.Mvc.Async.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49() +223
System.Web.Mvc.Async.<>c__DisplayClass37.<BeginInvokeActionMethodWithFilters>b__36(IAsyncResult asyncResult) +10
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +57
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +48
System.Web.Mvc.Async.<>c__DisplayClass2a.<BeginInvokeAction>b__20() +24
System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult asyncResult) +102
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +57
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +43
System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__18(IAsyncResult asyncResult) +14
System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +23
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +57
System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +23
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +47
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__3(IAsyncResult asyncResult) +25
System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +23
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +47
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9629296
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155 

2 个答案:

答案 0 :(得分:10)

@Sayse在上面的评论中敲响了头部。

使用Image.FromStream时:

  

您必须在图像的生命周期内保持流打开。

来源:http://msdn.microsoft.com/en-AU/library/93z9ee4x.aspx

using (var memStream = new MemoryStream())
{
    memStream.Write(fileData, 0, fileData.Length);
    using(Image image = Image.FromStream(memStream))
    {
        using (var graphics = Graphics.FromImage(image))
        {
            graphics.DrawImage(image, model.x1, model.y1, (model.x2 - model.x1), (model.y2 - model.y1));
            graphics.Save();
        }

        using (var outStream = new MemoryStream())
        {
            image.Save(outStream, System.Drawing.Imaging.ImageFormat.Jpeg);
            return File(outStream.ToArray(), "image/jpeg");
        }
    }
}

答案 1 :(得分:1)

如果您使用BitmapImage课程,您会发现一些问题。

如果使用Image.FromFile()加载图像,则框架在加载图像后不会关闭文件句柄。文件保持打开状态,直到垃圾回收器重新收集图像。这是GDI +的严重错误设计。在图像已经被读入内存后,无需保持文件打开。

所以我尝试使用Image.FromStream()来解决此问题。但这不是解决方案,因为当流关闭时,该映像上的DrawImage()操作将失败并且#34;内存不足&#34;。

因此,如果您想从文件中读取一个Bitmap,并且您想确保文件句柄已关闭,那么您必须使用这样一个丑陋的解决方法:

Bitmap ReadBitmapFromFile(String s_Path)
{
    using (FileStream i_Stream = new FileStream(s_Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    {
        using (Bitmap i_Bmp = new Bitmap(i_Stream))
        {
            return new Bitmap(i_Bmp);
        }
    }
}

顺便说一句:Image.Clone()会产生类似的问题。

而不是

Bitmap i_Clone = (Bitmap)i_Bmp.Clone() 

我不得不使用:

Bitmap i_Clone = new Bitmap(i_Bmp);