Fork us on GitHub

Image From URL Made Easy

ImageDownloadService is one of the first classes we wrote whe...

Image From URL Made Easy

ImageDownloadService is one of the first classes we wrote when creating the original IO package, as such we were still thinking over the API and the code... stinks.
I've had the task of writing a tutorial for ImageDownloadService for such a long time and I just kept procrastinating on it because it is so painful to deal with. Eventually I broke down and decided to solve the problem in the proper way of creating a completely new API that's simpler and thus doesn't really require an extensive tutorial: URLImage.

URLImage is an image created with a URL... Simple. It is seamlessly downloaded, scaled (adapted) and automatically updates itself in place. All good.

The simple use case is pretty trivial:
Image i = URLImage.createToStorage(placeholder, "fileNameInStorage", "http://xxx/myurl.jpg", URLImage.RESIZE_SCALE);

Alternatively you can use the similar
URLImage.createToFileSystem method instead of the Storage version.
This image can now be used anywhere a regular image will appear, it will initially show the placeholder image and then seamlessly replace it with the file after it was downloaded and stored.
Notice: Since ImageIO is used to perform the operations of the adapter interface its required that ImageIO will work. It is currently working in JavaSE, Android, iOS & Windows Phone. It doesn't work on J2ME/Blackberry devices so if you pass an adapter instance on those platforms it will probably fail to perform its task.

If the file in the URL contains an image that is too bit it will scale it to match the size of the placeholder precisely!
We currently also have an option to fail if the sizes don't match. Notice that the image that will be saved is the scaled image, which means you will have very little overhead in downloading images that are the wrong size although you will get some artifacts.

The last argument is really quite powerful, its an interface called URLImage.ImageAdapter and you can implement it to adapt the downloaded image in any way you like. E.g. you can use an image mask to automatically create a rounded version of the downloaded image or to scale based on aspect ratio. We will probably add some tools to implement such functionality based on user demand.

To do this you just override public EncodedImage adaptImage(EncodedImage downloadedImage, Image placeholderImage) in the adapter interface and just return the processed encoded image. If you do heavy processing (e.g. rounded edge images) you would need to convert the processed image back to an encoded image so it can be saved. You would then also want to indicate that this operation should run asynchronously via the appropriate method in the class.

If you need to download the file instantly and not wait for the image to appear before download initiates you can explicitly invoke the fetch() method which will asynchronously fetch the image from the network.

The biggest problem with image download service is with lists. We decided to attack this issue at the core by integrating URLImage support directly into GenericListCellRenderer which means it will work with MultiList, List & ContainerList. To use this support just define the name of the component (name not UIID) to end with _URLImage and give it an icon to use as the placeholder. This is easy to do in the multilist by changing the name of icon to icon_URLImage then using:
map.put("icon_URLImage", urlToActualImage); in the data.
Make sure you also set a "real" icon to the entry in the GUI builder or in handcoded applications. This is important since the icon will be implicitly extracted and used as the placeholder value. Everything else should be handled automatically. You can use setDefaultAdapter & setAdapter on the generic list cell renderer to install adapters for the images. The default is a scale adapter although we might change that to scale fill in the future.

Notice: This post was automatically converted using a script from an older blogging system. Some elements might not have come out as intended.... If that is the case please let us know via the comments section below.

Share this Post:

Posted by Shai Almog

Shai is the co-founder of Codename One. He's been a professional programmer for over 25 years. During that time he has worked with dozens of companies including Sun Microsystems.
For more follow Shai on Twitter & github.