.NET - 使用 GifBitmapEncoder 创建循环 .gif [英] .NET - Creating a looping .gif using GifBitmapEncoder

查看:26
本文介绍了.NET - 使用 GifBitmapEncoder 创建循环 .gif的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一些代码以使用 GifBitmapEncoder 从 WPF 应用程序导出动画 .gif.到目前为止,我所做的工作正常,但是当我查看生成的 .gif 时,它只运行一次然后停止 - 我希望它无限循环.

I'm trying to write some code to export animated .gifs from a WPF application using GifBitmapEncoder. What I have so far works fine but when I view the resulting .gif it only runs once and then stops - I'd like to have it looping indefinitely.

我发现了以前的类似问题:

I've found this previous similar question:

我该怎么做使用 BitmapEncoder 生成时循环重复 GIF

但是,他使用的是来自 Windows.Graphics.Imaging 的 BitmapEncoder 而不是 Windows.Media.Imaging 版本,这似乎有点不同.尽管如此,这给了我一个方向,经过更多的谷歌搜索后,我想出了这个:

However, he is using the BitmapEncoder from Windows.Graphics.Imaging rather than the Windows.Media.Imaging version, which seems to be a bit different. Nonetheless, that gave me a direction and after a bit more googling I came up with this:

Dim encoder As New GifBitmapEncoder
Dim metaData As New BitmapMetadata("gif")
metaData.SetQuery("/appext/Application", System.Text.Encoding.ASCII.GetBytes("NETSCAPE2.0"))
metaData.SetQuery("/appext/Data", New Byte() {3, 1, 0, 0, 0})

'The following line throws the exception "The designated BitmapEncoder does not support global metadata.":
'encoder.Metadata = metaData

If DrawingManager.Instance.SelectedFacing IsNot Nothing Then
   For Each Frame As Frame In DrawingManager.Instance.SelectedFacing.Frames
       Dim bmpFrame As BitmapFrame = BitmapFrame.Create(Frame.CombinedImage, Nothing, metaData, Nothing)
       encoder.Frames.Add(bmpFrame)
   Next
End If

Dim fs As New FileStream(newFileName, FileMode.Create)
encoder.Save(fs)
fs.Close()

最初我尝试将元数据直接添加到编码器(如上面代码中注释掉的行),但在运行时抛出异常指定的 BitmapEncoder 不支持全局元数据".我可以改为将我的元数据附加到每个帧,但尽管这不会使其崩溃,但生成的 .gif 也不会循环(我希望循环元数据无论如何都需要是全局的).

Initially I tried adding the metadata directly to the encoder (as in the commented-out line in the code above), but at runtime that throws the exception "The designated BitmapEncoder does not support global metadata". I can instead attach my metadata to each frame, but although that doesn't crash it the resultant .gif doesn't loop either (and I would expect that the looping metadata would need to be global anyway).

谁能给点建议?

推荐答案

我在学习了 这篇文章 并引用 GIF 文件的原始字节.如果你想自己这样做,你可以像这样使用 PowerShell 以十六进制格式获取字节...

I finally got this to work after studying this article and referencing the raw bytes of GIF files. If you want to do so yourself, you can get the bytes in hex format using PowerShell like so...

$bytes = [System.IO.File]::ReadAllBytes("C:\Users\Me\Desktop\SomeGif.gif")
[System.BitConverter]::ToString($bytes)

GifBitmapEncoder 似乎编写了标题、逻辑屏幕描述符,然后是图形控制扩展.缺少NETSCAPE2.0"扩展名.在 do 循环的其他来源的 GIF 中,缺少的扩展总是出现在图形控制扩展之前.

The GifBitmapEncoder appears to write the Header, Logical Screen Descriptor, then the Graphics Control Extension. The "NETSCAPE2.0" extension is missing. In GIFs from other sources that do loop, the missing extension always appears right before the Graphics Control Extension.

所以我只是在第 13 个字节之后插入字节,因为前两个部分总是这么长.

So I just plugged in the bytes after the 13th byte, since the first two sections are always this long.

        // After adding all frames to gifEncoder (the GifBitmapEncoder)...
        using (var ms = new MemoryStream())
        {
            gifEncoder.Save(ms);
            var fileBytes = ms.ToArray();
            // This is the NETSCAPE2.0 Application Extension.
            var applicationExtension = new byte[] { 33, 255, 11, 78, 69, 84, 83, 67, 65, 80, 69, 50, 46, 48, 3, 1, 0, 0, 0 };
            var newBytes = new List<byte>();
            newBytes.AddRange(fileBytes.Take(13));
            newBytes.AddRange(applicationExtension);
            newBytes.AddRange(fileBytes.Skip(13));
            File.WriteAllBytes(saveFile, newBytes.ToArray());
        }

这篇关于.NET - 使用 GifBitmapEncoder 创建循环 .gif的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