[英]Showing animated gif in Winforms without locking the file
I'm trying to display images of various file types (including animated .gif files) in my Winforms application. 我正在尝试在Winforms应用程序中显示各种文件类型的图像(包括动画.gif文件)。 I also have to be able to modify the files that are shown .
我还必须能够修改显示的文件 。 (change the file name, delete them).
(更改文件名,删除它们)。
The problem is that a Picturebox locks the image file until the application is closed when using the normal way. 问题是Picturebox锁定图像文件,直到应用程序关闭时使用正常方式。
That means I can't do this: 这意味着我不能这样做:
private void Form1_Load(object sender, EventArgs e)
{
PictureBox pic = new PictureBox();
pic.Size = new Size(250, 250);
pic.Image = Image.FromFile("someImage.gif");
this.Controls.Add(pic);
//No use to call pic.Image = null or .Dispose of it
File.Delete("someImage.gif"); //throws exception
}
The workaround in the link above is as follows: 上面链接中的解决方法如下:
private void Form1_Load2(object sender, EventArgs e)
{
PictureBox pic = new PictureBox();
pic.Size = new Size(250, 250);
//using a FileStream
var fs = new System.IO.FileStream("someImage.gif", System.IO.FileMode.Open, System.IO.FileAccess.Read);
pic.Image = System.Drawing.Image.FromStream(fs);
fs.Close();
this.Controls.Add(pic);
pic.MouseClick += pic_MouseClick;
}
That works fine for normal image types, but it won't load animated .gifs, which is important to me. 这适用于普通图像类型,但它不会加载动画.gifs,这对我很重要。 Trying to load one will make it look like this .
尝试加载一个将使它看起来像这样 。
I've found a few other topics about it ( this and this ) but they're all about WPF and use BitmapImage. 我已经找到了一些关于它的主题( 这个和这个 ),但它们都是关于WPF并使用BitmapImage。 I've searched about how to use BitmapImage in a Winforms application, but haven't found anything apart from that it is supposed to somehow work.
我已经搜索了如何在Winforms应用程序中使用BitmapImage,但除了应该以某种方式工作之外没有找到任何东西。
I would like to stay with Winforms because I'm just getting used to it, but that's not a necessity. 我想留在Winforms,因为我只是习惯了它,但这不是必需品。
To summarize: I need a way to show common image types (png, jpg, bmp, and animated gif) while still being able modify the file on the HDD. 总结一下:我需要一种方法来显示常见的图像类型(png,jpg,bmp和动画gif),同时仍然能够修改HDD上的文件。 It is OK if that means unloading->modifying->reloading the file.
如果这意味着卸载 - >修改 - >重新加载文件,那就没关系。 I'd prefer Winforms, but other Frameworks would do.
我更喜欢Winforms,但其他框架也可以。
Thanks for your help. 谢谢你的帮助。
Edit: Another way I've tried 编辑:我尝试过的另一种方式
using (System.IO.FileStream fs = new System.IO.FileStream("E:\\Pics\\small.gif", System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
System.IO.MemoryStream ms = new System.IO.MemoryStream();
fs.CopyTo(ms);
pic.Image = Image.FromStream(ms);
}
But shows the same problem as the second example. 但显示与第二个例子相同的问题。 The gif doesn't load.
gif没有加载。
Using a MemoryStream is indeed the right way to avoid the file lock. 使用MemoryStream确实是避免文件锁定的正确方法。 Which is a strong optimization btw, the lock is created by the memory-mapped file that the Image class uses to keep the pixel data out of the paging file.
这是一个强大的优化btw,锁是由内存映射文件创建的,Image类用它来保持像素数据不在页面文件中。 That matters a great deal when the bitmap is large.
当位图很大时,这很重要。 Hopefully not on an animated gif :)
希望不是动画的GIF :)
A small mistake in your code snippet, you forgot to reset the stream back to the start of the data. 您的代码段中的一个小错误,您忘记将流重置回数据的开头。 Fix:
固定:
using (var fs = new System.IO.FileStream(...)) {
var ms = new System.IO.MemoryStream();
fs.CopyTo(ms);
ms.Position = 0; // <=== here
if (pic.Image != null) pic.Image.Dispose();
pic.Image = Image.FromStream(ms);
}
In case it needs to be said: do not dispose the memory stream. 在情况下,它需要说:请不要将其内存流。 That causes very hard to diagnose random crashes later, pixel data is read lazily.
这导致很难诊断随后的随机崩溃,像素数据被懒惰地读取。
Essentialy you'll have to make a copy of the image file in your memory . 实际上,您必须在内存中制作图像文件的副本 。
Pre .Net 4.0
(2.0,3.0,3.5) you'd have to create a FileStream and copy it to a MemoryStream and rewind it, as seen in another answer. 在
.Net 4.0
(2.0,3.0,3.5)之前,你必须创建一个FileStream并将其复制到MemoryStream并回放它,如另一个答案所示。
Since .Net 4.0
(4.0,4.5,...) Image.FromFile supports animated GIF's 由于
.Net 4.0
(4.0,4.5,...)Image.FromFile支持动画GIF
If you work with .Net 4.0
or later following method will suffice: 如果您使用
.Net 4.0
或更高版本,则以下方法就足够了:
Using System.IO
, System.Drawing
and System.Drawing.Imaging
使用
System.IO
, System.Drawing
和System.Drawing.Imaging
private void Form1_Load(object sender, EventArgs e)
{
string szTarget = "C:\\someImage.gif";
PictureBox pic = new PictureBox();
pic.Dock = DockStyle.Fill;
Image img = Image.FromFile(szTarget); // Load image fromFile into Image object
MemoryStream mstr = new MemoryStream(); // Create a new MemoryStream
img.Save(mstr, ImageFormat.Gif); // Save Image to MemoryStream from Image object
pic.Image = Image.FromStream(mstr); // Load Image from MemoryStream into PictureBox
this.Controls.Add(pic);
img.Dispose(); // Dispose original Image object (fromFile)
// after this you should be able to delete/manipulate the file
File.Delete(szTarget);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.