B4A Library [B4X] APNG - animated PNG

elephant.png

(image source: https://apng.onevcat.com/demo/)

APNG is a format that extends PNG with support for animations, similar to animated gifs.
This class, which is implemented in B4X, extracts the frames from the APNG file and creates the animation.

It doesn't support all possible formats. If you encounter a file that is not supported then post it

Under the hood it uses RandomAccessFile + BytesBuilder + BitmapCreator + native CRC32 implementation to extract the frames, build temporary images that are loaded as regular bitmaps and then animate them.

Tip: You can use this tool to create APNG images: http://apngasm.sourceforge.net/

Versions history

- V1.10 - Adds support for images with inter-frame optimizations: http://littlesvr.ca/apng/inter-frame.html
 

Attachments

  • Example.zip
    395.9 KB · Views: 915
  • APNGView.b4xlib
    3.3 KB · Views: 648
Last edited:

Jorge M A

Well-Known Member
Licensed User
Is possible to have this with animated WEBP?
I don't know if it's related to your question, but maybe you missed this:
 

asales

Expert
Licensed User
Longtime User
I don't know if it's related to your question, but maybe you missed this:
Nope. Animated WebP is different.
It used in the new animated stickers to WhatsApp.
This lib works fine in B4J (in Android/B4A WebP has native support).
My goal is show the animated WebP like Erel made with this animated PNG.
 

ilan

Expert
Licensed User
Longtime User
wow, this is the first time i read about APNG. i never knew that there is another filetype that is animated like gif file.
this is very interesting.
 

saeed10051

Active Member
Licensed User
Longtime User
I am getting following error on running the example

Error description: Unknown member: internalbuffer
Error occurred on line: 246
CRC32.RunMethod("update", Array(Buffer.InternalBuffer, Start, Buffer.Length - Start))
Word: internalbuffer

Also in the log it says
unknown member append2
 

pkarim

Member
Licensed User
I am getting following error on running the example

Error description: Unknown member: internalbuffer
Error occurred on line: 246
CRC32.RunMethod("update", Array(Buffer.InternalBuffer, Start, Buffer.Length - Start))
Word: internalbuffer

Also in the log it says
unknown member append2
B4XCollections v1.08 should be copied to the internal libraries folder.
 

Guenter Becker

Active Member
Licensed User
Hi Erel,
I like to use APNG Object inside a custom View added as child of mBase in SUB Create.

What ist the correct way to initialize APNG inside a custom view, the code shown below leads to an Error on line 55
Using Sleep(0) does not help.
Writing Line SetData after Lines width/height does not help.

Custom View Cut out:
Sub Class_Globals
    'Globals
    Private mCallBack As Object 'ignore
    Private mEventName As String 'ignore
    Public Message As String
    Public doBeep As Boolean = False
    
    ' Objects
    Public mBase As B4XView
    Private xui As XUI 'ignore
    Public Tag As Object
    Public Label As Label
    Public APNG As APNGView
    Private signal As Beeper
    Private timer As Timer
End Sub
'## Function:    Initialize Globals + Objects
'## Parameter:    Callback (Root), Eventname (unique custom view name)
'## Return:        -
'## Remarks:    callback and eventname set automatically
'##                Sub called after load of custom view automatically
'## Tested:        2023/12/2 Version: wip()
Public Sub Initialize (Callback As Object, EventName As String)
    ' Globals
    mEventName = EventName
    mCallBack = Callback
    
    ' Objects
    Label.Initialize("label")
    signal.Initialize(300,300)
    timer.Initialize("tmr", 1000)
    APNG.Initialize(mCallBack,"apng")
End Sub
#end region

'###############################################

#region Base
'## Function:    Create View
'## Parameter:    -
'## Return:        -
'## Remarks:    -
'## Tested:        2023/12/2 Version: wip()
Public Sub DesignerCreateView (Base As Object, Lbl As Label, Props As Map)
    mBase = Base
    Tag = mBase.Tag
    mBase.Tag = Me
 
     ' customize and add label
    Label.Width = mBase.Width
    Label.Height = mBase.Height
    Label.Padding = Array As Int(5dip,5dip,5dip,5dip)
    mBase.AddView(Label,0,0,Label.Width,Label.Height)
    
    APNG.SetData(File.ReadBytes(File.DirAssets, "rolling.apng"))
    APNG.mBase.Width = Label.Height - 10dip
    APNG.mBase.Height = APNG.mbase.width
    APNG.mbase.top = Label.Top
    APNG.mBase.Left = 0
    APNG.mBase.Visible=False
    APNG.mBase.BringToFront
    mBase.AddView(APNG.mBase,Label.Width/2 -10dip - APNG.mBase.Width/2,5dip,APNG.mBase.Width,APNG.mBase.Height)
End Sub

Error Message:
** Service (starter) Start **
** Activity (main) Create (first time) **
Error occurred on line: 122 (APNGView)
java.lang.RuntimeException: Object should first be initialized (B4XView).
    at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:67)
    at anywheresoftware.b4a.objects.B4XViewWrapper.asViewWrapper(B4XViewWrapper.java:91)
    at anywheresoftware.b4a.objects.B4XViewWrapper.getWidth(B4XViewWrapper.java:144)
    at b4a.Standard.apngview$ResumableSub_Play.resume(apngview.java:325)
    at b4a.Standard.apngview._play(apngview.java:292)
    at b4a.Standard.apngview._setdata(apngview.java:246)
    at b4a.Standard.td_statusbar._designercreateview(td_statusbar.java:233)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:157)
    at anywheresoftware.b4a.objects.CustomViewWrapper.AfterDesignerScript(CustomViewWrapper.java:61)
    at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:147)
    at anywheresoftware.b4a.objects.PanelWrapper.LoadLayout(PanelWrapper.java:134)
    at anywheresoftware.b4a.objects.B4XViewWrapper.LoadLayout(B4XViewWrapper.java:329)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at java.lang.reflect.Method.invoke(Native Method)
 
Top