Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

image

A picture from a file: wallpapers, album art, avatars, thumbnails. It can decode off-thread, hold the previous picture while a new one loads, and cross-fade or run a shader between them. For theme icons, use an icon.

A wallpaper that crossfades when the path changes:

local path = state("wallpaper", "/usr/share/backgrounds/a.jpg")

return { panel {
    id = "wallpaper",
    layer = "Background",
    anchor = { top = true, bottom = true, left = true, right = true },
    width = "Fill",
    height = "Fill",
    child = image {
        id = "wallpaper_image", -- keeps the node, and so the held picture, across source changes
        source = path,
        async = true,
        transition = { duration = 600, easing = "InOutCubic" },
        width = "Fill",
        height = "Fill",
    },
} }

Properties

image takes the common properties, plus:

PropertyTypeDefaultBehaviour
sourcestring|Bound""A file path (mantle.config_dir .. "/img/a.png"), never a theme name; "" draws nothing. PNG, JPEG, WebP, GIF, SVG or SVGZ; animated GIFs loop
fit"cover"|"contain"|"stretch"|Bound"cover""cover" fills the box and crops, "contain" fits inside it, "stretch" distorts to it
asyncboolean|Boundfalsefalse decodes in the frame that first draws it. true decodes on a worker and draws nothing until ready; use it for many or large images
retainboolean|BoundfalseKeep drawing the last picture while a new source decodes, and on a failed decode. Needs async = true and a stable id
transitionTransition|BoundNoneCross from the held picture to each newly decoded source. Implies retain; needs async = true and a stable id. Unknown keys are refused. See transition
source_blurnumber|Bound, [0, 8192]0Blur sigma in px, baked into the pixels once at decode (three box passes approximating a Gaussian); see blurs. Animated GIFs ignore it. Under async, a change blanks the image until the re-decode lands; retain does not cover it

transition

FieldValuesDefaultBehaviour
durationms, [1, 60000]RequiredLength of the cross
easingAn easing"InOutQuad"Drives u_progress
shaderAbsolute .frag pathBuilt-in cross-dissolveReplaces the dissolve. Recompiled when the file changes
params{ name = number | { 2 to 4 numbers } }{}Uniforms for that shader, as on a shader node. Refused without shader

The first picture appears without a transition. A transition shader gets everything a shader node gets, plus:

NameWhat
mantle_from(uv), mantle_to(uv)Outgoing and incoming picture at a box coordinate, premultiplied, already placed by fit; transparent outside the picture
u_from_rect, u_to_rectEach picture’s (x, y, w, h) in box fractions; may pass 0..1 under "cover"

u_progress is the eased progress 0..1. A transition shader that fails to build logs once and the node falls back to the cross-dissolve.

How do I…

TaskAnswer
Crossfade a wallpaperThe example above: async, transition and a stable id
Wipe instead of fadetransition = { duration = 700, shader = mantle.config_dir .. "/shaders/wipe.frag" } with a .frag that mixes mantle_from and mantle_to
Round an image’s cornersBelow
Make a circular avatarThe same, with radius half the size (paint)
Show many thumbnails without stutterasync = true on each, in a list
Blur a wallpaper oncesource_blur = 20
Show a file that ships with the configsource = mantle.config_dir .. "/img/logo.png"

Round an image’s corners

An image has no radius. Put it in a box with radius and clip = "Rounded" (clip):

local cover = rect {
    width = 96,
    height = 96,
    radius = 12,
    clip = "Rounded", -- cut the image to the corners
    children = {
        image { source = "/usr/share/backgrounds/a.jpg", fit = "cover", async = true, width = "Fill", height = "Fill" },
    },
}

Gotchas

TrapFix
The image does not appearIt has no intrinsic size. Give width and height
An image flashes blank when its source changes despite retainretain needs async = true and a node that survives: give it a stable id
The shell stutters while images loadInline decode blocks drawing. Set async = true
source = "firefox" draws nothingsource is a path. Use icon for theme names
A relative source draws nothingIt resolves against the Renderer’s working directory, not the config. Build paths from mantle.config_dir
radius on an image is refusedIt is not a box. Wrap it, as above
transition.params is refusedparams needs a shader

See also: icon, shader, paint, animation.

Source: vocabulary, content parsers, transition, shader stage, decode.