Общая ошибка произошла в 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 в вашем приложении и попробуйте запустить как администратор тогда это должно решить вашу проблему.
мой, казалось, был проблемой разрешения.