Как я могу обрабатывать / отображать большие изображения без получения системы.OutOfMemoryExceptions?

Я пытаюсь отобразить изображение размером примерно 9000 x 9000 пикселей. Изображение хранится в файле. Я загружаю изображение с:

BitmapImage image = new BitmapImage(new Uri(dialog.FileName));

Я замораживаю изображение после этого заявления. Оттуда изображение хранится внутри / передается методам в программе как BitmapSource / BitmapImage.

Я написал методы, которые пытаются изменить размер / масштаб изображения с помощью объекта MemoryStream (который я помещаю в оператор using и все). Например, один из таких методов начинается со следующих утверждений.

        using(MemoryStream stream = new MemoryStream())
        {
            PngBitmapEncoder e = new PngBitmapEncoder(); //BmpBitmapEncoder();
            e.Frames.Add(BitmapFrame.Create(image));
            e.Save(stream);
            ...
        }

Я часто получаю систему.OutOfMemoryException () на e.Сохранить (stream) строку этой функции. Если я не попытаюсь изменить размер изображения, я получу систему.OutOfMemoryException () при создании окна, которое использует элемент управления Image для отображения изображения.

                <Image Source="{Binding Image}" HorizontalAlignment="Left" VerticalAlignment="Top"
                Width="{Binding ImageWidth}" Height="{Binding ImageHeight}" />

Теперь я понимаю, что исключения OutOfMemory могут быть неоднозначными в том, что они не обязательно означают, что программа исчерпала объем оперативной памяти, к которой у нее есть доступ. Иногда, программа будет управлять, чтобы отобразить изображение (хотя вскоре после того, как он выбросит исключение OutOfMemoryException), поэтому я не думаю, что файл в вопросе поврежден/имеет недопустимый формат или что-нибудь.

Есть ли лучший способ работы с большими файлами изображений в WPF / .NET? Любые предложения были бы очень признательны!

Edit: теперь я изменил способ замораживания изображения (я создавал замороженную копию вместо замораживания оригинала).

1 ответ

  1. В случае, если вам на самом деле не нужно полное разрешение для отображения изображения, вы можете просто установить BitmapImage DecodePixelWidthили DecodePixelHeight. Не устанавливайте оба параметра, чтобы сохранить соотношение сторон изображения.

    var image = new BitmapImage();
    image.BeginInit();
    image.DecodePixelWidth = 900;
    image.UriSource = new Uri(dialog.FileName);
    image.EndInit();
    image.Freeze();