lunedì 2 novembre 2009

Animated GIF using LWUIT

Since a couple of weeks ago, I'm working on moving my mobile applications to a new attractive user interface using LWUIT (LightWeigth User Interface Toolkit).
I found LWUIT really very impressive and the results are really excellent: my mobile apps now are much nicer then before.
But I found some little lacks in LWUIT. The most relevant is the lack of a class to manage animated GIF at runtime.
As of this writing, the current version of LWUIT supports animated gifs only if they are added in the resource file by the Resource Editor as "Animated Images". Such animated images can be added to a Label, to a Button or to another component and are animated when shown.
What I mean is that there are no way to use an animated GIF as animated image in a component if the gif is loaded at runtime from an input stream. Also, there is no way to manage the animation loop programmatically (i.e. stopping and starting the animation).
So, I googled a little to find a solution. First of all I found several posts related to that. This means that such a lack is involving several programmers. Second, I found the class GifDecoder ported to J2ME for decoding any animated gif.
Starting from that class and reading how the class StaticAnimation of LWUIT is implemented I wrote a new class AnimatedGIF, derived from the class com.sun.lwuit.Image, that allows to use animated gif at runtime in your applications.
You can use it as any other image.
The following is a snippet that shows how to create a Button with a animated gif image:

AnimatedGIF image = AnimatedGIF.createAnimatedGIF(
    new ByteArrayInputStream(btImage));
Button btn = new Button();
btn.setIcon(image);

The source code can be downloaded from here and it is published under LGPL.
Mainly this is the most relevant topics:
- the package must be com.sun.lwuit because I need the costructor Image(Object) that has package visibility (I think it should have protected visibility)
- an animated gif is rapresented as an array of frames
- the frames are generated by the class GifDecoder
- a gif is animated if it has more then one frame
- the animation can be started and stopped on demand by the method start and stop
- the loop counter can be set by the method setLoopCount
- the rest of the code has been taken and adapted from the class StaticAnimation

For more info about LWUIT visit this url http://lwuit.dev.java.net).

14 commenti:

Alok ha detto...

Thanks a lot Ugo. I was looking forward for this one, Will try it out now :)

mikezang ha detto...

Hi, Ugo
I tried your class, I got error as below when I run it, do you know why?

ALERT: java/lang/VerifyError: com/sun/lwuit/AnimatedGIF$GifDecoder

Ugo Chirico ha detto...

Hi Mikezang,
It's very strange. I'm using it without any problem.
What preverifier are you using?

mikezang ha detto...

Thanks for your reply.
I am using C:\Program Files\NetBeans 6.7\mobility8\Java_ME_platform_SDK_3.0.
Then that error don't happen if I run a special Proguard, I can send proguard config file to you if you want to confirm.

Jasmeet ha detto...

hey can u please be kind enuf to tell me, how do i put your class in com.sun.lwuit . kindly reply :)

PS : amazing job. i am exited to test it !!

Jasmeet ha detto...

ok, i got that done...but the problem is you are asking for byte array as an argument. i have an image which i want to animate...and i cant find a way to convert this image into pngbytearray. thanks for help.

Shai Almog ha detto...

Thanks for the great code Ugo. I posted a modified version to the incubator/blog with an example of how to seamlessly integrate this with LWUIT without modifying code:
http://lwuit.blogspot.com/2010/05/animated-gifs-everywhere.html

Mohammad Abu Hmead ha detto...

This does not work by sadly,
i copied your class,
and it does not work,
I want to solve problem, please if you have any way to solve animated gif problem in lwuit please help me!

Ugo Chirico ha detto...

In my apps it works perfectly.
What does exactly happen in you app?

Mohammad Abu Hmead ha detto...

Please if you can, Upload the solution

Ugo Chirico ha detto...

I cannot upload one of my apps!!!
Please why you are saying that it doesn't work?

Mohammad Abu Hmead ha detto...

when i try to use it, the first frame had been displayed, this is the code snippet :

Label figureLabel=new Label();
figureLabel.getStyle().setBgTransparency(255);
figureLabel.getStyle().setFgColor(0x000000);
// figureLabel.getStyle().setBgColor(0xFFACCD);
figureLabel.setAlignment(Label.CENTER);
AnimatedGIF image=null;
try {
image = AnimatedGIF.createAnimatedGIF(new ByteArrayInputStream(obtainByteData(imgName)));
image.start();
figureLabel.setIcon(image);
figureLabel.animate();
registerAnimated(figureLabel);

} catch (IOException ex) {
ex.printStackTrace();
}

getContentPane().addComponent(figureLabel);

this is the method to obtain byte array
-----------------------------------
private byte[] obtainByteData(String filename) throws IOException {

is=null;
is = getClass().getResourceAsStream("/"+filename+".gif");

if(is==null)
{
System.out.println("Is is empty");
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(1024);
byte[] bytes = new byte[512];

// Read bytes from the input stream in bytes.length-sized chunks and write
// them into the output stream
int readBytes;
while ((readBytes = is.read(bytes)) > 0) {
outputStream.write(bytes, 0, readBytes);
}

// Convert the contents of the output stream into a byte array
byte[] byteData = outputStream.toByteArray();

// Close the streams
is.close();
outputStream.close();

return byteData;
}
-----------------------------------
and in the your class have errors
i want to post new post contains urls for snapshots of errors in your class
----------------
Thanks a lot for replaying
and Thanks a lot for this excellent subject
=========
Regards
Mohammad

Mohammad Abu Hmead ha detto...

I uploaded the figures on my Facebook i think it is the shortest way,
this it's url

http://www.facebook.com/album.php?aid=41757&id=100000181362995&l=781e10cc3c

you can see them
please help me!
Thanks a lot

mani kanda ha detto...

how we set that animation into infinite entry.please mention. i am also looking for this.i already tried this methods set loop count , animate,set loop, start , stop methods separately and with the combinations also. and also what you mentioned that order also i followed. will you please help me .