Styling and band math
Inputs use SDK raster-style = "=0.4.0", protocol 3.0, and Rust 1.92.
The SDK validates structure and semantics; the adapter rejects unsupported
capabilities. Unknown fields and duplicate singleton parameters are errors.
The subset below targets Tiler::tile and MosaicTiler::tile, not full backend certification.
Rust inputs
Use TileStyle::from_raster_query for an original Q3 string, or
TileStyle::from_raster_style(&RasterStyle) for an SDK-validated document.
RasterStyle is re-exported from async_geotiff::style.
style.raster_style_json() returns normalized JSON. Reparse the document to
change a style. The parsed style is immutable; format() and tilesize() expose read-only output settings.
Tile and Mosaic are versioned extensions: list their exact Schema URLs in
extensions, and place settings in raster:tile / raster:mosaic.
Q3 carries the URL array in extensions and the fields object in extension_fields.
Use raster_style::encode_query to encode a validated SDK document.
Incomplete validation and third-party extension declarations are rejected before execution.
HTTP Q3
Single-band pseudocolor:
RGB with one range broadcast to all three outputs:
dataset, mode, and _v belong to the example server, not the style document.
TMS and tile coordinates remain in the path. The SDK decodes raw query fragments
once: encode + as %2B and spaces as %20. Never pre-decode Q3.
JSON is a Rust API entrypoint; the example HTTP service uses Q3 GET requests.
PNG is the default. WebP requires the webp feature, a declared Tile 1.0.0 extension with raster:tile: {format: "webp", lossless: true},
and a .webp path. The path extension must match the style format.
Stretch and color
- Renderers:
gray,rgb,pseudocolor,categorized,single_color. method=none, including omission, uses[0,255]on display paths and never triggers automatic statistics.method=linearrequiresrescale; RGB accepts one broadcast or three channel ranges.- Display paths support
range_policy=clamp|transparent, checked before color operations. - Named ramps use the project’s pinned
colorous256-entry tables: viridis, magma, inferno, plasma, cividis, turbo, greys. - Native
colormapobjects use exact data values; interval arrays use half-open[lo,hi)bounds, including the final interval. With explicit stretch or Gamma, pseudocolor uses 0–255 lookup indices; categorized always uses exact data values. - Gray supports
renderer_invert; valid zero and negative inputs work withsingle_color. opacitymultiplies output Alpha. Quantized zero Alpha produces transparent black.
Categorized supports explicit exact-value tables and nearest only. It reads the base level because source overviews lack category-preservation evidence. Numeric paths support the existing nearest, bilinear, cubic, cubic_spline, lanczos, and average kernels. Dependencies are resampled independently, preserving validity. Source Alpha bands are currently rejected before pixel reads.
cubic_spline smooths even at integer pixel centers. It therefore still runs
its kernel when the requested tile grid exactly matches the source grid;
direct tile rendering and the warp path preserve the same resampling semantics.
Cubic, CubicSpline and Lanczos also preserve finite constant F64 values near
the numeric limits without making them transparent through intermediate
overflow. Truly non-finite samples or unrepresentable results remain invalid.
Statistical stretch and curves
All seven methods are supported: none, linear, minmax, percentile,
stddev, histogram_equalization, and curve. The examples expose their parameters:
Percentiles use linear interpolation of sorted samples; standard deviation is
population deviation. Histogram equalization uses the empirical CDF, without bins.
Curve points are [data value, normalized output]; provide one broadcast curve
or three RGB curves. Percent-encode the JSON in an actual Q3 URL.
Tiler and MosaicTiler bind a fixed 1024 × 1024 EPSG:4326 grid over the
complete source footprint or union of the fixed mosaic collection. The grid has
north-up rows, equally spaced longitude/latitude centers, and coverage/validity
masks inherited from each source. Overview choice is fixed from each source’s full
extent at this grid size, independent of tile zoom. The same upstream resampling,
NoData, expressions, tuple validity and mosaic stages run on that grid. Statistics
never come from the requested tile or unverified embedded GDAL summaries.
Omitted statistics means dataset/mosaic scope, sample accuracy and a maximum of
1,000,000 row-major evenly spaced grid positions. statistics={"scope":"dataset", "accuracy":"exact"} visits all cells of this bound grid, not every native
resolution source pixel. NoData samples are discarded without replacement. Empty
statistics give transparent output; a constant range maps its value to 0.5.
Statistics are shared across tiles and cached with reader instance/order and the full normalized style. CPU work, source reads and retained median inputs use the existing resource limits. Complete reads of the selected overview can be rejected when they exceed the work budget. Two cached plans bound retained CDF storage.
MosaicJSON with quadkey_zoom=0 provides a complete fixed collection for statistics.
Partitioned MosaicJSON statistical stretches fail explicitly: flattening its index
would lose coverage masks and regional paint order. Tile rendering always uses the
index-selected assets. Custom MosaicSource implementations must provide
statistics_assets() whose full-footprint composite preserves tile selection semantics. Unbound dynamic STAC collections, viewport scope and external
statistics.ref snapshots fail explicitly. Low-level render(ImageData, ...)
requires a resolved plan for statistical methods; use the tilers to bind it.
Expressions
Decimal literals, parentheses, unary minus, and arithmetic + - * / are supported.
Band numbers are one-based; RGB expressions separate three outputs with ;.
This NDVI example requires band 5 to be near-infrared and band 4 red; check the
asset metadata first. Expressions cannot coexist with bidx, but may combine
with supported Gamma operations. Invalid inputs, division by zero, and non-finite
results become transparent. Functions, conditionals, and scientific notation
are unsupported. Both the SDK and existing arithmetic parser bound input size.
Color formulas
effects.color_formula supports Gamma, evaluated in array order. Q3 example:
Unsupported requests fail explicitly: external statistics snapshots, calibration other than none, index, color_mapping, source palettes, mode resampling, terrain, third-party extensions, other color operations, JPEG, and lossy WebP.
Mosaic
With the default mosaic feature enabled, declare this JSON member:
Declare the official Mosaic 1.0.0 schema URL in extensions. Q3 encodes the declaration array in extensions and the object containing raster:mosaic in extension_fields. The old mosaic short parameters are rejected.
All five methods (first, highest, lowest, mean, median) support before_channels
and after_channels. Call mosaic.tile(coord, &style).await? to take the
selection from the document. tile_with_options(coord, &style, &options) adds request cancellation and deadlines.
Before channels, ranking positions refer to deduplicated source dependencies
sorted by source band number; after channels, positions refer to output order.
rank_channel is one-based and only applies to highest/lowest. Only complete,
valid tuples from one source participate; channels are never stitched across
sources. Gamma, colormaps, and opacity apply once after merging. The source
Alpha limitation still applies.
Assets remain outside the style, supplied by MosaicJSON, STAC, or a custom MosaicSource. See the mosaic guide for configuration and limits.
Migration
Removed: from_query / from_pairs, ValidatedTileStyle, compile_validated,
mutable style fields, Stretch / ColourDefinition / Colour / lut_from_stops, and the separate mosaic
selection argument. Use from_json / from_raster_query / from_raster_style.
TileStyle::default() is a protocol gray-band-1 style with fixed 0–255 mapping.
HTTP requires version=3.0&type=...; old parameters and unknown fields fail.
All viewers emit Q3 only. Opacity is applied once by the server; MapLibre offers
mosaic stage and rank-channel controls.
| Legacy input | Raster Style input |
|---|---|
bidx=1&colormap_name=viridis&rescale=0,3000 | Add version=3.0&type=pseudocolor&method=linear |
| Three identical RGB ranges | One broadcast range; explicitly set type=rgb and three bidx values |
| Omitted stretch auto-selects stddev for non-U8 | Fixed [0,255]; explicitly supply a range when needed |
Continuous stops in colormap | Do not reuse: native arrays are interval tables; continuous color_mapping is not yet implemented |
stretch=percent&pc=2,98 | method=percentile&percentiles=2,98 |