Expand description
Fused elementwise kernels for TerraTexture, accelerating the
pure-numpy implementations in terra_texture.blend,
terra_texture.derivatives and terra_texture.stretch without
changing their public behaviour.
The Python package tries to import this compiled extension and falls
back to its numpy implementation if the import fails (unbuilt,
unsupported platform, or a plain pip install without the compiled
wheel). That fallback is load-bearing, not incidental: the package’s
stated design goal is that terra_texture.derivatives and
terra_texture.blend have zero hard dependencies beyond numpy/scipy.
§Kernels
| Module | Core function(s) | Input | Output |
|---|---|---|---|
soft_light | soft_light_core, soft_light_rgb_core | two f32 arrays, same shape, (H, W) or (H, W, C) | same shape |
luminosity_blend | luminosity_blend_core | f32 (H, W, 3) + f32 (H, W) | f32 (H, W, 3) |
curvature | curvatures_core | f32 DEM (H, W), NaN-free | two f32 (H, W) |
hillshade | hillshade_core | f32 DEM (H, W), NaN-free | f32 (H, W) in [0, 1] |
stretch | stretch_std_core | f32 (H, W), NaN allowed | f32 (H, W) in [0, 1] or NaN |
All arrays are f32 throughout, matching the float32 arrays the
Python side passes in.
§Structure
Each kernel is split into two layers:
- a
*_corefunction in its kernel module: purendarrayin, purendarrayout, no PyO3 types anywhere. This is whatbenches/blend_bench.rsand any#[test]s call directly, with no Python interpreter needed. - a
#[pyfunction]wrapper in the privatepythonmodule: unwraps the numpy arrays intondarrayviews, calls the core function, and wraps the result back up.pythonis the only module that importspyo3ornumpy.
This split is why [lib] crate-type includes "rlib" alongside the
"cdylib" Python needs: an rlib is what cargo bench/cargo test
link against to call the core functions in-process.
The public kernel functions are re-exported at the crate root, so
use terra_texture_rs::soft_light_serial;-style imports (e.g. in
benches/blend_bench.rs) work alongside the full module paths.
§Output buffers
Every core function writes into a caller-allocated out array rather
than returning a new one, so the Python wrappers can allocate once
and hand the buffer straight back to numpy. out must have the shape
stated in each function’s docs; mismatched shapes panic (see each
function’s Panics section).
§The serial/parallel threshold
Rayon’s parallel dispatch has fixed per-call overhead (splitting work,
synchronizing threads) that only pays for itself once there’s enough
work per thread to amortize it. Below PARALLEL_THRESHOLD elements,
kernels run a plain serial loop instead. The threshold is a
provisional placeholder, not a measured value; see its docs.
Re-exports§
pub use curvature::curvatures_core;pub use hillshade::hillshade_core;pub use luminosity_blend::luminosity_blend_core;pub use luminosity_blend::luminosity_blend_parallel;pub use luminosity_blend::luminosity_blend_serial;pub use soft_light::soft_light_core;pub use soft_light::soft_light_parallel;pub use soft_light::soft_light_rgb_core;pub use soft_light::soft_light_rgb_parallel;pub use soft_light::soft_light_rgb_serial;pub use soft_light::soft_light_serial;pub use stretch::stretch_std_core;
Modules§
- curvature
- Profile and planform curvature of a DEM, as a fused kernel.
- hillshade
- Hillshade of a DEM, as a fused kernel.
- luminosity_
blend - SVG/Photoshop ‘Luminosity’ blend mode, fused into a single per-pixel pass.
- soft_
light - Photoshop-style soft light blend, over 2-D (H, W) and 3-D (H, W, C) arrays.
- stretch
- Standard-deviation contrast stretch, as a fused single-pass kernel.
Constants§
- PARALLEL_
THRESHOLD - Element count at or above which kernels switch from a serial loop to rayon’s parallel iteration.