Image Format

The Image Engine makes the distinction between:

  • The input format: the format of the original image.

  • The output format: the image format used by the Image Renderer.

Several formats are managed in input: PNG, JPEG, BMP, etc. A specific VEE Port can support additional input formats.

Several formats are managed in output: the MicroEJ formats and the binary format. The output format can be:

The Image Renderer manages only the MicroEJ formats (MicroEJ Format: Standard, MicroEJ Format: Display, and MicroEJ Format: Custom).

The following table lists all the formats and their usage.

Image Formats

Format

Input

Output

BufferedImage

MicroEJ Format: Display

no

yes

yes

MicroEJ Format: Standard

no

yes

yes [1]

MicroEJ Format: Grayscale

no

yes

yes [1]

MicroEJ Format: RLE Compressed

no

yes

no

MicroEJ Format: Custom

no

not yet

yes [1]

Binary Format

no

yes

no

Original Input Format

yes

no

no

The following sections list all the formats and their usage.

MicroEJ Format: Display

The display back buffer holds a pixel encoding which is:

The non-standard display format can be customized to encode the pixel in the same encoding as the display. The number of bits per pixel and the pixel bit organization is asked during the MicroEJ format generation and when the drawImage algorithms are running. If the image to encode contains some transparent pixels, the output file will embed the transparency according to the display’s implementation capacity. When all pixels are fully opaque, no extra information will be stored in the output file to free up some memory space.

Notes:

  • From the Image Engine point of view, the non-standard display format stays a MicroEJ format, readable by the Image Renderer.

  • The required memory to encode an image with a non-standard display format is similar to MicroEJ Format: Standard.

  • When the display format is standard or grayscale, the encoded image format is replaced by the related standard format.

  • The Graphics Engine’s drawing software algorithms only target (are only compatible with) the buffered images whose format is the same as the display format (standard or non-standard).

MicroEJ Format: Standard

See Standard Output Formats.

This format requires a small header (around 20 bytes) to store the image size (width, height), format, flags (is_transparent, etc.), row stride, etc. The required memory also depends on the number of bits per pixel of the MicroEJ format:

required_memory = header + (image_width * image_height) * bpp / 8;

The pixel array is stored after the MicroEJ image file header. A padding between the header and the pixel array is added to force to start the pixel array at a memory address aligned on the number of bits-per-pixels.

../_images/uiFormat01.png

The pixel order follows this rule:

pixel_offset = (pixel_Y * image_width + pixel_X) * bpp / 8;

Here are the conversions of 32-bit to each format:

  • ARGB8888: 32-bit format, 8 bits for transparency, 8 per color.

    u32 convertARGB8888toRAWFormat(u32 c){
        return c;
    }
    
  • ARGB4444: 16-bit format, 4 bits for transparency, 4 per color.

    u32 convertARGB8888toRAWFormat(u32 c){
        return 0
                | ((c & 0xf0000000) >> 16)
                | ((c & 0x00f00000) >> 12)
                | ((c & 0x0000f000) >> 8)
                | ((c & 0x000000f0) >> 4)
                ;
    }
    
  • ARGB1555: 16-bit format, 1 bit for transparency, 5 per color.

    u32 convertARGB8888toRAWFormat(u32 c){
        return 0
                | (((c & 0xff000000) == 0xff000000) ? 0x8000 : 0)
                | ((c & 0xf80000) >> 9)
                | ((c & 0x00f800) >> 6)
                | ((c & 0x0000f8) >> 3)
                ;
    }
    
  • RGB888: 24-bit format, 8 per color.

    u32 convertARGB8888toRAWFormat(u32 c){
        return c & 0xffffff;
    }
    
  • RGB565: 16-bit format, 5 for red, 6 for green, 5 for blue.

    u32 convertARGB8888toRAWFormat(u32 c){
        return 0
                | ((c & 0xf80000) >> 8)
                | ((c & 0x00fc00) >> 5)
                | ((c & 0x0000f8) >> 3)
                ;
    }
    
  • A8: 8-bit format, only the source image’s transparency is encoded (option alpha), or the source image is pre-processed (option grayscale); see Alpha Format.

u32 convertARGB8888toRAWFormat(u32 c){
   return (c >> 24) & 0xff;
}
  • A4: 4-bit format, only the source image’s transparency is encoded (option alpha), or the source image is pre-processed (option grayscale); see Alpha Format.

u32 convertARGB8888toRAWFormat(u32 c){
   return (c >> 28) & 0xf;
}
  • A2: 2-bit format, only the source image’s transparency is encoded (option alpha), or the source image is pre-processed (option grayscale); see Alpha Format.

u32 convertARGB8888toRAWFormat(u32 c){
   return (c >> 30) & 0x3;
}
  • A1: 1-bit format, only the source image’s transparency is encoded (option alpha), or the source image is pre-processed (option grayscale); see Alpha Format.

u32 convertARGB8888toRAWFormat(u32 c){
   return (c >> 31) & 0x1;
}

MicroEJ Format: Grayscale

See Grayscale Output Formats.

This format requires a small header (around 20 bytes) to store the image size (width, height), format, flags (is_transparent, etc.), row stride, etc. The required memory also depends on the number of bits per pixel of the MicroEJ format:

