feat(imaging): add pure-Rust JPEG 2000 backend (#109)
Some checks failed
CI / required (push) Failing after 3m18s

This commit is contained in:
2026-08-13 05:44:30 +00:00
parent 27c860c225
commit 0bab5b4c8d
28 changed files with 2770 additions and 109 deletions

129
Cargo.lock generated
View File

@@ -609,6 +609,31 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "crossbeam-deque"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17"
[[package]] [[package]]
name = "crypto-bigint" name = "crypto-bigint"
version = "0.5.5" version = "0.5.5"
@@ -882,6 +907,12 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
[[package]]
name = "fearless_simd"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97b65636e5b9ef369943878ac74335ba1c55c1cb6adbf1e2c293c624248d693"
[[package]] [[package]]
name = "ff" name = "ff"
version = "0.13.1" version = "0.13.1"
@@ -1397,6 +1428,61 @@ version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "j2k"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0371832fbd6d4e7c83ab85545bb41474f91f565dd1e5660b733de11b54a257eb"
dependencies = [
"j2k-codec-math",
"j2k-core",
"j2k-native",
"j2k-types",
"moxcms",
"thiserror 2.0.20",
]
[[package]]
name = "j2k-codec-math"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "165366ed0d18b737c6f6cd2c3ffeb20c94dc40aac70e77c2f6dd1c8b518aec3e"
[[package]]
name = "j2k-core"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "058401c1957538158b1565d0b9453f8165ca0fc62e85197849364971d4be551a"
dependencies = [
"thiserror 2.0.20",
]
[[package]]
name = "j2k-native"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c8af5bf0762fdf381b2893a56a365c9a5916ec665716c981140afdbd0e9cb76"
dependencies = [
"fearless_simd",
"j2k-codec-math",
"j2k-profile",
"j2k-types",
"libm",
"rayon",
]
[[package]]
name = "j2k-profile"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be460f47625754ece6c087e869d80b119775d3b76b107ffaf2769b8ca5c1caca"
[[package]]
name = "j2k-types"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dae71c13c5e4c230bbc5dcf338faa3e5e45cc2906acef762e613b33110e9423d"
[[package]] [[package]]
name = "jni" name = "jni"
version = "0.22.4" version = "0.22.4"
@@ -1498,6 +1584,12 @@ dependencies = [
"windows-link", "windows-link",
] ]
[[package]]
name = "libm"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
[[package]] [[package]]
name = "libremetaverse" name = "libremetaverse"
version = "0.0.1" version = "0.0.1"
@@ -1558,6 +1650,7 @@ dependencies = [
name = "libremetaverse-imaging" name = "libremetaverse-imaging"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"j2k",
"libremetaverse-openjpeg", "libremetaverse-openjpeg",
"libremetaverse-types", "libremetaverse-types",
"stats_alloc", "stats_alloc",
@@ -1851,6 +1944,16 @@ dependencies = [
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
[[package]]
name = "moxcms"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b"
dependencies = [
"num-traits",
"pxfm",
]
[[package]] [[package]]
name = "ndk" name = "ndk"
version = "0.9.0" version = "0.9.0"
@@ -2409,6 +2512,12 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "pxfm"
version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea"
[[package]] [[package]]
name = "quinn" name = "quinn"
version = "0.11.11" version = "0.11.11"
@@ -2551,6 +2660,26 @@ dependencies = [
"rand_core 0.10.1", "rand_core 0.10.1",
] ]
[[package]]
name = "rayon"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]] [[package]]
name = "rcgen" name = "rcgen"
version = "0.14.9" version = "0.14.9"

View File

@@ -61,6 +61,7 @@ The currently available opt-in codec backends are:
| Capability | Feature | Build command | External prerequisite | | Capability | Feature | Build command | External prerequisite |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| Raw J2K and JP2 decoding/encoding through OpenJPEG | `libremetaverse/jpeg2000` | `cargo build -p libremetaverse --features jpeg2000` | OpenJPEG 2.5.4 or newer | | Raw J2K and JP2 decoding/encoding through OpenJPEG | `libremetaverse/jpeg2000` | `cargo build -p libremetaverse --features jpeg2000` | OpenJPEG 2.5.4 or newer |
| Raw J2K and JP2 decoding/encoding in pure Rust | `libremetaverse/rust-j2k` | `cargo build -p libremetaverse --no-default-features --features rust-j2k` | none |
| BMP, GIF, ICO, JPEG, PNG, WBMP, and WebP decoding through Skia | `libremetaverse-imaging-skia/skia` | `cargo build -p libremetaverse-imaging-skia --features skia` | A matching rust-skia binary cache, or the documented native source-build tools | | BMP, GIF, ICO, JPEG, PNG, WBMP, and WebP decoding through Skia | `libremetaverse-imaging-skia/skia` | `cargo build -p libremetaverse-imaging-skia --features skia` | A matching rust-skia binary cache, or the documented native source-build tools |
| PCM to Ogg Vorbis encoding | `libremetaverse/vorbis` | `cargo build -p libremetaverse --features vorbis` | `vorbis_rs` 0.5.6 and its native encoder build prerequisites | | PCM to Ogg Vorbis encoding | `libremetaverse/vorbis` | `cargo build -p libremetaverse --features vorbis` | `vorbis_rs` 0.5.6 and its native encoder build prerequisites |
@@ -68,6 +69,7 @@ Run their focused test suites with:
```sh ```sh
cargo test -p libremetaverse-imaging --features jpeg2000 cargo test -p libremetaverse-imaging --features jpeg2000
cargo test -p libremetaverse-imaging --no-default-features --features rust-j2k
cargo test -p libremetaverse-imaging-skia --features skia cargo test -p libremetaverse-imaging-skia --features skia
cargo test -p libremetaverse --no-default-features --features vorbis cargo test -p libremetaverse --no-default-features --features vorbis
``` ```
@@ -91,9 +93,10 @@ Deterministic task, socket, file, subscription, cancellation, and allocation
baselines are documented in the baselines are documented in the
[concurrency hardening guide](docs/concurrency-hardening.md). [concurrency hardening guide](docs/concurrency-hardening.md).
An independent optional `rust-j2k` backend is planned but has not been The independent `rust-j2k` backend is off by default and never enables the
implemented yet. There is deliberately no enablement command for it today; native OpenJPEG adapter. Its explicit `RustJ2kCodec` preserves the existing
the existing `jpeg2000` feature always selects the OpenJPEG backend. `J2kCodec` meaning when both features are enabled. Use the combined feature set
to run backend-interoperability tests without changing application selection.
`tests/upstream-tests.json` is the machine-readable NUnit parity catalog. `tests/upstream-tests.json` is the machine-readable NUnit parity catalog.
Translated tests live in hand-written Rust files with the `parity-case` marker Translated tests live in hand-written Rust files with the `parity-case` marker
@@ -212,6 +215,12 @@ including its alpha-only and opaque-alpha substitutions. See
[`crates/libremetaverse-openjpeg/README.md`](crates/libremetaverse-openjpeg/README.md) [`crates/libremetaverse-openjpeg/README.md`](crates/libremetaverse-openjpeg/README.md)
for OpenJPEG prerequisites, licensing, and deployment details. Default builds for OpenJPEG prerequisites, licensing, and deployment details. Default builds
do not discover or link OpenJPEG. do not discover or link OpenJPEG.
The independent opt-in `rust-j2k` feature provides the same bounded public
options through `RustJ2kCodec`, backed by the exact pure-Rust `j2k` 0.8.1
release. It supports J2K and JP2, reversible and irreversible encoding,
native component precision/signedness/order, reduced-resolution and progressive
quality-layer decoding, and strict or explicitly permissive truncation handling.
It has no C/C++ codec, CMake, pkg-config, vcpkg, CLR, or platform-specific API.
The optional Skia adapter decodes BMP, GIF, ICO, JPEG, PNG, WBMP, and WebP into The optional Skia adapter decodes BMP, GIF, ICO, JPEG, PNG, WBMP, and WebP into
the same checked planar representation. Its `skia` feature uses pinned the same checked planar representation. Its `skia` feature uses pinned
rust-skia binary-cache configurations on macOS, Linux, and Windows, normalizes rust-skia binary-cache configurations on macOS, Linux, and Windows, normalizes

View File

