繁体   English   中英

如何在 UWP 中使用动画 PNG?

[英]How can I use animated PNG in UWP?

我有这个api 的动画 png ,我想把它放在某人的个人资料照片上,但它只显示为 1 帧照片。

我有BitmapDecoder但我不知道如何在 XAML 中设置它。

在此处输入图像描述

任何人都可以帮助我吗?

到目前为止,我已经尝试过这个并给了我一个冻结的 img:

<Image   Source="https://steamcdn-a.akamaihd.net/steamcommunity/public/images/items/1263950/ebe6b674deca163b28423e3b925bd36b0f0f357b.png" />

这给了我一个糟糕的黑白图像:

<BitmapIcon   UriSource="https://steamcdn-a.akamaihd.net/steamcommunity/public/images/items/1263950/ebe6b674deca163b28423e3b925bd36b0f0f357b.png" />

当我发布此内容时,我只是注意到这是一篇旧帖子,但也许将来有人会使用它。

实际上,您可以使用以下方法:

Sorry, I Just noticed that this is a UWP question, not sure how WPF translates to UWP, but my answer works in WPF, but you can use the box class and just need to modify the converter.

我已经修改了这个库https://github.com/murrple-1/APNGManagement并且它有效。

它是用 C# 编写的,它针对 winforms .NET 框架 4.xx 的东西。 但我在 VB.NET 和 .NET5.0 上使用它没有问题。

我所做的是克隆存储库并将引用APNGLib添加到我的项目(您从编译/构建中获得的.dll 文件)。

然后创建一个用户控件(WPF)来保存图像:

XAML

<UserControl x:Class="ApngImg"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ToolSet"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Image x:Name="APNGcontrolIMG" Width="200" Height="200"/>
    </Grid>
</UserControl>

在 xaml 后面的代码中:


Imports System.IO
Imports APNGLib

Public Class ApngImg

    
    Sub New()
        DataContext = Me
        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        Dim pngFilePath As String = "C:\ebe6b674deca163b28423e3b925bd36b0f0f357b.png"
        Dim png As New APNG 'picturebox
        Using s As Stream = File.OpenRead(pngFilePath)
            png.Load(s)
        End Using
        Dim boxy As New APNGBox(png, APNGcontrolIMG)

    End Sub

