C#将gif图像转换为内存流并还原(动画丢失)

13
我有一个小问题,但我找不到任何解决方案。 我想将GIF转换为byte [],然后再将其转换回GIF。 它可以正常工作,但是动画效果丢失了。 当我开始时,它是完美的动画GIF(我在PictureBox元素中展示它)。 但是转换后,我卡在了第一帧上。
HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create("creativetechs.com/i/tip_images/ExampleAnimation.gif");
HttpWebResponse httpWebReponse = (HttpWebResponse)httpWebRequest.GetResponse();
Stream stream = httpWebReponse.GetResponseStream();
Image img = Image.FromStream(stream);

MemoryStream ms = new MemoryStream();
img.Save(ms,img.RawFormat);
byte [] bytes = ms.ToArray();
Image img2 = Image.FromStream(new MemoryStream(bytes));

int frames1 = img.GetFrameCount(System.Drawing.Imaging.FrameDimension.Time);
int frames2 = img2.GetFrameCount(System.Drawing.Imaging.FrameDimension.Time);
我尝试使用的是System.Drawing.Imaging.ImageFormat.Gif而不是RawFormat,但结果没有任何变化。frames1包含正确数量的帧,frames2为1。
我的GUI中有两个PictureBox元素,一个显示img,另一个显示img2。但img2不带动画,而img带有动画。出了什么问题呢?
我也尝试过使用序列化来创建我的byte[]。我对图像进行了序列化和反序列化,但结果并没有发生任何变化。这是怎么可能的呢?

3
GDI+ GIF编码器不支持SaveAdd()函数和动画GIF。 - Hans Passant
你有没有考虑过这可能是GIF的问题?我刚刚尝试了你的代码,使用了这个GIF,它完全正常工作。frames1frames2都等于17。 - Michael Minton
我为什么能够从Web ResponseStream加载和可视化动画gif呢? - Oliver Bernhardt
好的,我会尝试这个GIF。 ... 没有任何不同的结果。 - Oliver Bernhardt
在问题标题中不需要写"[未解决]",因为当您接受一个答案时,它将显示为带有绿色答案计数的列表,因此很明显什么时候已经解决/未解决。 - Igby Largeman
3个回答

9
当您从Stream中加载图像时,.NET框架会检测到GIF动画。由于它知道无法重新编码动画GIF,因此尝试存储GIF的原始编码。但是这发生在读取流并解码GIF之后。因此,当它尝试倒回流时,失败了,最终没有存储原始编码。
当您调用Save()时,它首先检查是否已存储原始编码。但由于该操作失败,它尝试重新编码GIF。由于.NET没有针对动画GIF的编码器,因此它只编码第一帧。
如果您改用FileStream,它可以正常工作,因为FileStream是可寻址的。
您可以通过先将响应加载到MemoryStream中使代码正常工作:
// ...
Stream stream = httpWebReponse.GetResponseStream();

MemoryStream memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
memoryStream.Position = 0;
stream = memoryStream;

Image img = Image.FromStream(stream);
// ...

如果您想查看发生了什么,请启用.NET引用源代码调试,并注意Image.EnsureSave()中发生的情况。您还会注意到,Image实现已经将Stream复制到MemoryStream中,因此他们可以使用该MemoryStream而不是原始的Stream来解决问题。


Rasmus:你的解决方案不会受到这个问题的影响吗?http://support.microsoft.com/kb/814675“此外,如果在 Bitmap 对象的生命周期内销毁了流,则无法成功访问基于流的图像。”Bitmap 对象不保留对流的引用。如果流被处理,对 Bitmap 的引用将失败。当使用常规位图时,您可以摆脱它,但是如果您从流创建动画 GIF,则在某些系统上重新绘制动画 GIF 将失败。 - MindModel

2

如果从文件加载gif,则它可以完美运行,但如果从http响应中加载,则无法正常工作。 - Oliver Bernhardt

0

正如“Rasmus Faber”在2012年1月17日20:00所引述的==>我按照他的建议开发了我的图像滑块程序,效果非常好。非常感谢。 我的示例代码如下。能够无误地加载LPG和动画GIF,并且能够删除所有不必要的文件。

Dim t1 As String
t1 = ListBox5.SelectedItem.ToString
Dim mmp As MemoryStream
mmp = New MemoryStream()

Using str As Stream = File.OpenRead(t1)
str.CopyTo(mmp)
End Using
PictureBox8.Image = Image.FromStream(mmp)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接