【问题标题】:Wpf - Save canvas as image and Load image to canvas. Error: "being used by another process" [duplicate]Wpf - 将画布另存为图像并将图像加载到画布。错误:“被另一个进程使用”[重复]
【发布时间】:2015-10-27 23:13:12
【问题描述】:

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

【问题讨论】:

    标签: c# wpf canvas


    【解决方案1】:

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

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

    【讨论】:

    • 很好的解释。我已经解决了我的问题,谢谢。
    • 可能将此标记为答案?
    【解决方案2】:

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

    例如:

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

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

    【讨论】:

    • 感谢您的帮助。我已经用另一种解决方案解决了我的问题。
    猜你喜欢
    • 2021-06-20
    • 1970-01-01
    • 1970-01-01
    • 2016-08-28
    • 2017-12-26
    • 1970-01-01
    • 1970-01-01
    • 2013-06-23
    相关资源
    最近更新 更多