Как скопировать Bitmap.Image в c #

У меня проблемы с сохранением изображения из memorystream.

Вот мой код:

MemoryStream ms = new MemoryStream(onimg);

if (ms.Length > 0)
{
    Bitmap bm = new Bitmap(ms);
    returnImage = (Image)bm.Clone();
}
ms.Close();
returnImage.Save(@"C:\img.jpeg");

И на returnImage.Save у меня есть следующее исключение:

Общая ошибка произошла в GDI +.

Если я не закрываю MemoryStream, все в порядке, но через некоторое время для этого потребуется много памяти.

Как я могу это сделать?

РЕДАКТИРОВАТЬ: это сохранение - это только демонстрация. Мне действительно нужен returnImage, чтобы поместить его в ObservableCollection и отобразить в окне, когда мне нужно преобразовать его в System.Windows.Media.Imaging.BitmapImage ();

[ValueConversion(typeof(System.Drawing.Image), typeof(System.Windows.Media.ImageSource))]
public class ImageConverter : IValueConverter
{
    public object Convert(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
            // empty images are empty...
            if (value == null) { return null; }

            var image = (System.Drawing.Image)value;
            // Winforms Image we want to get the WPF Image from...
            var bitmap = new System.Windows.Media.Imaging.BitmapImage();
            bitmap.BeginInit();
            MemoryStream memoryStream = new MemoryStream();
            // Save to a memory stream...
            image.Save(memoryStream, ImageFormat.Bmp);
            // Rewind the stream...
            memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
            bitmap.StreamSource = memoryStream;
            bitmap.EndInit();
            return bitmap;
    }

    public object ConvertBack(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        return null;
    }
}

И XAML, когда я это делаю

<DataTemplate>
   <Image Width="32" Height="32" Source="{ Binding Thumb, Converter={StaticResource    imageConverter} }" />
</DataTemplate>

person Aldos    schedule 15.01.2012    source источник
comment
Что произойдет, если вы .Save перед вами .Close MemoryStream?   -  person Brissles    schedule 15.01.2012
comment
Почему вам нужно использовать объект Bitmap? Не можете сохранить файл с помощью FileStream? Что такое onimg?   -  person craig1231    schedule 15.01.2012
comment
не можете ли вы сообщить о фактическом сообщении об исключении?   -  person Felice Pollano    schedule 15.01.2012
comment
Я сталкивался с этой проблемой раньше, сообщение об ошибке просто: «Общая ошибка произошла в GDI +». Дополнительную информацию можно найти здесь: social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/   -  person Brissles    schedule 15.01.2012
comment
Brissles: returnImage - глобальная переменная, и мне она понадобится в другом классе после завершения этого метода. Так что у меня нет возможности закрыть Memorystream после работы с returnImage.   -  person Aldos    schedule 15.01.2012


Ответы (2)


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

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

Растровое изображение должно хранить свои данные там же, и я делаю вывод (хотя для этого нет доказательств), что Bitmap не копирует данные, а вместо этого использует поток, сохраняя на нем блокировку.

Также нет свидетельств того, что Clone создаст новое растровое изображение с копией байтового представления. И ваш тестовый пример предполагает, что это не так.

Поэтому я боюсь, что вам нужно держать свой поток открытым на протяжении всего времени существования вашего изображения. Это требует памяти, правда, но в противном случае, если Bitmap скопировал данные, вам все равно понадобится эта память для представления растрового изображения. Следовательно, с открытым потоком больше не используется память (если мой предыдущий вывод был верным).

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

person Krizz    schedule 15.01.2012

Разве сохранение на диск не является клоном?

using (MemoryStream ms = new MemoryStream(onimg))
{
    if (ms.Length > 0)
    {
        using (Bitmap bm = new Bitmap(ms))
        {
            bm.Save(@"C:\img.jpeg");
        }
    }
}
person Joe    schedule 15.01.2012
comment
Верно, но я считаю, что ошибка «Общая ошибка произошла в GDI +» является проблемой (возможно, ошибкой, как говорили некоторые) с Bitmap.Save () - person Brissles; 16.01.2012
comment
Я не думаю, что это ошибка. Смотрите мой ответ. - person Krizz; 16.01.2012