From c1e0fac7199e3db7836ad1543ee3117c0eef2e59 Mon Sep 17 00:00:00 2001 From: uqio <276879906+uqio@users.noreply.github.com> Date: Sun, 26 Apr 2026 20:50:55 +1200 Subject: [PATCH 1/5] refactor: extract plane-slice helpers + tighten _impl visibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves the two deferred Copilot findings on PR #20 review #4176623587. Pure cleanup — zero behavior change. **Copilot #4 — RGBA-plane bounds-check helper extraction.** Added two `pub(super) fn` helpers in `src/sinker/mixed/mod.rs`: - `rgba_plane_row_slice(buf, one_plane_start, one_plane_end, w, h)` — centralises the `one_plane_end.checked_mul(4)? + one_plane_start * 4 + slice` pattern with `GeometryOverflow` reporting. - `rgb_row_buf_or_scratch(rgb, rgb_scratch, ...)` — picks RGB plane slice when attached, else grows the scratch buffer; same overflow handling. Refactored every `MixedSinker::process` impl across the 6 child modules (`planar_8bit` / `semi_planar_8bit` / `subsampled_4_*_high_bit` / `bayer`) to call the helpers instead of inlining the bounds-check + slice math: - Pattern A (RGB row buf-or-scratch): 37 substitutions across all 33 process impls (wired + unwired families). - Pattern B (standalone RGBA branch): 9 substitutions in the wired families (Yuv420p / Yuv422p / Yuv444p / Yuv440p / Nv12 / Nv16 / Nv21 / Nv24 / Nv42). - Pattern C (Strategy-A RGBA expand fan-out): 9 substitutions in the same wired families. **Copilot #2 — `_impl` visibility tightening.** Dropped `pub(crate)` from 23 of 24 `*_to_rgb_or_rgba_row[_impl]<...>` functions in `src/row/scalar.rs` and the 5 SIMD backends. The single exception kept `pub(crate)`: `scalar::yuv_420_to_rgb_or_rgba_row` — called by all 5 SIMD backends as the scalar tail handler (verified by grep across `src/row/arch/*.rs`). **Diff:** 13 files changed, +434 / -1134 (net -700 lines). All helpers and the visibility tightening shrink the production-facing surface without touching any wire-level behaviour. **Verified locally on aarch64 macOS:** - 479 lib tests pass (unchanged). - 1 doctest passes. - `cargo check --lib --target wasm32-unknown-unknown`: clean. - `cargo check --lib --target x86_64-unknown-linux-gnu`: clean. - `cargo clippy --lib --tests`: 0 warnings. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/row/arch/neon.rs | 8 +- src/row/arch/wasm_simd128.rs | 8 +- src/row/arch/x86_avx2.rs | 8 +- src/row/arch/x86_avx512.rs | 8 +- src/row/arch/x86_sse41.rs | 8 +- src/row/scalar.rs | 6 +- src/sinker/mixed/bayer.rs | 68 +--- src/sinker/mixed/mod.rs | 73 ++++ src/sinker/mixed/planar_8bit.rs | 230 +++--------- src/sinker/mixed/semi_planar_8bit.rs | 287 ++++----------- src/sinker/mixed/subsampled_4_2_0_high_bit.rs | 266 ++++---------- src/sinker/mixed/subsampled_4_2_2_high_bit.rs | 332 +++++------------- src/sinker/mixed/subsampled_4_4_4_high_bit.rs | 266 ++++---------- 13 files changed, 434 insertions(+), 1134 deletions(-) diff --git a/src/row/arch/neon.rs b/src/row/arch/neon.rs index 2e5de6e..f7b85c1 100644 --- a/src/row/arch/neon.rs +++ b/src/row/arch/neon.rs @@ -119,7 +119,7 @@ pub(crate) unsafe fn yuv_420_to_rgba_row( /// bytes long. #[inline] #[target_feature(enable = "neon")] -pub(crate) unsafe fn yuv_420_to_rgb_or_rgba_row( +unsafe fn yuv_420_to_rgb_or_rgba_row( y: &[u8], u_half: &[u8], v_half: &[u8], @@ -1214,7 +1214,7 @@ pub(crate) unsafe fn nv21_to_rgba_row( /// `vld2_u8`, `vst3q_u8` / `vst4q_u8`). #[inline] #[target_feature(enable = "neon")] -pub(crate) unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl< +unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl< const SWAP_UV: bool, const ALPHA: bool, >( @@ -1473,7 +1473,7 @@ pub(crate) unsafe fn nv42_to_rgba_row( /// No width parity constraint (4:4:4). #[inline] #[target_feature(enable = "neon")] -pub(crate) unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl< +unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl< const SWAP_UV: bool, const ALPHA: bool, >( @@ -1687,7 +1687,7 @@ pub(crate) unsafe fn yuv_444_to_rgba_row( /// No width parity constraint (4:4:4). #[inline] #[target_feature(enable = "neon")] -pub(crate) unsafe fn yuv_444_to_rgb_or_rgba_row( +unsafe fn yuv_444_to_rgb_or_rgba_row( y: &[u8], u: &[u8], v: &[u8], diff --git a/src/row/arch/wasm_simd128.rs b/src/row/arch/wasm_simd128.rs index 77e98ef..71bdfe9 100644 --- a/src/row/arch/wasm_simd128.rs +++ b/src/row/arch/wasm_simd128.rs @@ -122,7 +122,7 @@ pub(crate) unsafe fn yuv_420_to_rgba_row( /// bytes long. #[inline] #[target_feature(enable = "simd128")] -pub(crate) unsafe fn yuv_420_to_rgb_or_rgba_row( +unsafe fn yuv_420_to_rgb_or_rgba_row( y: &[u8], u_half: &[u8], v_half: &[u8], @@ -1441,7 +1441,7 @@ pub(crate) unsafe fn nv21_to_rgba_row( /// 5. `out.len() >= width * (if ALPHA { 4 } else { 3 })`. #[inline] #[target_feature(enable = "simd128")] -pub(crate) unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl< +unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl< const SWAP_UV: bool, const ALPHA: bool, >( @@ -1702,7 +1702,7 @@ pub(crate) unsafe fn nv42_to_rgba_row( /// `out.len() >= width * if ALPHA { 4 } else { 3 }`. #[inline] #[target_feature(enable = "simd128")] -pub(crate) unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl< +unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl< const SWAP_UV: bool, const ALPHA: bool, >( @@ -1969,7 +1969,7 @@ pub(crate) unsafe fn yuv_444_to_rgba_row( /// 3. `out.len() >= width * (if ALPHA { 4 } else { 3 })`. #[inline] #[target_feature(enable = "simd128")] -pub(crate) unsafe fn yuv_444_to_rgb_or_rgba_row( +unsafe fn yuv_444_to_rgb_or_rgba_row( y: &[u8], u: &[u8], v: &[u8], diff --git a/src/row/arch/x86_avx2.rs b/src/row/arch/x86_avx2.rs index 4530164..5d2249b 100644 --- a/src/row/arch/x86_avx2.rs +++ b/src/row/arch/x86_avx2.rs @@ -132,7 +132,7 @@ pub(crate) unsafe fn yuv_420_to_rgba_row( /// bytes long. #[inline] #[target_feature(enable = "avx2")] -pub(crate) unsafe fn yuv_420_to_rgb_or_rgba_row( +unsafe fn yuv_420_to_rgb_or_rgba_row( y: &[u8], u_half: &[u8], v_half: &[u8], @@ -1646,7 +1646,7 @@ pub(crate) unsafe fn nv21_to_rgba_row( /// 5. `out.len() >= width * (if ALPHA { 4 } else { 3 })`. #[inline] #[target_feature(enable = "avx2")] -pub(crate) unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl< +unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl< const SWAP_UV: bool, const ALPHA: bool, >( @@ -1898,7 +1898,7 @@ pub(crate) unsafe fn nv42_to_rgba_row( /// 4. `out.len() >= width * if ALPHA { 4 } else { 3 }`. #[inline] #[target_feature(enable = "avx2")] -pub(crate) unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl< +unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl< const SWAP_UV: bool, const ALPHA: bool, >( @@ -2144,7 +2144,7 @@ pub(crate) unsafe fn yuv_444_to_rgba_row( /// 3. `out.len() >= width * (if ALPHA { 4 } else { 3 })`. #[inline] #[target_feature(enable = "avx2")] -pub(crate) unsafe fn yuv_444_to_rgb_or_rgba_row( +unsafe fn yuv_444_to_rgb_or_rgba_row( y: &[u8], u: &[u8], v: &[u8], diff --git a/src/row/arch/x86_avx512.rs b/src/row/arch/x86_avx512.rs index 2a5ad81..90a8ea6 100644 --- a/src/row/arch/x86_avx512.rs +++ b/src/row/arch/x86_avx512.rs @@ -146,7 +146,7 @@ pub(crate) unsafe fn yuv_420_to_rgba_row( /// bytes long. #[inline] #[target_feature(enable = "avx512f,avx512bw")] -pub(crate) unsafe fn yuv_420_to_rgb_or_rgba_row( +unsafe fn yuv_420_to_rgb_or_rgba_row( y: &[u8], u_half: &[u8], v_half: &[u8], @@ -1693,7 +1693,7 @@ pub(crate) unsafe fn nv21_to_rgba_row( /// 5. `out.len() >= width * (if ALPHA { 4 } else { 3 })`. #[inline] #[target_feature(enable = "avx512f,avx512bw")] -pub(crate) unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl< +unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl< const SWAP_UV: bool, const ALPHA: bool, >( @@ -1950,7 +1950,7 @@ pub(crate) unsafe fn nv42_to_rgba_row( /// 4. `out.len() >= width * if ALPHA { 4 } else { 3 }`. #[inline] #[target_feature(enable = "avx512f,avx512bw")] -pub(crate) unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl< +unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl< const SWAP_UV: bool, const ALPHA: bool, >( @@ -2209,7 +2209,7 @@ pub(crate) unsafe fn yuv_444_to_rgba_row( /// 3. `out.len() >= width * (if ALPHA { 4 } else { 3 })`. #[inline] #[target_feature(enable = "avx512f,avx512bw")] -pub(crate) unsafe fn yuv_444_to_rgb_or_rgba_row( +unsafe fn yuv_444_to_rgb_or_rgba_row( y: &[u8], u: &[u8], v: &[u8], diff --git a/src/row/arch/x86_sse41.rs b/src/row/arch/x86_sse41.rs index 84bee7d..4c3ef5e 100644 --- a/src/row/arch/x86_sse41.rs +++ b/src/row/arch/x86_sse41.rs @@ -132,7 +132,7 @@ pub(crate) unsafe fn yuv_420_to_rgba_row( /// bytes long. #[inline] #[target_feature(enable = "sse4.1")] -pub(crate) unsafe fn yuv_420_to_rgb_or_rgba_row( +unsafe fn yuv_420_to_rgb_or_rgba_row( y: &[u8], u_half: &[u8], v_half: &[u8], @@ -1460,7 +1460,7 @@ pub(crate) unsafe fn nv21_to_rgba_row( /// 5. `out.len() >= width * (if ALPHA { 4 } else { 3 })`. #[inline] #[target_feature(enable = "sse4.1")] -pub(crate) unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl< +unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl< const SWAP_UV: bool, const ALPHA: bool, >( @@ -1693,7 +1693,7 @@ pub(crate) unsafe fn nv42_to_rgba_row( /// 4. `out.len() >= width * if ALPHA { 4 } else { 3 }`. #[inline] #[target_feature(enable = "sse4.1")] -pub(crate) unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl< +unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl< const SWAP_UV: bool, const ALPHA: bool, >( @@ -1909,7 +1909,7 @@ pub(crate) unsafe fn yuv_444_to_rgba_row( /// 3. `out.len() >= width * (if ALPHA { 4 } else { 3 })`. #[inline] #[target_feature(enable = "sse4.1")] -pub(crate) unsafe fn yuv_444_to_rgb_or_rgba_row( +unsafe fn yuv_444_to_rgb_or_rgba_row( y: &[u8], u: &[u8], v: &[u8], diff --git a/src/row/scalar.rs b/src/row/scalar.rs index ff356a3..f7ebe15 100644 --- a/src/row/scalar.rs +++ b/src/row/scalar.rs @@ -220,7 +220,7 @@ pub(crate) fn nv21_to_rgba_row( /// - `y.len() >= width`, `uv_or_vu_half.len() >= width`, /// `out.len() >= width * (if ALPHA { 4 } else { 3 })`. #[cfg_attr(not(tarpaulin), inline(always))] -pub(crate) fn nv12_or_nv21_to_rgb_or_rgba_row_impl( +fn nv12_or_nv21_to_rgb_or_rgba_row_impl( y: &[u8], uv_or_vu_half: &[u8], out: &mut [u8], @@ -353,7 +353,7 @@ pub(crate) fn nv42_to_rgba_row( /// - `y.len() >= width`, `uv_or_vu.len() >= 2 * width`, /// `out.len() >= width * (if ALPHA { 4 } else { 3 })`. #[cfg_attr(not(tarpaulin), inline(always))] -pub(crate) fn nv24_or_nv42_to_rgb_or_rgba_row_impl( +fn nv24_or_nv42_to_rgb_or_rgba_row_impl( y: &[u8], uv_or_vu: &[u8], out: &mut [u8], @@ -445,7 +445,7 @@ pub(crate) fn yuv_444_to_rgba_row( /// - `y.len() >= width`, `u.len() >= width`, `v.len() >= width`, /// `out.len() >= width * (if ALPHA { 4 } else { 3 })`. #[cfg_attr(not(tarpaulin), inline(always))] -pub(crate) fn yuv_444_to_rgb_or_rgba_row( +fn yuv_444_to_rgb_or_rgba_row( y: &[u8], u: &[u8], v: &[u8], diff --git a/src/sinker/mixed/bayer.rs b/src/sinker/mixed/bayer.rs index 1601c71..7a7fac2 100644 --- a/src/sinker/mixed/bayer.rs +++ b/src/sinker/mixed/bayer.rs @@ -4,7 +4,7 @@ use super::{ HsvBuffers, HsvPlane, LumaChannel, LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, - check_dimensions_match, rgb_row_to_luma_row, + check_dimensions_match, rgb_row_buf_or_scratch, rgba_plane_row_slice, rgb_row_to_luma_row, }; use crate::{ColorMatrix, PixelSink, SourceFormat, raw::*, row::*, yuv::*}; @@ -116,31 +116,14 @@ impl PixelSink for MixedSinker<'_, Bayer> { // 8-bit RGB scratch / output buffer. Bayer always derives every // output channel from the demosaiced RGB, so the RGB row exists // unconditionally when any of `rgb` / `luma` / `hsv` is set. - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; bayer_to_rgb_row( row.above(), @@ -336,31 +319,14 @@ impl PixelSink for MixedSinker<'_, Bayer16> { // 8-bit RGB scratch / output. Same lazy-grow pattern as the // 8-bit Bayer impl above. - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; bayer16_to_rgb_row::( row.above(), diff --git a/src/sinker/mixed/mod.rs b/src/sinker/mixed/mod.rs index 5ae8a3e..d506618 100644 --- a/src/sinker/mixed/mod.rs +++ b/src/sinker/mixed/mod.rs @@ -1093,6 +1093,79 @@ pub(super) fn check_dimensions_match( Ok(()) } +/// Slice the RGBA row out of an attached RGBA plane buffer. Returns +/// `Err(GeometryOverflow)` if `one_plane_end × 4` wraps `usize` (only +/// reachable on 32-bit targets at extreme dimensions). +/// +/// Centralises the duplicated bounds-check pattern that every +/// `MixedSinker::process` impl runs in both the standalone-RGBA +/// branch and the Strategy-A expand branch (Copilot review #4 on PR +/// #20). +#[cfg_attr(not(tarpaulin), inline(always))] +pub(super) fn rgba_plane_row_slice( + buf: &mut [u8], + one_plane_start: usize, + one_plane_end: usize, + width: usize, + height: usize, +) -> Result<&mut [u8], MixedSinkerError> { + let end = one_plane_end + .checked_mul(4) + .ok_or(MixedSinkerError::GeometryOverflow { + width, + height, + channels: 4, + })?; + let start = one_plane_start * 4; // ≤ end, fits. + Ok(&mut buf[start..end]) +} + +/// Pick an RGB row buffer for the kernel to write into: caller's RGB +/// plane slice when attached, or the growing scratch buffer otherwise +/// (HSV-only callers don't allocate an RGB plane). Returns +/// `Err(GeometryOverflow)` if `width × 3` or `one_plane_end × 3` wraps +/// `usize` — see [`rgba_plane_row_slice`] for the rationale. +/// +/// `rgb_scratch` is grown via `Vec::resize` only when too small; the +/// caller keeps the existing capacity across rows so steady-state +/// processing allocates zero times. +#[cfg_attr(not(tarpaulin), inline(always))] +pub(super) fn rgb_row_buf_or_scratch<'a>( + rgb: Option<&'a mut [u8]>, + rgb_scratch: &'a mut Vec, + one_plane_start: usize, + one_plane_end: usize, + width: usize, + height: usize, +) -> Result<&'a mut [u8], MixedSinkerError> { + match rgb { + Some(buf) => { + let end = one_plane_end + .checked_mul(3) + .ok_or(MixedSinkerError::GeometryOverflow { + width, + height, + channels: 3, + })?; + let start = one_plane_start * 3; + Ok(&mut buf[start..end]) + } + None => { + let row_bytes = width + .checked_mul(3) + .ok_or(MixedSinkerError::GeometryOverflow { + width, + height, + channels: 3, + })?; + if rgb_scratch.len() < row_bytes { + rgb_scratch.resize(row_bytes, 0); + } + Ok(&mut rgb_scratch[..row_bytes]) + } + } +} + /// Configurable-coefficients luma derivation from packed /// `R, G, B` u8 row. /// diff --git a/src/sinker/mixed/planar_8bit.rs b/src/sinker/mixed/planar_8bit.rs index e26ef8d..d1dc3d7 100644 --- a/src/sinker/mixed/planar_8bit.rs +++ b/src/sinker/mixed/planar_8bit.rs @@ -4,7 +4,7 @@ use super::{ HsvBuffers, HsvPlane, LumaChannel, LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, - check_dimensions_match, rgb_row_to_luma_row, + check_dimensions_match, rgb_row_buf_or_scratch, rgba_plane_row_slice, rgb_row_to_luma_row, }; use crate::{ColorMatrix, PixelSink, SourceFormat, raw::*, row::*, yuv::*}; @@ -166,20 +166,12 @@ impl PixelSink for MixedSinker<'_, Yuv420p> { if want_rgba && !need_rgb_kernel { let rgba_buf = rgba.as_deref_mut().unwrap(); - let rgba_plane_end = - one_plane_end - .checked_mul(4) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 4, - })?; - let rgba_plane_start = one_plane_start * 4; + let rgba_row = rgba_plane_row_slice(rgba_buf, one_plane_start, one_plane_end, w, h)?; yuv_420_to_rgba_row( row.y(), row.u_half(), row.v_half(), - &mut rgba_buf[rgba_plane_start..rgba_plane_end], + rgba_row, w, row.matrix(), row.full_range(), @@ -204,31 +196,14 @@ impl PixelSink for MixedSinker<'_, Yuv420p> { // through the `× 3` check at buffer attachment. Overflow here // returns `GeometryOverflow` instead of panicking inside the row // dispatcher's own checked multiplication. - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; // ≤ rgb_plane_end, fits. - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; // Fused YUV→RGB: upsample chroma in registers inside the row // primitive, no intermediate memory. @@ -256,16 +231,8 @@ impl PixelSink for MixedSinker<'_, Yuv420p> { } if let Some(buf) = rgba.as_deref_mut() { - let rgba_plane_end = - one_plane_end - .checked_mul(4) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 4, - })?; - let rgba_plane_start = one_plane_start * 4; - expand_rgb_to_rgba_row(rgb_row, &mut buf[rgba_plane_start..rgba_plane_end], w); + let rgba_row = rgba_plane_row_slice(buf, one_plane_start, one_plane_end, w, h)?; + expand_rgb_to_rgba_row(rgb_row, rgba_row, w); } Ok(()) @@ -392,20 +359,12 @@ impl PixelSink for MixedSinker<'_, Yuv422p> { if want_rgba && !need_rgb_kernel { let rgba_buf = rgba.as_deref_mut().unwrap(); - let rgba_plane_end = - one_plane_end - .checked_mul(4) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 4, - })?; - let rgba_plane_start = one_plane_start * 4; + let rgba_row = rgba_plane_row_slice(rgba_buf, one_plane_start, one_plane_end, w, h)?; yuv_420_to_rgba_row( row.y(), row.u_half(), row.v_half(), - &mut rgba_buf[rgba_plane_start..rgba_plane_end], + rgba_row, w, row.matrix(), row.full_range(), @@ -418,31 +377,14 @@ impl PixelSink for MixedSinker<'_, Yuv422p> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; // Reuses the Yuv420p dispatcher — 4:2:2's per-row contract is // identical (half-width chroma, one pair per Y pair). @@ -469,16 +411,8 @@ impl PixelSink for MixedSinker<'_, Yuv422p> { } if let Some(buf) = rgba.as_deref_mut() { - let rgba_plane_end = - one_plane_end - .checked_mul(4) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 4, - })?; - let rgba_plane_start = one_plane_start * 4; - expand_rgb_to_rgba_row(rgb_row, &mut buf[rgba_plane_start..rgba_plane_end], w); + let rgba_row = rgba_plane_row_slice(buf, one_plane_start, one_plane_end, w, h)?; + expand_rgb_to_rgba_row(rgb_row, rgba_row, w); } Ok(()) @@ -594,20 +528,12 @@ impl PixelSink for MixedSinker<'_, Yuv444p> { if want_rgba && !need_rgb_kernel { let rgba_buf = rgba.as_deref_mut().unwrap(); - let rgba_plane_end = - one_plane_end - .checked_mul(4) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 4, - })?; - let rgba_plane_start = one_plane_start * 4; + let rgba_row = rgba_plane_row_slice(rgba_buf, one_plane_start, one_plane_end, w, h)?; yuv_444_to_rgba_row( row.y(), row.u(), row.v(), - &mut rgba_buf[rgba_plane_start..rgba_plane_end], + rgba_row, w, row.matrix(), row.full_range(), @@ -620,31 +546,14 @@ impl PixelSink for MixedSinker<'_, Yuv444p> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv_444_to_rgb_row( row.y(), @@ -669,16 +578,8 @@ impl PixelSink for MixedSinker<'_, Yuv444p> { } if let Some(buf) = rgba.as_deref_mut() { - let rgba_plane_end = - one_plane_end - .checked_mul(4) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 4, - })?; - let rgba_plane_start = one_plane_start * 4; - expand_rgb_to_rgba_row(rgb_row, &mut buf[rgba_plane_start..rgba_plane_end], w); + let rgba_row = rgba_plane_row_slice(buf, one_plane_start, one_plane_end, w, h)?; + expand_rgb_to_rgba_row(rgb_row, rgba_row, w); } Ok(()) @@ -796,20 +697,12 @@ impl PixelSink for MixedSinker<'_, Yuv440p> { if want_rgba && !need_rgb_kernel { let rgba_buf = rgba.as_deref_mut().unwrap(); - let rgba_plane_end = - one_plane_end - .checked_mul(4) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 4, - })?; - let rgba_plane_start = one_plane_start * 4; + let rgba_row = rgba_plane_row_slice(rgba_buf, one_plane_start, one_plane_end, w, h)?; yuv_444_to_rgba_row( row.y(), row.u(), row.v(), - &mut rgba_buf[rgba_plane_start..rgba_plane_end], + rgba_row, w, row.matrix(), row.full_range(), @@ -822,31 +715,14 @@ impl PixelSink for MixedSinker<'_, Yuv440p> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv_444_to_rgb_row( row.y(), @@ -871,16 +747,8 @@ impl PixelSink for MixedSinker<'_, Yuv440p> { } if let Some(buf) = rgba.as_deref_mut() { - let rgba_plane_end = - one_plane_end - .checked_mul(4) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 4, - })?; - let rgba_plane_start = one_plane_start * 4; - expand_rgb_to_rgba_row(rgb_row, &mut buf[rgba_plane_start..rgba_plane_end], w); + let rgba_row = rgba_plane_row_slice(buf, one_plane_start, one_plane_end, w, h)?; + expand_rgb_to_rgba_row(rgb_row, rgba_row, w); } Ok(()) diff --git a/src/sinker/mixed/semi_planar_8bit.rs b/src/sinker/mixed/semi_planar_8bit.rs index 9a949eb..e068b56 100644 --- a/src/sinker/mixed/semi_planar_8bit.rs +++ b/src/sinker/mixed/semi_planar_8bit.rs @@ -4,7 +4,7 @@ use super::{ HsvBuffers, HsvPlane, LumaChannel, LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, - check_dimensions_match, rgb_row_to_luma_row, + check_dimensions_match, rgb_row_buf_or_scratch, rgba_plane_row_slice, rgb_row_to_luma_row, }; use crate::{ColorMatrix, PixelSink, SourceFormat, raw::*, row::*, yuv::*}; @@ -129,19 +129,11 @@ impl PixelSink for MixedSinker<'_, Nv12> { if want_rgba && !need_rgb_kernel { let rgba_buf = rgba.as_deref_mut().unwrap(); - let rgba_plane_end = - one_plane_end - .checked_mul(4) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 4, - })?; - let rgba_plane_start = one_plane_start * 4; + let rgba_row = rgba_plane_row_slice(rgba_buf, one_plane_start, one_plane_end, w, h)?; nv12_to_rgba_row( row.y(), row.uv_half(), - &mut rgba_buf[rgba_plane_start..rgba_plane_end], + rgba_row, w, row.matrix(), row.full_range(), @@ -154,31 +146,14 @@ impl PixelSink for MixedSinker<'_, Nv12> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; // Fused NV12 → RGB: UV deinterleave + chroma upsample both happen // in registers inside the row primitive, no intermediate memory. @@ -204,16 +179,8 @@ impl PixelSink for MixedSinker<'_, Nv12> { } if let Some(buf) = rgba.as_deref_mut() { - let rgba_plane_end = - one_plane_end - .checked_mul(4) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 4, - })?; - let rgba_plane_start = one_plane_start * 4; - expand_rgb_to_rgba_row(rgb_row, &mut buf[rgba_plane_start..rgba_plane_end], w); + let rgba_row = rgba_plane_row_slice(buf, one_plane_start, one_plane_end, w, h)?; + expand_rgb_to_rgba_row(rgb_row, rgba_row, w); } Ok(()) @@ -332,19 +299,11 @@ impl PixelSink for MixedSinker<'_, Nv16> { if want_rgba && !need_rgb_kernel { let rgba_buf = rgba.as_deref_mut().unwrap(); - let rgba_plane_end = - one_plane_end - .checked_mul(4) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 4, - })?; - let rgba_plane_start = one_plane_start * 4; + let rgba_row = rgba_plane_row_slice(rgba_buf, one_plane_start, one_plane_end, w, h)?; nv12_to_rgba_row( row.y(), row.uv(), - &mut rgba_buf[rgba_plane_start..rgba_plane_end], + rgba_row, w, row.matrix(), row.full_range(), @@ -357,31 +316,14 @@ impl PixelSink for MixedSinker<'_, Nv16> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; // Reuses the NV12 dispatcher — 4:2:2's row contract is identical. nv12_to_rgb_row( @@ -406,16 +348,8 @@ impl PixelSink for MixedSinker<'_, Nv16> { } if let Some(buf) = rgba.as_deref_mut() { - let rgba_plane_end = - one_plane_end - .checked_mul(4) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 4, - })?; - let rgba_plane_start = one_plane_start * 4; - expand_rgb_to_rgba_row(rgb_row, &mut buf[rgba_plane_start..rgba_plane_end], w); + let rgba_row = rgba_plane_row_slice(buf, one_plane_start, one_plane_end, w, h)?; + expand_rgb_to_rgba_row(rgb_row, rgba_row, w); } Ok(()) @@ -532,19 +466,11 @@ impl PixelSink for MixedSinker<'_, Nv21> { if want_rgba && !need_rgb_kernel { let rgba_buf = rgba.as_deref_mut().unwrap(); - let rgba_plane_end = - one_plane_end - .checked_mul(4) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 4, - })?; - let rgba_plane_start = one_plane_start * 4; + let rgba_row = rgba_plane_row_slice(rgba_buf, one_plane_start, one_plane_end, w, h)?; nv21_to_rgba_row( row.y(), row.vu_half(), - &mut rgba_buf[rgba_plane_start..rgba_plane_end], + rgba_row, w, row.matrix(), row.full_range(), @@ -557,31 +483,14 @@ impl PixelSink for MixedSinker<'_, Nv21> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; // Fused NV21 → RGB: VU deinterleave + chroma upsample both happen // in registers inside the row primitive, no intermediate memory. @@ -607,16 +516,8 @@ impl PixelSink for MixedSinker<'_, Nv21> { } if let Some(buf) = rgba.as_deref_mut() { - let rgba_plane_end = - one_plane_end - .checked_mul(4) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 4, - })?; - let rgba_plane_start = one_plane_start * 4; - expand_rgb_to_rgba_row(rgb_row, &mut buf[rgba_plane_start..rgba_plane_end], w); + let rgba_row = rgba_plane_row_slice(buf, one_plane_start, one_plane_end, w, h)?; + expand_rgb_to_rgba_row(rgb_row, rgba_row, w); } Ok(()) @@ -735,19 +636,11 @@ impl PixelSink for MixedSinker<'_, Nv24> { // Avoids both the scratch allocation and the expand-pad pass. if want_rgba && !need_rgb_kernel { let rgba_buf = rgba.as_deref_mut().unwrap(); - let rgba_plane_end = - one_plane_end - .checked_mul(4) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 4, - })?; - let rgba_plane_start = one_plane_start * 4; + let rgba_row = rgba_plane_row_slice(rgba_buf, one_plane_start, one_plane_end, w, h)?; nv24_to_rgba_row( row.y(), row.uv(), - &mut rgba_buf[rgba_plane_start..rgba_plane_end], + rgba_row, w, row.matrix(), row.full_range(), @@ -760,31 +653,14 @@ impl PixelSink for MixedSinker<'_, Nv24> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; nv24_to_rgb_row( row.y(), @@ -811,16 +687,8 @@ impl PixelSink for MixedSinker<'_, Nv24> { // derive RGBA from the just-computed RGB row (memory-bound copy + // 0xFF alpha pad) instead of running a second YUV→RGB kernel. if let Some(buf) = rgba.as_deref_mut() { - let rgba_plane_end = - one_plane_end - .checked_mul(4) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 4, - })?; - let rgba_plane_start = one_plane_start * 4; - expand_rgb_to_rgba_row(rgb_row, &mut buf[rgba_plane_start..rgba_plane_end], w); + let rgba_row = rgba_plane_row_slice(buf, one_plane_start, one_plane_end, w, h)?; + expand_rgb_to_rgba_row(rgb_row, rgba_row, w); } Ok(()) @@ -929,19 +797,11 @@ impl PixelSink for MixedSinker<'_, Nv42> { if want_rgba && !need_rgb_kernel { let rgba_buf = rgba.as_deref_mut().unwrap(); - let rgba_plane_end = - one_plane_end - .checked_mul(4) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 4, - })?; - let rgba_plane_start = one_plane_start * 4; + let rgba_row = rgba_plane_row_slice(rgba_buf, one_plane_start, one_plane_end, w, h)?; nv42_to_rgba_row( row.y(), row.vu(), - &mut rgba_buf[rgba_plane_start..rgba_plane_end], + rgba_row, w, row.matrix(), row.full_range(), @@ -954,31 +814,14 @@ impl PixelSink for MixedSinker<'_, Nv42> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; nv42_to_rgb_row( row.y(), @@ -1002,16 +845,8 @@ impl PixelSink for MixedSinker<'_, Nv42> { } if let Some(buf) = rgba.as_deref_mut() { - let rgba_plane_end = - one_plane_end - .checked_mul(4) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 4, - })?; - let rgba_plane_start = one_plane_start * 4; - expand_rgb_to_rgba_row(rgb_row, &mut buf[rgba_plane_start..rgba_plane_end], w); + let rgba_row = rgba_plane_row_slice(buf, one_plane_start, one_plane_end, w, h)?; + expand_rgb_to_rgba_row(rgb_row, rgba_row, w); } Ok(()) diff --git a/src/sinker/mixed/subsampled_4_2_0_high_bit.rs b/src/sinker/mixed/subsampled_4_2_0_high_bit.rs index 74427a3..451eca0 100644 --- a/src/sinker/mixed/subsampled_4_2_0_high_bit.rs +++ b/src/sinker/mixed/subsampled_4_2_0_high_bit.rs @@ -4,7 +4,7 @@ use super::{ HsvBuffers, HsvPlane, LumaChannel, LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, - check_dimensions_match, rgb_row_to_luma_row, + check_dimensions_match, rgb_row_buf_or_scratch, rgba_plane_row_slice, rgb_row_to_luma_row, }; use crate::{ColorMatrix, PixelSink, SourceFormat, raw::*, row::*, yuv::*}; @@ -136,31 +136,14 @@ impl PixelSink for MixedSinker<'_, Yuv420p9> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv420p9_to_rgb_row( row.y(), @@ -351,31 +334,14 @@ impl PixelSink for MixedSinker<'_, Yuv420p10> { // 8‑bit RGB path — either writes to the caller's buffer (when // `with_rgb` is set) or to the lazily‑grown scratch (when HSV is // requested without RGB). Mirrors the 8‑bit source impls' layout. - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv420p10_to_rgb_row( row.y(), @@ -535,31 +501,14 @@ impl PixelSink for MixedSinker<'_, Yuv420p12> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv420p12_to_rgb_row( row.y(), @@ -716,31 +665,14 @@ impl PixelSink for MixedSinker<'_, Yuv420p14> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv420p14_to_rgb_row( row.y(), @@ -897,31 +829,14 @@ impl PixelSink for MixedSinker<'_, Yuv420p16> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv420p16_to_rgb_row( row.y(), @@ -1081,31 +996,14 @@ impl PixelSink for MixedSinker<'_, P010> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; p010_to_rgb_row( row.y(), @@ -1255,31 +1153,14 @@ impl PixelSink for MixedSinker<'_, P012> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; p012_to_rgb_row( row.y(), @@ -1425,31 +1306,14 @@ impl PixelSink for MixedSinker<'_, P016> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; p016_to_rgb_row( row.y(), diff --git a/src/sinker/mixed/subsampled_4_2_2_high_bit.rs b/src/sinker/mixed/subsampled_4_2_2_high_bit.rs index 9fa9e2a..9662fb8 100644 --- a/src/sinker/mixed/subsampled_4_2_2_high_bit.rs +++ b/src/sinker/mixed/subsampled_4_2_2_high_bit.rs @@ -4,7 +4,7 @@ use super::{ HsvBuffers, HsvPlane, LumaChannel, LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, - check_dimensions_match, rgb_row_to_luma_row, + check_dimensions_match, rgb_row_buf_or_scratch, rgba_plane_row_slice, rgb_row_to_luma_row, }; use crate::{ColorMatrix, PixelSink, SourceFormat, raw::*, row::*, yuv::*}; @@ -134,31 +134,14 @@ impl PixelSink for MixedSinker<'_, Yuv422p9> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv420p9_to_rgb_row( row.y(), @@ -314,31 +297,14 @@ impl PixelSink for MixedSinker<'_, Yuv422p10> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv420p10_to_rgb_row( row.y(), @@ -485,31 +451,14 @@ impl PixelSink for MixedSinker<'_, Yuv422p12> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv420p12_to_rgb_row( row.y(), @@ -656,31 +605,14 @@ impl PixelSink for MixedSinker<'_, Yuv422p14> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv420p14_to_rgb_row( row.y(), @@ -835,31 +767,14 @@ impl PixelSink for MixedSinker<'_, Yuv422p16> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv420p16_to_rgb_row( row.y(), @@ -1005,31 +920,14 @@ impl PixelSink for MixedSinker<'_, Yuv440p10> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv444p10_to_rgb_row( row.y(), @@ -1172,31 +1070,14 @@ impl PixelSink for MixedSinker<'_, Yuv440p12> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv444p12_to_rgb_row( row.y(), @@ -1342,31 +1223,14 @@ impl PixelSink for MixedSinker<'_, P210> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; p010_to_rgb_row( row.y(), @@ -1508,31 +1372,14 @@ impl PixelSink for MixedSinker<'_, P212> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; p012_to_rgb_row( row.y(), @@ -1674,31 +1521,14 @@ impl PixelSink for MixedSinker<'_, P216> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; p016_to_rgb_row( row.y(), diff --git a/src/sinker/mixed/subsampled_4_4_4_high_bit.rs b/src/sinker/mixed/subsampled_4_4_4_high_bit.rs index 04d9db1..c0b6cfb 100644 --- a/src/sinker/mixed/subsampled_4_4_4_high_bit.rs +++ b/src/sinker/mixed/subsampled_4_4_4_high_bit.rs @@ -4,7 +4,7 @@ use super::{ HsvBuffers, HsvPlane, LumaChannel, LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, - check_dimensions_match, rgb_row_to_luma_row, + check_dimensions_match, rgb_row_buf_or_scratch, rgba_plane_row_slice, rgb_row_to_luma_row, }; use crate::{ColorMatrix, PixelSink, SourceFormat, raw::*, row::*, yuv::*}; @@ -124,31 +124,14 @@ impl PixelSink for MixedSinker<'_, Yuv444p9> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv444p9_to_rgb_row( row.y(), @@ -291,31 +274,14 @@ impl PixelSink for MixedSinker<'_, Yuv444p10> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv444p10_to_rgb_row( row.y(), @@ -456,31 +422,14 @@ impl PixelSink for MixedSinker<'_, Yuv444p12> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv444p12_to_rgb_row( row.y(), @@ -621,31 +570,14 @@ impl PixelSink for MixedSinker<'_, Yuv444p14> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv444p14_to_rgb_row( row.y(), @@ -787,31 +719,14 @@ impl PixelSink for MixedSinker<'_, Yuv444p16> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; yuv444p16_to_rgb_row( row.y(), @@ -950,31 +865,14 @@ impl PixelSink for MixedSinker<'_, P410> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; p410_to_rgb_row( row.y(), @@ -1106,31 +1004,14 @@ impl PixelSink for MixedSinker<'_, P412> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; p412_to_rgb_row( row.y(), @@ -1266,31 +1147,14 @@ impl PixelSink for MixedSinker<'_, P416> { return Ok(()); } - let rgb_row: &mut [u8] = match rgb.as_deref_mut() { - Some(buf) => { - let rgb_plane_end = - one_plane_end - .checked_mul(3) - .ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - let rgb_plane_start = one_plane_start * 3; - &mut buf[rgb_plane_start..rgb_plane_end] - } - None => { - let rgb_row_bytes = w.checked_mul(3).ok_or(MixedSinkerError::GeometryOverflow { - width: w, - height: h, - channels: 3, - })?; - if rgb_scratch.len() < rgb_row_bytes { - rgb_scratch.resize(rgb_row_bytes, 0); - } - &mut rgb_scratch[..rgb_row_bytes] - } - }; + let rgb_row = rgb_row_buf_or_scratch( + rgb.as_deref_mut(), + rgb_scratch, + one_plane_start, + one_plane_end, + w, + h, + )?; p416_to_rgb_row( row.y(), From f69f21d401b9d1a8449ad94cd1b0e16d3af973ee Mon Sep 17 00:00:00 2001 From: uqio <276879906+uqio@users.noreply.github.com> Date: Sun, 26 Apr 2026 20:57:06 +1200 Subject: [PATCH 2/5] update --- src/row/arch/neon.rs | 10 ++-------- src/row/arch/wasm_simd128.rs | 10 ++-------- src/row/arch/x86_avx2.rs | 10 ++-------- src/row/arch/x86_avx512.rs | 10 ++-------- src/row/arch/x86_sse41.rs | 10 ++-------- src/sinker/mixed/bayer.rs | 2 +- src/sinker/mixed/planar_8bit.rs | 2 +- src/sinker/mixed/semi_planar_8bit.rs | 2 +- src/sinker/mixed/subsampled_4_2_0_high_bit.rs | 2 +- src/sinker/mixed/subsampled_4_2_2_high_bit.rs | 2 +- src/sinker/mixed/subsampled_4_4_4_high_bit.rs | 2 +- 11 files changed, 16 insertions(+), 46 deletions(-) diff --git a/src/row/arch/neon.rs b/src/row/arch/neon.rs index f7b85c1..443b469 100644 --- a/src/row/arch/neon.rs +++ b/src/row/arch/neon.rs @@ -1214,10 +1214,7 @@ pub(crate) unsafe fn nv21_to_rgba_row( /// `vld2_u8`, `vst3q_u8` / `vst4q_u8`). #[inline] #[target_feature(enable = "neon")] -unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl< - const SWAP_UV: bool, - const ALPHA: bool, ->( +unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl( y: &[u8], uv_or_vu_half: &[u8], out: &mut [u8], @@ -1473,10 +1470,7 @@ pub(crate) unsafe fn nv42_to_rgba_row( /// No width parity constraint (4:4:4). #[inline] #[target_feature(enable = "neon")] -unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl< - const SWAP_UV: bool, - const ALPHA: bool, ->( +unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl( y: &[u8], uv_or_vu: &[u8], out: &mut [u8], diff --git a/src/row/arch/wasm_simd128.rs b/src/row/arch/wasm_simd128.rs index 71bdfe9..29e3f5a 100644 --- a/src/row/arch/wasm_simd128.rs +++ b/src/row/arch/wasm_simd128.rs @@ -1441,10 +1441,7 @@ pub(crate) unsafe fn nv21_to_rgba_row( /// 5. `out.len() >= width * (if ALPHA { 4 } else { 3 })`. #[inline] #[target_feature(enable = "simd128")] -unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl< - const SWAP_UV: bool, - const ALPHA: bool, ->( +unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl( y: &[u8], uv_or_vu_half: &[u8], out: &mut [u8], @@ -1702,10 +1699,7 @@ pub(crate) unsafe fn nv42_to_rgba_row( /// `out.len() >= width * if ALPHA { 4 } else { 3 }`. #[inline] #[target_feature(enable = "simd128")] -unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl< - const SWAP_UV: bool, - const ALPHA: bool, ->( +unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl( y: &[u8], uv_or_vu: &[u8], out: &mut [u8], diff --git a/src/row/arch/x86_avx2.rs b/src/row/arch/x86_avx2.rs index 5d2249b..2882928 100644 --- a/src/row/arch/x86_avx2.rs +++ b/src/row/arch/x86_avx2.rs @@ -1646,10 +1646,7 @@ pub(crate) unsafe fn nv21_to_rgba_row( /// 5. `out.len() >= width * (if ALPHA { 4 } else { 3 })`. #[inline] #[target_feature(enable = "avx2")] -unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl< - const SWAP_UV: bool, - const ALPHA: bool, ->( +unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl( y: &[u8], uv_or_vu_half: &[u8], out: &mut [u8], @@ -1898,10 +1895,7 @@ pub(crate) unsafe fn nv42_to_rgba_row( /// 4. `out.len() >= width * if ALPHA { 4 } else { 3 }`. #[inline] #[target_feature(enable = "avx2")] -unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl< - const SWAP_UV: bool, - const ALPHA: bool, ->( +unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl( y: &[u8], uv_or_vu: &[u8], out: &mut [u8], diff --git a/src/row/arch/x86_avx512.rs b/src/row/arch/x86_avx512.rs index 90a8ea6..e0385c4 100644 --- a/src/row/arch/x86_avx512.rs +++ b/src/row/arch/x86_avx512.rs @@ -1693,10 +1693,7 @@ pub(crate) unsafe fn nv21_to_rgba_row( /// 5. `out.len() >= width * (if ALPHA { 4 } else { 3 })`. #[inline] #[target_feature(enable = "avx512f,avx512bw")] -unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl< - const SWAP_UV: bool, - const ALPHA: bool, ->( +unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl( y: &[u8], uv_or_vu_half: &[u8], out: &mut [u8], @@ -1950,10 +1947,7 @@ pub(crate) unsafe fn nv42_to_rgba_row( /// 4. `out.len() >= width * if ALPHA { 4 } else { 3 }`. #[inline] #[target_feature(enable = "avx512f,avx512bw")] -unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl< - const SWAP_UV: bool, - const ALPHA: bool, ->( +unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl( y: &[u8], uv_or_vu: &[u8], out: &mut [u8], diff --git a/src/row/arch/x86_sse41.rs b/src/row/arch/x86_sse41.rs index 4c3ef5e..4aaecaf 100644 --- a/src/row/arch/x86_sse41.rs +++ b/src/row/arch/x86_sse41.rs @@ -1460,10 +1460,7 @@ pub(crate) unsafe fn nv21_to_rgba_row( /// 5. `out.len() >= width * (if ALPHA { 4 } else { 3 })`. #[inline] #[target_feature(enable = "sse4.1")] -unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl< - const SWAP_UV: bool, - const ALPHA: bool, ->( +unsafe fn nv12_or_nv21_to_rgb_or_rgba_row_impl( y: &[u8], uv_or_vu_half: &[u8], out: &mut [u8], @@ -1693,10 +1690,7 @@ pub(crate) unsafe fn nv42_to_rgba_row( /// 4. `out.len() >= width * if ALPHA { 4 } else { 3 }`. #[inline] #[target_feature(enable = "sse4.1")] -unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl< - const SWAP_UV: bool, - const ALPHA: bool, ->( +unsafe fn nv24_or_nv42_to_rgb_or_rgba_row_impl( y: &[u8], uv_or_vu: &[u8], out: &mut [u8], diff --git a/src/sinker/mixed/bayer.rs b/src/sinker/mixed/bayer.rs index 7a7fac2..49d1cfc 100644 --- a/src/sinker/mixed/bayer.rs +++ b/src/sinker/mixed/bayer.rs @@ -4,7 +4,7 @@ use super::{ HsvBuffers, HsvPlane, LumaChannel, LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, - check_dimensions_match, rgb_row_buf_or_scratch, rgba_plane_row_slice, rgb_row_to_luma_row, + check_dimensions_match, rgb_row_buf_or_scratch, rgb_row_to_luma_row, rgba_plane_row_slice, }; use crate::{ColorMatrix, PixelSink, SourceFormat, raw::*, row::*, yuv::*}; diff --git a/src/sinker/mixed/planar_8bit.rs b/src/sinker/mixed/planar_8bit.rs index d1dc3d7..d1507f1 100644 --- a/src/sinker/mixed/planar_8bit.rs +++ b/src/sinker/mixed/planar_8bit.rs @@ -4,7 +4,7 @@ use super::{ HsvBuffers, HsvPlane, LumaChannel, LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, - check_dimensions_match, rgb_row_buf_or_scratch, rgba_plane_row_slice, rgb_row_to_luma_row, + check_dimensions_match, rgb_row_buf_or_scratch, rgb_row_to_luma_row, rgba_plane_row_slice, }; use crate::{ColorMatrix, PixelSink, SourceFormat, raw::*, row::*, yuv::*}; diff --git a/src/sinker/mixed/semi_planar_8bit.rs b/src/sinker/mixed/semi_planar_8bit.rs index e068b56..fdc2cff 100644 --- a/src/sinker/mixed/semi_planar_8bit.rs +++ b/src/sinker/mixed/semi_planar_8bit.rs @@ -4,7 +4,7 @@ use super::{ HsvBuffers, HsvPlane, LumaChannel, LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, - check_dimensions_match, rgb_row_buf_or_scratch, rgba_plane_row_slice, rgb_row_to_luma_row, + check_dimensions_match, rgb_row_buf_or_scratch, rgb_row_to_luma_row, rgba_plane_row_slice, }; use crate::{ColorMatrix, PixelSink, SourceFormat, raw::*, row::*, yuv::*}; diff --git a/src/sinker/mixed/subsampled_4_2_0_high_bit.rs b/src/sinker/mixed/subsampled_4_2_0_high_bit.rs index 451eca0..9b70b94 100644 --- a/src/sinker/mixed/subsampled_4_2_0_high_bit.rs +++ b/src/sinker/mixed/subsampled_4_2_0_high_bit.rs @@ -4,7 +4,7 @@ use super::{ HsvBuffers, HsvPlane, LumaChannel, LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, - check_dimensions_match, rgb_row_buf_or_scratch, rgba_plane_row_slice, rgb_row_to_luma_row, + check_dimensions_match, rgb_row_buf_or_scratch, rgb_row_to_luma_row, rgba_plane_row_slice, }; use crate::{ColorMatrix, PixelSink, SourceFormat, raw::*, row::*, yuv::*}; diff --git a/src/sinker/mixed/subsampled_4_2_2_high_bit.rs b/src/sinker/mixed/subsampled_4_2_2_high_bit.rs index 9662fb8..147b8d8 100644 --- a/src/sinker/mixed/subsampled_4_2_2_high_bit.rs +++ b/src/sinker/mixed/subsampled_4_2_2_high_bit.rs @@ -4,7 +4,7 @@ use super::{ HsvBuffers, HsvPlane, LumaChannel, LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, - check_dimensions_match, rgb_row_buf_or_scratch, rgba_plane_row_slice, rgb_row_to_luma_row, + check_dimensions_match, rgb_row_buf_or_scratch, rgb_row_to_luma_row, rgba_plane_row_slice, }; use crate::{ColorMatrix, PixelSink, SourceFormat, raw::*, row::*, yuv::*}; diff --git a/src/sinker/mixed/subsampled_4_4_4_high_bit.rs b/src/sinker/mixed/subsampled_4_4_4_high_bit.rs index c0b6cfb..23e056d 100644 --- a/src/sinker/mixed/subsampled_4_4_4_high_bit.rs +++ b/src/sinker/mixed/subsampled_4_4_4_high_bit.rs @@ -4,7 +4,7 @@ use super::{ HsvBuffers, HsvPlane, LumaChannel, LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, - check_dimensions_match, rgb_row_buf_or_scratch, rgba_plane_row_slice, rgb_row_to_luma_row, + check_dimensions_match, rgb_row_buf_or_scratch, rgb_row_to_luma_row, rgba_plane_row_slice, }; use crate::{ColorMatrix, PixelSink, SourceFormat, raw::*, row::*, yuv::*}; From ce254b3ad2f51b1ec66529218617156c74859bf2 Mon Sep 17 00:00:00 2001 From: uqio <276879906+uqio@users.noreply.github.com> Date: Sun, 26 Apr 2026 21:05:54 +1200 Subject: [PATCH 3/5] update --- src/row/mod.rs | 6 ++++++ src/row/scalar.rs | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/src/row/mod.rs b/src/row/mod.rs index c64403c..5974753 100644 --- a/src/row/mod.rs +++ b/src/row/mod.rs @@ -34,6 +34,12 @@ pub(crate) mod arch; pub(crate) mod scalar; +// Re-exported only when a caller is compiled. The `MixedSinker` Strategy A +// fan-out is the sole consumer, and it lives in `crate::sinker::mixed` which +// is gated on `feature = "std"` / `feature = "alloc"` (needs `Vec`). Without +// either feature both this re-export and the underlying scalar function would +// be unused, which is a hard error under `cargo clippy -- -D warnings`. +#[cfg(any(feature = "std", feature = "alloc"))] pub(crate) use scalar::expand_rgb_to_rgba_row; use crate::ColorMatrix; diff --git a/src/row/scalar.rs b/src/row/scalar.rs index f7ebe15..71d1018 100644 --- a/src/row/scalar.rs +++ b/src/row/scalar.rs @@ -509,6 +509,11 @@ fn clamp_u8(v: i32) -> u8 { /// /// - `rgb.len() >= 3 * width` /// - `rgba_out.len() >= 4 * width` +// Only the `MixedSinker` Strategy A fan-out calls this; that lives in +// `crate::sinker::mixed`, gated on `feature = "std"` / `"alloc"`. Without +// either feature the helper would be unused and `-D dead_code` (set by +// `cargo clippy -- -D warnings` on CI) would fail the build. +#[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(not(tarpaulin), inline(always))] pub(crate) fn expand_rgb_to_rgba_row(rgb: &[u8], rgba_out: &mut [u8], width: usize) { debug_assert!(rgb.len() >= width * 3, "rgb row too short"); From eed5017101197de7297735cf99919d3c3b20fd05 Mon Sep 17 00:00:00 2001 From: uqio <276879906+uqio@users.noreply.github.com> Date: Sun, 26 Apr 2026 21:25:50 +1200 Subject: [PATCH 4/5] update --- src/sinker/mixed/bayer.rs | 8 +++----- src/sinker/mixed/planar_8bit.rs | 8 +++----- src/sinker/mixed/semi_planar_8bit.rs | 8 +++----- src/sinker/mixed/subsampled_4_2_0_high_bit.rs | 7 ++----- src/sinker/mixed/subsampled_4_2_2_high_bit.rs | 7 ++----- src/sinker/mixed/subsampled_4_4_4_high_bit.rs | 7 ++----- 6 files changed, 15 insertions(+), 30 deletions(-) diff --git a/src/sinker/mixed/bayer.rs b/src/sinker/mixed/bayer.rs index 49d1cfc..a4afc1e 100644 --- a/src/sinker/mixed/bayer.rs +++ b/src/sinker/mixed/bayer.rs @@ -1,12 +1,10 @@ //! Bayer / Bayer16 RAW `MixedSinker` impls. -#![allow(unused_imports)] - use super::{ - HsvBuffers, HsvPlane, LumaChannel, LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, - check_dimensions_match, rgb_row_buf_or_scratch, rgb_row_to_luma_row, rgba_plane_row_slice, + LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, check_dimensions_match, + rgb_row_buf_or_scratch, rgb_row_to_luma_row, }; -use crate::{ColorMatrix, PixelSink, SourceFormat, raw::*, row::*, yuv::*}; +use crate::{PixelSink, raw::*, row::*}; // ---- Bayer (8-bit) impl -------------------------------------------------- diff --git a/src/sinker/mixed/planar_8bit.rs b/src/sinker/mixed/planar_8bit.rs index d1507f1..a0d5c7e 100644 --- a/src/sinker/mixed/planar_8bit.rs +++ b/src/sinker/mixed/planar_8bit.rs @@ -1,12 +1,10 @@ //! 8-bit planar YUV `MixedSinker` impls: Yuv420p / Yuv422p / Yuv444p / Yuv440p. -#![allow(unused_imports)] - use super::{ - HsvBuffers, HsvPlane, LumaChannel, LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, - check_dimensions_match, rgb_row_buf_or_scratch, rgb_row_to_luma_row, rgba_plane_row_slice, + MixedSinker, MixedSinkerError, RowSlice, check_dimensions_match, rgb_row_buf_or_scratch, + rgba_plane_row_slice, }; -use crate::{ColorMatrix, PixelSink, SourceFormat, raw::*, row::*, yuv::*}; +use crate::{PixelSink, row::*, yuv::*}; // ---- Yuv420p impl -------------------------------------------------------- diff --git a/src/sinker/mixed/semi_planar_8bit.rs b/src/sinker/mixed/semi_planar_8bit.rs index fdc2cff..3961d4e 100644 --- a/src/sinker/mixed/semi_planar_8bit.rs +++ b/src/sinker/mixed/semi_planar_8bit.rs @@ -1,12 +1,10 @@ //! 8-bit semi-planar YUV `MixedSinker` impls: Nv12 / Nv16 / Nv21 / Nv24 / Nv42. -#![allow(unused_imports)] - use super::{ - HsvBuffers, HsvPlane, LumaChannel, LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, - check_dimensions_match, rgb_row_buf_or_scratch, rgb_row_to_luma_row, rgba_plane_row_slice, + MixedSinker, MixedSinkerError, RowSlice, check_dimensions_match, rgb_row_buf_or_scratch, + rgba_plane_row_slice, }; -use crate::{ColorMatrix, PixelSink, SourceFormat, raw::*, row::*, yuv::*}; +use crate::{PixelSink, row::*, yuv::*}; // ---- Nv12 impl ---------------------------------------------------------- diff --git a/src/sinker/mixed/subsampled_4_2_0_high_bit.rs b/src/sinker/mixed/subsampled_4_2_0_high_bit.rs index 9b70b94..9531a17 100644 --- a/src/sinker/mixed/subsampled_4_2_0_high_bit.rs +++ b/src/sinker/mixed/subsampled_4_2_0_high_bit.rs @@ -1,12 +1,9 @@ //! High-bit-depth 4:2:0 `MixedSinker` impls: Yuv420p9/10/12/14/16 + P010/P012/P016. -#![allow(unused_imports)] - use super::{ - HsvBuffers, HsvPlane, LumaChannel, LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, - check_dimensions_match, rgb_row_buf_or_scratch, rgb_row_to_luma_row, rgba_plane_row_slice, + MixedSinker, MixedSinkerError, RowSlice, check_dimensions_match, rgb_row_buf_or_scratch, }; -use crate::{ColorMatrix, PixelSink, SourceFormat, raw::*, row::*, yuv::*}; +use crate::{PixelSink, row::*, yuv::*}; // ---- Yuv420p9 impl ----------------------------------------------------- // diff --git a/src/sinker/mixed/subsampled_4_2_2_high_bit.rs b/src/sinker/mixed/subsampled_4_2_2_high_bit.rs index 147b8d8..c63085d 100644 --- a/src/sinker/mixed/subsampled_4_2_2_high_bit.rs +++ b/src/sinker/mixed/subsampled_4_2_2_high_bit.rs @@ -1,12 +1,9 @@ //! High-bit-depth 4:2:2 / 4:4:0 `MixedSinker` impls: Yuv422p9/10/12/14/16 + Yuv440p10/12 + P210/P212/P216. -#![allow(unused_imports)] - use super::{ - HsvBuffers, HsvPlane, LumaChannel, LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, - check_dimensions_match, rgb_row_buf_or_scratch, rgb_row_to_luma_row, rgba_plane_row_slice, + MixedSinker, MixedSinkerError, RowSlice, check_dimensions_match, rgb_row_buf_or_scratch, }; -use crate::{ColorMatrix, PixelSink, SourceFormat, raw::*, row::*, yuv::*}; +use crate::{PixelSink, row::*, yuv::*}; // ---- Yuv422p9 impl ----------------------------------------------------- // diff --git a/src/sinker/mixed/subsampled_4_4_4_high_bit.rs b/src/sinker/mixed/subsampled_4_4_4_high_bit.rs index 23e056d..f1dde93 100644 --- a/src/sinker/mixed/subsampled_4_4_4_high_bit.rs +++ b/src/sinker/mixed/subsampled_4_4_4_high_bit.rs @@ -1,12 +1,9 @@ //! High-bit-depth 4:4:4 `MixedSinker` impls: Yuv444p9/10/12/14/16 + P410/P412/P416. -#![allow(unused_imports)] - use super::{ - HsvBuffers, HsvPlane, LumaChannel, LumaCoefficients, MixedSinker, MixedSinkerError, RowSlice, - check_dimensions_match, rgb_row_buf_or_scratch, rgb_row_to_luma_row, rgba_plane_row_slice, + MixedSinker, MixedSinkerError, RowSlice, check_dimensions_match, rgb_row_buf_or_scratch, }; -use crate::{ColorMatrix, PixelSink, SourceFormat, raw::*, row::*, yuv::*}; +use crate::{PixelSink, row::*, yuv::*}; // ---- Yuv444p9 impl ----------------------------------------------------- From 08a613c22fb4eeb6209381838115ee31e7fa7044 Mon Sep 17 00:00:00 2001 From: Al Liu Date: Sun, 26 Apr 2026 17:36:24 +0800 Subject: [PATCH 5/5] Update src/sinker/mixed/mod.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/sinker/mixed/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/sinker/mixed/mod.rs b/src/sinker/mixed/mod.rs index d506618..0369929 100644 --- a/src/sinker/mixed/mod.rs +++ b/src/sinker/mixed/mod.rs @@ -1097,10 +1097,9 @@ pub(super) fn check_dimensions_match( /// `Err(GeometryOverflow)` if `one_plane_end × 4` wraps `usize` (only /// reachable on 32-bit targets at extreme dimensions). /// -/// Centralises the duplicated bounds-check pattern that every +/// Centralises the duplicated overflow/bounds-check pattern that every /// `MixedSinker::process` impl runs in both the standalone-RGBA -/// branch and the Strategy-A expand branch (Copilot review #4 on PR -/// #20). +/// branch and the Strategy-A expand branch. #[cfg_attr(not(tarpaulin), inline(always))] pub(super) fn rgba_plane_row_slice( buf: &mut [u8],