Images
Overview
The SDK handles images and textures via the M2ResourcesService (accessed from Evs.resourcesService).
Image resources are uploaded from the application to the glasses over BLE and bound to drawables for rendering.
Image Sources
The SDK supports several image source types:
| Source | Class | Description |
|---|---|---|
| File | M2ImageFile |
Load an image from a file bundled with the application (PNG, JPG). The file is loaded lazily on first use. |
| Bytes | M2ImageBytes |
Create an image from in-memory pixel data or pre-encoded bytes (PNG, JPEG). Useful for dynamically generated images. |
| URL | M2ImageResourceUrl |
Download an image from a remote URL. The image is fetched asynchronously and converted for the glasses. |
| Texture | M2TextureResource |
An off-screen render target - renders a drawable tree into a firmware texture slot that other drawables can display. |
| Sprite | M2SpriteFill |
References a sub-region of an M2ImageResource, allowing you to display a portion of a sprite sheet or atlas. |
Usage Examples
// From a bundled file
val fileImage = M2ImageFile("logo.png", M2CacheScope.CachedAutoReleaseWhenUnused)
// From in-memory bytes
val bytesImage = M2ImageBytes(imageData, width, height, M2CacheScope.NotCached)
// From a remote URL (downscaled to width x height on the phone before upload)
M2ImageResourceUrl.fromUrl(
url = "https://example.com/image.png",
width = 200,
height = 100,
cacheScope = M2CacheScope.NotCached
) { urlImage ->
myDrawable.setResource(urlImage)
}
Binding to Drawables
val res = M2ImageFile("logo.png", M2CacheScope.CachedAutoReleaseWhenUnused)
val logo = M2Image(res, "logo")
logo.setXY(width / 2f - res.getWidth() / 2f, height / 2f - res.getHeight() / 2f)
screen.add(logo)
Caching
Resources are uploaded to the glasses over BLE and cached in firmware memory. The cache lifetime is controlled by M2CacheScope:
| Scope | Cached (Flash) | Release | Description |
|---|---|---|---|
NotCached |
No | Auto | RAM only; released when no drawables reference it |
NotCachedManualRelease |
No | Manual | RAM only; caller must release |
CachedAutoDeleteByScreen |
Yes | Auto | Cache and slot freed when the owning screen is removed |
CachedAutoReleaseWhenUnused |
Yes | Auto | Cache persists; active slot released when unused |
CachedManualDeleteAutoRelease |
Yes | Manual delete, auto release | Caller deletes the cache slot; active slot auto-released |
CachedManualDelete |
Yes | Manual | Caller must both delete cache and release active slot |
NotCachedBackgroundUpload |
No | Auto | Uploaded in a background queue so the draw loop is not blocked |
Resources are CRC-checked to avoid duplicate uploads - if the same resource is already cached on the glasses, it is reused.
Limitations
| Constraint | Value |
|---|---|
| Maximum image data size | 48 KB (per resource) |
| Maximum pixel area | 640 × 400 (display resolution) |
Image Format & Conversion
Maverick AI uses a custom EVS image format optimized for the on-board display. Standard image files (PNG, JPG) must be converted to EVS format before uploading to the glasses.
The converted output is a PNG file with embedded custom chunks that carry the pixel data. The glasses firmware reads these chunks directly.
Converting Images - evsimgconvert.py
The evsimgconvert.py tool converts standard images to EVS format. It can be found in the SDK repository.
Basic usage:
# Convert an image
python3 evsimgconvert.py -c logo.png
# Convert with dithering for smoother gradients
python3 evsimgconvert.py -c photo.png -d
# View an existing EVS image
python3 evsimgconvert.py -s converted_image.png
Options:
| Flag | Description |
|---|---|
-c / --convert |
Convert mode (default) |
-s / --show |
View an existing EVS image |
-a / --alpha |
Preserve alpha channel |
-d / --dither |
Apply ordered dithering for better visual quality |
-v |
Verbose logging |
-o <path> |
Custom output file path |
Requirements: Python 3, Pillow ≥ 8.1.0
See Also