Managing Resources

This topic describes how Qt Quick Ultralite applications make use of image resources.

Font resources are not added through the resource system. For more information about font handling, see Text Rendering and Fonts.

See also topic on Image Caching.


To use resources in a Qt Quick Ultralite application, you must declare them using the CMake API.

The resource compiler (qulrcc) uses the resource declarations to prepare the contents for inclusion. It may perform optimizations on the raw resource data. For example, image optimization can result in lowering color depth, replacing with alphamap, removing outline transparent areas, and swizzling.

Adding files to the resource system

Use the qul_add_resource CMake function to add resources to a Qt Quick Ultralite application.

qul_add_resource(myapp FILES ui/spinner.png background.png)

The function adds the files into to a virtual resource filesystem. Resources in the filesystem are referenced through resource URIs with the optional "qrc:" scheme.

  |-- background.png
  |-- ui/
       |-- spinner.png

In the above example, qrc:/ui/spinner.png is a resource URI for the resource data based on the ui/spinner.png file from the source directory. It can be displayed by using its URI as source in an Image:

Image {
    source: "qrc:/ui/spinner.png"

When using relative paths in resource URIs, the paths are relative to the root of the virtual resource filesystem. The scheme of the URI can be omited. The following URIs all refer to ui/spinner.png:

  • ui/spinner.png
  • /ui/spinner.png
  • qrc:ui/spinner.png
  • qrc:/ui/spinner.png
  • qrc:///ui/spinner.png

Resource properties

Optionally, use the set_source_files_properties CMake function to set resource properties. It must be done before calling qul_add_resource.

set_source_files_properties(filename.png PROPERTIES QUL_RESOURCE_COMPRESSION ON)

Image resources support a number of resource properties that control how the image is stored on the device, or can trigger different optimizations. See CMake Source File Properties for the full list.

In the following example, the large background.png is stored in a compressed format by setting QUL_RESOURCE_COMPRESSION, while spinner.png is tagged with QUL_RESOURCE_OPTIMIZE_FOR_ROTATION to optimize it for runtime rotation:

set_source_files_properties(spinner.png PROPERTIES QUL_RESOURCE_OPTIMIZE_FOR_ROTATION ON)
set_source_files_properties(background.png PROPERTIES QUL_RESOURCE_COMPRESSION ON)
qul_add_resource(myapp FILES spinner.png background.png)
Image {
    source: "qrc:/background.png"

    Image {
        anchors.centerIn: parent
        source: "qrc:/spinner.png"
        transform: Rotation {
            NumberAnimation on angle { from: 0; to: 360; running: true; loops: Animation.Infinite }

Lossless compressed image formats

Qt for MCUs supports Run-Length Encoding (RLE) compression formats as an alternative to QUL_RESOURCE_COMPRESSION. It is useful if significant parts of an image have the same color. The RLE format options for the QUL_RESOURCE_IMAGE_PIXEL_FORMAT property are: RGB888RLE, XRGB8888RLE, and ARGB888RLE.

The supported RLE formats vary depending on the platform. Therefore, use the AutomaticCompressedLossless option to automatically choose the ideal format depending on the QUL_PLATFORM_DEFAULT_RESOURCE_COMPRESSED_LOSSLESS_PIXEL_FORMAT_OPAQUE and QUL_PLATFORM_DEFAULT_RESOURCE_COMPRESSED_LOSSLESS_PIXEL_FORMAT_ALPHA settings for the platform.

The benefit of using AutomaticCompressedLossless is that the images can be decoded on the fly as they are being blended, without decompressing them into the image cache. This means, less volatile memory is needed compared to images that use QUL_RESOURCE_COMPRESSION.

However, the average compression ratio is not as good, and transformed images are not supported. It could also have a negative impact on the blending performance, as it uses CPU fallback on most platforms. The CPU is usually slow at blending images that contain a lot of semi-transparent pixels or if the computed Item::opacity value is less than one. Refer to the Supported Features table for information about platforms that support hardware accelerated blending of RLE pixel formats.

The following table shows two example images along with their uncompressed and compressed (RLE or PNG) sizes. The first image compresses a lot better due to the contiguous areas that contain the same pixel value. Compressing such images into PNG using QUL_RESOURCE_COMPRESSION produces even better compression ratios, but they must be decompressed onto the image cache before drawing on screen.


Uncompressed82.9 kB82.9 kB
RLE compression23.2 kB72.6 kB
PNG compression6.7 kB27.5 kB

Here are some useful heuristics for when to use PNG or RLE compression to better blending performance:

  • OnStartup cache policy - On platforms that have sufficient flash and volatile memory for the application.
  • RLE compression - On platforms that support hardware accelerated blending without intermediate buffers. You could also use it on platforms without hardware acceleration, if the performance overhead is acceptable.
  • PNG compression with QUL_RESOURCE_COMPRESSION - On platforms that do not have sufficient memory required to store all the uncompressed image resources. If the image cache is big enough to fit all the visible images on screen at the same time, animation performance will be good as all the required images are in the volatile memory.
  • AutomaticCompressedLossless or uncompressed images without caching to retain the images in flash memory. One of these two techniques is ideal on platforms with limited volatile memory, as PNG compression is not an option on such platforms.

Here's how to enable the use of lossless compression for a given image resource:

set_source_file_properties(example.png PROPERTIES QUL_RESOURCE_IMAGE_PIXEL_FORMAT AutomaticCompressedLossless)

Resource placement in memory

By default a resource is placed in a reserved memory section named QulResourceData. Resources can be placed in a different storage section by setting the QUL_RESOURCE_STORAGE_SECTION property. The {QUL_RESOURCE_CACHE_POLICY} property controls when and how resources are loaded into volatile memory. When different kinds of volatile memory are available (for example RAM, VRAM or HyperRAM), the QUL_RESOURCE_RUNTIME_ALLOCATION_TYPE property can be used to choose the volatile memory region to use for a given resource.

In the following example, three images are stored in a memory section named Arrows.


set_source_files_properties(${ARROWS} PROPERTIES QUL_RESOURCE_STORAGE_SECTION "Arrows")
qul_add_resource(app FILES ${ARROWS})

The section name can be freely chosen as long as a section with the same name is defined in the linker script. The section start address needs to be aligned to the largest alignment requirement among resources within the same section.

Arrows :
    . = ALIGN(4);

OTA resources update

If the user wants to do an over-the-air (OTA) update of some resources, these resources should be placed in a specific memory section (for example OTAResourceSection) as shown above in Resource placement in memory.

Once the user has updated the images that are part of the OTA update on the host, it is possible to regenerate the binary content of the OTAResourceSection for a given target application.

Such binary generation is performed by the resource compiler and can be invoked via CMake as follows:

cmake --build . --target <application>_resource_binaries

without the need of recompiling the whole application. The resource binaries are named qul_resources_<section_name>.bin (for example qul_resources_OTAResourceSection.bin) and can be found in the target application build folder.

Since some of the images might either be cached (OnDemand) or preloaded at startup (OnStartup) with QUL_RESOURCE_CACHE_POLICY, the Qt Quick Ultralite application must be restarted for the images part of the OTA update to be effectively used by the application.


  • Apart from generating new binary data, Qt Quick Ultralite does not offer any direct mechanism for rewriting the data to Flash memory. An application specific solution will need to be implemented.
  • The resource binary content is in Little-Endian format.
  • Filenames need to match with the ones that have been used in the QML application originally. Otherwise the resource lookup will fail.
  • To avoid overwriting other memory areas, the section part of an OTA update should be placed last in Flash.
  • The flash memory must be erased and rewritten on a block-by-block basis. If the binary data does not start and end on the exact block boundaries, it might be necessary to read the old data for the memory blocks that will be erased. Ensure to take this into consideration if the flashing tool or library you are using does not handle it automatically.


Available under certain Qt licenses.
Find out more.