Image.Save(..) генерирует исключение GDI +, поскольку поток памяти закрыт
У меня есть несколько двоичных данных, которые я хочу сохранить как изображение. Когда я пытаюсь сохранить изображение, он генерирует исключение, если поток памяти, используемый для создания изображения, был закрыт до сохранения. Причина, по которой я делаю это, - это то, что я динамически создаю изображения и как таковые.. Мне нужно использовать поток памяти.
это код:
[TestMethod]
public void TestMethod1()
{
// Grab the binary data.
byte[] data = File.ReadAllBytes("Chick.jpg");
// Read in the data but do not close, before using the stream.
Stream originalBinaryDataStream = new MemoryStream(data);
Bitmap image = new Bitmap(originalBinaryDataStream);
image.Save(@"c:\test.jpg");
originalBinaryDataStream.Dispose();
// Now lets use a nice dispose, etc...
Bitmap2 image2;
using (Stream originalBinaryDataStream2 = new MemoryStream(data))
{
image2 = new Bitmap(originalBinaryDataStream2);
}
image2.Save(@"C:\temp\pewpew.jpg"); // This throws the GDI+ exception.
}
Есть ли у кого-нибудь предложения, как я могу сохранить изображение с закрытым потоком? Я не могу полагаться на разработчиков, чтобы не забудьте закрыть поток после сохранения изображения. Фактически у разработчика не было бы ИДЕИ, чтобы изображение было сгенерировано с использованием потока памяти (потому что это происходит в другом коде, в другом месте).
Я действительно смущен: (
Ответы
Ответ 1
Как и MemoryStream, вам действительно не нужно закрывать поток - ничего плохого не произойдет, если вы этого не сделаете, хотя, очевидно, хорошая практика - распоряжаться всем, что доступно в любом случае. (Подробнее см. этот вопрос).
Однако вам следует удалять битмап - и это закроет поток для вас. В принципе, когда вы даете конструктору Bitmap поток, он "владеет" потоком, и вы не должны его закрывать. Как документы для этого конструктора говорят:
Вы должны оставить поток открытым для время жизни растрового изображения.
Я не могу найти никаких документов, обещающих закрыть поток, когда вы удаляете растровое изображение, но вы должны быть в состоянии проверить это довольно легко.
Ответ 2
Общая ошибка произошла в GDI +.
Может также возникнуть из неправильного пути сохранения!
Принял меня полдня, чтобы заметить это.
Поэтому убедитесь, что вы дважды проверили путь, чтобы сохранить изображение.
Ответ 3
Возможно, стоит упомянуть, что если каталог C:\Temp не существует, он также выкинет это исключение, даже если ваш поток все еще существует.
Ответ 4
У меня была та же проблема, но на самом деле причина заключалась в том, что у приложения не было разрешения на сохранение файлов на C. Когда я изменился на "D: \..", изображение было сохранено.
Ответ 5
Эта ошибка возникла у меня, когда я пытался использовать Citrix. Папка изображения была установлена на C:\на сервере, для которой у меня нет привилегий. После того, как папка с изображениями была перенесена на общий диск, ошибка исчезла.
Ответ 6
Скопировать растровое изображение. Вы должны держать поток открытым для жизни растрового изображения.
При рисовании изображения: System.Runtime.InteropServices.ExternalException: Общая ошибка в GDI
public static Image ToImage(this byte[] bytes)
{
using (var stream = new MemoryStream(bytes))
using (var image = Image.FromStream(stream, false, true))
{
return new Bitmap(image);
}
}
[Test]
public void ShouldCreateImageThatCanBeSavedWithoutOpenStream()
{
var imageBytes = File.ReadAllBytes("bitmap.bmp");
var image = imageBytes.ToImage();
image.Save("output.bmp");
}
Ответ 7
Вы можете попытаться создать другую копию растрового изображения:
using (var memoryStream = new MemoryStream())
{
// write to memory stream here
memoryStream.Position = 0;
using (var bitmap = new Bitmap(memoryStream))
{
var bitmap2 = new Bitmap(bitmap);
return bitmap2;
}
}
Ответ 8
Общая ошибка произошла в GDI+. Это может произойти из-за проблем с сохранением образа, я получил эту ошибку, потому что мой путь хранения слишком длинный, я исправил это, сначала сохраняя изображение в кратчайшем пути и переместив его в нужное место с помощью методов обработки длинного пути.
Ответ 9
Я получал эту ошибку, потому что автоматизированный тест, который я выполнял, пытался хранить моментальные снимки в папку, которая не существовала. После создания папки ошибка устранена.
Ответ 10
Одно странное решение, которое заставило мой код работать.
Откройте изображение в краске и сохраните его как новый файл с таким же форматом (.jpg). Теперь попробуйте этот новый файл, и он работает. Это ясно объясняет вам, что файл может быть поврежден каким-то образом.
Это может помочь только в том случае, если в вашем коде исправлены все другие ошибки.
Ответ 11
Он также появился со мной, когда я пытался сохранить изображение в пути
C:\Program Files (x86)\some_directory
и .exe
не был выполнен для запуска как администратор, я надеюсь, что это может помочь кому-то, у кого тоже есть проблема.
Ответ 12
Для меня код ниже разбился с A generic error occurred in GDI+
на строке, которая сохраняет значение MemoryStream
. Код выполнялся на веб-сервере, и я разрешил его, остановив и запустив пул приложений, на котором был запущен сайт.
Должна быть некоторая внутренняя ошибка в GDI +
private static string GetThumbnailImageAsBase64String(string path)
{
if (path == null || !File.Exists(path))
{
var log = ContainerResolver.Container.GetInstance<ILog>();
log.Info($"No file was found at path: {path}");
return null;
}
var width = LibraryItemFileSettings.Instance.ThumbnailImageWidth;
using (var image = Image.FromFile(path))
{
using (var thumbnail = image.GetThumbnailImage(width, width * image.Height / image.Width, null, IntPtr.Zero))
{
using (var memoryStream = new MemoryStream())
{
thumbnail.Save(memoryStream, ImageFormat.Png); // <= crash here
var bytes = new byte[memoryStream.Length];
memoryStream.Position = 0;
memoryStream.Read(bytes, 0, bytes.Length);
return Convert.ToBase64String(bytes, 0, bytes.Length);
}
}
}
}