Wpf-将画布另存为图像并将图像加载到画布.错误:“;被另一个过程使用”;

本文关键字:图像 另一个 过程 错误 另存为 加载 Wpf- | 更新日期: 2023-09-27 18:19:33

我正在尝试将一个包含一些形状的画布保存为图像(*.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;
        }

Wpf-将画布另存为图像并将图像加载到画布.错误:“;被另一个过程使用”;

当您加载图像并试图通过覆盖它来保存它时,引用到其物理文件的图像仍然由您的应用程序使用,因此该文件不能被覆盖。我想,当您从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();
  }
}

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

文件仍然被锁定,因为您直接在笔刷中引用它。如果没有一个可靠地再现问题的好的、最小的complete代码示例,就不可能确切地知道最佳解决方案是什么。但最有可能的是,如果你在画笔中使用位图对象之前只是克隆它,那么当你再次尝试保存到文件时,它就会被释放。

例如:

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

不幸的是,我不知道有好的确定性方法可以强制关闭BitmapImage对象,尤其是它对文件的引用。你可以调用Freeze(),它可能会断开与文件的连接(但我还没有尝试过)。或者,强制垃圾收集也可以(即调用GC.Collect())。