Never crash: algo is panic-free (Rule 9) (#56)
- apply_tiled reads the shared image for a global filter instead of unreachable! if it were missing. - panorama: bundle-adjustment params come from the placed transforms via filter_map; the pyramid size loop and the collapse use let-else instead of expect. - inpaint/pyramid: the same while-let/let-else hunks as #40, so the two PRs merge in either order. - quick selection's constant broad model keeps one documented narrow expect (eight fixed corners always fit). - algo denies unwrap/expect/panic/unimplemented/todo/unreachable. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
f8f48db78a
commit
6dffa0894c
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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<f64> = movable.iter().flat_map(|&i| motion.to_params(&tf[i].expect("placed"))).collect();
|
||||
let mut params: Vec<f64> = 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<f32>], 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<Vec<f32>> = 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<f32>], 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];
|
||||
|
|
|
|||
|
|
@ -108,6 +108,8 @@ pub fn segment(img: &RgbImage, seeds: &[bool]) -> (Gmm, Gmm, Vec<bool>) {
|
|||
/// 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")
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue