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

时间:2014-10-01 11:24:16

标签: windows-phone-8 windows-runtime winrt-xaml windows-phone-8.1 win-universal-app

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

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

    代码如下:

  3.     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);
            }
        }
    

    问题是我从GIF图像中得到的帧是搞砸了

    like this one

    这种方法我做错了吗?为了获得好结果,我应该修改什么?

    我不想使用SharpDX,因为它看起来非常复杂,我是初学者。

    ImageTools仅适用于Silverlight

2 个答案:

答案 0 :(得分:6)

我制作了一个非常基本GifImage控件,您可以从中开始。 这是一个起点,您必须对其进行改进,使其更适合作为可重复使用的控件。请查看here

GifImage windows phone screenshot


修改

  

您是否知道如何提高加载速度(并行化等)?

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

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

  

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

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

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

答案 1 :(得分:2)

我有类似的问题。我试图在ScrollViewer for Windows Phone 8.1应用程序中显示从外部源加载的动画GIF。由于Web控件接管事件,因此滚动不起作用。

我使用了这个技巧:我将Web控件放在网格中,并在web控件上放置另一个网格。 Web控件上的网格设置为完全相同的大小,我将背景设置为透明。这样,网格就会收到事件并且滚动会再次起作用。

<ScrollViewer Visibility="Visible" HorizontalAlignment="Left" VerticalAlignment="Top" Width="380">
    <Grid>
        <StackPanel>

            <!--
            Some items ...
            -->

            <Grid >
                <WebView x:Name="animationWebView" HorizontalAlignment="Left" Height="315" Width="390" Visibility="Visible" />
                <Grid Width="390" Height="315" Background="Transparent" />
            </Grid>

            <!--
            Some other items ...
            -->
        </StackPanel>
    </Grid>
</ScrollViewer>