required_memory = header + (image_width * image_height) * bpp / 8;
  • AC44: 4 bits for transparency, 4 bits with grayscale conversion.

    u32 convertARGB8888toRAWFormat(u32 c){
        return 0
            | ((color >> 24) & 0xf0)
            | ((toGrayscale(color) & 0xff) / 0x11)
            ;
    }
    
  • AC22: 2 bits for transparency, 2 bits with grayscale conversion.

    u32 convertARGB8888toRAWFormat(u32 c){
        return 0
            | ((color >> 28) & 0xc0)
            | ((toGrayscale(color) & 0xff) / 0x55)
            ;
    }
    
  • AC11: 1 bit for transparency, 1 bit with grayscale conversion.

    u32 convertARGB8888toRAWFormat(u32 c){
        return 0
            | ((c & 0xff000000) == 0xff000000 ? 0x2 : 0x0)
            | ((toGrayscale(color) & 0xff) / 0xff)
            ;
    }
    
  • C4: 4 bits with grayscale conversion.

    u32 convertARGB8888toRAWFormat(u32 c){
        return (toGrayscale(c) & 0xff) / 0x11;
    }
    
  • C2: 2 bits with grayscale conversion.

    u32 convertARGB8888toRAWFormat(u32 c){
        return (toGrayscale(c) & 0xff) / 0x55;
    }
    
  • C1: 1 bit with grayscale conversion.

    u32 convertARGB8888toRAWFormat(u32 c){
        return (toGrayscale(c) & 0xff) / 0xff;
    }
    
The pixel order follows this rule:
pixel_offset = (pixel_Y * image_width + pixel_X) * bpp / 8;

MicroEJ Format: RLE Compressed

See Compressed Output Formats.

MicroEJ Format: Custom

A custom format embeds a buffer whose data are VEE Port specific. This data may be:

  • a pixel buffer whose encoding is different than the formats proposed before,

  • a buffer that is not a pixel buffer.

This format is identified by a specific format value between 0 and 7: see custom formats.

Images with a custom format can be used as any other image. For that, it requires some support at different levels depending on their usage:

  • To convert an image to this format at compile-time and embed it, an extension of the image generator is necessary; see VEE Port MicroEJ Custom Format.

  • To create a new one at runtime, some native extension is necessary; see Buffered Image.

  • To use it as a source (to draw the image in another buffer), some native extension is necessary; see Custom Format Support.

  • To use it as a destination (to draw into the image), some native extension is necessary; see Buffered Image.

Binary Format

This format is not compatible with the Image Renderer and MicroUI. It can be used by MicroUI addon libraries which provide their image management procedures.

Advantages:

  • Encoding is known by VEE Port.

  • Compression is inherent to the format itself.

Disadvantages:

  • This format cannot target a MicroUI Image (unsupported format).

Original Input Format

See Unspecified Output Format.

An image can be embedded without any conversion/compression. This allows embedding the resource as it is to keep the source image characteristics (compression, bpp, etc.). This option produces the same result as specifying an image as a resource in the MicroEJ launcher.

The following table lists the original formats that can be decoded at run-time and/or compile-time:

  • Image Generator: the off-board tool that converts an image into an output format. All AWT ImageIO default formats are supported and always enabled.

  • Front Panel: the decoders embedded by the simulator part. All AWT ImageIO default formats are supported but disabled by default.

  • Runtime Decoders: the decoders embedded by the embedded part.

Original Image Formats

Type

Image Generator

Front Panel

Runtime Decoders

Graphics Interchange Format (GIF)

yes

yes [2]

no [7]

Joint Photographic Experts Group (JPEG)

yes

yes [2]

no [7]

Portable Network Graphics (PNG)

yes

yes [3]

yes [3]

Windows bitmap (BMP)

yes

yes [4]

yes/no [4]

Web Picture (WebP)

yes [5]

yes [5]

yes [6]

GPU Format Support

The MicroEJ formats display, standard and grayscale may be customized to be compatible with the hardware (usually GPU). It can be extended by one or several restrictions on the pixels array:

  • Its start address has to be aligned on a higher value than the number of bits-per-pixels.

  • A padding has to be added after each line (row stride).

  • The MicroEJ format can hold a VEE Port-dependent header between the MicroEJ format header (start of file) and the pixel array. The MicroEJ format is designed to let the VEE Port encode and decode this additional header. This header is unnecessary and never used for Image Engine software algorithms.

Note

From the Image Engine point of view, the format stays a MicroEJ format, readable by the Image Engine Renderer.

Advantages:

  • The GPU recognizes encoding.

  • Drawing an image is often very fast.

  • Supports opacity encoding.

Disadvantages:

  • No compression: the image size in bytes is proportional to the number of pixels. The required memory is similar to MicroEJ Format: Standard when no custom header exists.

When the MicroEJ format holds another header (called custom_header), the required memory is:

required_memory = header + custom_header + (image_width * image_height) * bpp / 8;

The row stride allows adding some padding at the end of each line to start the next line at an address with a specific memory alignment; it is often required by hardware accelerators (GPU). The row stride is, by default, a value in relation to the image width: row_stride_in_bytes = image_width * bpp / 8. Thanks to the Abstraction Layer API LLUI_DISPLAY_IMPL_getNewImageStrideInBytes, it can be customized at image buffer creation. The required memory becomes:

required_memory = header + custom_header + row_stride * image_height;
../_images/uiFormat02.png