Reuse the face grid's decoded crops across a redraw

A confirm or a reject changes one row and redraws the whole grid, and the
redraw re-read every crop blob of the selected person (4 MB for the
largest) and decoded every one — 316 ms per click on the reference
library's 754-face person, to arrive at the pixels already on screen.

`load_faces` now takes the crops the previous load decoded, keyed by face,
and moves each into its new cell; the blob read is skipped when every face
is already in hand. `refresh` drains the old cells into it rather than
cloning them. The redraw is 2.6 ms.
This commit is contained in:
2026-09-20 10:56:36 +02:00
parent e0e193efb4
commit 97a854833d
4 changed files with 53 additions and 11 deletions
+11 -1
View File
@@ -260,7 +260,17 @@ pub fn refresh(
match (ctl.selected.get(), store.as_deref()) {
(Some(person), Some(store)) => {
let cells = identity::load_faces(cat, store, person).unwrap_or_else(|e| {
// The crops the grid is showing now, handed over to be reused
// rather than decoded again — see `load_faces`. Drained, not
// cloned: a crop is 64 KB of pixels and the largest groups hold
// hundreds.
let cut = ctl
.faces
.borrow_mut()
.drain(..)
.filter_map(|c| Some((c.face, c.crop?)))
.collect();
let cells = identity::load_faces(cat, store, person, cut).unwrap_or_else(|e| {
log::warn!("identity: reading faces: {e}");
Vec::new()
});