Saturday, May 15, 2010

Animated Gifs Everywhere

Its not that LWUIT doesn't support animated GIF's as much as the underlying implementation doesn't support them. MIDP doesn't provide any API's to extract the frames of the animated GIF's and get any indication of when to repaint them.
The solution would seem to parse animated GIF's ourselves and paint them ourselves, this isn't trivial since the animated GIF compression and painting logic is rather complex. However, Ugo Chirico seems to have done just that quite a while back!
His image class allows loading and displaying an animated GIF within LWUIT and works for many animated GIF's. It probably won't become a part of LWUIT in part due to copyright issues, but I have made some changes to the way he chose to integrate into LWUIT so you don't actually need to change LWUIT in order to integrate with his code.
Furthermore, when using my modified LWUIT implementation animated GIF's will be automatically detected and "just work" even within the HTML component and other elaborate use cases in LWUIT.
I achieved this by overriding the LWUIT implementation (the VKB version) and all that's necessary to integrate it is to invoke AnimatedGifFactory.install(); before the Display.init() call.

You can get my code from the vprise directory in the LWUIT incubator project, the project includes a small test application within as well.

This can serve as a template to anyone wishing to add additional image support to LWUIT, there are several tricks I used to achieve this:

  • Image loading requires detecting the image type from the stream, however once I started reading the stream I will need to handle all image types.... To solve this I added BufferedInputStream which guarantees that mark()/reset() would work on the stream and thus I'm able to restore the input stream to its original state in case the image is not a GIF!
  • I return an internal "native" image, but I don't use MIDP at any point. While I haven't tested it I bet my code works well on Android/RIM since I only use LWUIT logic internally.
    One would obviously need to modify the classes from which I derive to the appropriate Android/RIM implementations for this to work...
  • LWUIT animation calls update the state of the GIF, Ugo did this perfectly and I just used the implementation to map directly to his code.

Monday, May 10, 2010

Wednesday, May 5, 2010

Timeline Animations

When I was working on the original resource editor we really wanted to add an easy to use animation tool. The main issue was getting it to work on a Series 40 device with 2mb of heap space and a relatively high resolution.

I came up with the notions of IndexedImage and StaticAnimation to solve these problems by limiting the bits per pixel in the image/animation. The animations provided were very static and limited, they still suffered from memory issues and performance issues so the problems weren't completely solved.

Sometime along the way I came up with the concept of EncodedImage that allows us to leverage the JPEG/PNG compression in runtime to trade RAM overhead for performance. This allowed us far more power than IndexedImage and to a great degree we shifted all our current code to use EncodedImage rather than IndexedImage. For StaticAnimation we had no substitute, until now... Recently I committed the Timeline animation which is supposed to be a more elaborate animation model leveraging encoded image, its highly experimental and probably buggy but it already shows off the general direction.

Its not supposed to rival the elaborate use cases of Java FX/Flash/SVG, its a simple animation engine designed mostly for Spalsh screens and small effects. In the video to your right you can see the resource editor editing a simple timeline composed of 3 images a background, a logo and a flying saucer. You can generally add an image and determine an effect and a duration for said effect. Not much in general but in the right hands it can be plenty.

I hope to enhance this significantly and would like reasonable feature requests/suggestions to decide on direction. You can try the current resource editor in the webstart link at the lwuit site (click the orange "Launch" button, I can't place it here since the JavaScript doesn't work in Blogger).

The video demonstrates the creation of a simple timeline from 3 images, AnimationObjects are then added to position and move these images appropriately. One of these images is a Sprite which is automatically broken down into frames. Try the resource editor and the new classes within the animation package to get a better grasp of what I'm talking about and comment on the post.

On a different subject matter we are looking for some feedback on the HTML component from people who are taking it to production. If you represent such a company please drop us a line to lwuit at Sun.com.

Wednesday, April 28, 2010

Musix On The BlackBerry Device

I got a demo device from TriPlay to show off Musix running on the blackberry device using the blackberry native LWUIT port.

The UI worked pretty smoothly and was relatively easy to port, most of the work in porting was related to networking on the RIM devices which is really complicated.

While the menus/UI is in Hebrew the application shows off background downloading with decryption on the fly of DRM protected music. It also shows off album purchase (e.g. the Pixies album in the video).

Tuesday, April 20, 2010

New Article From Biswajit On Styles & Themes

Biswajit Sarkar has written another java.net article about styles, painters & themes. Its more up to date with the current style architecture in LWUIT than other articles covering the subject.
His article also covers some other new LWUIT features such as tables.

On an unrelated note Ofir got tasked last week with getting a LWUIT application to run efficiently on Symbian OS 8. He benchmarked the application and discovered that the cause of performance issues is the existence of an alpha channel in the images. The performance difference he showed us was staggering!
We always new bitmap fonts were slower on such devices (an image with an alpha channel) but it seems that even simpler transparency (without translucency) might make a huge difference.

Sunday, April 11, 2010

Back On The Touch

I always liked the aesthetics of the iPhone back behavior, placing the back button as a small arrow within the title bar is a stroke of UI design genius. I don't share Apple's disdain for physical buttons so I'm much more in favor of a physical back button, however having that button in the title area is both handy and none intrusive.

Often people ask us to customize the title area for things other than Labels, normally when a use case is so common we comply even when it goes against our core aesthetics of UI design. However, this is a special case where making such a change would break the simplicity of customization to everyone else involved.

However, in the spirit of LWUIT for making everything reasonably easy to accomplish even these iPhone like back buttons are very possible and easy to accomplish. There are two challenges involved: the shape of the button and its position in the title.

The shape of the button is solved by creating an image border with the proper shape and updating the theme, I won't publish the resource file since the images here aren't owned by myself.

Placing the button in the title of the UI Demo requires the following change to the Demo.java class in the UI Demo. In the run() method change the demo form creation to this:
final Form demoForm = new BackTitleForm(backCommand);

And add the BackTitleForm as an inner class (pasted bellow). Back title form is a simple form extension that essentially creates a content pane within the content pane and creates an alternate title component that can be anything.

    class BackTitleForm extends Form {
private Container contentPane = new Container();
private Container title = new Container(new BoxLayout(BoxLayout.X_AXIS));

public BackTitleForm(Command backCommand) {
super.getContentPane().setLayout(new BorderLayout());
super.getContentPane().addComponent(BorderLayout.CENTER, contentPane);
super.getContentPane().addComponent(BorderLayout.NORTH, title);
Label titleLabel = new Label(getName());
title.getStyle().setPadding(0, 0, 0, 0);
title.getStyle().setMargin(0, 0, 0, 0);
titleLabel.getStyle().setPadding(0, 0, 0, 0);
titleLabel.getStyle().setMargin(0, 0, 40, 0);
titleLabel.getStyle().setBgTransparency(0);
title.setUIID("Title");
Button backButton = new Button(backCommand);
backButton.setUIID("BackButton");
backButton.setPreferredH(42);
title.addComponent(backButton);
title.addComponent(titleLabel);
}

public Container getContentPane() {
return contentPane;
}

/**
* Removes all Components from the Content Pane
*/

public void removeAll() {
contentPane.removeAll();
}


/**
* @inheritDoc
*/

public void setLayout(Layout layout) {
contentPane.setLayout(layout);
}

/**
* Adds Component to the Form's Content Pane
*
* @param cmp the added param
*/

public void addComponent(Component cmp) {
contentPane.addComponent(cmp);
}

/**
* @inheritDoc
*/

public void addComponent(Object constraints, Component cmp) {
contentPane.addComponent(constraints, cmp);
}

/**
* @inheritDoc
*/

public void addComponent(int index, Object constraints, Component cmp) {
contentPane.addComponent(index, constraints, cmp);
}

/**
* Adds Component to the Form's Content Pane
*
* @param cmp the added param
*/

public void addComponent(int index, Component cmp) {
contentPane.addComponent(index, cmp);
}

/**
* @inheritDoc
*/

public void replace(Component current, Component next, Transition t) {
contentPane.replace(current, next, t);
}

/**
* @inheritDoc
*/

public void replaceAndWait(Component current, Component next, Transition t) {
contentPane.replaceAndWait(current, next, t);
}

/**
* Removes a component from the Form's Content Pane
*
* @param cmp the component to be removed
*/

public void removeComponent(Component cmp) {
contentPane.removeComponent(cmp);
}
}

Sunday, April 4, 2010

Biswajit Sarkar Talking About J2ME & LWUIT

With the current holidays around here and quite a bit of work I didn't keep up the blog as I probably should. I'll try to get back into posting soon when everything calms down around here. While waiting for me to get my act together here is a talk that Biswajit Sarkar (author of the LWUIT 1.1 book) gave at the IndicThreads conference in India.
This talk is mostly for introduction to J2ME development and covers LWUIT among many of the subjects mentioned.
Its probably too introductory level for most of the readers of this blog, however it might be very useful to pass along to colleagues as a means of introducing them to J2ME/LWUIT. Biswajit is as usual very thorough in his details which is always important when discussing something as elaborate as mobile development.