【问题标题】:Show frame of GIF in Image control在 Image 控件中显示 GIF 的帧
【发布时间】:2019-08-23 03:44:44
【问题描述】:

我尝试在 Image 控件中显示加载的 gif 图像(来自文件)的单帧。我在图像控件中显示(完整)gif 图像没有问题,但我无法显示框架。出于测试目的,我总是尝试加载帧“0”(第一帧)。

XAML:

<Image>
    <Image.Source>
        <BitmapImage x:Name="GifFrame" AutoPlay="False" />
    </Image.Source>
</Image>

我并没有在网上找到太多关于如何执行此操作的信息,但这里有一些代码片段,不幸的是,有些可能来自 WPF,我不能 100% 确定它们是否也可用于 UWP。

当打开图片时,会调用下面的“_OnImageOpened”方法(_gifStream是打开的gif图片,流还没有关闭):

private IRandomAccessStream _gifStream = null;

private async void GifImage_OnImageOpened(object sender, RoutedEventArgs e)
{
    // ...

    uint frameCount = 0;
    if (_gifStream != null)
    {
        var decoder = await BitmapDecoder.CreateAsync(_gifStream);
        frameCount = decoder.FrameCount;

        var frame = await decoder.GetFrameAsync(0);

        // Create frame image
        var pixelData = await frame.GetPixelDataAsync(
            BitmapPixelFormat.Bgra8,
            BitmapAlphaMode.Premultiplied,
            new BitmapTransform(),
            ExifOrientationMode.IgnoreExifOrientation,
            ColorManagementMode.DoNotColorManage
            ).AsTask().ConfigureAwait(false);
        var frameBytes = pixelData.DetachPixelData();
        var memoryStream = new MemoryStream(frameBytes);
        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                GifFrame.SetSource(memoryStream.AsRandomAccessStream());
            });
    }
}

当我设置新的源 (GifFrame.SetSource(...)) 时,窗口冻结并且没有任何反应,我必须终止该进程。在我围绕新源的设置添加 Dispatcher.RunAsync(...) 之前,我遇到了一个异常“应用程序调用了一个为不同线程编组的接口...”。

我不知道是什么原因造成的。也许我需要将字节转换为图像控件可以理解的内容,或者整个像素数据的创建是错误的?

【问题讨论】:

    标签: c# uwp uwp-xaml animated-gif memorystream


    【解决方案1】:

    这是实现您想要的目标的一种方法:

    XAML:

    <Page
        x:Class="App1.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid>
            <StackPanel>
                <Button Content="Open" Click="Button_Click" />
                <Image x:Name="Image" Width="100" Height="100" />
            </StackPanel>
        </Grid>
    </Page>
    

    代码:

    using System;
    using Windows.Graphics.Imaging;
    using Windows.Storage;
    using Windows.Storage.Pickers;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Media.Imaging;
    
    namespace App1
    {
        public sealed partial class MainPage
        {
            public MainPage()
            {
                InitializeComponent();
            }
    
            private async void Button_Click(object sender, RoutedEventArgs e)
            {
                var picker = new FileOpenPicker();
    
                picker.FileTypeFilter.Add(".gif");
    
                picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
    
                var file = await picker.PickSingleFileAsync();
                if (file == null)
                    return;
    
                var stream = await file.OpenAsync(FileAccessMode.Read);
    
                var decoder = await BitmapDecoder.CreateAsync(stream);
    
                var frame = await decoder.GetFrameAsync(0);
    
                var softwareBitmap = await frame.GetSoftwareBitmapAsync();
    
                var convert = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
    
                var softwareBitmapSource = new SoftwareBitmapSource();
    
                await softwareBitmapSource.SetBitmapAsync(convert);
    
                Image.Source = softwareBitmapSource;
            }
        }
    }
    

    结果:

    至少可以说相当复杂的过程......

    原始 GIF:

    您的实际错误是您尝试向SetSource 提供原始像素数据流,这不是what it expects

    【讨论】:

    • 谢谢,看起来很有希望。几个小时后会试试这个。我已经在试验“frame.GetSoftwareBitmapAsync();”但放弃了它,因为我不知道我是否走对了路。
    • 我注意到第 0 帧包含所有图像数据,其他帧似乎只是增量。但我还没有对此进行一些研究......也许是未来的stackoverflow问题:-)
    • 这很有趣!!!让我想起了 Media Foundation,它支持 MP3,但除非你解压缩整首歌曲,否则不可能精确搜索?如果我是你,我会去寻找更好的解码器,例如 github.com/mrousavy/AnimatedGif
    • 是的,我之前看过 AnimatedGif,但它看起来只适用于文件,而不适用于内存中的 GIF。那真的很不酷。
    • 只需 fork 并破解它,让它接受流应该不会太难。
    猜你喜欢
    • 1970-01-01
    • 2010-11-10
    • 2019-08-14
    • 1970-01-01
    • 2011-06-09
    • 2021-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多