如何在Windows Phone 8.1(RT)应用程序中显示动画GIF?

rhc*_*fan 7 windows-runtime winrt-xaml windows-phone-8 windows-phone-8.1 win-universal-app

我试图显示存储在Windows Phone 8.1(RT)应用程序的本地文件夹中的GIF文件.到现在为止,我尝试了几种方法:

  1. 在WebView控件中加载GIF.这不是解决方案,因为我想在FlipView控件中显示图像(我无法翻转到另一个图像).而且,它很慢.
  2. 使用BitmapDecoder类获取GIF帧,并使用故事板为它们设置动画.

    代码如下:

    using (var stream = await storageFile.OpenReadAsync())
    {
        //I don't specify the type since I would like to load other type of images also
        //It doesn't make any difference if I would use "BitmapDecoder.GifDecoderId"

        var decoder = await BitmapDecoder.CreateAsync(stream);
        uint frameCount = decoder.FrameCount;

        for (uint frameIndex = 0; frameIndex < frameCount; frameIndex++)
        {
            var frame = await decoder.GetFrameAsync(frameIndex);
            var writableBitmap = new WriteableBitmap((int)decoder.OrientedPixelWidth, 
                                                     (int)decoder.OrientedPixelHeight);

            var pixelDataProvider = await frame.GetPixelDataAsync
               (BitmapPixelFormat.Bgra8,
                decoder.BitmapAlphaMode, new BitmapTransform(),
                ExifOrientationMode.IgnoreExifOrientation, 
                ColorManagementMode.DoNotColorManage);

            var pixelData = pixelDataProvider.DetachPixelData();
            using (var pixelStream = writableBitmap.PixelBuffer.AsStream())
            {
                pixelStream.Write(pixelData, 0, pixelData.Length);
            }

            _bitmapFrames.Add(writableBitmap);
        }
    }
Run Code Online (Sandbox Code Playgroud)

问题是我从GIF图像得到的帧是混乱的

像这个

我在这种方法中做错了吗?我应该修改什么才能获得好结果?

我不想使用SharpDX,因为它似乎非常复杂,我是初学者.

ImageTools仅适用于Silverlight

Dec*_*oon 6

我做了一个非常基本的GifImage控制,你可以从这开始.这是一个起点,您必须对其进行改进,使其更可用作可重复使用的控件.检查它在这里.

GifImage windows手机截图


编辑

你知道如何提高加载速度(并行化等)吗?

我假设你指的是准备框架的过程.从我测试的内容来看,它似乎无论如何都会立即加载,因此不需要进行大幅度的性能改进.但是,如果动画可能有数百帧,那么它可能是一个瓶颈?需要进行更多测试以评估是否有必要进行优化.

我也不认为它可以很容易并行,因为每个帧需要从前一帧按顺序渲染.我唯一的建议是在后台线程上运行加载代码,这样UI线程就不会阻塞大图像.

如果我将此控件作为a FlipViewItem,如何在项目被翻转后释放内存?

我不确定你是否使用MVVM,但无论如何,这里有一些建议:

  • 设置SourceGifImage为空,如果它不是当前可见的(检查SelectedIndex翻转视图).请注意,目前我的repo中的代码不处理设置Source为null.就像我之前说的那样,它需要很多改进.您必须确保控件不包含对帧的任何引用,以便垃圾收集器可以从内存中释放它们(即,调用animation.KeyFrames.Clear()以清除对帧的所有引用).
  • VirtualizingStackPanel在翻转视图内使用.这将确保仅在内存中创建先前,当前和下一个翻转视图项.你这样设置:
<FlipView>
    <FlipView.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </FlipView.ItemsPanel>
</FlipView>
Run Code Online (Sandbox Code Playgroud)