从文件中打开图像,然后释放锁定?
Posted
技术标签:
【中文标题】从文件中打开图像,然后释放锁定?【英文标题】:Open Image from file, then release lock? 【发布时间】:2011-09-28 09:55:47 【问题描述】:我正在使用以下代码行从文件中打开Image
:
pictureBox1.Image = Image.FromFile("test.png");
我希望它锁定文件,将图像加载到内存,将pictureBox1.Image
设置为内存中的副本,然后释放锁定。实际上,直到我在内存中的Image
中的Dispose()
之前,锁才会消失。在我正在使用的内存中的文件删除之前,我无法释放硬盘上不再使用的文件的锁定。
微软的网站在一篇标有 C# 的文章中提到了它,但是他们的解决方案是用 visual basic 编写的,这对我来说毫无用处。
总结:
我想将pictureBox1.Image
设置为存储在"test.png"
中的图像,然后让用户编辑或删除"test.png"
或其他任何东西。
【问题讨论】:
.Net 的优点是 VB 代码很容易翻译成 C#,反之亦然:developerfusion.com/tools/convert/vb-to-csharp 您的图片是 GIF 吗?此条目中的当前答案不适用于此。请参阅此***.com/a/22017675/354756 【参考方案1】:使用流的方法不正确。
请看这里https://***.com/a/8701748/355264
以上链接的正确代码:
Image img;
using (var bmpTemp = new Bitmap("image_file_path"))
img = new Bitmap(bmpTemp);
【讨论】:
是的,你的应该是接受的答案。将代码粘贴到您的答案中 有关正在发生的事情的详细讨论,请参阅this answer。值得注意的是,.Clone()
方法将保持文件锁定,即使在原始文件为 .Disposed()
之后也是如此。复制构造的克隆,如本答案所示,是这样做的方法。
Better approach 如果要保留原始位图的 PixelFormat。【参考方案2】:
或者更好的是,使用using
语句(下面的代码是从 sylon 的 [已删除] 帖子中复制的)。这样,如果Image.FromStream
抛出异常,您仍然可以确保流立即关闭。
using (FileStream stream = new FileStream("test.png", FileMode.Open, FileAccess.Read))
pictureBox1.Image = Image.FromStream(stream);
【讨论】:
非常糟糕。你永远不要这样做,它会在以后引起问题。阅读:***.com/a/8701748/355264 路人,不要这样做。最好在打开后复制构造Image
或Bitmap
,然后复制构造用于从文件打开的.Dispose()
。这将释放文件锁定。请注意,.Clone()
副本将保持文件锁定,即使在原始文件为 .Disposed()
之后也是如此。复制构造的副本将释放文件锁定。 See here.
如果你这样做,你会得到 GDI+ 错误,如果你尝试 .Clone() 图像也会出现“OutOfMemory”错误。
我喜欢这种方法,因为 .NET 4.6.2/4.7 和 .NET Core 中的 FileStream 有第三个参数,它允许在读取时释放锁以允许多个用户同时读取相同的文件。但是,我使用 ImageMagick 进行转换。【参考方案3】:
您也可以使用流读取图像然后关闭流。
FileStream stream = new FileStream("test.png", FileMode.Open, FileAccess.Read);
pictureBox1.Image = Image.FromStream(stream);
stream.Close();
【讨论】:
【参考方案4】:我发现的最简单的方法是冻结包含源(文件路径)的对象。所有可以包含图像的控件,似乎都有一个 .Source,如果不为空,它将锁定它指向的文件。
现在的诀窍是将 Image 控件更改为“只读”状态,然后解锁文件。
我的解决方案:
private Image CreatePreviewImage()
Image ReportImage = new Image();
Uri path = new Uri(@"C:\Folder\Image1.png");
if (File.Exists(path.OriginalString))
ReportImage.Name = "Report1";
ReportImage.Source = LoadImageFromFile(path);
return ReportImage;
public ImageSource LoadImageFromFile(Uri path)
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = path;
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
bitmap.DecodePixelWidth = 900;
bitmap.EndInit();
bitmap.Freeze(); //This is the magic line that releases/unlocks the file.
return bitmap;
【讨论】:
注意:BitmapImage
是一个 WPF 类;最初的问题是关于 WinForms Bitmap
。很高兴看到,如果有人使用 WPF,BitmapImage
为这个长期存在的烦恼提供了解决方案。【参考方案5】:
谈论开放、阅读和释放
StreamReader streamReader = new StreamReader("picture.png"); 位图 tmpBitmap = (Bitmap)Bitmap.FromStream(streamReader.BaseStream); streamReader.Close(); 图片框1.Image = tmpBitmap;`【讨论】:
你所说的“敞开心扉”是什么意思? 我刚刚阅读了主要问题“打开图像文件”,所以我假设第一个操作是定位图像文件以获取路径和文件名。我理解这个问题是否有误? 4行代码由“Open”作为第一行,“Read”作为第二行,“Release”作为第三行组成。以及额外的第 4 行来显示结果。 这似乎是一个很好的答案,我只是不知道你所说的“说话”是什么意思 这似乎类似于五年前的lahsrah's answer。以上是关于从文件中打开图像,然后释放锁定?的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server:本地查询时间与网络查询时间...和锁定