C# GDI+;中发生一般性错误;,JPEG图像到内存流

C# GDI+;中发生一般性错误;,JPEG图像到内存流,c#,gdi+,C#,Gdi+,这似乎是网络上一个臭名昭著的错误。如此之多以至于我一直无法找到我的问题的答案,因为我的场景不适合。当我将图像保存到流时,会引发异常 奇怪的是,这在png上非常有效,但在jpg和gif上会出现上述错误,这相当令人困惑 最类似的问题是在没有权限的情况下将图像保存到文件中。具有讽刺意味的是,解决方案是像我这样使用内存流 public static byte[] ConvertImageToByteArray(Image imageToConvert) { using (var ms = new

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

奇怪的是,这在png上非常有效,但在jpg和gif上会出现上述错误,这相当令人困惑

最类似的问题是在没有权限的情况下将图像保存到文件中。具有讽刺意味的是,解决方案是像我这样使用内存流

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();
    }
}
更详细的例外情况。造成如此多问题的原因是缺乏解释:(

用户代码未处理System.Runtime.InteropServices.ExternalException Message=“GDI+中发生一般错误。” Source=“System.Drawing” 错误代码=-2147467259 堆栈跟踪: 在System.Drawing.Image.Save(Stream、ImageCodeInfo编码器、EncoderParameters encoderParams) 在System.Drawing.Image.Save(流、图像格式) 在C:\Users\Ian\SVN\Caldoo\Caldoo.Coordinator\PhotoEditor.cs中的Caldoo.Infrastructure.PhotoEditor.ConvertImageToByteArray(Image imageToConvert)中 在C:\Users\Ian\SVN\Caldoo\Caldoo.Web\Controllers\PictureController.cs中的Caldoo.Web.Controllers.PictureController.crappable()处:第132行 在lambda_方法上(ExecutionScope、ControllerBase、Object[]) 位于System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller,Object[]参数) 位于System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext ControllerContext,IDictionary`2参数) 位于System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext ControllerContext,ActionDescriptor ActionDescriptor,IDictionary`2参数) 在System.Web.Mvc.ControllerActionInvoker.c_uuDisplayClassA.b_uuu7()中 位于System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter筛选器、ActionExecutingContext预文本、Func`1 continuation) 内部异常: 好的,我已经试过了

  • 克隆图像并处理它
  • 正在检索通过jpeg质量设置的MIME的编码器
  • 我注意到您的“jpeg”案例实际上是:

                default:
                    format = ImageFormat.Jpeg;
                    break;
    
    您确定格式是jpeg而不是其他格式吗

    我会尝试:

                case "image/jpg": // or "image/jpeg" !
                    format = ImageFormat.Jpeg;
                    break;
    
    或者检查
    imageToConvert.MimeType()
    实际返回的内容

    更新


    你还需要对MemoryStream对象进行其他初始化吗?

    好的,我似乎完全幸运地找到了原因,而且这个方法没有什么问题,它是调用堆栈的进一步备份

    前面我调整了图像的大小,作为该方法的一部分,我返回了调整大小的对象,如下所示

    // 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;
     }
    
    似乎创建对象的内存流在对象保存时处于打开状态。我不确定这是为什么。是否有人能告诉我以及我如何解决这一问题

    我只从流返回,因为在使用类似于目标文件的调整大小代码后,目标文件有一个未知的mime类型(img.RawFormat.Guid),并且我希望mime类型在所有图像对象上都是正确的,因为它使编写通用处理代码变得困难

    编辑


    这在我最初的搜索中没有出现,但是Jon Skeet的答案有一个非常类似的问题,并且还尝试了克隆不起作用的图像。我发现最好的解决方案是从从内存流加载的图像创建一个新的位图对象。这样可以处理流,例如

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

    希望这有帮助。

    如果您的代码如下所示,则也会发生此错误

    private Image GetImage(byte[] byteArray)
    {
       using (var stream = new MemoryStream(byteArray))
       {
           return Image.FromStream(stream);
        }
    }
    
    正确的答案是

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

    这可能是因为我们从使用块返回,本文详细解释了具体发生的情况:

    简而言之,对于从流构造的
    图像
    的生命周期,流不能被破坏

    因此,与其

    using (var strm = new ... )  {
        myImage = Image.FromStream(strm);
    }
    
    image_instance.Load(file_name);
    
    试试这个

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

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

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


    这可能不是你的问题,但如果是的话,这是一个很容易解决的问题。

    我还将添加此错误原因,希望它能帮助一些未来的互联网旅行者。:)

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

    我们做了一些基本的图像大小调整,但在调整大小时,我们试图保持纵横比。我们有一个QA人员,他对这项工作有点太在行了;他决定用一张480像素高的一像素宽的照片来测试这一点。当图像缩放到符合我们的尺寸时,高度在68000像素以北,我们的应用程序爆炸了
    ,GDI+
    中出现了一个通用错误

    您可以通过以下测试来验证这一点:

      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+."
      }
    

    很遗憾,位图的构造函数中没有抛出一个友好的.net
    ArgumentException
    ,如果您遇到了这个错误,那么我可以说您的应用程序没有对某个目录的写入权限

    例如,如果试图将图像从内存流保存到文件系统,则可能会出现该错误

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

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


    希望它能帮助一些人

    在我的例子中,问题出在我保存的路径上(根
    C:\
    )。将其更改为
    D:\111\
    使e
    var img = System.Drawing.Image.FromStream(incomingStream);
    
    // img.Save(path);
    System.IO.File.WriteAllText(path, "Testing valid path & permissions.");
    
    using (var ms = new MemoryStream())
    {
        Bitmap bmp = new Bitmap(imageToConvert);
        bmp.Save(ms, format);
        return ms.ToArray();
    }
    
    new Bitmap(oldbitmap).Save(filename);
    
        for (int i = 65498; i <= 100000; i++)
        {
            using (Bitmap t = new Bitmap(800, i))
            using (Graphics gBmp = Graphics.FromImage(t))
            {
                Color green = Color.FromArgb(0x40, 0, 0xff, 0);
                using (Brush greenBrush = new SolidBrush(green))
                {
                    // draw a green rectangle to the bitmap in memory
                    gBmp.FillRectangle(greenBrush, 0, 0, 799, i);
                    if (File.Exists("c:\\temp\\i.jpg"))
                    {
                        File.Delete("c:\\temp\\i.jpg");
                    }
                    t.Save("c:\\temp\\i.jpg", ImageFormat.Jpeg);
                }
            }
            GC.Collect();
        }
    
    image_instance = Image.FromFile(file_name);
    
    image_instance.Load(file_name);
    
    using (System.Drawing.Image img = Bitmap.FromFile(fileName))
    {
          ... do some manipulation of img ...
          img.Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg);
    }
    
    byte[] bts = (byte[])page1.EnhMetaFileBits; 
    using (var ms = new MemoryStream(bts)) 
    { 
        var image = System.Drawing.Image.FromStream(ms); 
        System.Drawing.Image img = image.GetThumbnailImage(200, 260, null, IntPtr.Zero);      
        img.Save(NewPath, System.Drawing.Imaging.ImageFormat.Png);
    }
    
      try
      {
        img.SaveJpeg(tmpFile, quality); // This is always successful for say image1.jpg, but always throws the GDI+ exception for image2.jpg
      }
      catch (Exception ex)
      {
        // Try HU's method: Convert it to a Bitmap first
        img = new Bitmap(img); 
        img.SaveJpeg(tmpFile, quality); // This is always successful
      }
    
    private static void SaveJpeg(this Image img, string filename, int quality)
    {
      EncoderParameter qualityParam = new EncoderParameter(Encoder.Quality, (long)quality);
      ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");
      EncoderParameters encoderParams = new EncoderParameters(1);
      encoderParams.Param[0] = qualityParam;
      img.Save(filename, jpegCodec, encoderParams);
    }
    
    private static ImageCodecInfo GetEncoderInfo(string mimeType)
    {
        var encoders = ImageCodecInfo.GetImageEncoders();
        var encoder = encoders.SingleOrDefault(c => string.Equals(c.MimeType, mimeType, StringComparison.InvariantCultureIgnoreCase));
        if (encoder == null) throw new Exception($"Encoder not found for mime type {mimeType}");
        return encoder;
    }
    
    public Image Base64ToImage(string base64String)
        {
            // Convert Base64 String to byte[]
            byte[] imageBytes = Convert.FromBase64String(base64String);
            MemoryStream ms = new MemoryStream(imageBytes, 0,
              imageBytes.Length);
    
            // Convert byte[] to Image
            ms.Write(imageBytes, 0, imageBytes.Length);
            Image image = Image.FromStream(ms, true);
            return image;
        }
    
     img.Save("YOUR PATH TO SAVE IMAGE")
    
    string imagePath = Path.Combine(Environment.CurrentDirectory, $"Bhatti{i}.png");
    Bitmap bitmap = new Bitmap(image);
    bitmap.Save(imagePath);
    
    String path = Server.MapPath("~/last_img.png");//Path