Skip to content

Raster

Image-processing ops over Raster (and, where noted, Sprite): generators, composition, colour, warp, morphology, dither, terrain.

37 ops: blend, blur, brightness-contrast, channel-shuffle, circle, color-ramp, color-to-alpha, density, dilate, displace, dither, edge-detect, erode, gradient-conic, gradient-diamond, gradient-linear, gradient-radial, hillshade, hsl, invert, levels, map-range, mix, mosaic, noise, place, posterize, quantize, saturate, sharpen, slope, solid, stack, threshold, tiling, vibrance, warp.

Composite over onto base with a W3C blend mode. clip: true clips result to base alpha (Photoshop-style clipping mask, i.e. source-atop): the result takes the base’s alpha, so clipping onto a 0.12-alpha wash caps the whole overlay at 0.12 — when you mean “restrict this to an area”, give an opaque shape as mask instead. composite: "destination-out" makes over erase base (brush-eraser effect when over is a brush-shaped raster). Optional mask raster’s alpha modulates source coverage.

The shared basemap, before blendThe same tile after blend
A colour multiplied over the base — one of sixteen W3C blend modes. style
Field Type Required Description
base @node yes Reference to another node (@name).
clip boolean | $param | @node no
composite over | source-over | destination-out | dest-out | erase no
mask @node no Reference to another node (@name).
mode normal | multiply | screen | overlay | darken | lighten | color-dodge | color-burn | hard-light | soft-light | difference | exclusion | hue | saturation | color | luminosity no
opacity number (0…1) | $param | @node no
over @node yes Reference to another node (@name).

Gaussian blur on a raster (libblur, exact). Grows upstream pad by 3σ, so sigma needs an upper bound the build can see: a literal, a $param with max, or sigma-max alongside an @node port (the port’s value is then clamped to it).

The shared basemap, before blurThe same tile after blur
Gaussian blur, σ = 6 px. style
Field Type Required Description
input @node yes Reference to another node (@name).
sigma number (0…∞) | $param | @node yes
sigma-max number (0…∞) no Upper bound on sigma for padding, required when sigma is an @node port. Values above it are clamped.

Linear brightness shift and contrast slope around mid-gray. Both in [-1, 1], 0 = no change.

The shared basemap, before brightness-contrastThe same tile after brightness-contrast
Darkened, with contrast raised around mid-grey. style
Field Type Required Description
brightness number (-1…1) | $param | @node no
contrast number (-1…1) | $param | @node no
input @node yes Reference to another node (@name).

Rearrange RGBA channels. Each output (r/g/b/a) names which input channel feeds it, or a constant (0/1). Identity by default. Operates in non-premultiplied sRGB.

The shared basemap, before channel-shuffleThe same tile after channel-shuffle
Channels permuted — red and blue swapped. style
Field Type Required Description
a r | g | b | a | 0 | 1 no
b r | g | b | a | 0 | 1 no
g r | g | b | a | 0 | 1 no
input @node yes Reference to another node (@name).
r r | g | b | a | 0 | 1 no

Centred disk source. kind: raster (default) renders at canvas size with radius = radius-frac × tile-size. kind: sprite renders at width-px × height-px with radius = radius-frac × min(width, height).

A tile rendered with circle
A canvas-sized circle — the sprite behind MapLibre’s circle layers. style
Field Type Required Description
color color | $param | @node yes sRGB hex color, $param reference, or @node scalar port.
hardness number (0…1) | $param | @node no
height-px integer (1…∞) no
kind raster | sprite no
radius-frac number (0…1) | $param | @node yes
width-px integer (1…∞) no

Map a ScalarField (or a Raster, by its luminance — a gradient map) to colour through a stop table, interpolating between stops in space. Samples outside [stops[0].value, stops[-1].value] clamp to the end colours. Canonical use case is hypsometric tinting over a DEM (stops[i].value = elevation in metres). Give ramp-expr instead of stops to drive the ramp from a MapLibre color expression over heatmap-density.

