#c# #vb.net #xaml #uwp
#c# #vb.net #xaml #uwp
Вопрос:
У меня есть этот анимированный png из этого API, и я хочу поместить его на чью-то фотографию профиля, но она отображается только как фотография в 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" />
Комментарии:
1. В UWP нет API для поддержки анимированного изображения PNG. Мы предлагаем вам использовать GIF-изображение в качестве анимированного iamge . Вы можете получить более подробную информацию об анимированном изображении GIF, обратившись к образцу .
2. @YanGu-MSFT проблема в том, что ответы API — это только png, поэтому, когда я конвертирую img в gif в любом месте, я получаю изображение с плохим размытием.
3. Я действительно ценю, что вы нашли время поделиться своими мыслями. Однако на данный момент нет поддержки API для анимации анимированного изображения png, предоставляемого вашим веб-сайтом.
Ответ №1:
Когда я опубликовал это, я только что заметил, что это старый пост, но, возможно, кто-то воспользуется им в будущем.
На самом деле, есть кое-что, с чем вы можете работать:
Извините, я только что заметил, что это вопрос UWP, не уверен, как WPF переводится в UWP, но мой ответ работает в WPF, но вы можете использовать класс box и просто нужно изменить конвертер.
Я изменил эту библиотеку https://github.com/murrple-1/APNGManagement и это работает.
Он был написан на C # и нацелен на winforms .NET framework 4.xx что-то. Но я использовал его в VB.NET и на .NET5.0 без проблем.
Что я сделал, так это клонировал репозиторий и добавил ссылку APNGLib
на мой проект (the .dll-файл, который вы получаете при компиляции / сборке).
Затем создал usercontrol (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
as 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
Обратите внимание, что в моем случае возврат не требуется, потому что я не мог понять, как обновить свойство при преобразовании, чтобы элемент управления изображением заметил. Вместо этого я просто устанавливаю свойство container 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
Это изображение добавлено в исходный код github с помощью winforms: