diff --git a/crates/algo/src/lib.rs b/crates/algo/src/lib.rs index 0c1c0a96..368888d8 100644 --- a/crates/algo/src/lib.rs +++ b/crates/algo/src/lib.rs @@ -16,6 +16,7 @@ //! [`apply`] runs a filter over an area, tile by tile (in parallel with //! rayon on native targets; single-threaded on wasm). #![forbid(unsafe_code)] +#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)] mod artistic; mod artistic_fx; @@ -906,7 +907,11 @@ pub fn apply_tiled( }; &owned } - (None, Halo::Bounds) => unreachable!("shared image exists for global filters"), + // `shared` is always read for global filters; read the same image if it weren't. + (None, Halo::Bounds) => { + owned = Image::read(surface, bounds.union(&area)); + &owned + } }; let mut data = kernel(params, src, *t, &ctx); if let Some(sel) = selection { diff --git a/crates/algo/src/panorama.rs b/crates/algo/src/panorama.rs index 0246e156..fd7ccbc5 100644 --- a/crates/algo/src/panorama.rs +++ b/crates/algo/src/panorama.rs @@ -616,7 +616,7 @@ fn align_layout(feats: &[ImageFeatures], matches: &[PairMatch], opts: &AlignOpti let mp = motion.n_params(); let refine_focal = projection != Projection::Plane; let n_glob = usize::from(opts.geometric) + usize::from(refine_focal); - let mut params: Vec = movable.iter().flat_map(|&i| motion.to_params(&tf[i].expect("placed"))).collect(); + let mut params: Vec = movable.iter().filter_map(|&i| tf[i].as_ref()).flat_map(|t| motion.to_params(t)).collect(); if opts.geometric { params.push(0.0); } @@ -1105,7 +1105,7 @@ pub fn multiband(w: usize, h: usize, imgs: &[RoiImage], weights: &[Vec], le // Level sizes of the panorama. let mut sizes = vec![(w, h)]; for _ in 1..levels { - let (pw, ph) = *sizes.last().expect("non-empty"); + let Some(&(pw, ph)) = sizes.last() else { break }; sizes.push((pw.div_ceil(2), ph.div_ceil(2))); } let mut acc: Vec> = sizes.iter().map(|&(lw, lh)| vec![0.0; lw * lh * ch]).collect(); @@ -1195,7 +1195,8 @@ pub fn multiband(w: usize, h: usize, imgs: &[RoiImage], weights: &[Vec], le } } // Collapse. - let mut cur = acc.pop().expect("levels ≥ 1"); + // `levels ≥ 1`, so there is always a coarsest level. + let Some(mut cur) = acc.pop() else { return (vec![0.0; w * h * ch], vec![0.0; w * h]) }; for l in (0..levels - 1).rev() { let (pw, ph) = sizes[l]; let (sw, sh) = sizes[l + 1]; diff --git a/crates/algo/src/segment/quick.rs b/crates/algo/src/segment/quick.rs index 2521b415..05644134 100644 --- a/crates/algo/src/segment/quick.rs +++ b/crates/algo/src/segment/quick.rs @@ -108,6 +108,8 @@ pub fn segment(img: &RgbImage, seeds: &[bool]) -> (Gmm, Gmm, Vec) { /// A near-uniform density over the RGB cube. pub fn broad_model() -> Gmm { let corners: Vec<[f32; 3]> = (0..8).map(|i| [(i & 1) as f32, ((i >> 1) & 1) as f32, ((i >> 2) & 1) as f32]).collect(); + // Eight fixed, distinct samples: the fit cannot fail. + #[allow(clippy::expect_used)] Gmm::fit(&corners, 1, 0.0).expect("non-degenerate") }