Image assets

A common use of an image is as an asset that's packaged with your application. These types of images might include backgrounds, borders, icons, or other UI-related images. Images stored within the app's assets directory are packaged with the application binary at compile time, so they can be accessed by the app very quickly. Even though the images are loaded asynchronously, the load time should be very short and they generally should not fail to load.

A set of layered images.

Loading image assets

Images, just like other assets, should be placed in the assets folder of your Cascades project. As a best practice, you should create an images folder within assets and store your images there.

To load an image asset, you can use an absolute path or a relative path. Both methods load the image asynchronously, so they might show up after other UI elements appear. To use an absolute path, you must specify the asset:/// prefix followed by the path to the image from the assets folder, and the name of the image including the file extension (always remember to use three slashes in the asset:/// prefix). The asset:/// prefix resolves to a URL that points to the assets folder in your application. You can also use a path that's relative to the location of the QML file that's loading the image.

Let's say that you have an image called myimage.png that you've placed in the assets/images folder in your project. Here's how you can load the image using both absolute and relative paths:

QML

// Absolute path
ImageView {
    imageSource: "asset:///images/myimage.png"   
}

// Relative path
ImageView {
    imageSource: "images/myimage.png"   
}

C++

The relative path for loading an image in C++ is different from QML, since the binary for the application is stored in the parent directory of assets.

// Absolute path
Image image = Image(QUrl("asset:///images/myimage.png"));

// Relative path
Image image = Image(QUrl("assets/images/myimage.png"));

Nine-slice scaling

Nine-slice scaling is a technique that is typically used for background and border images. It allows an image to scale nicely to virtually any size while keeping its corners sharp and borders uniform. Using nine-slice scaling can help minimize the size and number of image assets that you bundle with your application.

For example, if you're developing a chat application, you will need a standard background image for messages. The image below on the left represents such a background image. To support large amounts of text, you'll need to scale the image vertically to fit more text in the center of the background image. However, without the nine-slice scaling technique, the borders of the image get scaled as well, as shown below in the image on the right. As the image scales in height, the top and bottom borders become thicker than the borders on the sides, which causes the corners to stretch. As a best practice, you want the borders and corners to stay uniform no matter what size the image is scaled to. To ensure that your image borders and corners are not scaled, you must specify nine-slice margins for the image.


An image with uniform borders.


An image with scaled borders.

Specifying nine-slice margins

Nine-slice margins can be specified in a metadata file with the same name as the image but with an .amd extension (the metadata file must be placed in the same directory as the image assets). When defining the nine-slice margins, you must use the following format:

#RimCascadesAssetMetaData version=1.0
source: "image.png"
sliceMargins: 15 15 15 15

The source contains the name of the image that you want to perform nine-slice scaling on. The sliceMargins property indicates the number of pixels that need to be sliced off of each side of the image (in the order of left, right, top, and bottom). By specifying the slice margins, the image is sliced into nine parts:


A grid showing an image sliced into nine parts.

In the image above, using the nine-slice scaling technique will prevent the corners (1,3,7,9) from being scaled. Similarly, the top and bottom borders (2,8) can only be scaled in the horizontal direction and the borders on the sides (4,6) can only be scaled in the vertical direction; the thickness of the borders is never altered. The center part of the image (5) can be scaled in any direction. Since we want to scale the image vertically, the center part of the image and both of the side borders (4,5,6) are scaled. The resulting image looks like this:


A scaled image with uniform borders.

Loading images

When loading an image that uses nine-slice scaling, you must load the .amd file instead of the image itself. Otherwise, the nine-slice margins are ignored. If addition, , make sure that you load the file as an asset.

ImageView {
    imageSource: "asset:///nine_sliced_background.amd"
    preferredWidth: 500
    preferredHeight: 500
}

Tools

Cascades Exporter lets you specify nine-slice margins on your images so that the settings can be imported directly into QML. For more information, see Explore Cascades Exporter.

The QML Editing perspective in the Momentics IDE lets you view your images and set the nine-slice margins directly within the editor. For more information, see Image viewer.

Image colorization 10.3

Image colorization allows you to apply a color filter to an image during runtime to minimize the number of image variants you need to package with your app. All images can have a color filter applied, and images used as action item icons can be colorized automatically according to the current theme. This can be especially useful if you create multiple themes for your app. For more information about themes, see Themes and colors.

As a best practice for colorization, you should create an .amd (asset metadata) file for the image you want to colorize. A .amd file is placed in the same folder as your image asset, and contains metadata for the image. In the .amd file, you can use the type attribute to enable or disable colorization. Setting the type to template enables colorization of an image. Using the template type, Cascades accepts colorization of images using the filterColor property, and also attempts to colorize images used as action item icons according to the device theme. A type of normal overrides the framework and uses the original image, even if a filterColor is applied. For more information on overriding the framework, see Action item images. The following code sample shows the structure of an .amd file for an image named myImage.png with a type of template:

#RimCascadesAssetMetaData version=1.1
type: template
source: "myImage.png"

To use colorization, the #RIMCascadesAssetMetaData version must be set to 1.1.

A color filter can then be applied to an image using the filterColor property, which recolors the pixels in an image with the specified color. White pixels are recolored to the color you specify, black pixels remain black, and color pixels appear as a new color representing a combination of the original color and the filter color.

Image colorization supports predefined color constants, as well as custom colors you specify using Color.create(). For more information on supported colors, see the Color API reference.

The following code sample applies a filterColor derived from a hex value to an image in QML:

import bb.cascades 1.3

Page {
    Container {
        ImageView {
            imageSource: "asset:///images/myImage.amd"
            // This colorizes the image with 
            // the provided color. 
            filterColor: Color.create("#ff2c2c")
        }

    }
}

Here is how to apply a filterColor derived from a 32-bit ARGB value in C++:

#include <bb/cascades/Application>
#include <bb/cascades/Page>
#include <bb/cascades/ImageView>
#include <bb/cascades/Color>
#include <bb/cascades/Container>

using namespace bb::cascades;

ApplicationUI::ApplicationUI(bb::cascades::Application *app) :
        QObject(app)
{
    // Create a Container and set the layout
    Page *page = new Page();

    Container *root = Container::create();

    ImageView *myImageView = ImageView::create()
            .image(Image(QUrl("asset:///images/myImage.amd")))
            .filterColor(Color::fromARGB(0xffff2c2c));

    root->add(myImageView);
    page->setContent(root);
    app->setScene(page);
}

The following image demonstrates the difference between the standard image appearance and the image appearance with a filter color applied using the code sample above:


Screen shot showing the difference between the standard image and an image with a filter color applied.

Last modified: 2014-05-14



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus