mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-15 06:52:23 +00:00
Image equality no longer short-cuts on a shared buffer. An image holding NaN compared equal to its clone but unequal to the same image built again; it is now unequal to both, as f32 comparison gives.
craft-texture
Linear float image planes and texture sampling. An Image is a gray (1 channel) or RGBA plane of
f32, row-major with the top row first, shared copy-on-write through an Arc. Values are stored
as given, so HDR values above 1 and negative values are kept. The crate has no UI, does no file or
network I/O and has no unsafe code.
- Construction.
try_filled,try_generate,try_generate_uvandfrom_datacheck the size againstLimits(longest side, pixel count, bytes) before allocating and return anImageError.from_dataalso checks that the buffer holds width × height × channels floats.filled,generate,generate_uvandgrayclamp each side to1..=MAX_SIDE(8192). A plane is never larger thanisize::MAXbytes (2 GiB minus one byte onwasm32), even with raised limits: thetry_forms returnImageError::TooLargefor a larger one, andmap,to_colorandto_kindclamp each side to1..=MAX_SIDEand map the top-left part instead.try_map,try_to_kind,try_resizeandtry_to_rgba8_displayreserve their pixel buffer first and returnImageError::OutOfMemorywhen that reservation fails. They still make small allocations that are not fallible: theArcaround a new image's buffer, and the boxed resampler oftry_resize. The forms withouttry_allocate likeVec. A failed infallible allocation ends the process. - Sampling.
sample(bilinear) andsample_nearesttake normalized(u, v)with(0, 0)at the upper-left corner andvincreasing downward, as glTF 2.0 section 3.8.3 defines them (https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html).tilepicks repeat (glTFREPEAT) or clamp to edge (CLAMP_TO_EDGE) for both axes. The texel coordinate, the wrapping and the bilinear weights follow the Vulkan specification, sections 20.4.1, 20.6.1 and 20.6.3 (https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#textures-texel-filtering). Repeat keeps its period at any finite coordinate. A NaN or infinite coordinate gives[0, 0, 0, 1]. Bilinear sums are taken inf64and clamped to thef32range, so finite texels give a finite sample. - Other operations.
getreads one texel,map,to_gray,to_colorandto_kindconvert,resizebox-averages whole-factor shrinks and samples bilinearly otherwise, andto_rgba8_displayencodes 8-bit sRGB RGBA.linear_to_srgb,srgb_to_linearandluminance(Rec. 709) are scalar helpers.resource_keyandsplit_resource_keytag a bitmap name with its color space.
Mirrored repeat, mip chains, height to normal, channel packing, decoding and texture-set recognition are not in the crate yet.
Cargo features
No default features.
| Feature | Provides | Pulls in |
|---|---|---|
parallel |
generated images and display conversion fill rows on several threads; the results are the same | rayon |
Without parallel the crate builds for wasm32-unknown-unknown.
Limits
| Field | Default | Checked by |
|---|---|---|
max_side |
8192 | every try_ constructor and from_data |
max_pixels |
2^26 (8192 × 8192) | the same |
max_bytes |
1 GiB (an 8192 × 8192 RGBA plane) | the same |
Origin
| Part | Source |
|---|---|
Image, Kind, sampling, resizing, conversions, sRGB helpers, resource keys and the six tests sample_survives_huge_coordinates, resource_keys_round_trip, sample_wraps_and_clamps, resize_box_and_bilinear, hostile_sizes_are_clamped, conversions |
MaterialCraft crates/image/src/lib.rs at 3133062 |
Limits, the try_ constructors, from_data, private fields with getters, the parallel feature |
written here |
Migration
| App | Status |
|---|---|
| MaterialCraft | materialcraft-image is the source. The app switches to this crate in its own pull request. |
| EffectCraft | Its texture sampling moves into this crate later, with mirrored repeat. |
For MaterialCraft:
materialcraft-image |
craft-texture |
|---|---|
image.w, image.h, image.kind, image.data |
width(), height(), kind(), data() and shared_data() |
Image { w, h, kind, data } built by hand |
Image::from_data(w, h, kind, data, &Limits::default()) |
rayon always on |
the parallel feature |
linear_to_srgb(NaN) returned −0.055 |
it returns NaN |