@@ -415,6 +415,7 @@ MSRV, features, and licenses at adoption time.
| release artifact inspection | [`goblin` 0.10.5](https://crates.io/crates/goblin/0.10.5) | Parse ELF, PE, and Mach-O imports, symbols, and linked libraries without executing an artifact or relying on platform-only inspection tools. | | release artifact inspection | [`goblin` 0.10.5](https://crates.io/crates/goblin/0.10.5) | Parse ELF, PE, and Mach-O imports, symbols, and linked libraries without executing an artifact or relying on platform-only inspection tools. |
| XML and URL | [`quick-xml` 0.41.0](https://crates.io/crates/quick-xml/0.41.0), [`url` 2.5.8](https://crates.io/crates/url/2.5.8), [`base64` 0.23.1](https://crates.io/crates/base64/0.23.1) | Streaming XML for LLSD/login; retain exact URL escaping behavior with fixtures. | | XML and URL | [`quick-xml` 0.41.0](https://crates.io/crates/quick-xml/0.41.0), [`url` 2.5.8](https://crates.io/crates/url/2.5.8), [`base64` 0.23.1](https://crates.io/crates/base64/0.23.1) | Streaming XML for LLSD/login; retain exact URL escaping behavior with fixtures. |
| CoreJ2K 2.3.3.91 | system [OpenJPEG](https://www.openjpeg.org/) 2.5.4+ through the private `libremetaverse-openjpeg` adapter | Opt-in `jpeg2000` feature; checked-in minimal bindings avoid a libclang build dependency. Bounded memory streams and header validation isolate native code. Golden tests cover channel order, alpha, 16-bit precision, dimensions, discard levels, lossless/lossy modes, and malformed input. | | CoreJ2K 2.3.3.91 | system [OpenJPEG](https://www.openjpeg.org/) 2.5.4+ through the private `libremetaverse-openjpeg` adapter | Opt-in `jpeg2000` feature; checked-in minimal bindings avoid a libclang build dependency. Bounded memory streams and header validation isolate native code. Golden tests cover channel order, alpha, 16-bit precision, dimensions, discard levels, lossless/lossy modes, and malformed input. |
| CoreJ2K pure-Rust extension | [`j2k`](https://crates.io/crates/j2k) 0.8.1 | Independent opt-in `rust-j2k` feature with no native library. The safe adapter provides J2K/JP2 encode/decode, native component preservation, bounded streams and allocations, reduced resolution, progressive quality layers, strict/permissive truncation, and OpenJPEG interoperability. |
| SkiaSharp 4.150.1 | [`skia-safe` 0.99.0](https://crates.io/crates/skia-safe/0.99.0) | Adopted behind the opt-in `skia` feature. Target-specific official binary-cache feature sets provide BMP/GIF/ICO/JPEG/PNG/WBMP/WebP decoding on macOS, Linux, and Windows; checked owned buffers keep Skia types out of the core image API. | | SkiaSharp 4.150.1 | [`skia-safe` 0.99.0](https://crates.io/crates/skia-safe/0.99.0) | Adopted behind the opt-in `skia` feature. Target-specific official binary-cache feature sets provide BMP/GIF/ICO/JPEG/PNG/WBMP/WebP decoding on macOS, Linux, and Windows; checked owned buffers keep Skia types out of the core image API. |
| Pfim 0.11.4 | [`image` 0.25.10](https://crates.io/crates/image/0.25.10), [`ddsfile` 0.6.0](https://crates.io/crates/ddsfile/0.6.0) | `image` covers TGA and common DDS decoding; `ddsfile` exposes DDS container details. Golden files decide whether both are needed. | | Pfim 0.11.4 | [`image` 0.25.10](https://crates.io/crates/image/0.25.10), [`ddsfile` 0.6.0](https://crates.io/crates/ddsfile/0.6.0) | `image` covers TGA and common DDS decoding; `ddsfile` exposes DDS container details. Golden files decide whether both are needed. |
| OggVorbisEncoder 1.2.2 | [`vorbis_rs` 0.5.6](https://crates.io/crates/vorbis_rs/0.5.6) | BSD-3-Clause, MSRV 1.82, backed by C libraries. Feature-gate native audio encoding. | | OggVorbisEncoder 1.2.2 | [`vorbis_rs` 0.5.6](https://crates.io/crates/vorbis_rs/0.5.6) | BSD-3-Clause, MSRV 1.82, backed by C libraries. Feature-gate native audio encoding. |

View File

@@ -20,10 +20,10 @@ The compatibility source is pinned at [`2aa70bb68513b39795da5d13c88f31b86e85a3ba
| Crate | Mapped types | Mapped members | Rust declarations | Features | Declaration SHA-256 | | Crate | Mapped types | Mapped members | Rust declarations | Features | Declaration SHA-256 |
| --- | ---: | ---: | ---: | --- | --- | | --- | ---: | ---: | ---: | --- | --- |
| `libremetaverse` | 2711 | 27281 | 24562 | dds-bc67, default, jpeg2000, vorbis | `b1c578bb84f352dc5c920fa87751b560eaba2b0d83db4ba8ff560535eeb51afa` | | `libremetaverse` | 2711 | 27281 | 24562 | dds-bc67, default, jpeg2000, rust-j2k, vorbis | `b1c578bb84f352dc5c920fa87751b560eaba2b0d83db4ba8ff560535eeb51afa` |
| `libremetaverse-types` | 45 | 942 | 887 | none | `532cdfc175a60cb6ab109b2c43cfdda1d89cf0aadffccbcd7c9b18e1a3215bee` | | `libremetaverse-types` | 45 | 942 | 887 | none | `532cdfc175a60cb6ab109b2c43cfdda1d89cf0aadffccbcd7c9b18e1a3215bee` |
| `libremetaverse-structured-data` | 16 | 295 | 304 | none | `b1c2ca9a683efe92ea22293384189f9e7c9a1926860893ab78c41829e641a8c3` | | `libremetaverse-structured-data` | 16 | 295 | 304 | none | `b1c2ca9a683efe92ea22293384189f9e7c9a1926860893ab78c41829e641a8c3` |
| `libremetaverse-imaging` | 3 | 20 | 63 | default, jpeg2000 | `bc3f5cf5a8f472b3d4092032be35202787f443f06a4998fe2533e21aadef2e86` | | `libremetaverse-imaging` | 3 | 20 | 70 | default, jpeg2000, rust-j2k | `19423a5aec60e38d547b809ab947e7aff6366318f97f69cde824f57ae6194c0e` |
| `libremetaverse-imaging-skia` | 1 | 3 | 13 | default, skia | `a6a1445725410a036204496ad4953c84dcfea1e6a00390ce4e10d12d36f2876b` | | `libremetaverse-imaging-skia` | 1 | 3 | 13 | default, skia | `a6a1445725410a036204496ad4953c84dcfea1e6a00390ce4e10d12d36f2876b` |
| `libremetaverse-prim-mesher` | 17 | 207 | 117 | none | `dde798e86c485948f1d67e093f8194a76082101416516df3f8dca4de04c2d415` | | `libremetaverse-prim-mesher` | 17 | 207 | 117 | none | `dde798e86c485948f1d67e093f8194a76082101416516df3f8dca4de04c2d415` |
| `libremetaverse-rendering-simple` | 1 | 6 | 12 | none | `4dc284ea0abb16de63494435758c8b7c5eeb57a80d2e32a141e488e5861f2fad` | | `libremetaverse-rendering-simple` | 1 | 6 | 12 | none | `4dc284ea0abb16de63494435758c8b7c5eeb57a80d2e32a141e488e5861f2fad` |

View File

@@ -20,7 +20,7 @@
"type_mapping_sha256": "21025889c62b0f8666a2dda46a03ff4f28931f51156927822a1c04e97b49f221", "type_mapping_sha256": "21025889c62b0f8666a2dda46a03ff4f28931f51156927822a1c04e97b49f221",
"member_mapping_sha256": "cd99420643c665ea393dd59418c33fb00f97f7030e71540c00b2b27470abb1d4", "member_mapping_sha256": "cd99420643c665ea393dd59418c33fb00f97f7030e71540c00b2b27470abb1d4",
"exported_mapping_sha256": "5b8a502ce229d26732744f2b44c029fc4a86b403966dc2f9b4a1c913a7b242b9", "exported_mapping_sha256": "5b8a502ce229d26732744f2b44c029fc4a86b403966dc2f9b4a1c913a7b242b9",
"rust_declaration_sha256": "6f815653b4aa337ae6135f25e1961d1586e29f00405cd25d38462413c07091fa", "rust_declaration_sha256": "687d3d29bb0e79651881ffdda962be21df8716a4d96417175611541d0fe27a8e",
"crates": [ "crates": [
{ {
"name": "libremetaverse", "name": "libremetaverse",
@@ -35,6 +35,9 @@
"jpeg2000": [ "jpeg2000": [
"libremetaverse-imaging/jpeg2000" "libremetaverse-imaging/jpeg2000"
], ],
"rust-j2k": [
"libremetaverse-imaging/rust-j2k"
],
"vorbis": [ "vorbis": [
"dep:vorbis_rs" "dep:vorbis_rs"
] ]
@@ -69,12 +72,15 @@
"default": [], "default": [],
"jpeg2000": [ "jpeg2000": [
"dep:libremetaverse-openjpeg" "dep:libremetaverse-openjpeg"
],
"rust-j2k": [
"dep:j2k"
] ]
}, },
"mapped_types": 3, "mapped_types": 3,
"mapped_members": 20, "mapped_members": 20,
"public_declarations": 63, "public_declarations": 70,
"declaration_sha256": "bc3f5cf5a8f472b3d4092032be35202787f443f06a4998fe2533e21aadef2e86" "declaration_sha256": "19423a5aec60e38d547b809ab947e7aff6366318f97f69cde824f57ae6194c0e"
}, },
{ {
"name": "libremetaverse-imaging-skia", "name": "libremetaverse-imaging-skia",

View File

@@ -12,6 +12,7 @@
"compatibility-parity", "compatibility-parity",
"minimal-features", "minimal-features",
"jpeg2000", "jpeg2000",
"rust-j2k",
"skia-binary", "skia-binary",
"program-offline-smoke", "program-offline-smoke",
"clippy", "clippy",
@@ -66,10 +67,10 @@
}, },
{ {
"workflow": "jpeg2000.yml", "workflow": "jpeg2000.yml",
"responsibility": "Optional OpenJPEG/JPEG 2000 feature build and tests", "responsibility": "Independent OpenJPEG and pure-Rust JPEG 2000 feature builds, tests, and interoperability",
"destination": "required", "destination": "required",
"checks": ["jpeg2000"], "checks": ["jpeg2000", "rust-j2k"],
"rationale": "The optional native codec is tested independently with an exact cached OpenJPEG 2.5.4 identity." "rationale": "The optional native codec is tested with exact OpenJPEG 2.5.4 and the pure-Rust codec is tested independently and together with it."
}, },
{ {
"workflow": "performance.yml", "workflow": "performance.yml",
@@ -89,7 +90,7 @@
"workflow": "release-matrix.yml", "workflow": "release-matrix.yml",
"responsibility": "MSRV, default, minimal, features, release profiles, and portable cross-target checks", "responsibility": "MSRV, default, minimal, features, release profiles, and portable cross-target checks",
"destination": "split", "destination": "split",
"checks": ["minimal-features", "jpeg2000", "skia-binary", "msrv", "portable-cross-targets", "release-profile"], "checks": ["minimal-features", "jpeg2000", "rust-j2k", "skia-binary", "msrv", "portable-cross-targets", "release-profile"],
"rationale": "Fast feature isolation remains required; clean MSRV, cross-target, and release-profile builds run non-routinely." "rationale": "Fast feature isolation remains required; clean MSRV, cross-target, and release-profile builds run non-routinely."
}, },
{ {

View File

@@ -15,6 +15,7 @@
{ "name": "getrandom", "versions": ["0.4.3"], "purpose": "Operating-system entropy for protocol identifiers", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`getrandom`" }, { "name": "getrandom", "versions": ["0.4.3"], "purpose": "Operating-system entropy for protocol identifiers", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`getrandom`" },
{ "name": "goblin", "versions": ["0.10.5"], "purpose": "Cross-platform ELF, PE, and Mach-O release artifact inspection", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`goblin`" }, { "name": "goblin", "versions": ["0.10.5"], "purpose": "Cross-platform ELF, PE, and Mach-O release artifact inspection", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`goblin`" },
{ "name": "hound", "versions": ["3.5.1"], "purpose": "Bounded PCM WAV parsing for WebRTC playback", "maintenance": "stable", "transitive_cost": "low", "native": false, "rewrite_anchor": "`hound`" }, { "name": "hound", "versions": ["3.5.1"], "purpose": "Bounded PCM WAV parsing for WebRTC playback", "maintenance": "stable", "transitive_cost": "low", "native": false, "rewrite_anchor": "`hound`" },
{ "name": "j2k", "versions": ["0.8.1"], "purpose": "Opt-in pure-Rust bounded JPEG 2000 and JP2 encoding and decoding", "maintenance": "active", "transitive_cost": "medium", "native": false, "rewrite_anchor": "`j2k`" },
{ "name": "mac_address2", "versions": ["2.0.2"], "purpose": "Cross-platform machine identity compatibility input", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`mac_address2`" }, { "name": "mac_address2", "versions": ["2.0.2"], "purpose": "Cross-platform machine identity compatibility input", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`mac_address2`" },
{ "name": "md-5", "versions": ["0.10.6"], "purpose": "Legacy protocol checksum compatibility", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`md-5`" }, { "name": "md-5", "versions": ["0.10.6"], "purpose": "Legacy protocol checksum compatibility", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`md-5`" },
{ "name": "os_info", "versions": ["3.15.0"], "purpose": "Cross-platform login platform reporting", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`os_info`" }, { "name": "os_info", "versions": ["3.15.0"], "purpose": "Cross-platform login platform reporting", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`os_info`" },

View File

@@ -42,12 +42,12 @@
"execution": "native", "execution": "native",
"toolchain": "1.96.0", "toolchain": "1.96.0",
"target": "x86_64-unknown-linux-gnu", "target": "x86_64-unknown-linux-gnu",
"feature_sets": ["no-default-features"], "feature_sets": ["no-default-features", "rust-j2k"],
"prerequisites": ["libopus-1.3"], "prerequisites": ["libopus-1.3"],
"commands": [ "commands": [
{ {
"label": "Compile the portable public crates on the declared MSRV", "label": "Compile the portable public crates on the declared MSRV",
"args": ["check", "--locked", "-j", "1", "--all-targets", "--no-default-features", "-p", "libremetaverse-types", "-p", "libremetaverse-structured-data", "-p", "libremetaverse-imaging", "-p", "libremetaverse-imaging-skia", "-p", "libremetaverse-prim-mesher", "-p", "libremetaverse-lsl-tools", "-p", "libremetaverse-rlv", "-p", "metacrate-ci-matrix"] "args": ["check", "--locked", "-j", "1", "--all-targets", "--no-default-features", "--features", "libremetaverse-imaging/rust-j2k", "-p", "libremetaverse-types", "-p", "libremetaverse-structured-data", "-p", "libremetaverse-imaging", "-p", "libremetaverse-imaging-skia", "-p", "libremetaverse-prim-mesher", "-p", "libremetaverse-lsl-tools", "-p", "libremetaverse-rlv", "-p", "metacrate-ci-matrix"]
}, },
{ {
"label": "Compile the safe native Opus boundary and WebRTC voice on the declared MSRV", "label": "Compile the safe native Opus boundary and WebRTC voice on the declared MSRV",
@@ -106,7 +106,7 @@
"execution": "native", "execution": "native",
"toolchain": "stable", "toolchain": "stable",
"target": "x86_64-unknown-linux-gnu", "target": "x86_64-unknown-linux-gnu",
"feature_sets": ["all-features", "dds-bc67", "jpeg2000", "skia", "vorbis", "real-audio", "tests"], "feature_sets": ["all-features", "dds-bc67", "jpeg2000", "rust-j2k", "skia", "vorbis", "real-audio", "tests"],
"prerequisites": ["openjpeg-2.5.4", "skia-safe-0.99.0", "libopus-1.3", "alsa-1.2", "vorbis-rs-0.5.6"], "prerequisites": ["openjpeg-2.5.4", "skia-safe-0.99.0", "libopus-1.3", "alsa-1.2", "vorbis-rs-0.5.6"],
"commands": [ "commands": [
{ {
@@ -117,6 +117,14 @@
"label": "Test the OpenJPEG feature independently", "label": "Test the OpenJPEG feature independently",
"args": ["test", "-p", "libremetaverse-imaging", "--no-default-features", "--features", "jpeg2000", "--locked", "-j", "1"] "args": ["test", "-p", "libremetaverse-imaging", "--no-default-features", "--features", "jpeg2000", "--locked", "-j", "1"]
}, },
{
"label": "Test the pure-Rust JPEG 2000 feature independently",
"args": ["test", "-p", "libremetaverse-imaging", "--no-default-features", "--features", "rust-j2k", "--locked", "-j", "1"]
},
{
"label": "Test OpenJPEG and pure-Rust JPEG 2000 interoperability",
"args": ["test", "-p", "libremetaverse-imaging", "--no-default-features", "--features", "jpeg2000,rust-j2k", "--locked", "-j", "1"]
},
{ {
"label": "Test the Skia feature independently", "label": "Test the Skia feature independently",
"args": ["test", "-p", "libremetaverse-imaging-skia", "--no-default-features", "--features", "skia", "--locked", "-j", "1"] "args": ["test", "-p", "libremetaverse-imaging-skia", "--no-default-features", "--features", "skia", "--locked", "-j", "1"]
@@ -162,12 +170,12 @@
"execution": "cross", "execution": "cross",
"toolchain": "stable", "toolchain": "stable",
"target": "x86_64-pc-windows-gnu", "target": "x86_64-pc-windows-gnu",
"feature_sets": ["no-default-features", "dds-bc67"], "feature_sets": ["no-default-features", "dds-bc67", "rust-j2k"],
"prerequisites": [], "prerequisites": [],
"commands": [ "commands": [
{ {
"label": "Cross-check portable crates for Windows GNU", "label": "Cross-check portable crates for Windows GNU",
"args": ["check", "--locked", "-j", "1", "--target", "x86_64-pc-windows-gnu", "--all-targets", "--no-default-features", "-p", "libremetaverse-types", "-p", "libremetaverse-structured-data", "-p", "libremetaverse-imaging", "-p", "libremetaverse-imaging-skia", "-p", "libremetaverse-prim-mesher", "-p", "libremetaverse-lsl-tools", "-p", "libremetaverse-rlv", "-p", "metacrate-ci-matrix"] "args": ["check", "--locked", "-j", "1", "--target", "x86_64-pc-windows-gnu", "--all-targets", "--no-default-features", "--features", "libremetaverse-imaging/rust-j2k", "-p", "libremetaverse-types", "-p", "libremetaverse-structured-data", "-p", "libremetaverse-imaging", "-p", "libremetaverse-imaging-skia", "-p", "libremetaverse-prim-mesher", "-p", "libremetaverse-lsl-tools", "-p", "libremetaverse-rlv", "-p", "metacrate-ci-matrix"]
} }
] ]
}, },
@@ -178,12 +186,12 @@
"execution": "cross", "execution": "cross",
"toolchain": "stable", "toolchain": "stable",
"target": "x86_64-apple-darwin", "target": "x86_64-apple-darwin",
"feature_sets": ["no-default-features", "dds-bc67"], "feature_sets": ["no-default-features", "dds-bc67", "rust-j2k"],
"prerequisites": [], "prerequisites": [],
"commands": [ "commands": [
{ {
"label": "Cross-check portable crates for macOS", "label": "Cross-check portable crates for macOS",
"args": ["check", "--locked", "-j", "1", "--target", "x86_64-apple-darwin", "--all-targets", "--no-default-features", "-p", "libremetaverse-types", "-p", "libremetaverse-structured-data", "-p", "libremetaverse-imaging", "-p", "libremetaverse-imaging-skia", "-p", "libremetaverse-prim-mesher", "-p", "libremetaverse-lsl-tools", "-p", "libremetaverse-rlv", "-p", "metacrate-ci-matrix"] "args": ["check", "--locked", "-j", "1", "--target", "x86_64-apple-darwin", "--all-targets", "--no-default-features", "--features", "libremetaverse-imaging/rust-j2k", "-p", "libremetaverse-types", "-p", "libremetaverse-structured-data", "-p", "libremetaverse-imaging", "-p", "libremetaverse-imaging-skia", "-p", "libremetaverse-prim-mesher", "-p", "libremetaverse-lsl-tools", "-p", "libremetaverse-rlv", "-p", "metacrate-ci-matrix"]
} }
] ]
} }

View File

@@ -10,10 +10,12 @@ description = "Texture codec abstractions for the MetaCrate LibreMetaverse rewri
[features] [features]
default = [] default = []
jpeg2000 = ["dep:libremetaverse-openjpeg"] jpeg2000 = ["dep:libremetaverse-openjpeg"]
rust-j2k = ["dep:j2k"]
[dependencies] [dependencies]
libremetaverse-types = { version = "0.0.1", path = "../libremetaverse-types" } libremetaverse-types = { version = "0.0.1", path = "../libremetaverse-types" }
libremetaverse-openjpeg = { version = "0.0.1", path = "../libremetaverse-openjpeg", optional = true } libremetaverse-openjpeg = { version = "0.0.1", path = "../libremetaverse-openjpeg", optional = true }
j2k = { version = "=0.8.1", optional = true }
[dev-dependencies] [dev-dependencies]
stats_alloc = "0.1.10" stats_alloc = "0.1.10"

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,15 @@
//! Image and texture abstractions corresponding to `LibreMetaverse.Imaging`. //! Image and texture abstractions corresponding to `LibreMetaverse.Imaging`.
//! //!
//! The default surface provides managed images plus native `TGA`/`DDS` handling. //! The default surface provides managed images plus native `TGA`/`DDS` handling.
//! Enable `jpeg2000` only when the audited system `OpenJPEG` adapter is available; //! Enable `jpeg2000` for the audited system `OpenJPEG` adapter or `rust-j2k`
//! ordinary users can consume the traits without a native image dependency. //! for the independently selectable pure-Rust JPEG 2000 backend. Ordinary
//! users can consume the traits without either codec dependency.
extern crate self as libremetaverse_imaging; extern crate self as libremetaverse_imaging;
pub mod codec; pub mod codec;
#[cfg(feature = "jpeg2000")] #[cfg(any(feature = "jpeg2000", feature = "rust-j2k"))]
mod jpeg2000; mod jpeg2000;
mod generated; mod generated;
@@ -16,6 +17,10 @@ mod managed_image;
pub use generated::*; pub use generated::*;
#[cfg(feature = "jpeg2000")] #[cfg(feature = "jpeg2000")]
pub use jpeg2000::{J2kCodec, J2kCompression, J2kDecodeOptions, J2kEncodeOptions, J2kFormat}; pub use jpeg2000::J2kCodec;
#[cfg(feature = "rust-j2k")]
pub use jpeg2000::RustJ2kCodec;
#[cfg(any(feature = "jpeg2000", feature = "rust-j2k"))]
pub use jpeg2000::{J2kCompression, J2kDecodeOptions, J2kEncodeOptions, J2kFormat};
pub use libremetaverse_types::Error; pub use libremetaverse_types::Error;
pub use managed_image::{DEFAULT_MAX_ENCODED_BYTES, DEFAULT_MAX_PIXELS}; pub use managed_image::{DEFAULT_MAX_ENCODED_BYTES, DEFAULT_MAX_PIXELS};

View File

@@ -11,6 +11,7 @@ description = "Rust rewrite shell for the LibreMetaverse client library"
default = ["dds-bc67"] default = ["dds-bc67"]
dds-bc67 = ["dep:bcdec_rs"] dds-bc67 = ["dep:bcdec_rs"]
jpeg2000 = ["libremetaverse-imaging/jpeg2000"] jpeg2000 = ["libremetaverse-imaging/jpeg2000"]
rust-j2k = ["libremetaverse-imaging/rust-j2k"]
vorbis = ["dep:vorbis_rs"] vorbis = ["dep:vorbis_rs"]
[dependencies] [dependencies]

View File

@@ -15,10 +15,10 @@ they use those APIs directly.
| Crate | Choose it for | Features or system boundary | | Crate | Choose it for | Features or system boundary |
| --- | --- | --- | | --- | --- | --- |
| `libremetaverse` | Grid client, login, network, agents, inventory, assets, appearance, world, and social APIs | Default pure-Rust BC6H/BC7; optional `jpeg2000` and `vorbis` | | `libremetaverse` | Grid client, login, network, agents, inventory, assets, appearance, world, and social APIs | Default pure-Rust BC6H/BC7; optional `jpeg2000`, `rust-j2k`, and `vorbis` |
| `libremetaverse-types` | UUIDs, vectors, matrices, colors, cancellation, compatibility collections, and boundary types | Pure Rust | | `libremetaverse-types` | UUIDs, vectors, matrices, colors, cancellation, compatibility collections, and boundary types | Pure Rust |
| `libremetaverse-structured-data` | LLSD/OSD XML, JSON, binary, and notation | Pure Rust | | `libremetaverse-structured-data` | LLSD/OSD XML, JSON, binary, and notation | Pure Rust |
| `libremetaverse-imaging` | Managed images, TGA/DDS, codec traits | Optional `jpeg2000` | | `libremetaverse-imaging` | Managed images, TGA/DDS, codec traits | Optional `jpeg2000` or pure-Rust `rust-j2k` |
| `libremetaverse-imaging-skia` | Common raster formats through Skia | Optional `skia`; native Skia build/cache | | `libremetaverse-imaging-skia` | Common raster formats through Skia | Optional `skia`; native Skia build/cache |
| `libremetaverse-prim-mesher` | Legacy prim and sculpt geometry | Pure Rust | | `libremetaverse-prim-mesher` | Legacy prim and sculpt geometry | Pure Rust |
| `libremetaverse-rendering-simple` | Deterministic reference geometry | Pure Rust | | `libremetaverse-rendering-simple` | Deterministic reference geometry | Pure Rust |
@@ -190,6 +190,7 @@ The default client build needs no image-codec system library. Optional native
features require: features require:
- `OpenJPEG` 2.5.4 or newer for `jpeg2000`; - `OpenJPEG` 2.5.4 or newer for `jpeg2000`;
- no native prerequisite for the pure-Rust `rust-j2k` feature;
- the rust-skia prerequisites/cache for `skia`; - the rust-skia prerequisites/cache for `skia`;
- system libopus for WebRTC voice and the `libremetaverse-opus` adapter; - system libopus for WebRTC voice and the `libremetaverse-opus` adapter;
- ALSA development headers on Linux, `CoreAudio` on macOS, or WASAPI on Windows - ALSA development headers on Linux, `CoreAudio` on macOS, or WASAPI on Windows

View File

@@ -150,7 +150,7 @@ impl Baker {
let texture = crate::assets::AssetTexture::new_with_managed_image(output)?; let texture = crate::assets::AssetTexture::new_with_managed_image(output)?;
// JPEG2000 is the protocol representation. Keep the decoded image even // JPEG2000 is the protocol representation. Keep the decoded image even
// when a build intentionally excludes that optional codec. // when a build intentionally excludes that optional codec.
#[cfg(feature = "jpeg2000")] #[cfg(any(feature = "jpeg2000", feature = "rust-j2k"))]
texture.encode()?; texture.encode()?;
self.baked_texture = Some(texture); self.baked_texture = Some(texture);
Ok(()) Ok(())

View File

@@ -9,7 +9,11 @@
)] )]
use crate::{Error, Permissions}; use crate::{Error, Permissions};
#[cfg(feature = "jpeg2000")]
use libremetaverse_imaging::J2kCodec as TextureJ2kCodec;
use libremetaverse_imaging::ManagedImage; use libremetaverse_imaging::ManagedImage;
#[cfg(all(not(feature = "jpeg2000"), feature = "rust-j2k"))]
use libremetaverse_imaging::RustJ2kCodec as TextureJ2kCodec;
use libremetaverse_structured_data::{OSD, OSDMap, OSDParser}; use libremetaverse_structured_data::{OSD, OSDMap, OSDParser};
use libremetaverse_types::{AssetType, SaleType, UUID, Vector3, WearableType}; use libremetaverse_types::{AssetType, SaleType, UUID, Vector3, WearableType};
use std::collections::HashMap; use std::collections::HashMap;
@@ -526,9 +530,9 @@ impl AssetTexture {
if self.image.is_some() { if self.image.is_some() {
return Ok(true); return Ok(true);
} }
#[cfg(feature = "jpeg2000")] #[cfg(any(feature = "jpeg2000", feature = "rust-j2k"))]
{ {
self.image = Some(libremetaverse_imaging::J2kCodec::decode_bytes( self.image = Some(TextureJ2kCodec::decode_bytes(
&self.raw.bytes(), &self.raw.bytes(),
libremetaverse_imaging::J2kDecodeOptions::default(), libremetaverse_imaging::J2kDecodeOptions::default(),
)?); )?);
@@ -543,7 +547,7 @@ impl AssetTexture {
}; };
Ok(true) Ok(true)
} }
#[cfg(not(feature = "jpeg2000"))] #[cfg(not(any(feature = "jpeg2000", feature = "rust-j2k")))]
{ {
Err(Error::InvalidOperation) Err(Error::InvalidOperation)
} }
@@ -570,15 +574,15 @@ impl AssetTexture {
}) })
} }
pub fn decode(&self) -> Result<bool, Error> { pub fn decode(&self) -> Result<bool, Error> {
#[cfg(feature = "jpeg2000")] #[cfg(any(feature = "jpeg2000", feature = "rust-j2k"))]
{ {
Ok(libremetaverse_imaging::J2kCodec::decode_bytes( Ok(TextureJ2kCodec::decode_bytes(
&self.raw.bytes(), &self.raw.bytes(),
libremetaverse_imaging::J2kDecodeOptions::default(), libremetaverse_imaging::J2kDecodeOptions::default(),
) )
.is_ok()) .is_ok())
} }
#[cfg(not(feature = "jpeg2000"))] #[cfg(not(any(feature = "jpeg2000", feature = "rust-j2k")))]
{ {
validate_bytes(&self.raw.bytes())?; validate_bytes(&self.raw.bytes())?;
Err(Error::InvalidOperation) Err(Error::InvalidOperation)
@@ -586,15 +590,15 @@ impl AssetTexture {
} }
pub fn encode(&self) -> Result<(), Error> { pub fn encode(&self) -> Result<(), Error> {
let image = self.image.as_ref().ok_or(Error::InvalidOperation)?; let image = self.image.as_ref().ok_or(Error::InvalidOperation)?;
#[cfg(feature = "jpeg2000")] #[cfg(any(feature = "jpeg2000", feature = "rust-j2k"))]
{ {
let encoded = libremetaverse_imaging::J2kCodec::encode( let encoded = TextureJ2kCodec::encode(
image, image,
libremetaverse_imaging::J2kEncodeOptions::default(), libremetaverse_imaging::J2kEncodeOptions::default(),
)?; )?;
self.raw.replace(encoded) self.raw.replace(encoded)
} }
#[cfg(not(feature = "jpeg2000"))] #[cfg(not(any(feature = "jpeg2000", feature = "rust-j2k")))]
{ {
let _ = image; let _ = image;
Err(Error::InvalidOperation) Err(Error::InvalidOperation)

View File

@@ -1,10 +1,10 @@
#[cfg(feature = "jpeg2000")] #[cfg(any(feature = "jpeg2000", feature = "rust-j2k"))]
use crate::assets::AssetTexture; use crate::assets::AssetTexture;
use crate::assets::{AssetMesh, AssetMutable, AssetSound}; use crate::assets::{AssetMesh, AssetMutable, AssetSound};
use crate::{ use crate::{
AssetCache, AssetCacheComputeAssetCacheFilenameDelegate, Error, GridClient, ImageCodec, AssetCache, AssetCacheComputeAssetCacheFilenameDelegate, Error, GridClient, ImageCodec,
}; };
#[cfg(feature = "jpeg2000")] #[cfg(any(feature = "jpeg2000", feature = "rust-j2k"))]
use libremetaverse_imaging::{ManagedImage, ManagedImageImageChannels}; use libremetaverse_imaging::{ManagedImage, ManagedImageImageChannels};
use libremetaverse_types::{AssetType, UUID}; use libremetaverse_types::{AssetType, UUID};
use std::fs; use std::fs;
@@ -58,7 +58,7 @@ fn sound_codec_is_explicitly_feature_gated() {
} }
#[test] #[test]
#[cfg(feature = "jpeg2000")] #[cfg(any(feature = "jpeg2000", feature = "rust-j2k"))]
fn texture_codec_produces_real_valid_payload() { fn texture_codec_produces_real_valid_payload() {
let mut image = ManagedImage::new(2, 2, ManagedImageImageChannels::COLOR).unwrap(); let mut image = ManagedImage::new(2, 2, ManagedImageImageChannels::COLOR).unwrap();
image.red.fill(255); image.red.fill(255);

View File

@@ -11,6 +11,10 @@ use std::path::{Component, Path, PathBuf};
use flate2::{Compression, write::ZlibEncoder}; use flate2::{Compression, write::ZlibEncoder};
use libremetaverse_imaging::ITextureCodec; use libremetaverse_imaging::ITextureCodec;
#[cfg(feature = "jpeg2000")]
use libremetaverse_imaging::J2kCodec as TextureJ2kCodec;
#[cfg(all(not(feature = "jpeg2000"), feature = "rust-j2k"))]
use libremetaverse_imaging::RustJ2kCodec as TextureJ2kCodec;
use libremetaverse_structured_data::{OSD, OSDFormat, OSDParser}; use libremetaverse_structured_data::{OSD, OSDFormat, OSDParser};
use libremetaverse_types::compat::{CancellationToken, Uri}; use libremetaverse_types::compat::{CancellationToken, Uri};
use libremetaverse_types::{AssetType, Color4, Error, Quaternion, UUID, Vector2, Vector3}; use libremetaverse_types::{AssetType, Color4, Error, Quaternion, UUID, Vector2, Vector3};
@@ -956,14 +960,14 @@ fn load_texture(
return Err(Error::InvalidOperation); return Err(Error::InvalidOperation);
}; };
let image = codec.decode(Box::new(std::io::Cursor::new(bytes)))?; let image = codec.decode(Box::new(std::io::Cursor::new(bytes)))?;
#[cfg(feature = "jpeg2000")] #[cfg(any(feature = "jpeg2000", feature = "rust-j2k"))]
{ {
return libremetaverse_imaging::J2kCodec::encode( return TextureJ2kCodec::encode(
&image, &image,
libremetaverse_imaging::J2kEncodeOptions::default(), libremetaverse_imaging::J2kEncodeOptions::default(),
); );
} }
#[cfg(not(feature = "jpeg2000"))] #[cfg(not(any(feature = "jpeg2000", feature = "rust-j2k")))]
{ {
let _ = image; let _ = image;
return Err(Error::InvalidOperation); return Err(Error::InvalidOperation);

View File

@@ -49,6 +49,7 @@ All native boundaries have Linux, Windows, and macOS strategies:
|---|---|---|---| |---|---|---|---|
| libopus 1.3+ | `pkg-config` package `opus` | vcpkg `opus` for MSVC; `pkg-config` for GNU | WebRTC voice crate | | libopus 1.3+ | `pkg-config` package `opus` | vcpkg `opus` for MSVC; `pkg-config` for GNU | WebRTC voice crate |
| OpenJPEG 2.5.4+ | `pkg-config` package `libopenjp2` | vcpkg `openjpeg` for MSVC; `pkg-config` for GNU | opt-in `jpeg2000` | | OpenJPEG 2.5.4+ | `pkg-config` package `libopenjp2` | vcpkg `openjpeg` for MSVC; `pkg-config` for GNU | opt-in `jpeg2000` |
| j2k 0.8.1 | pure Rust, no platform prerequisite | same pure-Rust graph | opt-in `rust-j2k` |
| Skia 0.99.0 | target-specific official binary cache or source build | same target-specific strategy | opt-in `skia` | | Skia 0.99.0 | target-specific official binary cache or source build | same target-specific strategy | opt-in `skia` |
| Vorbis 0.5.6 stack | `vorbis_rs` builds its reviewed C codec stack | same crate strategy | opt-in `vorbis` | | Vorbis 0.5.6 stack | `vorbis_rs` builds its reviewed C codec stack | same crate strategy | opt-in `vorbis` |
| Physical audio | ALSA development files on Linux; CoreAudio is system-provided on macOS | WASAPI is system-provided | opt-in `real-audio` | | Physical audio | ALSA development files on Linux; CoreAudio is system-provided on macOS | WASAPI is system-provided | opt-in `real-audio` |

View File

@@ -17,12 +17,16 @@ and [`MeshFoundry` guide](../crates/libremetaverse-rendering-mesh-foundry/README
| --- | --- | --- | --- | | --- | --- | --- | --- |
| Managed images and TGA | enabled | n/a | none | | Managed images and TGA | enabled | n/a | none |
| JPEG 2000 | disabled | `libremetaverse-imaging/jpeg2000` | OpenJPEG 2.5.x | | JPEG 2000 | disabled | `libremetaverse-imaging/jpeg2000` | OpenJPEG 2.5.x |
| JPEG 2000 (pure Rust) | disabled | `libremetaverse-imaging/rust-j2k` | none (`j2k` 0.8.1) |
| BMP/GIF/ICO/JPEG/PNG/WBMP/WebP | disabled | `libremetaverse-imaging-skia/skia` | Skia | | BMP/GIF/ICO/JPEG/PNG/WBMP/WebP | disabled | `libremetaverse-imaging-skia/skia` | Skia |
| Prim and sculpt meshing, OBJ ingestion | enabled | n/a | none | | Prim and sculpt meshing, OBJ ingestion | enabled | n/a | none |
OpenJPEG is a non-default workspace member so release tooling can package the OpenJPEG is a non-default workspace member so release tooling can package the
adapter explicitly, and imaging reaches it only through the optional adapter explicitly, and imaging reaches it only through the optional
dependency. Skia is likewise an optional, target-specific dependency. The dependency. The independent `rust-j2k` feature reaches only the audited
pure-Rust `j2k` graph; enabling both features keeps both explicit codec types
available for interoperability testing. Skia is likewise an optional,
target-specific dependency. The
consolidated required Gitea gate exercises both optional features on consolidated required Gitea gate exercises both optional features on
`ubuntu-latest` while its minimal-feature check proves that no native codec is `ubuntu-latest` while its minimal-feature check proves that no native codec is
needed for the owned Rust and translated compatibility tests. needed for the owned Rust and translated compatibility tests.

View File

@@ -23,6 +23,7 @@ Optional boundaries are explicit:
| Feature | Capability | Native/build prerequisite | | Feature | Capability | Native/build prerequisite |
| --- | --- | --- | | --- | --- | --- |
| `jpeg2000` | J2K/JP2 through the safe OpenJPEG adapter | OpenJPEG 2.5.4 or newer | | `jpeg2000` | J2K/JP2 through the safe OpenJPEG adapter | OpenJPEG 2.5.4 or newer |
| `rust-j2k` | J2K/JP2 through `RustJ2kCodec` | none; exact pure-Rust `j2k` 0.8.1 |
| `skia` | PNG/JPEG/WebP and other Skia formats | Skia 0.99 target cache or documented source tools | | `skia` | PNG/JPEG/WebP and other Skia formats | Skia 0.99 target cache or documented source tools |
| `vorbis` | PCM to Ogg Vorbis | the locked `vorbis_rs` native build stack | | `vorbis` | PCM to Ogg Vorbis | the locked `vorbis_rs` native build stack |
| default WebRTC | native ICE/DTLS/SRTP/RTP/SCTP and Opus | system libopus 1.3 or newer | | default WebRTC | native ICE/DTLS/SRTP/RTP/SCTP and Opus | system libopus 1.3 or newer |

View File

@@ -15,10 +15,10 @@ they use those APIs directly.
| Crate | Choose it for | Features or system boundary | | Crate | Choose it for | Features or system boundary |
| --- | --- | --- | | --- | --- | --- |
| `libremetaverse` | Grid client, login, network, agents, inventory, assets, appearance, world, and social APIs | Default pure-Rust BC6H/BC7; optional `jpeg2000` and `vorbis` | | `libremetaverse` | Grid client, login, network, agents, inventory, assets, appearance, world, and social APIs | Default pure-Rust BC6H/BC7; optional `jpeg2000`, `rust-j2k`, and `vorbis` |
| `libremetaverse-types` | UUIDs, vectors, matrices, colors, cancellation, compatibility collections, and boundary types | Pure Rust | | `libremetaverse-types` | UUIDs, vectors, matrices, colors, cancellation, compatibility collections, and boundary types | Pure Rust |
| `libremetaverse-structured-data` | LLSD/OSD XML, JSON, binary, and notation | Pure Rust | | `libremetaverse-structured-data` | LLSD/OSD XML, JSON, binary, and notation | Pure Rust |
| `libremetaverse-imaging` | Managed images, TGA/DDS, codec traits | Optional `jpeg2000` | | `libremetaverse-imaging` | Managed images, TGA/DDS, codec traits | Optional `jpeg2000` or pure-Rust `rust-j2k` |
| `libremetaverse-imaging-skia` | Common raster formats through Skia | Optional `skia`; native Skia build/cache | | `libremetaverse-imaging-skia` | Common raster formats through Skia | Optional `skia`; native Skia build/cache |
| `libremetaverse-prim-mesher` | Legacy prim and sculpt geometry | Pure Rust | | `libremetaverse-prim-mesher` | Legacy prim and sculpt geometry | Pure Rust |
| `libremetaverse-rendering-simple` | Deterministic reference geometry | Pure Rust | | `libremetaverse-rendering-simple` | Deterministic reference geometry | Pure Rust |
@@ -190,6 +190,7 @@ The default client build needs no image-codec system library. Optional native
features require: features require:
- `OpenJPEG` 2.5.4 or newer for `jpeg2000`; - `OpenJPEG` 2.5.4 or newer for `jpeg2000`;
- no native prerequisite for the pure-Rust `rust-j2k` feature;
- the rust-skia prerequisites/cache for `skia`; - the rust-skia prerequisites/cache for `skia`;
- system libopus for WebRTC voice and the `libremetaverse-opus` adapter; - system libopus for WebRTC voice and the `libremetaverse-opus` adapter;
- ALSA development headers on Linux, `CoreAudio` on macOS, or WASAPI on Windows - ALSA development headers on Linux, `CoreAudio` on macOS, or WASAPI on Windows

View File

@@ -1,6 +1,6 @@
{ {
"schema": 1, "schema": 1,
"cargo_lock_sha256": "4753d29e32012fcf82584ea9a5d73037ccf3e63114ad2d1b9295c41808862ddd", "cargo_lock_sha256": "68988caa2c014bf2c67563df3dd0a8348d67eeb06559649798463fd8211fc0cb",
"packages": [ "packages": [
{ {
"name": "adler2", "name": "adler2",
@@ -1065,6 +1065,57 @@
} }
] ]
}, },
{
"name": "crossbeam-deque",
"version": "0.8.7",
"checksum": "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb",
"license": "MIT OR Apache-2.0",
"repository": "https://github.com/crossbeam-rs/crossbeam",
"notice_files": [
{
"path": "LICENSE-APACHE",
"sha256": "a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2"
},
{
"path": "LICENSE-MIT",
"sha256": "5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab"
}
]
},
{
"name": "crossbeam-epoch",
"version": "0.9.20",
"checksum": "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f",
"license": "MIT OR Apache-2.0",
"repository": "https://github.com/crossbeam-rs/crossbeam",
"notice_files": [
{
"path": "LICENSE-APACHE",
"sha256": "a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2"
},
{
"path": "LICENSE-MIT",
"sha256": "5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab"
}
]
},
{
"name": "crossbeam-utils",
"version": "0.8.22",
"checksum": "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17",
"license": "MIT OR Apache-2.0",
"repository": "https://github.com/crossbeam-rs/crossbeam",
"notice_files": [
{
"path": "LICENSE-APACHE",
"sha256": "a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2"
},
{
"path": "LICENSE-MIT",
"sha256": "5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab"
}
]
},
{ {
"name": "crypto-bigint", "name": "crypto-bigint",
"version": "0.5.5", "version": "0.5.5",
@@ -1453,6 +1504,23 @@
} }
] ]
}, },
{
"name": "fearless_simd",
"version": "0.4.1",
"checksum": "b97b65636e5b9ef369943878ac74335ba1c55c1cb6adbf1e2c293c624248d693",
"license": "Apache-2.0 OR MIT",
"repository": "https://github.com/linebender/fearless_simd",
"notice_files": [
{
"path": "LICENSE-APACHE",
"sha256": "a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9"
},
{
"path": "LICENSE-MIT",
"sha256": "23c23145f6eac25c28cdcc03d38506a5712a9a8cffb5bd5301457f6173ea696e"
}
]
},
{ {
"name": "ff", "name": "ff",
"version": "0.13.1", "version": "0.13.1",
@@ -2293,6 +2361,200 @@
} }
] ]
}, },
{
"name": "j2k",
"version": "0.8.1",
"checksum": "0371832fbd6d4e7c83ab85545bb41474f91f565dd1e5660b733de11b54a257eb",
"license": "MIT OR Apache-2.0",
"repository": "https://github.com/frames-sg/j2k",
"notice_files": [
{
"path": "generated-package-license-notice.txt",
"sha256": "d21f134a7fcc8164e65f3f31ede9ab6c3bba8d1621845e4a5e92a7693d7bd73e"
},
{
"path": "repository-license/j2k-native-0.8.1/LICENSE-APACHE",
"sha256": "0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594"
},
{
"path": "repository-license/j2k-native-0.8.1/LICENSE-MIT",
"sha256": "c945f59ea69b7c9eff45a54d9ebd9294524291399393d7bf86800507e4af7bfe"
},
{
"path": "repository-license/j2k-native-0.8.1/assets/LICENSE.txt",
"sha256": "286e4fd7b447330b2c88e23890e3cd0a9d38cb398d4a59cb247f578ccbda3213"
},
{
"path": "repository-license/j2k-native-0.8.1/fixtures/htj2k/LICENSE.OpenHTJ2K",
"sha256": "5369097362538b0a5b348476248240ab713674fa2fa4bdde511906d949985b63"
},
{
"path": "repository-license/j2k-native-0.8.1/fixtures/htj2k/LICENSE.OpenJPH",
"sha256": "5ddf5177863dfc9ab65fa129d587db651241f00e21ed2427b218bea997591f98"
}
]
},
{
"name": "j2k-codec-math",
"version": "0.8.1",
"checksum": "165366ed0d18b737c6f6cd2c3ffeb20c94dc40aac70e77c2f6dd1c8b518aec3e",
"license": "MIT OR Apache-2.0",
"repository": "https://github.com/frames-sg/j2k",
"notice_files": [
{
"path": "generated-package-license-notice.txt",
"sha256": "5e8685f009d9fe56954cd78f1cd99dbedcebc527a65b17c4ab7f52ef00ab0d31"
},
{
"path": "repository-license/j2k-native-0.8.1/LICENSE-APACHE",
"sha256": "0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594"
},
{
"path": "repository-license/j2k-native-0.8.1/LICENSE-MIT",
"sha256": "c945f59ea69b7c9eff45a54d9ebd9294524291399393d7bf86800507e4af7bfe"
},
{
"path": "repository-license/j2k-native-0.8.1/assets/LICENSE.txt",
"sha256": "286e4fd7b447330b2c88e23890e3cd0a9d38cb398d4a59cb247f578ccbda3213"
},
{
"path": "repository-license/j2k-native-0.8.1/fixtures/htj2k/LICENSE.OpenHTJ2K",
"sha256": "5369097362538b0a5b348476248240ab713674fa2fa4bdde511906d949985b63"
},
{
"path": "repository-license/j2k-native-0.8.1/fixtures/htj2k/LICENSE.OpenJPH",
"sha256": "5ddf5177863dfc9ab65fa129d587db651241f00e21ed2427b218bea997591f98"
}
]
},
{
"name": "j2k-core",
"version": "0.8.1",
"checksum": "058401c1957538158b1565d0b9453f8165ca0fc62e85197849364971d4be551a",
"license": "MIT OR Apache-2.0",
"repository": "https://github.com/frames-sg/j2k",
"notice_files": [
{
"path": "generated-package-license-notice.txt",
"sha256": "62c91c3bde6a45ab5071c69a6f03db3d027119ddb192787d98a31e5cb42617e0"
},
{
"path": "repository-license/j2k-native-0.8.1/LICENSE-APACHE",
"sha256": "0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594"
},
{
"path": "repository-license/j2k-native-0.8.1/LICENSE-MIT",
"sha256": "c945f59ea69b7c9eff45a54d9ebd9294524291399393d7bf86800507e4af7bfe"
},
{
"path": "repository-license/j2k-native-0.8.1/assets/LICENSE.txt",
"sha256": "286e4fd7b447330b2c88e23890e3cd0a9d38cb398d4a59cb247f578ccbda3213"
},
{
"path": "repository-license/j2k-native-0.8.1/fixtures/htj2k/LICENSE.OpenHTJ2K",
"sha256": "5369097362538b0a5b348476248240ab713674fa2fa4bdde511906d949985b63"
},
{
"path": "repository-license/j2k-native-0.8.1/fixtures/htj2k/LICENSE.OpenJPH",
"sha256": "5ddf5177863dfc9ab65fa129d587db651241f00e21ed2427b218bea997591f98"
}
]
},
{
"name": "j2k-native",
"version": "0.8.1",
"checksum": "7c8af5bf0762fdf381b2893a56a365c9a5916ec665716c981140afdbd0e9cb76",
"license": "MIT OR Apache-2.0",
"repository": "https://github.com/frames-sg/j2k",
"notice_files": [
{
"path": "LICENSE-APACHE",
"sha256": "0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594"
},
{
"path": "LICENSE-MIT",
"sha256": "c945f59ea69b7c9eff45a54d9ebd9294524291399393d7bf86800507e4af7bfe"
},
{
"path": "assets/LICENSE.txt",
"sha256": "286e4fd7b447330b2c88e23890e3cd0a9d38cb398d4a59cb247f578ccbda3213"
},
{
"path": "fixtures/htj2k/LICENSE.OpenHTJ2K",
"sha256": "5369097362538b0a5b348476248240ab713674fa2fa4bdde511906d949985b63"
},
{
"path": "fixtures/htj2k/LICENSE.OpenJPH",
"sha256": "5ddf5177863dfc9ab65fa129d587db651241f00e21ed2427b218bea997591f98"
}
]
},
{
"name": "j2k-profile",
"version": "0.8.1",
"checksum": "be460f47625754ece6c087e869d80b119775d3b76b107ffaf2769b8ca5c1caca",
"license": "MIT OR Apache-2.0",
"repository": "https://github.com/frames-sg/j2k",
"notice_files": [
{
"path": "generated-package-license-notice.txt",
"sha256": "72c509b36ef706c6d202cbfdb3fc0ab279b9d66e4b4f6df331048395ee4c75ef"
},
{
"path": "repository-license/j2k-native-0.8.1/LICENSE-APACHE",
"sha256": "0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594"
},
{
"path": "repository-license/j2k-native-0.8.1/LICENSE-MIT",
"sha256": "c945f59ea69b7c9eff45a54d9ebd9294524291399393d7bf86800507e4af7bfe"
},
{
"path": "repository-license/j2k-native-0.8.1/assets/LICENSE.txt",
"sha256": "286e4fd7b447330b2c88e23890e3cd0a9d38cb398d4a59cb247f578ccbda3213"
},
{
"path": "repository-license/j2k-native-0.8.1/fixtures/htj2k/LICENSE.OpenHTJ2K",
"sha256": "5369097362538b0a5b348476248240ab713674fa2fa4bdde511906d949985b63"
},
{
"path": "repository-license/j2k-native-0.8.1/fixtures/htj2k/LICENSE.OpenJPH",
"sha256": "5ddf5177863dfc9ab65fa129d587db651241f00e21ed2427b218bea997591f98"
}
]
},
{
"name": "j2k-types",
"version": "0.8.1",
"checksum": "dae71c13c5e4c230bbc5dcf338faa3e5e45cc2906acef762e613b33110e9423d",
"license": "MIT OR Apache-2.0",
"repository": "https://github.com/frames-sg/j2k",
"notice_files": [
{
"path": "generated-package-license-notice.txt",
"sha256": "113b9e80f5fbda8d6290f1bee47b019b54f0da3d43a609e18efc886e8e4c3129"
},
{
"path": "repository-license/j2k-native-0.8.1/LICENSE-APACHE",
"sha256": "0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594"
},
{
"path": "repository-license/j2k-native-0.8.1/LICENSE-MIT",
"sha256": "c945f59ea69b7c9eff45a54d9ebd9294524291399393d7bf86800507e4af7bfe"
},
{
"path": "repository-license/j2k-native-0.8.1/assets/LICENSE.txt",
"sha256": "286e4fd7b447330b2c88e23890e3cd0a9d38cb398d4a59cb247f578ccbda3213"
},
{
"path": "repository-license/j2k-native-0.8.1/fixtures/htj2k/LICENSE.OpenHTJ2K",
"sha256": "5369097362538b0a5b348476248240ab713674fa2fa4bdde511906d949985b63"
},
{
"path": "repository-license/j2k-native-0.8.1/fixtures/htj2k/LICENSE.OpenJPH",
"sha256": "5ddf5177863dfc9ab65fa129d587db651241f00e21ed2427b218bea997591f98"
}
]
},
{ {
"name": "jni", "name": "jni",
"version": "0.22.4", "version": "0.22.4",
@@ -2455,6 +2717,19 @@
} }
] ]
}, },
{
"name": "libm",
"version": "0.2.16",
"checksum": "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981",
"license": "MIT",
"repository": "https://github.com/rust-lang/compiler-builtins",
"notice_files": [
{
"path": "LICENSE.txt",
"sha256": "3823dda7cf046602f4b4e77ec8e227863dc4736037cc85bb33d9f19febe16bb7"
}
]
},
{ {
"name": "linux-raw-sys", "name": "linux-raw-sys",
"version": "0.12.1", "version": "0.12.1",
@@ -2679,6 +2954,23 @@
} }
] ]
}, },
{
"name": "moxcms",
"version": "0.8.1",
"checksum": "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b",
"license": "BSD-3-Clause OR Apache-2.0",
"repository": "https://github.com/awxkee/moxcms.git",
"notice_files": [
{
"path": "LICENSE-APACHE.md",
"sha256": "90bf2d659c43045111b65c733ab2a6d4cbcb422a098368c8c58a9ba3db4ed0c5"
},
{
"path": "LICENSE.md",
"sha256": "4b6c5ac5c550bea22b1d6455684b21d94ca96f3bcbbc2840b793180707ed582a"
}
]
},
{ {
"name": "ndk", "name": "ndk",
"version": "0.9.0", "version": "0.9.0",
@@ -3555,6 +3847,23 @@
} }
] ]
}, },
{
"name": "pxfm",
"version": "0.1.30",
"checksum": "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea",
"license": "BSD-3-Clause OR Apache-2.0",
"repository": "https://github.com/awxkee/pxfm",
"notice_files": [
{
"path": "LICENSE-APACHE.md",
"sha256": "90bf2d659c43045111b65c733ab2a6d4cbcb422a098368c8c58a9ba3db4ed0c5"
},
{
"path": "LICENSE.md",
"sha256": "4b6c5ac5c550bea22b1d6455684b21d94ca96f3bcbbc2840b793180707ed582a"
}
]
},
{ {
"name": "quinn", "name": "quinn",
"version": "0.11.11", "version": "0.11.11",
@@ -3796,6 +4105,40 @@
} }
] ]
}, },
{
"name": "rayon",
"version": "1.12.0",
"checksum": "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d",
"license": "MIT OR Apache-2.0",
"repository": "https://github.com/rayon-rs/rayon",
"notice_files": [
{
"path": "LICENSE-APACHE",
"sha256": "a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2"
},
{
"path": "LICENSE-MIT",
"sha256": "0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720"
}
]
},
{
"name": "rayon-core",
"version": "1.13.0",
"checksum": "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91",
"license": "MIT OR Apache-2.0",
"repository": "https://github.com/rayon-rs/rayon",
"notice_files": [
{
"path": "LICENSE-APACHE",
"sha256": "a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2"
},
{
"path": "LICENSE-MIT",
"sha256": "0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720"
}
]
},
{ {
"name": "rcgen", "name": "rcgen",
"version": "0.14.9", "version": "0.14.9",

View File

@@ -1,6 +1,6 @@
{ {
"schema": 1, "schema": 1,
"cargo_lock_sha256": "4753d29e32012fcf82584ea9a5d73037ccf3e63114ad2d1b9295c41808862ddd", "cargo_lock_sha256": "68988caa2c014bf2c67563df3dd0a8348d67eeb06559649798463fd8211fc0cb",
"provenance_policy_sha256": "f95475a2284ab282e9432865d4a7ed103498a56ed5ec2393017bc312c77da890", "provenance_policy_sha256": "f95475a2284ab282e9432865d4a7ed103498a56ed5ec2393017bc312c77da890",
"upstream_repository": "https://github.com/cinderblocks/libremetaverse", "upstream_repository": "https://github.com/cinderblocks/libremetaverse",
"upstream_commit": "2aa70bb68513b39795da5d13c88f31b86e85a3ba", "upstream_commit": "2aa70bb68513b39795da5d13c88f31b86e85a3ba",
@@ -42,8 +42,8 @@
}, },
{ {
"path": "Cargo.lock", "path": "Cargo.lock",
"bytes": 100424, "bytes": 103842,
"sha256": "4753d29e32012fcf82584ea9a5d73037ccf3e63114ad2d1b9295c41808862ddd" "sha256": "68988caa2c014bf2c67563df3dd0a8348d67eeb06559649798463fd8211fc0cb"
}, },
{ {
"path": "Cargo.toml", "path": "Cargo.toml",
@@ -62,13 +62,13 @@
}, },
{ {
"path": "README.md", "path": "README.md",
"bytes": 35156, "bytes": 35953,
"sha256": "d9e75ef87bbd9ab6dc87c1222b3eebf601cc0e088be0e8f2ccae912336a0a298" "sha256": "dea4a52f12e5885e2c53356c56b122c9bbf00382cbff21ff179e05b1d8714f05"
}, },
{ {
"path": "RUSTREWRITE.md", "path": "RUSTREWRITE.md",
"bytes": 54108, "bytes": 54472,
"sha256": "6da24d9e0c2ca89122b4daa494376097acd90820efa5668654f4742bf484f965" "sha256": "b3bc471cb82e76cca0c3d251090634de3ed29e24ef91b01d3cc89723e31854be"
}, },
{ {
"path": "api/API-COVERAGE.md", "path": "api/API-COVERAGE.md",
@@ -102,13 +102,13 @@
}, },
{ {
"path": "api/SEMVER-AUDIT.md", "path": "api/SEMVER-AUDIT.md",
"bytes": 5538, "bytes": 5558,
"sha256": "f7b5e98facc572792d3a150915f220be978de637fb6b210d4bb9aa104dc3c47d" "sha256": "3c44b4b0ea579d975492fd5f9395a29fc597e43b126f8cbae4a0c14792232dd0"
}, },
{ {
"path": "api/SEMVER-BASELINE.json", "path": "api/SEMVER-BASELINE.json",
"bytes": 5771, "bytes": 5901,
"sha256": "7170e85dbab28a70ffcd392a0482ead23a1d7d2742fa1736a6f27a54148bc6d9" "sha256": "cd422369af58c6f60dbdda202ae4bb331f68ca3aacb5171839512100c027432e"
}, },
{ {
"path": "api/SHIM-COVERAGE.md", "path": "api/SHIM-COVERAGE.md",
@@ -212,8 +212,8 @@
}, },
{ {
"path": "ci/ci-coverage.json", "path": "ci/ci-coverage.json",
"bytes": 5480, "bytes": 5593,
"sha256": "4d1633c1cb396f934a8eff5f4e27362f6872b95ac66b95e9c4ac8e75ef833b29" "sha256": "241e7bc687b1c2395885e4cd2a95c446e5d4847e3bf9a34d8cee3d76bcbc2903"
}, },
{ {
"path": "ci/concurrency-thresholds.json", "path": "ci/concurrency-thresholds.json",
@@ -222,8 +222,8 @@
}, },
{ {
"path": "ci/dependency-policy.json", "path": "ci/dependency-policy.json",
"bytes": 10628, "bytes": 10851,
"sha256": "2807ccae43c9f0cf011978e5d63217aa3ac827406b52db2b04945ce4064f988e" "sha256": "781d497a7a0ddd53fb9158e74e1c5f967eaf3b97535596b42bf34fa38e59b482"
}, },
{ {
"path": "ci/evidence/api-audit.json", "path": "ci/evidence/api-audit.json",
@@ -267,8 +267,8 @@
}, },
{ {
"path": "ci/release-matrix.json", "path": "ci/release-matrix.json",
"bytes": 7898, "bytes": 8560,
"sha256": "4ba7d1dfb7ed7a8bb06d5702179af569ff52c2db33d10b0008389d2c13a40d93" "sha256": "f6a641f66c023cd00d5d8b8692b5d6f4a8273fee8e8b5411cab4481de1b0f602"
}, },
{ {
"path": "codegen/README.md", "path": "codegen/README.md",
@@ -362,8 +362,8 @@
}, },
{ {
"path": "crates/libremetaverse-imaging/Cargo.toml", "path": "crates/libremetaverse-imaging/Cargo.toml",
"bytes": 644, "bytes": 713,
"sha256": "b28b70a09f4916624dfb1d54869a4084996615304b7e04449d331ccd067ff20b" "sha256": "b05533b2b63f1dc7c0228488b649dc5ee74e50b27a5260ebaf3c2cfa5b93f3f6"
}, },
{ {
"path": "crates/libremetaverse-imaging/benches/image_pipeline.rs", "path": "crates/libremetaverse-imaging/benches/image_pipeline.rs",
@@ -382,13 +382,13 @@
}, },
{ {
"path": "crates/libremetaverse-imaging/src/jpeg2000.rs", "path": "crates/libremetaverse-imaging/src/jpeg2000.rs",
"bytes": 25288, "bytes": 66076,
"sha256": "9c6458dd1312288fc639361b6d7b4c09da268ed9d68f74ec8df5299955cd3579" "sha256": "59569f3c7324df38b48edbb7bae7ab29fb2ff5cc7094c03a30cff9abd2c50e8f"
}, },
{ {
"path": "crates/libremetaverse-imaging/src/lib.rs", "path": "crates/libremetaverse-imaging/src/lib.rs",
"bytes": 720, "bytes": 940,
"sha256": "1d90f7cecf5320914682e44109ab61d916ac617c6f6140c38a9dc57b8eb0d34b" "sha256": "b052dd1aab4a12f7eeb338473082819f5e453b0b127311d0ff6cb38e5da10111"
}, },
{ {
"path": "crates/libremetaverse-imaging/src/managed_image.rs", "path": "crates/libremetaverse-imaging/src/managed_image.rs",
@@ -887,13 +887,13 @@
}, },
{ {
"path": "crates/libremetaverse/Cargo.toml", "path": "crates/libremetaverse/Cargo.toml",
"bytes": 1403, "bytes": 1450,
"sha256": "c1fa65e64affcf6d3422d31f2fdc13e5d67af7c84757e5abcda29c1927fd9131" "sha256": "858687a6afd8d990eec7f7984d06ffde084971122c9106e8cba6e54fdf531330"
}, },
{ {
"path": "crates/libremetaverse/README.md", "path": "crates/libremetaverse/README.md",
"bytes": 12959, "bytes": 13059,
"sha256": "22dc9242d755d6b81214081dc534c02bf84380c16d5f873729033dd04ec1d16c" "sha256": "871b0b94073aafa46235bba7d150c13d4c4900da5e4e2d82201604365d2c5c40"
}, },
{ {
"path": "crates/libremetaverse/assets/avatar_lad.xml", "path": "crates/libremetaverse/assets/avatar_lad.xml",
@@ -947,8 +947,8 @@
}, },
{ {
"path": "crates/libremetaverse/src/appearance_baker.rs", "path": "crates/libremetaverse/src/appearance_baker.rs",
"bytes": 22271, "bytes": 22298,
"sha256": "6a6274c14114ce189df1057b1b2b49d686000dc2830f3f30912f5d56b12ff1dc" "sha256": "ff49dc968d029d66965064303f65886be623c491a7bce74a39ecd5a4e4cc17c4"
}, },
{ {
"path": "crates/libremetaverse/src/appearance_baker_semantics.rs", "path": "crates/libremetaverse/src/appearance_baker_semantics.rs",
@@ -987,13 +987,13 @@
}, },
{ {
"path": "crates/libremetaverse/src/asset_models.rs", "path": "crates/libremetaverse/src/asset_models.rs",
"bytes": 28293, "bytes": 28612,
"sha256": "38b127db078d6aad5279193bea45ca45681669633f1a614962585f162d1b79b1" "sha256": "52f7df531c6e9c5d3fa21ee39e6ed258f7041a890e723cf7e534665ec9b5341a"
}, },
{ {
"path": "crates/libremetaverse/src/asset_pipeline_semantics.rs", "path": "crates/libremetaverse/src/asset_pipeline_semantics.rs",
"bytes": 5191, "bytes": 5272,
"sha256": "07318170717c3399707f8bf5c9fb2f90ce73b4da5278c9895637ca35dea0fb5a" "sha256": "ea876f35d0c03abe85b1f2086312bbd5f4aa55c742dcc3ff136df21a376d911e"
}, },
{ {
"path": "crates/libremetaverse/src/asset_prim.rs", "path": "crates/libremetaverse/src/asset_prim.rs",
@@ -1262,8 +1262,8 @@
}, },
{ {
"path": "crates/libremetaverse/src/model_workflow.rs", "path": "crates/libremetaverse/src/model_workflow.rs",
"bytes": 42237, "bytes": 42482,
"sha256": "2a00452d3c610b87aaae45731643d7a6ef0ab6bf5a384879c6c0cd87c21b748f" "sha256": "363d4a07086130dceeb3bba70e6376f0541b3cc01bb251167d265430a0403408"
}, },
{ {
"path": "crates/libremetaverse/src/name_value.rs", "path": "crates/libremetaverse/src/name_value.rs",
@@ -1567,8 +1567,8 @@
}, },
{ {
"path": "docs/dependency-policy.md", "path": "docs/dependency-policy.md",
"bytes": 4488, "bytes": 4583,
"sha256": "2e822f2deefa949a4d2173ee6d993a7e3c5874c01cb4b90755d98d1b8805f3e8" "sha256": "ec62e39b40f6070fb746f76f7ae934570de01caa4426d453e2db5c29ac3fa1ae"
}, },
{ {
"path": "docs/discovery.md", "path": "docs/discovery.md",
@@ -1582,8 +1582,8 @@
}, },
{ {
"path": "docs/imaging-meshing.md", "path": "docs/imaging-meshing.md",
"bytes": 3406, "bytes": 3678,
"sha256": "51ae2dfb88f5a40a01ab9394ae0545806377c6cbb2cbd85da2b7947b5534859e" "sha256": "c63e434d5181dc903c83f00c7649ee2040028c6d4bda698f57da8c1c3b1416c6"
}, },
{ {
"path": "docs/inventory.md", "path": "docs/inventory.md",
@@ -1612,8 +1612,8 @@
}, },
{ {
"path": "docs/release-candidate.md", "path": "docs/release-candidate.md",
"bytes": 4243, "bytes": 4327,
"sha256": "ebddf2e4922ed7e8cea262501ede951b35b50a35ea19e17eaa317ae2af50199d" "sha256": "20aa8c39de842ca1dee15808c44f1e71ee33441796b17d03feea8e14ef99165f"
}, },
{ {
"path": "docs/release-ci-matrix.md", "path": "docs/release-ci-matrix.md",
@@ -1627,8 +1627,8 @@
}, },
{ {
"path": "docs/rust-api-guide.md", "path": "docs/rust-api-guide.md",
"bytes": 11958, "bytes": 12058,
"sha256": "2ffcd84234a996ff97480dabda64fc815eb88d4b5fdf42e0836734d7277b046f" "sha256": "db4d0ee7986eebe9434e5c51ca65a31ffc3b32323240d9dc62cbd931b21b21b1"
}, },
{ {
"path": "docs/social.md", "path": "docs/social.md",
@@ -2407,8 +2407,8 @@
}, },
{ {
"path": "tools/check_milestone_06.py", "path": "tools/check_milestone_06.py",
"bytes": 5598, "bytes": 5740,
"sha256": "18f389b59020a6705595cfa18e6c374e09e4d81c8c3b1e397aa01da13c885e33" "sha256": "a206b123b4202e81ef832c31bed10a1117e030c9927638727cc99ca7d5f5914d"
}, },
{ {
"path": "tools/check_milestone_08.py", "path": "tools/check_milestone_08.py",
@@ -2517,8 +2517,8 @@
}, },
{ {
"path": "tools/ci-matrix/src/api_surface.rs", "path": "tools/ci-matrix/src/api_surface.rs",
"bytes": 48385, "bytes": 48586,
"sha256": "b4a873a869a4d2af11ecda0c95e11f83e044e6002271a30b4fa424103ceacbc7" "sha256": "a82ac15da446f2f393ba267f8c7537d43cb4595a6be3e08f27d2f718e2aad4e8"
}, },
{ {
"path": "tools/ci-matrix/src/artifact.rs", "path": "tools/ci-matrix/src/artifact.rs",
@@ -2527,8 +2527,8 @@
}, },
{ {
"path": "tools/ci-matrix/src/ci_gate.rs", "path": "tools/ci-matrix/src/ci_gate.rs",
"bytes": 45047, "bytes": 45662,
"sha256": "73ebb225ef1128e82bd38e7d41d2a164e4bd82c89cbe241f547762f132c0c790" "sha256": "5a3666a3c84993fb3c3ac8d920aed4ea6ecdd2bfa06b6c94ab84942ba7a33db5"
}, },
{ {
"path": "tools/ci-matrix/src/dependency.rs", "path": "tools/ci-matrix/src/dependency.rs",
@@ -2542,8 +2542,8 @@
}, },
{ {
"path": "tools/ci-matrix/src/lib.rs", "path": "tools/ci-matrix/src/lib.rs",
"bytes": 21175, "bytes": 21271,
"sha256": "096d055e5d295be43ae1db78acbc98557d27d63631c7699b6eb5d281fcc18424" "sha256": "53f4286d600c78d7a3ea593e7d663854e722787573dc5bbf3e48d41e28ac8267"
}, },
{ {
"path": "tools/ci-matrix/src/main.rs", "path": "tools/ci-matrix/src/main.rs",
@@ -2664,13 +2664,13 @@
"generated_release_files": [ "generated_release_files": [
{ {
"path": "release/DEPENDENCY-LICENSES.json", "path": "release/DEPENDENCY-LICENSES.json",
"bytes": 217171, "bytes": 230084,
"sha256": "a4095621c7975f6b01c5b1653b375c571be15657f7fa824d6b5a2e46f3434dcc" "sha256": "64ee30790d4b3b643514098184bf15b2e9901fe177333dbd7950b4311a47292e"
}, },
{ {
"path": "release/THIRD-PARTY-NOTICES.md", "path": "release/THIRD-PARTY-NOTICES.md",
"bytes": 846570, "bytes": 897381,
"sha256": "da051a965d39715d10da5c17fdfdafd8059b83d2491837d223607e9c5e16a5fa" "sha256": "47d10a98d94bfe09124cbbfcf57f91a34231286aaec71a3265372ee9006d3eab"
}, },
{ {
"path": "release/NATIVE-LICENSES.md", "path": "release/NATIVE-LICENSES.md",

File diff suppressed because it is too large Load Diff

View File

@@ -44,6 +44,8 @@ def check_features() -> None:
raise SystemExit("imaging default features must stay empty") raise SystemExit("imaging default features must stay empty")
if imaging["features"].get("jpeg2000") != ["dep:libremetaverse-openjpeg"]: if imaging["features"].get("jpeg2000") != ["dep:libremetaverse-openjpeg"]:
raise SystemExit("JPEG 2000 must stay isolated behind its optional feature") raise SystemExit("JPEG 2000 must stay isolated behind its optional feature")
if imaging["features"].get("rust-j2k") != ["dep:j2k"]:
raise SystemExit("pure-Rust JPEG 2000 must stay isolated behind rust-j2k")
if not imaging["dependencies"]["libremetaverse-openjpeg"].get("optional"): if not imaging["dependencies"]["libremetaverse-openjpeg"].get("optional"):
raise SystemExit("the OpenJPEG adapter dependency must stay optional") raise SystemExit("the OpenJPEG adapter dependency must stay optional")

View File

@@ -916,6 +916,10 @@ fn validate_features(name: &str, actual: &BTreeMap<String, Vec<String>>) -> Resu
"jpeg2000".to_owned(), "jpeg2000".to_owned(),
vec!["libremetaverse-imaging/jpeg2000".to_owned()], vec!["libremetaverse-imaging/jpeg2000".to_owned()],
), ),
(
"rust-j2k".to_owned(),
vec!["libremetaverse-imaging/rust-j2k".to_owned()],
),
("vorbis".to_owned(), vec!["dep:vorbis_rs".to_owned()]), ("vorbis".to_owned(), vec!["dep:vorbis_rs".to_owned()]),
]), ]),
"libremetaverse-imaging" => BTreeMap::from([ "libremetaverse-imaging" => BTreeMap::from([
@@ -924,6 +928,7 @@ fn validate_features(name: &str, actual: &BTreeMap<String, Vec<String>>) -> Resu
"jpeg2000".to_owned(), "jpeg2000".to_owned(),
vec!["dep:libremetaverse-openjpeg".to_owned()], vec!["dep:libremetaverse-openjpeg".to_owned()],
), ),
("rust-j2k".to_owned(), vec!["dep:j2k".to_owned()]),
]), ]),
"libremetaverse-imaging-skia" => BTreeMap::from([ "libremetaverse-imaging-skia" => BTreeMap::from([
("default".to_owned(), Vec::new()), ("default".to_owned(), Vec::new()),

View File

@@ -637,6 +637,30 @@ fn test_commands() -> Vec<CommandSpec> {
"--locked", "--locked",
], ],
), ),
CommandSpec::new(
"cargo",
&[
"test",
"-p",
"libremetaverse-imaging",
"--no-default-features",
"--features",
"rust-j2k",
"--locked",
],
),
CommandSpec::new(
"cargo",
&[
"test",
"-p",
"libremetaverse-imaging",
"--no-default-features",
"--features",
"jpeg2000,rust-j2k",
"--locked",
],
),
] ]
} }

View File

@@ -38,7 +38,7 @@ const REQUIRED_PROFILES: [&str; 7] = [
"windows-stable-portable", "windows-stable-portable",
"macos-stable-portable", "macos-stable-portable",
]; ];
const REQUIRED_FEATURE_SETS: [&str; 11] = [ const REQUIRED_FEATURE_SETS: [&str; 12] = [
"all-features", "all-features",
"dds-bc67", "dds-bc67",
"default", "default",
@@ -47,15 +47,18 @@ const REQUIRED_FEATURE_SETS: [&str; 11] = [
"jpeg2000", "jpeg2000",
"no-default-features", "no-default-features",
"real-audio", "real-audio",
"rust-j2k",
"skia", "skia",
"tests", "tests",
"vorbis", "vorbis",
]; ];
const REQUIRED_FEATURES: [(&str, &str); 6] = [ const REQUIRED_FEATURES: [(&str, &str); 8] = [
("libremetaverse", "dds-bc67"), ("libremetaverse", "dds-bc67"),
("libremetaverse", "jpeg2000"), ("libremetaverse", "jpeg2000"),
("libremetaverse", "rust-j2k"),
("libremetaverse", "vorbis"), ("libremetaverse", "vorbis"),
("libremetaverse-imaging", "jpeg2000"), ("libremetaverse-imaging", "jpeg2000"),
("libremetaverse-imaging", "rust-j2k"),
("libremetaverse-imaging-skia", "skia"), ("libremetaverse-imaging-skia", "skia"),
("libremetaverse-voice-webrtc", "real-audio"), ("libremetaverse-voice-webrtc", "real-audio"),
]; ];