C# GDI+, JPEG Image to MemoryStream 中发生一般错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1053052/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 07:06:07  来源:igfitidea点击:

A generic error occurred in GDI+, JPEG Image to MemoryStream

c#gdi+

提问by madcapnmckay

This seems to be a bit of an infamous error all over the web. So much so that I have been unable to find an answer to my problem as my scenario doesn't fit. An exception gets thrown when I save the image to the stream.

这似乎是整个网络上一个臭名昭著的错误。如此之多以至于我一直无法找到我的问题的答案,因为我的场景不适合。当我将图像保存到流时抛出异常。

Weirdly this works perfectly with a png but gives the above error with jpg and gif which is rather confusing.

奇怪的是,这与 png 完美配合,但在 jpg 和 gif 中出现了上述错误,这很令人困惑。

Most similar problem out there relate to saving images to files without permissions. Ironically the solution is to use a memory stream as I am doing....

大多数类似的问题都与在没有权限的情况下将图像保存到文件有关。具有讽刺意味的是,解决方案是像我一样使用内存流......

public static byte[] ConvertImageToByteArray(Image imageToConvert)
{
    using (var ms = new MemoryStream())
    {
        ImageFormat format;
        switch (imageToConvert.MimeType())
        {
            case "image/png":
                format = ImageFormat.Png;
                break;
            case "image/gif":
                format = ImageFormat.Gif;
                break;
            default:
                format = ImageFormat.Jpeg;
                break;
        }

        imageToConvert.Save(ms, format);
        return ms.ToArray();
    }
}

More detail to the exception. The reason this causes so many issues is the lack of explanation :(

异常的更多细节。这导致这么多问题的原因是缺乏解释:(

System.Runtime.InteropServices.ExternalException was unhandled by user code
Message="A generic error occurred in GDI+."
Source="System.Drawing"
ErrorCode=-2147467259
StackTrace:
   at System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder, EncoderParameters    encoderParams)
   at System.Drawing.Image.Save(Stream stream, ImageFormat format)
   at Caldoo.Infrastructure.PhotoEditor.ConvertImageToByteArray(Image imageToConvert) in C:\Users\Ian\SVN\Caldoo\Caldoo.Coordinator\PhotoEditor.cs:line 139
   at Caldoo.Web.Controllers.PictureController.Croppable() in C:\Users\Ian\SVN\Caldoo\Caldoo.Web\Controllers\PictureController.cs:line 132
   at lambda_method(ExecutionScope , ControllerBase , Object[] )
   at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassa.<InvokeActionMethodWithFilters>b__7()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
 InnerException: 

OK things I have tried so far.

到目前为止我已经尝试过的东西。

  1. Cloning the image and working on that.
  2. Retrieving the encoder for that MIME passing that with jpeg quality setting.
  1. 克隆图像并进行处理。
  2. 检索该 MIME 的编码器,并使用 jpeg 质量设置传递该编码器。

采纳答案by madcapnmckay

OK I seem to have found the cause just by sheer luck and its nothing wrong with that particular method, it's further back up the call stack.

好吧,我似乎只是靠运气找到了原因,并且该特定方法没有任何问题,它进一步备份了调用堆栈。

Earlier I resize the image and as part of that method I return the resized object as follows. I have inserted two calls to the above method and a direct save to a file.

早些时候,我调整了图像的大小,作为该方法的一部分,我按如下方式返回了调整大小的对象。我插入了对上述方法的两次调用并直接保存到文件。

// At this point the new bitmap has no MimeType
// Need to output to memory stream
using (var m = new MemoryStream())
{
       dst.Save(m, format);

       var img = Image.FromStream(m);

       //TEST
       img.Save("C:\test.jpg");
       var bytes = PhotoEditor.ConvertImageToByteArray(img);


       return img;
 }

It appears that the memory stream that the object was created on hasto be open at the time the object is saved. I am not sure why this is. Is anyone able to enlighten me and how I can get around this.

看来,该对象被创建在内存流已经是在保存对象时打开。我不确定这是为什么。有没有人能够启发我以及我如何解决这个问题。

I only return from a stream because after using the resize code similar to thisthe destination file has an unknown mime type (img.RawFormat.Guid) and Id like the Mime type to be correct on all image objects as it makes it hard write generic handling code otherwise.

我只从流返回,因为在使用与此类似的调整大小代码后,目标文件具有未知的 MIME 类型 (img.RawFormat.Guid) 并且 Id 喜欢 Mime 类型在所有图像对象上都是正确的,因为它使其难以编写通用否则处理代码。

EDIT

编辑

This didn't come up in my initial search but here'sthe answer from Jon Skeet

这在我最初的搜索中没有出现,但这Jon Skeet 的答案

回答by ChrisF

I notice that your "jpeg" case is actually:

我注意到您的“jpeg”案例实际上是:

            default:
                format = ImageFormat.Jpeg;
                break;

Are you sure that the format is jpeg and not something else?

您确定格式是 jpeg 而不是其他格式吗?

I'd try:

我会尝试:

            case "image/jpg": // or "image/jpeg" !
                format = ImageFormat.Jpeg;
                break;

Or check what imageToConvert.MimeType()is actually returning.

或检查imageToConvert.MimeType()实际返回的内容。

UPDATE

更新

Is there any other initialisation you need to do to the MemoryStream object?

您还需要对 MemoryStream 对象进行任何其他初始化吗?

回答by HU.

Had a very similar problem and also tried cloning the image which doesn't work. I found that the best solution was to create a new Bitmap object from the image that was loaded from the memory stream. That way the stream can be disposed of e.g.

有一个非常相似的问题,还尝试克隆不起作用的图像。我发现最好的解决方案是根据从内存流加载的图像创建一个新的 Bitmap 对象。这样可以处理流,例如

using (var m = new MemoryStream())
{
    var img = new Bitmap(Image.FromStream(m));
    return img;
}

Hope this helps.

希望这可以帮助。

回答by dhinesh

if your code is as follows then also this error occurs

如果您的代码如下,那么也会发生此错误

private Image GetImage(byte[] byteArray)
{
   using (var stream = new MemoryStream(byteArray))
   {
       return Image.FromStream(stream);
    }
}

The correct one is

正确的是

private Image GetImage(byte[] byteArray)
{
   var stream = new MemoryStream(byteArray))
   return Image.FromStream(stream);        
}

