Wpf - 将画布保存为图像并将图像加载到画布。错误:"被另一个进程使用"

时间:2015-10-27 03:08:51

标签: c# wpf canvas

我试图将包含某些形状的画布保存为图像(* .jpg,* .bmp,* .png)并再次将该图像加载到画布。

当我点击"保存按钮"然后我点击"加载按钮"然后我点击了"保存按钮"再次,我有以下错误:

进程无法访问文件' H:\ VisualC \ HK5 \ LT Win \ ForTesting \ TestSaveCanvasToBitmap \ bin \ Debug \ TestImage.bmp'因为它正被另一个进程使用。

似乎有一个文件流已打开但尚未关闭。 有人可以帮我解释一下吗?

提前致谢!

这是我的代码

public void SaveImage(Canvas canvas, int width, int height, string filePath)
        {
            Rect bounds = VisualTreeHelper.GetDescendantBounds(canvas);
            double dpi = 96d;
            RenderTargetBitmap rtb = new RenderTargetBitmap(width, height, dpi, dpi, System.Windows.Media.PixelFormats.Default);

            DrawingVisual dv = new DrawingVisual();
            using (DrawingContext dc = dv.RenderOpen())
            {
                VisualBrush vb = new VisualBrush(canvas);
                dc.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
            }

            rtb.Render(dv);

            BmpBitmapEncoder image = new BmpBitmapEncoder();
            image.Frames.Add(BitmapFrame.Create(rtb));

            using (Stream fs = File.Create(filePath))
            {
                image.Save(fs);
                fs.Close();
            }
        }
        private void btnSave_Click(object sender, RoutedEventArgs e)
        {
            int width = (int)myCanvas.ActualWidth;
            int height = (int)myCanvas.ActualHeight;
            string filePath = "TestImage.bmp";

            SaveImage(myCanvas, width, height, filePath);
        }

        private void btnLoad_Click(object sender, RoutedEventArgs e)
        {
            Uri uri = new Uri(@"TestImage.bmp", UriKind.Relative);

            BitmapImage bmi = new BitmapImage(uri);

            ImageBrush brush = new ImageBrush();
            brush.ImageSource = bmi;

            myCanvas.Background = brush;
        }

2 个答案:

答案 0 :(得分:0)

文件仍处于锁定状态,因为您直接在画笔中引用它。如果没有a good, minimal, complete code example可靠地再现问题,就无法确定最佳解决方案是什么。但最有可能的是,如果您只是在刷子中使用它之前克隆位图对象,那么当您再次尝试保存到该文件时,它将被释放。

例如:

BitmapImage bmi = new BitmapImage(uri).Clone();

不幸的是,我不知道强制BitmapImage对象的良好的确定性方法,特别是它对文件的引用是关闭的。您可以致电Freeze(),它会与文件断开连接(但我还没有尝试过)。或者,强制垃圾收集应该起作用(即调用GC.Collect())。

答案 1 :(得分:0)

加载图像并尝试通过覆盖保存图像时,应用程序仍会使用引用其物理文件的图像,因此无法覆盖该文件。我想当你从URI创建BitmapImage对象时,总是打开附加到文件的流。尝试像这样更改加载方法。

private void btnLoad_Click(object sender, RoutedEventArgs e)
{
  MemoryStream memoStream = new MemoryStream();

  using (FileStream fs = File.OpenRead("TestImage.bmp"))
  {
    fs.CopyTo(memoStream);

    BitmapImage bmi = new BitmapImage();

    bmi.BeginInit();

    bmi.StreamSource = memoStream;

    bmi.EndInit();

    ImageBrush brush = new ImageBrush(bmi);

    myCanvas.Background = brush;

    fs.Close();
  }
}

我们的想法是将文件流复制到内存流中,这样您的图像对象就会存在于不再依赖于文件的内存中。