7

我正在尝试显示存储在Windows Phone 8.1(RT)应用程序的本地文件夹中的GIF文件。到目前为止,我已经尝试了几种方法:如何在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); 
     } 
    } 

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

like this one

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

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

ImageTools仅适用于Silverlight的

+0

这些日子人们还在使用动画.gif吗?我讨厌甚至不得不提出保留它,但你可以做'' - 虽然我猜如果你要保留它,让我知道,我会把它作为回答,所以我可以拿出一些简单的点。 :) – 2014-10-02 19:29:18

+1

我已经尝试添加一个MediaElement到页面,并设置gif文件作为其源。在将'AreTransportControlsEnabled'设置为true后,我可以看到错误消息:'不支持的视频类型或无效的文件路径'。此外,GIF文件的路径设置正确。 – rhcpfan 2014-10-03 07:11:14

+0

可能发誓我之前使用过它,也许不是WP?如果我有时间的话,我会稍后修改它。对于那个很抱歉。 – 2014-10-03 12:46:18

回答

6

我做了一个非常基本控制GifImage,您可以从启动。 这是一个起点,您必须对其进行改进才能使其更可用作可重用控件。检查一下here

GifImage windows phone screenshot


编辑

你有什么想法如何提高加载速度(并行等)?

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

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

如果我将此控件设置为FlipViewItem,在物品翻转后如何释放内存?

我不知道你是否正在使用MVVM与否,但无论如何,这里有一些建议:

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

谢谢你的解决方案!我只做了小测试,但它工作正常。 你有什么想法如何提高加载速度(并行化等)? 此外,如果我将此控件作为FlipViewItem使用,在物品翻转后如何释放内存? 再次感谢您的时间! – rhcpfan 2014-10-06 13:53:08

2

我有类似的问题。我试图显示一个从Windows Phone 8.1应用程序的ScrollViewer内部的外部源加载的GIF动画。由于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>