Field Type Required Description
field @node yes Reference to another node (@name).
opacity number (0…1) | $param | @node no Uniform output-alpha multiplier (layer opacity). Default 1.0. Feed an expr node via @node for a zoom curve.
ramp-expr no A MapLibre color expression over heatmap-density (e.g. a heatmap-color value). When present it overrides stops: the expression is baked into a 256-entry LUT per eval (zoom in context), inputs clamp to [0, 1], and lookups interpolate linearly between entries — mirroring MapLibre’s 256-px ramp texture. stops is only required when this is absent.
space rgb | hsl | hsv | hcl | lab no Colour space the stops interpolate in. rgb (default) is a straight sRGB lerp; hsl/hsv/hcl interpolate hue on the shortest path; hcl/lab are perceptual (ported from the MapLibre style spec).
stops array of object no Either half of a stop may be a $param, so a ramp can be recoloured or rescaled at render time. The table is sorted by value on every eval, so a param may reorder it.

Make pixels close to color transparent. Distance ≤ threshold → alpha 0, distance ≥ threshold + softness → alpha unchanged, linear in between. Distance is Chebyshev (max per-channel) in non-premultiplied sRGB.

The shared basemap, before color-to-alphaThe same tile after color-to-alpha
The paper colour knocked out to transparency. style
Field Type Required Description
color color | $param | @node yes sRGB hex color, $param reference, or @node scalar port.
input @node yes Reference to another node (@name).
softness number (0…1) | $param | @node no
threshold number (0…1) | $param | @node no

Kernel-density estimate of the input’s point features as a ScalarField (the MapLibre heatmap kernel: support = radius px, falloff exp(-0.5·3²·(d/radius)²)/√(2π)). Points only — lines and polygons contribute nothing, so a line or polygon layer comes out an all-zero field with no error; put centroid in front of it. Buffer points outside the tile still contribute, so tile borders match. Output is raw accumulated density, unclamped and scaling with intensity, so probe its range before placing ramp stops. Map it with color-ramp or extract isolines with contour. Grows upstream pad by radius.

Field Type Required Description
features @node yes Reference to another node (@name).
intensity number (0…∞) | $param | @node no Global multiplier on every point’s contribution.
intensity-expr no A MapLibre number expression giving the intensity multiplier, evaluated per feature group; overrides the constant intensity.
radius number (0…∞) | $param | @node no Kernel radius in px. Pad is computed at build time, so this needs a static bound: a literal, or a $param with max.
radius-expr no A MapLibre number expression (px), evaluated per feature group; overrides the constant radius. Evaluated values are clamped to radius’s static bound so the pad stays sound.
weight-expr no A MapLibre number expression giving a point’s weight, evaluated per feature group. A group without it (or whose expression doesn’t resolve to a number) weighs 1.

Per-channel morphological max over a square kernel. Grows bright / opaque regions; pair with erode to clean up speckle noise (open / close). Being a max, it also flattens detail finer than the kernel — a few px of radius-px is enough to erase grain, so add grain after morphology, never before. Separable box implementation; grows upstream pad by radius-px.

A tile rendered with dilate
Dilation of a water mask — coverage grows by the kernel radius. style
Field Type Required Description
input @node yes Reference to another node (@name).
radius-px integer (0…256) | $param | @node yes
radius-px-max number (0…∞) no Upper bound on radius-px for padding, required when radius-px is an @node port. Values above it are clamped.

Photoshop-style displacement map. Output pixel reads input at a position offset by the displacement raster’s R/G channels (0.5 means no offset). Grows upstream pad by amp-px so warped samples stay seamless across tile borders, provided the displacement source is itself seamless (e.g. noise with anchor: world).

The shared basemap, before displaceThe same tile after displace
Displaced by a separate low-frequency noise raster. style
Field Type Required Description
amp-px number (0…∞) | $param | @node yes
amp-x-px number (0…∞) | $param | @node no
amp-x-px-max number (0…∞) no Upper bound on amp-x-px for padding, required when amp-x-px is an @node port. Values above it are clamped.
amp-y-px number (0…∞) | $param | @node no
amp-y-px-max number (0…∞) no Upper bound on amp-y-px for padding, required when amp-y-px is an @node port. Values above it are clamped.
boundary clamp | transparent | mirror no
displacement @node yes Reference to another node (@name).
input @node yes Reference to another node (@name).

Reduce to a fixed palette with dithering so gradients survive a small palette. method: "floyd-steinberg" (default) diffuses error to neighbours; method: "ordered" uses a 4×4 Bayer matrix with strength amount (0..1). Nearest-colour distance uses space (lab default / rgb). Alpha preserved.

The shared basemap, before ditherThe same tile after dither
The same four inks, error-diffused — gradients survive the reduction. style
Field Type Required Description
amount number (0…1) no Ordered-dither strength (ignored for floyd-steinberg).
input @node yes Reference to another node (@name).
method floyd-steinberg | ordered no
palette array of string yes Each entry is #rrggbb / #rrggbbaa (alpha ignored for matching) or a $param, so a palette can be recoloured at render time.
space lab | rgb no

Sobel gradient magnitude per channel, scaled by strength and clamped to [0, 255]. Pass-through over Raster / Sprite. Use after a hillshade for stylised outlines, or on a flat fill to derive an outline mask.

A tile rendered with edge-detect
Sobel over a flat water fill — the outline mask the op is usually used for. style
Field Type Required Description
input @node yes Reference to another node (@name).
strength number (0…∞) | $param | @node no Scale factor applied to the gradient magnitude before clamping.

Per-channel morphological min over a square kernel. Shrinks bright / opaque regions; classic mask cleanup after color-to-alpha. Removes anything thinner than the kernel outright, so erode then dilate (an opening) keeps only features wider than radius-px — a way to select by size when the source carries no size attribute. Detail finer than the radius does not survive either op: add grain after morphology, never before. Separable box implementation; grows upstream pad by radius-px.

A tile rendered with erode
Erosion of the same mask — coverage shrinks, and the narrow channels vanish. style
Field Type Required Description
input @node yes Reference to another node (@name).
radius-px integer (0…256) | $param | @node yes
radius-px-max number (0…∞) no Upper bound on radius-px for padding, required when radius-px is an @node port. Values above it are clamped.

Conic (sweep) gradient around center. Gradient parameter is the clockwise angle from start-angle (degrees) normalized to [0, 1). 0° points along +x. kind: sprite switches to sprite-local [0, 1] coords.

A tile rendered with gradient-conic
A conic gradient sweeping around the centre. style
Field Type Required Description
anchor tile | world no
center array of number no
height-px integer (1…∞) no
kind raster | sprite no
space rgb | hsl | hsv | hcl | lab no Colour space the stops interpolate in; hue-based spaces take the shortest path.
start-angle number | $param | @node no
stops array of array of — yes [[t, color], ...]. Either half of a pair may be a $param; the table is sorted by t on every eval, so stops need not be declared in order.
width-px integer (1…∞) no

Diamond gradient from center. Gradient parameter is Manhattan (|dx| + |dy|) distance / radius. kind: sprite switches to sprite-local [0, 1] coords.

A tile rendered with gradient-diamond
A diamond gradient — square distance rather than radial. style
Field Type Required Description
anchor tile | world no
center array of number no
height-px integer (1…∞) no
kind raster | sprite no
radius number (0…∞) | $param | @node no
space rgb | hsl | hsv | hcl | lab no Colour space the stops interpolate in; hue-based spaces take the shortest path.
stops array of array of — yes [[t, color], ...]. Either half of a pair may be a $param; the table is sorted by t on every eval, so stops need not be declared in order.
width-px integer (1…∞) no

Linear gradient from start to end (fractional coords). kind: raster (default) samples in tile/world coords; kind: sprite samples in [0, 1] sprite coords at width-px × height-px.

A tile rendered with gradient-linear
A linear gradient across the canvas. style
Field Type Required Description
anchor tile | world no
end array of number no
height-px integer (1…∞) no
kind raster | sprite no
space rgb | hsl | hsv | hcl | lab no Colour space the stops interpolate in; hue-based spaces take the shortest path.
start array of number no
stops array of array of — yes [[t, color], ...]. Either half of a pair may be a $param; the table is sorted by t on every eval, so stops need not be declared in order.
width-px integer (1…∞) no

Radial gradient from center outward. Gradient parameter is Euclidean distance / radius. aspect > 1 stretches the ellipse along X, < 1 along Y. kind: sprite switches to sprite-local [0, 1] coords.

