当我发布此内容时,我只是注意到这是一篇旧帖子,但也许将来有人会使用它。
实际上,您可以使用一些东西:
抱歉,我刚刚注意到这是一个 UWP 问题,不确定 WPF 如何转换为 UWP,但我的答案在 WPF 中有效,但您可以使用 box 类,只需要修改转换器。
我已经修改了这个库 https://github.com/murrple-1/APNGManagement 并且它可以工作。
它是用 C# 编写的,它以 winforms .NET framework 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)
我所做的只是将container 添加为System.Windows.Controls.Image 到构造函数,为容器添加私有属性并添加一个函数,将System.Drawing.Bitmap 转换为System.Windows.Media.Imaging.BitmapImage,以便图像可以显示在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 属性。
这很老套,但很有效。
这是完整的 APNGBox 类:
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 代码中的图像:
这是我在 wpf 中的结果: