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