A tile rendered with gradient-radial
A radial gradient from the canvas centre. style
Field Type Required Description
anchor tile | world no
aspect number (0…∞) | $param | @node no
center array of number no
height-px integer (1…∞) no
kind raster | sprite no
radius number (0…∞) | $param | @node no
space rgb | hsl | hsv | hcl | lab no Colour space the stops interpolate in; hue-based spaces take the shortest path.
stops array of array of — yes [[t, color], ...]. Either half of a pair may be a $param; the table is sorted by t on every eval, so stops need not be declared in order.
width-px integer (1…∞) no

Analytical hillshade (Horn 1981) from a ScalarField. mode: shade outputs grayscale; mode: relief outputs transparent black scaled by 1-shade for multiply-blend over a base map.

Field Type Required Description
altitude-deg number | $param | @node no Light elevation above the horizon (degrees).
azimuth-deg number | $param | @node no Light direction (0 = north, clockwise).
exaggeration number | $param | @node no Extra vertical exaggeration on top of z-factor.
field @node yes Reference to another node (@name).
highlight-color color | $param | @node no sRGB hex color, $param reference, or @node scalar port.
mode shade | relief no
multidirectional boolean | $param | @node no ESRI-style 4-direction weighted hillshade — softer, more legible at small zooms.
shadow-color color | $param | @node no sRGB hex color, $param reference, or @node scalar port.
z-factor number | $param | @node no Multiplier on elevation before gradient — use ~1/cos(lat) for high latitudes.

HSL adjustment: rotate hue by hue-shift degrees, shift saturation/lightness in [-1, 1] (0 = no change, +1 = toward max, -1 = toward 0).

The shared basemap, before hslThe same tile after hsl
Hue rotated and saturation raised. style
Field Type Required Description
hue-shift number | $param | @node no
input @node yes Reference to another node (@name).
lightness number (-1…1) | $param | @node no
saturation number (-1…1) | $param | @node no

Negate RGB channels (1 - c). Alpha is preserved.

The shared basemap, before invertThe same tile after invert
Every channel inverted. style
Field Type Required Description
input @node yes Reference to another node (@name).

Photoshop-style levels: remap input range [in-black, in-white] through gamma onto output range [out-black, out-white]. All values in [0, 1] (non-premultiplied sRGB). gamma > 1 lightens midtones; gamma < 1 darkens them.

The shared basemap, before levelsThe same tile after levels
Input range remapped — the tonal-range expansion before a screen. style
Field Type Required Description
gamma number (0.01…∞) | $param | @node no
in-black number (0…1) | $param | @node no
in-white number (0…1) | $param | @node no
input @node yes Reference to another node (@name).
out-black number (0…1) | $param | @node no
out-white number (0…1) | $param | @node no

Linearly remap scalar field values from [in-min, in-max] to [out-min, out-max]. With clamp: true, results outside the output range are pinned to the range bounds. Useful for normalising elevation or distance fields before a color-ramp.

Field Type Required Description
clamp boolean | $param | @node no
field @node yes Reference to another node (@name).
in-max number | $param | @node no
in-min number | $param | @node no
out-max number | $param | @node no
out-min number | $param | @node no

Interpolate two rasters per-pixel by scalar t (0..1) in colour space. A straight colour tween (contrast with blend, which composites with alpha). t accepts a literal, $param, or @node scalar for param-driven theming.

The shared basemap, before mixThe same tile after mix
A straight crossfade between two rasters. style
Field Type Required Description
a @node yes Reference to another node (@name).
b @node yes Reference to another node (@name).
space rgb | hsl | hsv | hcl | lab no Colour space the interpolation runs in; hue-based spaces take the shortest path.
t number (0…1) | $param | @node no

Quantize a raster into uniform square blocks. mode selects how each block is summarized: average (default) takes the mean of covered pixels (smooth, classic mosaic); nearest takes the block’s centre pixel (crisp, no inter-colour blending). World-anchored by default so adjacent map tiles share the same block grid.

The shared basemap, before mosaicThe same tile after mosaic
Averaged into 8 px blocks, on a world-anchored grid. style
Field Type Required Description
anchor world | tile no world (default) makes the block grid seamless across map tiles by growing the upstream pad. tile restarts the grid at every map tile’s top-left and requires no extra padding.
block integer (1…∞) | $param | @node yes Block edge length in canvas pixels. With anchor: world the block size sets the canvas padding, which is fixed before anything renders — so this needs an upper bound the build can see: a literal, a $param with max, or block-max beside an @node port.
block-max number (0…∞) no Upper bound on block for padding, required when block is an @node port. Values above it are clamped.
input @node yes Reference to another node (@name).
mode average | nearest no average (default) blends covered pixels into a mean colour. nearest samples the block’s centre pixel verbatim — produces hard block edges without inter-colour averaging.

