Общая ошибка произошла в GDI+, JPEG-изображении в MemoryStream
это, кажется, немного печально известная ошибка во всем интернете. Настолько, что я не смог найти ответ на свою проблему, поскольку мой сценарий не подходит. Исключение возникает, когда я сохраняю изображение в потоке.
странно, это отлично работает с 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 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:UsersIanSVNCaldooCaldoo.CoordinatorPhotoEditor.cs:line 139
   at Caldoo.Web.Controllers.PictureController.Croppable() in C:UsersIanSVNCaldooCaldoo.WebControllersPictureController.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 вещи, которые я пробовал до сих пор.
- клонирование изображения и работа над этим.
- получение кодировщика для этого MIME, передающего это с настройкой качества jpeg.
28 ответов
хорошо, кажется, я нашел причину просто по чистой случайности, и в этом нет ничего плохого с этим конкретным методом, это еще более резервное копирование стека вызовов.
ранее я изменял размер изображения и как часть этого метода я возвращаю измененный объект следующим образом. Я вставил два вызова вышеуказанного метода и прямое сохранение в файл.
// 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) и Id, как тип Mime, чтобы быть правильным для всех объектов изображения, поскольку это затрудняет запись общего кода обработки в противном случае.
редактировать
Это не в моем первоначальном поиске, но здесь ответ от Jon скит
Если вы получаете эту ошибку , то я могу сказать, что ваше приложение не имеет разрешения на запись в некоторые директории.
например, если вы пытаетесь сохранить изображение из потока памяти в файловой системе , вы можете получить эту ошибку.
пожалуйста, если вы используете XP, не забудьте добавить разрешение на запись для учетной записи aspnet в этой папке.
Если вы используете windows server (2003,2008) или Vista, убедитесь, что добавить разрешение на запись для Учетная запись сетевой службы.
надеюсь, это поможет кому-то.
Я добавлю эту причину ошибки, а также в надежде, что это поможет будущему интернет-путешественнику. :)
GDI + ограничивает максимальную высоту изображения до 65500
мы делаем некоторые основные изменения размера изображения, но при изменении размера мы стараемся поддерживать соотношение сторон.  У нас есть парень QA, который слишком хорош в этой работе; он решил проверить это с помощью фотографии шириной в один пиксель, которая была высотой 480 пикселей.  Когда изображение было масштабировано, чтобы соответствовать нашим размерам, высота была к северу от 68,000 пикселей и наше приложение взорвалось с A generic error occurred in 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 брошен в конструктор Bitmap.
в этой статье подробно объясняется, что именно происходит:зависимости конструктора растровых и изображений
короче говоря, на всю жизнь Image состоящий из поток поток не должен быть разрушен. 
Итак, вместо
using (var strm = new ... )  {
    myImage = Image.FromStream(strm);
}
попробуй такое
Stream imageStream;
...
    imageStream = new ...;
    myImage = Image.FromStream(strm);
и вблизи imageStream в форме закрыть или закрыть веб-страницу.
вы также получите это исключение, если вы попытаетесь сохранить недопустимый путь или если есть проблема с разрешениями.
Если вы не уверены на 100%, что путь к файлу доступен и разрешения верны, попробуйте записать a в текстовый файл. Это займет всего несколько секунд, чтобы исключить то, что было бы очень простым решением.
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();
}
Я обнаружил, что если одна из родительских папок, где я сохранял файл, имела конечное пространство, то GDI+ выдаст общее исключение.
другими словами, если бы я попытался сохранить "C:\Documents и настройки\myusername\локальные настройки\Temp\ABC DEF M1 трендовые значения \Images\picture.png " затем он выбросил общее исключение.
имя моей папки создавалось из имени файла, у которого было конечное пространство, поэтому это было легко .Обрезать () это и переместить на.
Это расширение / квалификация ответа Фреда, который заявил:"GDI ограничивает высоту изображения до 65534". Мы столкнулись с этой проблемой с одним из наших приложений .NET, и, увидев сообщение, наша команда аутсорсинга подняла руки в воздух и сказала, что не может решить проблему без серьезных изменений.
на основе моего тестирования можно создавать / манипулировать изображениями с высотой больше 65534, но проблема возникает при сохранении в поток или файл В ОПРЕДЕЛЕННЫХ ФОРМАТАХ. В следующем коде t.Вызов метода Save () выбрасывает нашему другу общее исключение, когда высота пикселя составляет 65501 для меня. Из любопытства я повторил тест на ширину, и тот же предел применялся к экономии.
    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();
    }
та же ошибка также возникает при записи в поток памяти.
чтобы обойти это, вы можете повторить приведенный выше код и заменить ImageFormat.Tiff или ImageFormat.Bmp для ImageFormat.Формате JPEG.
это работает до высоты / ширины 100,000 для меня - я не проверял пределы. Так уж получилось .Tiff был жизнеспособным вариантом для нас.
ПРЕДУПРЕДИЛ
потоки / файлы TIFF в памяти потребляют больше памяти, чем их аналоги JPG.
на всякий случай, если кто-то делает такие глупые вещи, как я. 1. убедитесь, что path существует. 2. убедитесь, что у вас есть разрешения на запись. 3. убедитесь, что ваш путь правильный, в моем случае мне не хватало имени файла в TargetPath : (
Он должен был сказать, что ваш путь отстой, чем " общая ошибка произошла в GDI+"
Я также получил эту ошибку при сохранении JPEG, но только для определенных изображений.
мой окончательный код:
  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
  }
Я не создавал изображения, поэтому я не могу сказать, в чем разница.
Я был бы признателен, если бы кто-нибудь смог это объяснить.
Это моя функция SaveJpeg просто FYI:
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 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
была очень похожая проблема, а также попытался клонировать изображение, которое не работает. Я обнаружил, что лучшим решением было создать новый растровый объект из изображения, загруженного из потока памяти. Таким образом, поток может быть удален, например
using (var m = new MemoryStream())
{
    var img = new Bitmap(Image.FromStream(m));
    return img;
}
надеюсь, что это помогает.
решено-у меня была эта точная проблема. Исправление для меня заключалось в увеличении дисковой квоты для IUSR на сервере IIS. В этом случае у нас есть приложение каталога с изображениями элементов и тому подобное. Квота загрузки для "анонимного веб-пользователя" была установлена на 100 МБ, что является значением по умолчанию для серверов IIS этой конкретной хостинговой компании. Я поднял его до 400MB и смог загрузить изображения без ошибок.
Это может быть не ваша проблема, но если это так, это легко исправить.
ошибка, возникающая из-за разрешения. убедитесь, что у папки есть все разрешения.
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")
в моем случае проблема была в пути, который я сохранял (корень C:\). Изменение его на D:1\ сделал исключение.
другая причина этой ошибки-путь, указанный в методе сохранения экземпляра растрового изображения, не существует или вы не указали полный / допустимый путь.
просто была эта ошибка, потому что я передавал имя файла, а не полный путь!
Это произойдет!
моя очередь!
using (System.Drawing.Image img = Bitmap.FromFile(fileName))
{
      ... do some manipulation of img ...
      img.Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg);
}
получил его на .Спасать... потому что using () держит файл открытым, поэтому я не могу его перезаписать. Возможно, это поможет кому-то в будущем.
та же проблема, с которой я столкнулся. Но в моем случае я пытался сохранить файл на диске C, и он был недоступен. Поэтому я попытался сохранить его в D-диске, который был полностью доступен, и мне это удалось.
поэтому сначала проверьте свои папки, в которых вы пытаетесь сохранить. У вас должны быть все права (чтение и запись) для этой конкретной папки.
Я заметил, что ваш случай "jpeg" на самом деле:
            default:
                format = ImageFormat.Jpeg;
                break;
вы уверены, что формат JPEG, а не что-то другое?
Я бы попробовал:
            case "image/jpg": // or "image/jpeg" !
                format = ImageFormat.Jpeg;
                break;
или imageToConvert.MimeType() на самом деле возвращаются.
обновление
есть ли другая инициализация, которую вам нужно сделать для объекта MemoryStream?
просто чтобы бросить еще одно возможное решение в кучу, я упомяну случай, с которым я столкнулся с этим сообщением об ошибке.  Метод Bitmap.Save будет через это исключение при сохранении растрового изображения, которое я преобразовал и отображал.  Я обнаружил, что он не будет бросать исключение, если у оператора есть точка останова, и не будет, если Bitmap.Save предшествовал Thread.Sleep(500) поэтому я полагаю, что происходит какое-то соревнование ресурсов.
просто скопируйте изображение в новое растровое изображение объекта было достаточно, чтобы предотвратить появление этого исключения:
new Bitmap(oldbitmap).Save(filename);
Если вы пытаетесь сохранить изображение к удаленное расположение обязательно добавьте NETWORK_SERVICE учетная запись пользователя в настройки безопасности и дать этому пользователю права на чтение и запись. Иначе это не сработает.
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);
}
Я также получаю эту ошибку, потому что я пытаюсь сохранить изображения с тем же именем ранее сохраненных изображений.
убедитесь, что вы не сохраняете изображения с повторяющимся именем.
используйте для thar, например, "случайную" функцию (как работает генератор случайных чисел C#?) или, например, создайте Guid (http://betterexplained.com/articles/the-quick-guide-to-guids/)
- У меня была эта проблема на тестовом сервере, но не на живом сервере.
- я записывал изображение в поток, поэтому это не было проблемой разрешения.
- Я непосредственно развертывал некоторые из них .dll на тестовый сервер.
- развертывание всего решения исправило проблему, поэтому, вероятно, это было странное несоответствие компиляции
У нас была такая же проблема при создании PDF на производственном сервере.
перезапустить пул приложений исправить эту проблему.
надеюсь, это поможет кому-то.
для меня я использовал Image.Save(Stream, ImageCodecInfo, EncoderParameters) и, по-видимому, это было причиной печально известного A generic error occurred in GDI+ ошибка.
Я пытался использовать EncoderParameter сохранить jpegs в качестве 100%. Это отлично работало на " моей машине "(doh!) и не на производстве.
когда я использовал Image.Save(Stream, ImageFormat) вместо этого ошибка исчезла! Поэтому, как идиот, я продолжал использовать последний, хотя он сохраняет их в качестве по умолчанию, которое я предполагаю, составляет всего 50%.
Надеюсь, эта информация поможет кто-то.
Я тоже столкнулся с проблемой. Проблема была связана с утилизацией потока загрузки. Но я не утилизировал его, он был внутри .Net framework. Все, что мне нужно было сделать, это использовать:
image_instance = Image.FromFile(file_name);
вместо
image_instance.Load(file_name);
image_instance имеет тип System.Окна.Формы.Управления PictureBox! Picturebox'S Load () размещает поток, из которого было загружено изображение, и я этого не знал.
на основе ответа от @savindra, если вы RHM в вашем приложении и попробуйте запустить как администратор тогда это должно решить вашу проблему.
мой, казалось, был проблемой разрешения.
