Как скопировать Bitmap.Image в c # - PullRequest
3 голосов
/ 15 января 2012

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

Вот мой код:

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>

Ответы [ 2 ]

4 голосов
/ 16 января 2012

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

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

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

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

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

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

2 голосов
/ 15 января 2012

Не является ли сохранение на диск по сути клоном?

using (MemoryStream ms = new MemoryStream(onimg))
{
    if (ms.Length > 0)
    {
        using (Bitmap bm = new Bitmap(ms))
        {
            bm.Save(@"C:\img.jpeg");
        }
    }
}
...