Procedural noise source. With kind: raster (default) the noise is mapped to RGBA via low-color/high-color/opacity. With kind: scalar it emits a ScalarField of raw fBm values — compose with map-range before feeding hillshade/color-ramp. Every type lands in [-1, 1], but they are not distributed alike: white/value/perlin/simplex sit around 0, while worley is 1 − 2·distance and so piles up at +1 over the cell interiors — more than half a tile can be exactly 1.0. Evenly spaced ramp stops over a field like that leave most of the ramp unreachable and the render unchanged, so probe the distribution before choosing stops. anchor=world (default) keeps the field seamless across tile borders.

A tile rendered with noise
Fractal noise, world-anchored so it is continuous across tiles. style
Field Type Required Description
anchor tile | world no
gain number | $param | @node no
high-color color | $param | @node no sRGB hex color, $param reference, or @node scalar port.
kind raster | scalar no
lacunarity number | $param | @node no
low-color color | $param | @node no sRGB hex color, $param reference, or @node scalar port.
octaves integer (1…12) no
opacity number (0…1) | $param | @node no
scale-px number | array of number yes Noise wavelength in pixels. A single number for isotropic noise; an [x, y] array for anisotropic noise (larger value = longer wavelength along that axis, i.e. stretched pattern).
seed integer (0…∞) no Field seed. Omitted, anchor: world uses a fixed seed so every tile samples the same field, and anchor: tile uses the host’s per-tile seed so each tile gets its own. Set it to pin either.
type white | value | perlin | simplex | worley no
warp-amp number | $param | @node no
warp-freq number | $param | @node no

Draw the source raster onto the canvas exactly once. fit:none (default) uses position/anchor/scale; cover/contain/stretch derive the destination rect from the canvas (and treat position-px as an offset from canvas center). Companion to tiling (repeats) and stamp (per-point).

Field Type Required Description
anchor top-left | top-center | top-right | center-left | center | center-right | bottom-left | bottom-center | bottom-right no Only used when fit=none.
fit none | cover | contain | stretch no
input @node yes Reference to another node (@name).
opacity number (0…1) | $param | @node no
position-px array of number no fit=none: canvas pixel where the image’s anchor point lands. Other fits: offset from canvas center.
rotation-deg number | $param | @node no Rotation (degrees clockwise) around the placement anchor / canvas center.
scale number (0…∞) | $param | @node no Uniform scale for fit=none. Ignored for other fits.

Quantise each RGB channel into steps evenly-spaced levels (in non-premultiplied sRGB). Alpha preserved. Pair with levels to control which tonal band gets the strongest banding.

The shared basemap, before posterizeThe same tile after posterize
Each channel snapped to four levels. style
Field Type Required Description
input @node yes Reference to another node (@name).
steps integer (2…256) no

Snap each pixel to the nearest colour in palette, measuring distance in space (lab = perceptual ΔE, default; or rgb). Alpha is preserved. Use for limited-palette / poster / pixel-art looks; see dither for the error-diffused variant.

The shared basemap, before quantizeThe same tile after quantize
Mapped to a four-ink palette, no dithering. style
Field Type Required Description
input @node yes Reference to another node (@name).
palette array of string yes Each entry is #rrggbb / #rrggbbaa (alpha ignored for matching) or a $param, so a palette can be recoloured at render time.
space lab | rgb no Colour space the nearest-colour distance is measured in.

Scale CIELAB chroma uniformly by amount (1 = identity, 0 = greyscale, >1 = more saturated). Hue and lightness are preserved.

The shared basemap, before saturateThe same tile after saturate
Saturation pushed up. style
Field Type Required Description
amount number (0…∞) | $param | @node no
input @node yes Reference to another node (@name).

4-neighbour Laplacian sharpen: amplifies each pixel relative to its orthogonal neighbours by amount. Around 0.5–1.0 is a typical unsharp-mask look; negative values give a soft halo. Grows upstream pad by 1.

