Image Loader

Principle

The Image Loader is a module of the MicroUI runtime that:

  • retrieves image data that is ready to be displayed without needing additional runtime memory,
  • retrieves image data that is required to be converted into the format known by the Image Renderer (MicroEJ format),
  • retrieves image in external memories (External Resource loader),
  • converts images in MicroEJ format,
  • creates a runtime buffer to manage MicroUI Buffered Image,
  • manages dynamic images life cycle.

Note

The Image Loader is managing images to be compatible with Image Renderer. It does manage image in custom format (see Binary Format)

Functional Description

  1. The application is using one of three ways to create a MicroUI Image object.
  2. The Image Loader creates the image according the MicroUI API, image location, image input format and image output format to be compatible with Image Renderer.
  3. When the application closes the image, the Image Loader frees the RAM memory.

Images Heap

There are several ways to create a MicroUI Image. Except few specific cases, the Image Loader requires some RAM memory to store the image content in MicroEJ format. This format requires a small header as explained here: MicroEJ Format: Standard. It can be GPU compatible as explained here: GPU Format Support.

The heap size is application dependant. In the application launcher, set its size in Libraries > MicroUI > Images heap size (in bytes). It will declare a section whose name is .bss.microui.display.imagesHeap.

By default, the Image Loader uses an internal best fit allocator to allocate the image buffers (internal Graphics Engine’s allocator). Some specific Abstraction Layer API (LLAPI) are available to override this default implementation. These LLAPIs may be helpful to control the buffers allocation, retrieve the remaining space, etc. When not implemented by the BSP, the default internal Graphics Engine’s allocator is used.

External Resource

Principle

An image is retrieved by its path (except for BufferedImage). The path describes a location in the application classpath. The resource may be generated at the same time as the application (internal resource) or be external (external resource). The Image Loader can load some images located outside the CPU addresses’ space range. It uses the External Resource Loader.

When an image is located in such memory, the Image Loader copies it into RAM (into the CPU addresses’ space range). Then it considers the image as an internal resource: it can continue to load the image (see following chapters). The RAM section used to load the external image is automatically freed when the Image Loader does not need it again.

The image may be located in external memory but be available in CPU addresses’ space ranges (byte-addressable). In this case, the Image Loader considers the image as internal and does not need to copy its content in RAM.

Configuration File

Like internal resources, the Image Generator uses a configuration file (also called the “list file”) for describing images that need to be processed. The list file must be specified in the application launcher (see Standalone Application Options). However, all the files in the application classpath with the suffix .imagesext.list are automatically parsed by the Image Generator tool.

Process

This chapter describes the steps to setup the loading of an external resource from the application:

  1. Add the image to the application project resources (typically in the source folder src/main/resources and in the package images).
  2. Create / open the configuration file (e.g. application.imagesext.list).
  3. Add the relative path of the image and its output format (e.g. /images/myImage.png:RGB565 see Images).
  4. Build the application: the Image Generator converts the image in RAW format in the external resources folder ([application_output_folder]/externalResources).
  5. Deploy the external resources to the external memory (SDCard, flash, etc.) of the device.
  6. (optional) Configure the External Resources Loader to load from this source.
  7. Build the application and run it on the device.
  8. The application loads the external resource using ResourceImage.loadImage(String).
  9. The image loader looks for the image and copies it in the images heap (no copy if the external memory is byte-addressable).
  10. (optional) The image may be decoded (for instance: PNG), and the source image is removed from the images heap.
  11. The external resource is immediately closed: the image’s bytes have been copied in the images heap, or the image’s bytes are always available (byte-addressable memory).
  12. The application can use the image.
  13. The application closes the image: the image is removed from the image heap.

Simulation

The Simulator automatically manages the external resources like internal resources. All images listed in *.imagesext.list files are copied in the external resources folder, and this folder is added to the Simulator’s classpath.

Image in MicroEJ Format

An image may be pre-processed (Image Generator) and so already in the format compatible with Image Renderer: MicroEJ format.

  • When application is loading an image which is in such format and without specifying another output format, the Image Loader has just to make a link between the MicroUI Image object and the resource location. No more runtime decoder or converter is required, and so no more RAM memory.
  • When application specifies another output format than MicroEJ format encoded in the image, Image Loader has to allocate a buffer in RAM. It will convert the image in the expected MicroEJ format.
  • When application is loading an image in MicroEJ format stored as External Resource, the Image Loader has to copy the image into RAM memory to be usable by Image Renderer.

Encoded Image

An image can be encoded (PNG, JPEG, etc.). In this case Image Loader asks to its Image Decoders module if a decoder is able to decode the image. The source image is not copied in RAM (expect for images stored as External Resource). Image Decoder allocates the decoded image buffer in RAM first and then inflates the image. The image is encoded in MicroEJ format specified by the application, when specified. When not specified, the image in encoded in the default MicroEJ format specified by the Image Decoder itself.

The UI extension provides two internal Image Decoders modules:

  • PNG Decoder: a full PNG decoder that implements the PNG format (https://www.w3.org/Graphics/PNG ). Regular, interlaced, indexed (palette) compressions are handled.
  • BMP Monochrome Decoder: .bmp format files that embed only 1 bit per pixel can be decoded by this decoder.

Some additional decoders can be added. Implement the function LLUI_DISPLAY_IMPL_decodeImage to add a new decoder. The implementation must respect the following rules:

  • Fills the MICROUI_Image structure with the image characteristics: width, height and format.

    Note

    The output image format might be different than the expected format (given as argument). In this way, the Display module will perform a conversion after the decoding step. During this conversion, an out of memory error can occur because the final RAW image cannot be allocated.

  • Allocates the RAW image data calling the function LLUI_DISPLAY_allocateImageBuffer. This function will allocates the RAW image data space in the display working buffer according the RAW image format and size.

  • Decodes the image in the allocated buffer.

  • Waiting the end of decoding step before returning.

Installation

The Image Decoders modules are some additional modules to the Display module. The decoders belong to distinct modules, and either or several may be installed.

In the VEE Port configuration file, check UI > Image PNG Decoder to install the runtime PNG decoder. Check UI > Image BMP Monochrome Decoder to install the runtime BMP monochrom decoder.

Use

The MicroUI Image APIs are available in the class ej.microui.display.Image. There is no specific API that uses a runtime image. When an image has not been pre-processed (see Image Generator), the MicroUI Image APIs createImage* will load this image.