Fork us on GitHub

Sizing Images Just Right with Cloudinary

Sizing images for multiple DPIs and device sizes is challengi...
Post Image

Sizing Images Just Right with Cloudinary

As I discussed in a previous article, creating a beautiful user interface that behaves appropriately across multiple devices can be a challenge, what with the vast array of screen sizes that your app may be deployed to. Codename One provides you with some power tools on this front. E.g.:

  1. Multi-images

  2. Pixel to Millimetre unit conversion (approximate)

  3. On-device image scaling

In this article, I would like to share with you another powerful tool to add to your kit, the Cloudinary library.

The Motivation

Let’s take a look at a screen mock-up from a a nice UI kit that I’ve been working with lately:

4a91f952 9295 11e5 953b 850dc84c0fb0

Replicating this UI in Codename One is pretty straight forward:

  1. Use the ToolBar for the top bar, and a BoxLayout Y_AXIS for the contents.

  2. Use multi-images for the icons so that they come out to the correct "real" size on every device.

The main photo is a bit more challenging though. The design calls for us to span the entire width of the device. If we just use a multi-image we can get it to size approximately to this space. But not exactly. We could set a multi-image as a background image for a container, and specify that it "scale to fill" the space. In fact this solution will work perfectly, if we are able to store the image in our resource file.

Unfortunately, it looks like this app is some sort of news app, where articles are loaded from a server, and each article comes with its own photo. Hence, there could be thousands or millions of photos that need to be sized this way in this app. Using the "multi-image" solution won’t scale well, since multi-images need to be stored inside the resource file, and you can’t realistically store thousands or millions of images in the resource file.

Loading images over the network isn’t a problem. You can just use the URLImage class with a "scale to fill" filter. The PropertyCross demo actually uses a hybrid solution with URLImage to load images of housing properties, multi-images serving as the placeholder image so that the image will scale to the right size. This approach, while workable still has fairly major problem:

How do we resize the image to be the correct size on all devices, and maintain quality. E.g. On the iPhone 3G, we need an image to be 320 px wide to span the width of the screen, whereas on the iPhone 6+, the image needs to be 1080 px. If we download a 320px image from the network, and resize it on device, it will look great on the 3G but horrible on the 6+. If we instead download a 1080px image, it will look great on the 6+ but quite poor on the 3G. In addition, this will waste a lot of unnecessary bandwidth for 3G users, downloading hi-res images that they don’t need.

We could try to split the difference by downloading say 720px image, but this just leads to sub-par results on both devices. The ideal solution would be to download a 320px image on the 3G and a 1080px image on the 6+. That way, quality is optimal on both devices, and we don’t waste any bandwidth.

One possible solution is to produce multiple versions of the image on your server, and have the device automatically select the correct one. This wouldn’t be too difficult to do, but before you go off and create a server-side script for resizing your images, I recommend you check out Cloudinary. Because they already do this. And they do it very well.

The Solution

Before you begin, you’ll need to sign up for a free cloudinary account. The free account gives you up to 75,000 image transformations per month, and up to 5 gigs of bandwidth.

Then, you’ll need to add the cloudinary cn1lib to your project.

When you sign up for cloudinary, you’ll receive an API key, and associated credentials for accessing their API. You just need to initialize the API in your app’s init() method, as follows:

import com.cloudinary.Cloudinary;

Cloudinary cloudinary;


public void init() {


    Cloudinary cloudinary = new Cloudinary(ObjectUtils.asMap(
      "cloud_name", "my_cloud_name",
      "api_key", "my_api_key",
      "api_secret", "my_api_secret"));

    // Disable private CDN URLs as this doesn't seem to work with free accounts
    cloudinary.config.privateCdn = false;


Loading and Displaying an Image

Once Cloudinary is initialized you can use the API to fetch images, upload images, and much more. The following example loads an image from the internet, and resizes it to a square image that spans the width of the device screen:

        Form f = new Form("Test");
        f.setLayout(new BoxLayout(BoxLayout.Y_AXIS));

        int deviceWidth = Display.getInstance().getDisplayWidth();

        // We create a placeholder image to set the size for the image to fit
        // to.
        Image placeholder = Image.createImage(deviceWidth, deviceWidth);
        EncodedImage encImage = EncodedImage.createFromImage(placeholder, false);

        // Load an image from cloudinary
        Image img2 = cloudinary.url()
                .type("fetch")  // Says we are fetching an image
                .format("jpg")  // We want it to be a jpg
                    new Transformation().crop("fill")  //  We crop the image to fill the given width/height
                .image(encImage, "");

        // Add the image to a label and place it on the form.
        Label l = new Label(img2);

        // Get rid of margin and padding so that the image spans the full width of the device.
        l.getAllStyles().setMargin(0, 0, 0, 0);
        l.getAllStyles().setPadding(0, 0, 0, 0);

The result is:

251ad556 929d 11e5 8f07 d4d2e2b9ec0e

You’ll notice that if you try to load that image directly from the URL, it is massive! The Cloudinary service automatically resizes the image before sending it to the device in the requested size. Performing the resize on the server produces stellar results. Much better than you could achieve with on-device resizing. In addition, you save a lots of bandwidth for your users, which also improves app performance. It’s a win-win all 'round.

But That’s Not All

This is the most basic example, I could come up with, but Cloudinary can do much more. See their features page for a full list of capabilities. Here is a few nice features that caught my eye:

  1. Resizing & Cropping

  2. Face detection, and appropriate cropping

  3. Watermark overlays

  4. Circular thumbnails, rounded corners

  5. Text overlays, shadows, and borders

  6. Photo effects, like Sepia, Blur, Black & White, etc..

  7. PDF and Office document processing. E.g. you can extract pages from PDFs or Word documents as images.

  8. Convert image format / modify quality.

Learn More

The cn1lib is a fairly straight port of Cloudinary’s official Java API, and should support most of its features (including uploading). Check out the README for more information.

Share this Post:

Posted by Steve Hannah

Steve writes software for Codename One. He is an open source enthusiast who loves to tinker with new technologies.