Image.Save () создает исключение ExternalException для изображения, загруженного из Stream (Image.FromStream ()) - PullRequest
4 голосов
/ 18 октября 2010

Я выслеживаю неприятную проблему, сузил ее и понял, что это происходит только тогда, когда я имею дело с экземпляром Image, возвращенным Image.FromStream (). У меня есть служебный метод, который возвращает экземпляр Image из файла, используя Stream, поэтому у меня нет открытого дескриптора файла. Вот этот служебный метод (ничего особенного):

public static Image ImageFromFileReleaseHandle(string filename)
{
    using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
    {
        return Image.FromStream(fs);
    }
}

Когда я пытаюсь сохранить изображение, загруженное из вышеуказанного метода, я получаю InteropServices.ExternalException «Общая ошибка произошла в GDI +». Следующий пример кода продемонстрирует это:

private void button6_Click(object sender, EventArgs e)
{
    var filename = @"D:\My Documents\My Pictures\2010-03-27 hangover hike.jpg";

    //  Get an Image instance
    Image image;
    using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
    {
        image = Image.FromStream(fs);
    }

    //  Save to a temp file - this is the code that throws the exception
    image.Save(Path.GetTempFileName());
}

Если я загружаю изображение с помощью Image.FromFile (), я могу сохранить без проблем:

private void button6_Click(object sender, EventArgs e)
{
    var filename = @"D:\My Documents\My Pictures\2010-03-27 hangover hike.jpg";

    //  Get an Image instance
    Image image = Image.FromFile(filename);

    //  Save to a temp file - this is the code that throws the exception
    image.Save(Path.GetTempFileName());
}

Я не могу придумать какую-либо дополнительную информацию, которая была бы полезна. Надеюсь, мои примеры кода достаточно просты, чтобы вы могли ясно увидеть проблему.

Спасибо, Стив

Ответы [ 4 ]

3 голосов
/ 18 октября 2010

Согласно документации :

Вы должны держать поток открытым в течение всего времени жизни изображения.

Попробуйте вызвать Сохранить внутрииспользование блока для проверки отсутствия исключения, если поток еще открыт.

1 голос
/ 18 октября 2010

попробуйте вместо этого

//  Get an Image instance
    Image image;
    using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
    {
        image = Image.FromStream(fs);
        //  Save to a temp file - this is the code that throws the exception
        image.Save(Path.GetTempFileName());
    }

Я думаю, что использование блока вызывает проблемы

0 голосов
/ 20 июля 2012

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

public class ImageConverter
{
    public static byte[] imageToByteArray(Image imageIn)
    {
        if (imageIn == null)
            return new byte[] { 45 };

        using (MemoryStream ms = new MemoryStream())
        {
            imageIn.Save(ms, imageIn.RawFormat);
            return ms.ToArray();
        }
    }

    public static Image byteArrayToImage(byte[] byteArrayIn)
    {
        if (byteArrayIn == null)
            return null;

        using (MemoryStream ms = new MemoryStream(byteArrayIn))
        {
            Image returnImage = Image.FromStream(ms);
            return returnImage;
        }
    }

} 
0 голосов
/ 18 октября 2010

Основываясь на предложениях и комментариях, а также на моем собственном дополнительном чтении, я думаю, что у меня есть рабочее решение. В основном проблема в том, что я не могу закрыть поток. Хорошо, но я также не могу оставить FileStream открытым без гарантии, что он будет закрыт должным образом.

Вместо этого я читаю файл в буфер, затем создаю MemoryStream и передаю его Image.FromStream ().

var filename = @"D:\My Documents\My Pictures\2010-03-27 hangover hike.jpg";

byte[] imageData = FileUtils.ReadWholeFileBytes(filename);
Image image = Image.FromStream(new MemoryStream(imageData));

//  dump the buffer to test if this upsets the Memory Stream.  I need to read more
//  about MemoryStream and how it may keep the GC from cleaning up it's underlying data
imageData = null;        

//  Save to a temp file
image.Save(Path.GetTempFileName());

Спасибо всем за ваши предложения и вопросы.

...