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