如何在c#中复制Bitmap.Image

时间:2012-01-15 19:45:05

标签: c# image memorystream bitmapimage

我在从内存流中保存图像时遇到了一些麻烦。

这是我的代码:

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一切都没问题,但一段时间后需要大量内存。

我该怎么做?

编辑:Save只是演示..我真的需要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 个答案:

答案 0 :(得分:4)

根据documentation

  

您必须在Bitmap的生命周期内保持流打开。

位图需要将其数据存储在同一个地方,我推断(虽然没有证据证明这一点)Bitmap不会复制数据,而是使用流来保持锁定。

此外,没有证据表明Clone将使用字节表示的副本创建新的位图。而你的测试用例表明它不是一个案例。

因此,我担心您需要在图片的生命周期内保持您的信息流畅通。它需要内存,true,但是如果Bitmap复制了数据,你仍然需要那个内存用于位图表示。因此,开放流不会消耗更多内存(如果我以前的推论是真的)。​​

如果你真的想要克服位图对原始内存流的依赖性,你需要绘制新的原始位图而不是克隆,如{{ 3}}。 但是这会影响性能,我最好重新分析是否保留原始流不是一个好主意,只是确保在位图处理时它已关闭。

答案 1 :(得分:2)

基本上不是保存到磁盘克隆吗?

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