从文件中打开图像,然后释放锁定?


73

我正在使用以下代码行Image从文件打开文件:

pictureBox1.Image = Image.FromFile("test.png");

我希望它可以锁定文件,将图像加载到内存,设置pictureBox1.Image为内存中的副本并释放锁定。在现实中,锁不会消失,直到我Dispose()Image记忆。我不能释放文件上的锁的硬盘,我不再使用,直到我摆脱了文件的存储,我正在使用。
微软的站点在带有C#标签的文章中对此进行了提及,但是他们的解决方案是使用Visual Basic编写的,这对我没有用。

总结:我想设置pictureBox1.Image存储在中的图像"test.png",然后让用户编辑或删除"test.png"


5
.Net的优点是VB代码易于转换为C#,反之亦然:developerfusion.com/tools/convert/vb-to-csharp
thomasb 2012年

您的图片是GIF吗?此项中的当前答案不适用于该内容。请改为查看此stackoverflow.com/a/22017675/354756
daniloquio

Answers:


98

使用stream的方法不正确

看到这里https://stackoverflow.com/a/8701748/355264

正确的代码从上面的链接:

Image img;
using (var bmpTemp = new Bitmap("image_file_path"))
{
    img = new Bitmap(bmpTemp);
}

2
是的,您应该是接受的答案。将代码粘贴到您的答案中
FrostyFire 2015年

1
要对发生的事情进行很好的讨论,请参见此答案。值得注意的是,.Clone()即使原始文件为,该方法也将保持文件锁定.Disposed()。如此答案中所述,复制构建的克隆是实现此目的的方法。
kdbanman

1
如果要保留原始位图的PixelFormat,则为更好的方法
ToolmakerSteve

47

最好还是使用一条using语句(否则,下面的代码是从sylon的[deleted]帖子中复制的)。这样,如果Image.FromStream引发异常,仍然可以确保流立即关闭。

using (FileStream stream = new FileStream("test.png", FileMode.Open, FileAccess.Read))
{
    pictureBox1.Image = Image.FromStream(stream);
}

7
很坏。您永远不会这样做,以后会引起问题。阅读
此书

3
路人,不要这样做。最好在打开文件后复制ImageBitmap,然后再.Dispose()从文件中打开文件。那将释放文件锁。请注意.Clone(),即使原始副本为,副本也会将文件锁定.Disposed()。复制构造的副本将释放文件锁定。 看这里。
kdbanman

1
如果以此方式执行操作,则尝试.Clone()映像时,将收到GDI +错误以及“ OutOfMemory”错误。

我喜欢这种方法,因为.NET 4.6.2 / 4.7和.NET Core中有FileStream的第三个参数,该参数允许在读取时释放锁,以允许多个用户同时读取同一文件。但是,我使用ImageMagick进行转换。
justdan23 '19

10

您还可以使用流读取图像,然后关闭流。

FileStream stream = new FileStream("test.png", FileMode.Open, FileAccess.Read);
pictureBox1.Image = Image.FromStream(stream);
stream.Close();

2

我找到的最简单的方法是冻结包含Source(文件路径)的对象。所有可以包含图像的控件似乎都有一个.Source,如果不为null,它将锁定其指向的文件。

现在的诀窍是将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;
    }

1
注意:BitmapImage是WPF类;最初的问题是关于WinForms的Bitmap。很高兴看到,如果使用WPF,BitmapImage可以为这种长期困扰提供解决方案。
ToolmakerSteve

0

交谈开放,阅读和发布

    StreamReader streamReader =新的StreamReader(“ picture.png”);
    位图tmpBitmap =(Bitmap)Bitmap.FromStream(streamReader.BaseStream);
    streamReader.Close();
    pictureBox1.Image = tmpBitmap;`
    


“公开交谈”是什么意思?
杰夫·普基特

我刚刚阅读了主要问题“打开图像文件”,因此我假设第一个操作是查找图像文件以获取路径和文件名..我错了吗?
psycobot's

1
这4行代码由“ Open”(第一行),“ Read”(第二行),“ Release”(释放)作为第三行组成。并附加第4行以显示结果。
psycobot's

看来这是一个不错的答案,我根本不知道您所说的“说话”是什么意思
杰夫·普基特

1
这似乎与五年前拉赫拉的答案相似。
ToolmakerSteve
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.