Image.Save (..) генерирует исключение GDI +, потому что поток памяти закрыт - PullRequest
103 голосов
/ 03 декабря 2008

У меня есть некоторые двоичные данные, которые я хочу сохранить в виде изображения. Когда я пытаюсь сохранить изображение, оно выдает исключение, если поток памяти, использованный для создания изображения, был закрыт до сохранения. Причина, по которой я это делаю, заключается в том, что я динамически создаю изображения и, следовательно, мне нужно использовать поток памяти.

это код:

[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.
}

У кого-нибудь есть предложения, как мне сохранить изображение с закрытым потоком? Я не могу рассчитывать на то, что разработчики не забудут закрыть поток после сохранения изображения. Фактически, у разработчика не было бы ИДЕИ, чтобы изображение было создано с использованием потока памяти (потому что это происходит в каком-то другом коде, в другом месте).

Я действительно запутался: (

Ответы [ 14 ]

0 голосов
/ 16 марта 2018

Я сталкивался с этой ошибкой при попытке простого редактирования изображений в приложении WPF.

Установка в качестве источника элемента Image растрового изображения предотвращает сохранение файла. Кажется, даже установка Source = null не освобождает файл.

Теперь я просто никогда не использую изображение в качестве элемента «Источник изображения», поэтому я могу перезаписать его после редактирования!

EDIT

Услышав о свойстве CacheOption (спасибо @Nyerguds), я нашел решение: Поэтому вместо использования конструктора Bitmap я должен установить Uri после установки CacheOption BitmapCacheOption.OnLoad. (Image1 ниже - элемент Wpf Image)

Вместо

Image1.Source = new BitmapImage(new Uri(filepath));

Использование:

var image = new BitmapImage();
image.BeginInit();
image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = new Uri(filepath);
image.EndInit();
Image1.Source = image;

См. Это: Кэширование изображений WPF

0 голосов
/ 22 декабря 2017

Для меня код ниже потерпел крах с 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);
                }
            }
        }
    }
0 голосов
/ 27 марта 2017

Он также появился у меня, когда я пытался сохранить изображение в путь

C:\Program Files (x86)\some_directory

и .exe не был запущен от имени администратора, надеюсь, это может помочь кому-то, у кого такая же проблема.

0 голосов
/ 19 февраля 2014

Одно странное решение, которое заставило мой код работать. Откройте изображение в краске и сохраните его как новый файл в том же формате (.jpg). Теперь попробуйте с этим новым файлом, и он работает. Это ясно объясняет вам, что файл может быть каким-то образом поврежден. Это может помочь, только если в вашем коде исправлены все другие ошибки

...