This may be because we are returning from the using block

这可能是因为我们正在从 using 块返回

回答by Ivan Mesic

This article explains in detail what exactly happens: Bitmap and Image constructor dependencies

这篇文章详细解释了到底发生了什么:位图和图像构造函数依赖

In short, for a lifetime of an Imageconstructed from a stream, the stream must not be destroyed.

简而言之,对于Image构造的 的生命周期,流不能被销毁。

So, instead of

所以,而不是

using (var strm = new ... )  {
    myImage = Image.FromStream(strm);
}

try this

尝试这个

Stream imageStream;
...

    imageStream = new ...;
    myImage = Image.FromStream(strm);

and close imageStreamat the form close or web page close.

并在表单关闭或网页关闭时关闭imageStream

回答by Marco

SOLVED - I had this exact problem. The fix, for me, was to up the disk quota for IUSR on the IIS server. In this instance, we have a catalog app with images of items and such. The upload quota for the "Anonymous Web User" was set to 100MB, which is the default for this particular hosting company's IIS servers. I upped it to 400MB and was able to upload images without error.

已解决 - 我遇到了这个确切的问题。对我来说,修复是提高 IIS 服务器上 IUSR 的磁盘配额。在这种情况下,我们有一个目录应用程序,其中包含项目图像等。“匿名 Web 用户”的上传配额设置为 100MB,这是该特定托管公司的 IIS 服务器的默认值。我将其增加到 400MB,并且能够毫无错误地上传图像。

This might not be your issue, but if it is, it's an easy fix.

这可能不是您的问题,但如果是,则很容易解决。

回答by Fred

I'll add this cause of the error as well in hopes it helps some future internet traveler. :)

我也会添加这个错误原因,希望它可以帮助一些未来的互联网旅行者。:)

GDI+ limits the maximum height of an image to 65500

GDI+ 将图像的最大高度限制为 65500

We do some basic image resizing, but in resizing we try to maintain aspect ratio. We have a QA guy who's a little too good at this job; he decided to test this with a ONE pixel wide photo that was 480 pixels tall. When the image was scaled to meet our dimensions, the height was north of 68,000 pixels and our app exploded with A generic error occurred in GDI+.

我们做了一些基本的图像大小调整,但在调整大小时我们尽量保持纵横比。我们有一个 QA 人员,他对这项工作有点过分;他决定用一张 480 像素高的 ONE 像素宽照片来测试这一点。当图像缩放到符合我们的尺寸时,高度在 68,000 像素以北,我们的应用程序以A generic error occurred in GDI+.

You can verify this yourself with test:

您可以通过测试自己验证这一点:

  int width = 480;
  var height = UInt16.MaxValue - 36; //succeeds at 65499, 65500
  try
  {
    while(true)
    {
      var image = new Bitmap(width, height);
      using(MemoryStream ms = new MemoryStream())
      {
        //error will throw from here
        image.Save(ms, ImageFormat.Jpeg);
      }
      height += 1;
    }
  }
  catch(Exception ex)
  {
    //explodes at 65501 with "A generic error occurred in GDI+."
  }

It's too bad there's not a friendly .net ArgumentExceptionthrown in the constructor of Bitmap.

太糟糕了,.netArgumentException的构造函数中没有抛出友好的 .net Bitmap

回答by Savindra

If you are getting that error , then I can say that your application doesn't have a write permission on some directory.

如果您收到该错误,那么我可以说您的应用程序对某个目录没有写权限。

For example, if you are trying to save the Image from the memory stream to the file system , you may get that error.

例如,如果您尝试将 Image 从内存流保存到文件系统,您可能会收到该错误。

Please if you are using XP, make sure to add write permission for the aspnet account on that folder.

如果您使用的是 XP,请确保为该文件夹上的 aspnet 帐户添加写入权限。

If you are using windows server (2003,2008) or Vista, make sure that add write permission for the Network service account.

如果您使用的是 windows server (2003,2008) 或 Vista,请确保为网络服务帐户添加写入权限。

Hope it help some one.

希望它帮助某人。

回答by Ani

In my case the problem was in the path I was saving (the root C:\). Changing it to D:\111\made the exception go away.

在我的情况下,问题出在我保存的路径(根C:\)中。将其更改为D:\111\使异常消失。

回答by Kirk Broadhurst

You'll also get this exception if you try to save to an invalid path or if there's a permissions issue.

如果您尝试保存到无效路径或存在权限问题,您也会收到此异常。

If you're not 100% sure that the file path is available and permissions are correct then try writing a to a text file. This takes just a few seconds to rule out what would be a very simple fix.

如果您不是 100% 确定文件路径可用且权限正确,请尝试将 a 写入文本文件。这只需几秒钟即可排除什么是非常简单的修复。

var img = System.Drawing.Image.FromStream(incomingStream);

// img.Save(path);
System.IO.File.WriteAllText(path, "Testing valid path & permissions.");

And don't forget to clean up your file.

并且不要忘记清理您的文件。