Web: leave the JPEG XL DNG decoder out of the wasm (0.88 MB, 23.1 MiB now)
The 0.6.0 web build went over packaging/web/package.sh's 24 MiB gate (26,980,503 bytes on782bcb67). Today's landings added 1.34 MB; the biggest single item was jxl-oxide (#2047, JPEG XL-compressed DNG): ~0.6 MB of jxl_* code plus brotli-decompressor and tables, 0.88 MB after wasm-opt.0c72d954brought the wasm back to 25,144,413 bytes (21 KB under the gate) by deflating catalogs and fonts; this takes it to 24,262,088 bytes (23.14 MiB, 904 KB of headroom). jxl-oxide is now a native-only dependency of photocraft-raw. On wasm32 a JPEG XL DNG segment returns RawError::Unsupported ("can't be opened in the browser version of PhotoCraft; open it in the desktop app"), like the other cfg-gated web features; every other DNG compression and raw format still opens in the browser. Native builds are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
0c72d95425
commit
e633d17a09
|
|
@ -17,13 +17,14 @@ corpus = []
|
|||
[dependencies]
|
||||
# Adobe DNG compression 8: zlib (RFC 1950) with the TIFF predictor (pure-Rust backend).
|
||||
flate2 = { workspace = true }
|
||||
# JPEG XL-compressed DNG (DNG 1.7, e.g. Samsung Expert RAW). Pure Rust, MIT OR Apache-2.0. Pinned
|
||||
# exactly: it parses untrusted files; moving the pin is a reviewed change (re-run the raw fuzz target).
|
||||
jxl-oxide = { version = "=0.12.6", default-features = false }
|
||||
|
||||
# Parallel bands on native; wasm builds stay single-threaded.
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
rayon = { workspace = true }
|
||||
# JPEG XL-compressed DNG (DNG 1.7, e.g. Samsung Expert RAW). Pure Rust, MIT OR Apache-2.0. Pinned
|
||||
# exactly: it parses untrusted files; moving the pin is a reviewed change (re-run the raw fuzz target).
|
||||
# Native only: it added 0.88 MB to the browser build's wasm, which has a hard size cap
|
||||
# (packaging/web/package.sh); there JPEG XL DNG is reported as unsupported (src/jxl.rs).
|
||||
jxl-oxide = { version = "=0.12.6", default-features = false, features = ["rayon"] }
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
A clean-room, pure-Rust camera raw decoder and developer. The crate is standalone (no workspace
|
||||
dependencies; its decoding dependencies are `flate2` for Deflate DNG and `jxl-oxide`, a pure-Rust
|
||||
JPEG XL decoder, for DNG 1.7), has no `unsafe`, does no I/O (`&[u8]` in), builds for `wasm32-unknown-unknown`
|
||||
JPEG XL decoder, for DNG 1.7, native builds only), has no `unsafe`, does no I/O (`&[u8]` in), builds for `wasm32-unknown-unknown`
|
||||
(sequential there, rayon-parallel on native) and never panics on hostile input: every offset is
|
||||
bounds-checked and sizes are checked against `Limits` before allocating.
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ camera colour tables were copied.
|
|||
|
||||
| Format | Status |
|
||||
|---|---|
|
||||
| DNG | Uncompressed (8–16 bit, packed or not), Deflate (compression 8, predictors 1 and 2), lossless JPEG and JPEG XL (DNG 1.7, e.g. Samsung Expert RAW; decoded by `jxl-oxide`); strips and tiles; CFA (Bayer) and LinearRaw; LinearizationTable, BlackLevel (+ repeat, DeltaH/V), WhiteLevel, ActiveArea, DefaultCrop, ColorMatrix1/2, CameraCalibration, ForwardMatrix, AnalogBalance, AsShotNeutral / AsShotWhiteXY, BaselineExposure, Orientation, OpcodeList2 GainMap (lens shading) |
|
||||
| DNG | Uncompressed (8–16 bit, packed or not), Deflate (compression 8, predictors 1 and 2), lossless JPEG and JPEG XL (DNG 1.7, e.g. Samsung Expert RAW; decoded by `jxl-oxide`; not in wasm32 builds, where it is `Unsupported`); strips and tiles; CFA (Bayer) and LinearRaw; LinearizationTable, BlackLevel (+ repeat, DeltaH/V), WhiteLevel, ActiveArea, DefaultCrop, ColorMatrix1/2, CameraCalibration, ForwardMatrix, AnalogBalance, AsShotNeutral / AsShotWhiteXY, BaselineExposure, Orientation, OpcodeList2 GainMap (lens shading) |
|
||||
| DNG (lossy JPEG, floating point; opcodes other than GainMap; ProfileGainTableMap) | Unsupported / not applied (reported) |
|
||||
| CR2 | Lossless JPEG with slices, borders and as-shot white balance from the maker note, black measured on the masked border. CR2 has no CFA tag and the row phase varies by model, so it is measured from the data (the green diagonal), with a Canon model-ID table as the fallback (see `src/cr2.rs`) |
|
||||
| CR2 sRAW / mRAW | Unsupported |
|
||||
|
|
|
|||
|
|
@ -5,14 +5,26 @@
|
|||
//! Expert RAW writes LinearRaw this way. Decoding is done by `jxl-oxide`, a pure-Rust decoder;
|
||||
//! like heic-rs in `photocraft-heif`, every call into it runs under `catch_unwind` so a decoder
|
||||
//! panic on a malformed file becomes [`RawError::Malformed`].
|
||||
//!
|
||||
//! The browser build (wasm32) leaves the decoder out: jxl-oxide added 0.88 MB to a wasm that
|
||||
//! must stay under the per-file cap of static hosts (packaging/web/package.sh), for a format only
|
||||
//! a few phones write. There, these segments are [`RawError::Unsupported`] with a clear message.
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use jxl_oxide::{AllocTracker, JxlImage};
|
||||
|
||||
use crate::Limits;
|
||||
use crate::error::{RawError, Result};
|
||||
|
||||
/// The browser build has no JPEG XL decoder (see the module docs).
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub(crate) fn decode(_src: &[u8], _w: usize, _h: usize, _samples: usize, _bits: u32, _limits: &Limits) -> Result<Vec<u16>> {
|
||||
Err(RawError::unsupported("JPEG XL-compressed DNG (DNG 1.7) can't be opened in the browser version of PhotoCraft; open it in the desktop app"))
|
||||
}
|
||||
|
||||
/// Decodes one segment into `w * h * samples` interleaved samples at `bits` per sample (the
|
||||
/// TIFF BitsPerSample, which DNG requires the codestream's bit depth to match).
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub(crate) fn decode(src: &[u8], w: usize, h: usize, samples: usize, bits: u32, limits: &Limits) -> Result<Vec<u16>> {
|
||||
limits.check(w as u64, h as u64, samples as u64 * 2)?;
|
||||
// jxl-oxide decodes into f32/i32 planes: allow a few times the output size, and never more
|
||||
|
|
@ -54,6 +66,7 @@ pub(crate) fn decode(src: &[u8], w: usize, h: usize, samples: usize, bits: u32,
|
|||
})
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn guarded<T>(f: impl FnOnce() -> Result<T>) -> Result<T> {
|
||||
std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)).unwrap_or_else(|_| Err(RawError::malformed("the JPEG XL decoder failed on this file")))
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue