From 2ed9207c3f2496eb09e81ad51ee1274100635a6c Mon Sep 17 00:00:00 2001 From: Mert <101130780+mertalev@users.noreply.github.com> Date: Mon, 26 Oct 2026 08:45:49 -0400 Subject: [PATCH] perf(mobile): cache srgb transform (#32730) (cherry picked from commit 18f1a44d1b934fc9d98ddb2be6918b7617c9c896) --- native/crates/native_core/src/jxl.rs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/native/crates/native_core/src/jxl.rs b/native/crates/native_core/src/jxl.rs index afdd1957f..cc2384486 100644 --- a/native/crates/native_core/src/jxl.rs +++ b/native/crates/native_core/src/jxl.rs @@ -1,5 +1,5 @@ -use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::{Arc, LazyLock}; use jxl::api::{ AlphaMode, Endianness, Event, ExtraChannel, JxlColorEncoding, JxlColorProfile, JxlColorType, @@ -7,6 +7,7 @@ use jxl::api::{ JxlParallelRunnerFun, JxlPixelFormat, JxlPrimaries, JxlTransferFunction, JxlWhitePoint, }; use moxcms::{Layout, MatrixCoefficients, Transform16BitExecutor}; +use quick_cache::sync::Cache; use rayon::prelude::*; use crate::color::{self, CicpColorPrimaries, CicpProfile, Target, TransferCharacteristics}; @@ -98,7 +99,7 @@ impl<'a> Jxl<'a> { transform: None, }); } - let (transform, layout) = color::to_srgb(&profile.try_as_icc()?)?; + let (transform, layout) = srgb_transform(profile)?; decoder .set_pixel_format(JxlPixelFormat { color_type: match layout { @@ -233,3 +234,23 @@ fn cicp(profile: &JxlColorProfile) -> Option { full_range: true, }) } + +/// Reuse the transform to sRGB for a given source profile. +type Transforms = Cache, Layout)>; + +/// [`color::to_srgb`] for `profile`, built once per distinct profile. +fn srgb_transform(profile: &JxlColorProfile) -> Option<(Arc, Layout)> { + const TRANSFORMS: usize = 8; + static ENCODINGS: LazyLock> = LazyLock::new(|| Cache::new(TRANSFORMS)); + static ICCS: LazyLock>> = LazyLock::new(|| Cache::new(TRANSFORMS)); + match profile { + JxlColorProfile::Simple(encoding) => ENCODINGS + .get_or_insert_with(&encoding.get_color_encoding_description(), || { + color::to_srgb(&profile.try_as_icc().ok_or(())?).ok_or(()) + }), + JxlColorProfile::Icc(icc) => { + ICCS.get_or_insert_with(icc.as_slice(), || color::to_srgb(icc).ok_or(())) + } + } + .ok() +}