The shared basemap, before sharpenThe same tile after sharpen
Unsharp-mask style sharpening. style
Field Type Required Description
amount number | $param | @node no Sharpening strength. 0 = pass-through, ~1 = strong.
input @node yes Reference to another node (@name).

Slope angle as grayscale, normalised to 0..1 against max-deg.

Field Type Required Description
field @node yes Reference to another node (@name).
invert boolean | $param | @node no If true, flat = white and steep = black.
max-deg number | $param | @node no Slope angle (degrees) that maps to white.

Solid-colour source. kind: raster (default) fills the full canvas; kind: sprite emits a Sprite at width-px × height-px for use as a synthetic placement/tiling source.

A tile rendered with solid
A single flat colour over the whole canvas. style
Field Type Required Description
color color | $param | @node yes sRGB hex color, $param reference, or @node scalar port.
height-px integer (1…∞) no
kind raster | sprite no
width-px integer (1…∞) no

Composite an ordered list of raster layers bottom-to-top with plain source-over (equivalent to a chain of blend nodes with mode: normal, composite: over, opacity: 1), folded into one pass over a single accumulator. Fully-transparent layers are skipped. For per-layer opacity, blend modes, clipping, masks, or the eraser composite, use blend.

The shared basemap, before stackThe same tile after stack
Several rasters composited bottom-to-top in one pass. style
Field Type Required Description
layers array of @node yes Raster (or sprite) layers, bottom first. The output mirrors the bottom layer’s kind.

Binarise a scalar field: emit low for samples ≤ value, high otherwise. With softness > 0 the transition is a linear ramp of width softness centred on value.

Field Type Required Description
field @node yes Reference to another node (@name).
high number | $param | @node no
low number | $param | @node no
softness number (0…∞) | $param | @node no
value number | $param | @node no

Repeat a raster across the canvas with bilinear wrap-around sampling. Primary use case is paper / canvas texture composition. Does not stretch-to-fit — use a dedicated cover/contain node if that’s what you want.

Field Type Required Description
anchor world | tile no world (default) makes the pattern seamless across map tiles; tile restarts the pattern at every map tile’s top-left.
input @node yes Reference to another node (@name).
offset-px array of number no Pattern offset in canvas pixels [x, y].
opacity number (0…1) | $param | @node no
rotation-deg number | $param | @node no Rotation of the pattern in degrees (clockwise).
scale-px number (0.5…∞) no Canvas pixels per one source repetition. Defaults to the source image’s native width.

Adaptively boost CIELAB chroma — low-chroma pixels rise more than already-vivid ones (amount = strength, 0 = identity). Hue and lightness preserved.

The shared basemap, before vibranceThe same tile after vibrance
Saturation raised on muted colours only, leaving saturated ones alone. style
Field Type Required Description
amount number (0…∞) | $param | @node no
input @node yes Reference to another node (@name).

Domain warp via an internal noise field. With anchor: world (default) the warp is seamless across tile borders; the upstream pad grows by amp-px to keep samples inside the available raster.

The shared basemap, before warpThe same tile after warp
Pixels pushed around by internal noise — the paper-wobble op. style
Field Type Required Description
amp-px number (0…∞) | $param | @node yes
amp-x-px number (0…∞) | $param | @node no
amp-x-px-max number (0…∞) no Upper bound on amp-x-px for padding, required when amp-x-px is an @node port. Values above it are clamped.
amp-y-px number (0…∞) | $param | @node no
amp-y-px-max number (0…∞) no Upper bound on amp-y-px for padding, required when amp-y-px is an @node port. Values above it are clamped.
anchor tile | world no
boundary clamp | transparent | mirror no
gain number | $param | @node no
input @node yes Reference to another node (@name).
lacunarity number | $param | @node no
octaves integer (1…12) no
scale-px number (0…∞) | $param | @node yes
seed integer (0…∞) no Field seed. Omitted, anchor: world uses a fixed seed so every tile samples the same field, and anchor: tile uses the host’s per-tile seed so each tile gets its own. Set it to pin either.
type white | value | perlin | simplex | worley no

Map renders on this site are made fromOpenStreetMap data viaProtomaps (© OpenStreetMap contributors), elevation from Re:Earth Terrain,Mapterhorn andEGM2008 (NGA), and aerial imagery from GSI Japan(© 国土地理院). The painterly styles use CC0 brushes byDavid Revoy.