Windows 8 透過 Windows Imaging Component (WIC) 提供強大的影像編碼功能。本文示範如何使用 BitmapEncoder 與 GifEncoderId 建立翻頁式動畫 (Flipbook Animation) 並匯出為 GIF 檔案,核心技術來自 Flipflop 應用實作。
封裝動畫幀管理與 GIF 產生邏輯:
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Graphics.Imaging;
using Windows.Storage;
namespace Utilities
{
public sealed class GifMaker
{
readonly List frames = new List();
private readonly uint frameWidth;
private readonly uint frameHeight;
public GifMaker(uint width, uint height)
{
frameWidth = width;
frameHeight = height;
}
public void AppendNewFrame([ReadOnlyArray] byte[] frame)
{
frames.Add(frame);
}
public IAsyncInfo GenerateAsync(StorageFile file, int delay = 100)
{
return AsyncInfo.Run(async ctx =>
{
var outStream = await file.OpenAsync(FileAccessMode.ReadWrite);
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.GifEncoderId, outStream);
for (int i = 0; i < frames.Count; i++)
{
var pixels = frames[i];
encoder.SetPixelData(
BitmapPixelFormat.Rgba8,
BitmapAlphaMode.Ignore,
frameWidth, frameHeight,
92.0, 92.0, // DPI
pixels);
// 設定幀延遲 (僅第一幀需設定全域延遲)
if (i == 0)
{
var properties = new BitmapPropertySet
{
{ "/grctlext/Delay", new BitmapTypedValue(delay / 10, PropertyType.UInt16) }
};
await encoder.BitmapProperties.SetPropertiesAsync(properties);
}
if (i < frames.Count - 1)
await encoder.GoToNextFrameAsync();
}
await encoder.FlushAsync();
outStream.Dispose();
});
}
}
}
BitmapEncoder.GoToNextFrameAsync() 會在目前幀之後建立新的空白幀,讓開發者依序填入每一張動畫畫面。
透過 BitmapProperties 設定 Graphics Control Extension 的 Delay 欄位,單位為 1/100 秒:
var properties = new BitmapPropertySet
{
{ "/grctlext/Delay", new BitmapTypedValue(delay / 10, PropertyType.UInt16) }
};
await encoder.BitmapProperties.SetPropertiesAsync(properties);
使用 BitmapPixelFormat.Rgba8 (32-bit RGBA) 搭配 BitmapAlphaMode.Ignore,DPI 設為 92.0 (標準螢幕解析度)。
var picker = new Windows.Storage.Pickers.FileSavePicker();
picker.fileTypeChoices.insert("Gif files", [".gif"]);
picker.pickSaveFileAsync().then(function(file) {
if (!file) return;
var gifMaker = new Utilities.GifMaker(800, 600);
for (var i = 0; i < currentFlipflop.pages.length; i++) {
var bytes = Flipflop.Tools.GetBytesfromFlipflop(currentFlipflop.pages[i], 800, 600);
gifMaker.appendNewFrame(bytes);
}
gifMaker.generateAsync(file, 200).done();
});
GifMaker 實例,指定畫面寬高AppendNewFrame() 加入每一幀的像素位元組陣列GenerateAsync() 非同步產生 GIF 檔案delay 參數控制播放速度 (毫秒)

作者:cnblogs Kevin Fan