然后编辑了原始的APNGViewer_WinForms APNGBox (从 C# 翻译成 VB.NET)

All i did was add container as System.Windows.Controls.Image to constructor, added private property for the container and added a function, which converts System.Drawing.Bitmap to System.Windows.Media.Imaging.BitmapImage so that the image could在 wpf 图像控制中显示。

    Public Function Convert(ByVal src As Bitmap) As BitmapImage
        Dim ms As MemoryStream = New MemoryStream()
        src.Save(ms, System.Drawing.Imaging.ImageFormat.Png)
        Dim image As BitmapImage = New BitmapImage()
        image.BeginInit()
        ms.Seek(0, SeekOrigin.Begin)
        image.StreamSource = ms
        image.EndInit()
        IMGcontainer.Source = image
        Return image
    End Function

请注意,在我的情况下不需要返回,因为我无法弄清楚在进行转换时如何更新属性以便图像控件会注意到。 相反,我只是设置了容器 Source 属性。

这很hacky,但有效。

这是完整的 APNGBox class:

Imports System
Imports System.Collections.Generic
Imports System.Drawing
Imports System.Windows.Forms
Imports APNGLib
'addition made by dumi
Imports System.IO
Imports System.Windows.Media.Imaging
Imports System.ComponentModel
'---------------------------------------------------------
Public Class APNGBox
    Inherits PictureBox
    'addition made by dumi
    Implements INotifyPropertyChanged
    Public Event PropertyChanged As PropertyChangedEventHandler _
        Implements INotifyPropertyChanged.PropertyChanged

    Public Sub NotifyPropertyChanged(ByVal info As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
    End Sub
    '---------------------------------------------------------
    Public Property CurrentFrameNumber As Integer
    Public Property Images As IList(Of Bitmap)
    Private APNGFile As APNG
    'addition made by dumi
    Private IMGcontainer As System.Windows.Controls.Image
    '---------------------------------------------------------
    Private timer As Timer
    Private playthroughs As UInteger
    Private _ImageBitmap As BitmapImage

    'addition made by dumi
    Public Property ImageBitmap As BitmapImage
        Get
            Return _ImageBitmap
        End Get
        Set
            _ImageBitmap = Value
            NotifyPropertyChanged(NameOf(ImageBitmap))
        End Set
    End Property
    '---------------------------------------------------------

    Public Sub New(ByVal png As APNG, Container As System.Windows.Controls.Image)
        APNGFile = png
        'addition made by dumi
        IMGcontainer = Container
        '---------------------------------------------------------
        CurrentFrameNumber = 0
        Images = New List(Of Bitmap)()
        InitImages()
        'addition made by dumi
        ImageBitmap = Convert(Images(0))
        '---------------------------------------------------------
        Image = Images(0)
        Size = Image.Size
        playthroughs = 0

        If APNGFile.IsAnimated Then
            timer = New Timer()
            timer.Interval = APNGFile.GetFrame(0).Milliseconds
            AddHandler timer.Tick, New EventHandler(AddressOf timer_Tick)
        End If
    End Sub

    'addition made by dumi
    Public Function Convert(ByVal src As Bitmap) As BitmapImage
        Dim ms As MemoryStream = New MemoryStream()
        src.Save(ms, System.Drawing.Imaging.ImageFormat.Png)
        Dim image As BitmapImage = New BitmapImage()
        image.BeginInit()
        ms.Seek(0, SeekOrigin.Begin)
        image.StreamSource = ms
        image.EndInit()
        IMGcontainer.Source = image
        Return image
    End Function
    '---------------------------------------------------------
    Private Sub timer_Tick(ByVal sender As Object, ByVal e As EventArgs)
        If APNGFile.MaxPlays = 0 OrElse playthroughs < APNGFile.MaxPlays Then
            NextImage()
            Dim f As Frame = APNGFile.GetFrame(CurrentFrameNumber)
            timer.Interval = f.Milliseconds
        End If
    End Sub

    Private Sub InitImages()
        If APNGFile.IsAnimated Then
            Dim current As Bitmap = New Bitmap(CInt(APNGFile.Width), CInt(APNGFile.Height))
            Dim previous As Bitmap = Nothing
            ImageRender.RenderNextFrame(current, Point.Empty, APNGFile.ToBitmap(0), Frame.BlendOperation.SOURCE)
            Images.Add(New Bitmap(current))

            For i As Integer = 1 To APNGFile.FrameCount - 1
                Dim oldFrame As APNGLib.Frame = APNGFile.GetFrame(i - 1)
                Dim prev As Bitmap = If(previous Is Nothing, Nothing, New Bitmap(previous))

                If oldFrame.DisposeOp <> APNGLib.Frame.DisposeOperation.PREVIOUS Then
                    previous = New Bitmap(current)
                End If

                ImageRender.DisposeBuffer(current, New Rectangle(CInt(oldFrame.XOffset), CInt(oldFrame.YOffset), CInt(oldFrame.Width), CInt(oldFrame.Height)), oldFrame.DisposeOp, prev)
                Dim currFrame As APNGLib.Frame = APNGFile.GetFrame(i)
                ImageRender.RenderNextFrame(current, New Point(CInt(currFrame.XOffset), CInt(currFrame.YOffset)), APNGFile.ToBitmap(i), currFrame.BlendOp)
                Images.Add(New Bitmap(current))
            Next
        Else
            Images.Add(APNGFile.ToBitmap())
        End If
    End Sub

    Public Sub NextImage()
        CurrentFrameNumber += 1

        If CurrentFrameNumber >= APNGFile.FrameCount Then
            playthroughs += 1
            CurrentFrameNumber = 0
        End If
        'addition made by dumi
        ImageBitmap = Convert(Images(CurrentFrameNumber))
        '---------------------------------------------------------
        Image = Images(CurrentFrameNumber)
    End Sub

    Public Sub ToImage(ByVal index As Integer)
        'addition made by dumi
        ImageBitmap = Convert(Images(index))
        '---------------------------------------------------------
        Image = Images(index)
        CurrentFrameNumber = index
    End Sub

    Public Sub Start()
        If timer IsNot Nothing Then
            timer.Start()
        End If
    End Sub

    Public Sub [Stop]()
        If timer IsNot Nothing Then
            timer.[Stop]()
        End If
    End Sub
End Class

这是使用 winforms 添加到原始 github 代码中的图像: 这是添加到原始 github 代码中的图像

这是我在 wpf 中的结果: 这是来自我的 wpf 应用程序

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM