mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-25 19:00:31 +00:00
fdad5a4ad4
Photos imported before focus points were read got one only through Reload from Disk, which
hashes whole files on the UI thread. Now:
- lightcraft_meta::focus::read_header reads only what the decoder looks at: IFD0 (Make,
Model), the Exif IFD, the maker note's IFD and the focus tags' values (a JPEG: its segments
up to the Exif one), walked round by round and decoded with the whole-file code from a
buffer of the file's length holding just those ranges. Bounded rounds, bytes (2 MB) and
size (1 GB). One 32 KB read per α1 / A7S III ARW; on 109 real files (83 with a point)
it gives the whole-file read's point for every one.
- A background job (crates/engine/src/focus_scan.rs) reads photos with no point from a
supported body (by the stored camera; nothing else is opened), ARW or JPEG, one at a
time in path order, with a "Reading focus points" activity row (Cancel::Flag). The UI's
per-frame focus.pump gives it the face scan's pace (paused while dragging or typing) and
starts it once per library opening. Commits every 200 photos or 3 s as system ops (no
undo step, no sidecar write), only meta.focus, only on photos that still have none at the
same path. "Looked, none" goes to focus-scanned.bin beside the library, headed by the
decoder's tag so a decoder knowing more bodies starts afresh; unreadable files are retried
at the next opening.
- photo.readFocusPoints {ids?, wait?} (Photo > Read Focus Points) runs it on demand.
Measured cold on a 5400 rpm USB drive: 200 α1 / A7S III ARWs in 1.9 s (~100 photos/s,
32 KB each), so 58,796 raws take about 10 minutes instead of re-reading 2.25 TB.
51 lines
2.2 KiB
Rust
51 lines
2.2 KiB
Rust
//! Focus points for photos already in the library: `photo.readFocusPoints` (Photo ▸ Read Focus Points) and the
|
||
//! per-frame `focus.pump` that keeps the background job going. The job itself is `crate::focus_scan`.
|
||
|
||
use serde_json::Value;
|
||
|
||
use super::{CommandSpec, cmd};
|
||
use crate::{Result, Session};
|
||
|
||
#[cfg(not(target_arch = "wasm32"))]
|
||
fn read_points(s: &mut Session, p: &Value) -> Result<Value> {
|
||
crate::focus_scan::read_points(s, p)
|
||
}
|
||
|
||
#[cfg(target_arch = "wasm32")]
|
||
fn read_points(_: &mut Session, _: &Value) -> Result<Value> {
|
||
Err(super::bad("photo.readFocusPoints", "reading focus points needs the photos' files on disk"))
|
||
}
|
||
|
||
#[cfg(not(target_arch = "wasm32"))]
|
||
fn pump(s: &mut Session, p: &Value) -> Result<Value> {
|
||
crate::focus_scan::pump(s, p)
|
||
}
|
||
|
||
#[cfg(target_arch = "wasm32")]
|
||
fn pump(_: &mut Session, _: &Value) -> Result<Value> {
|
||
Ok(serde_json::json!({"active": false}))
|
||
}
|
||
|
||
pub fn specs() -> Vec<CommandSpec> {
|
||
vec![
|
||
cmd!(
|
||
"photo.readFocusPoints",
|
||
"Read Focus Points",
|
||
["Photo"],
|
||
None,
|
||
"{ids?, wait?: false} → {queued, running, last?: {total, done, found, none, unavailable, bytesRead, seconds, cancelled}} — read the camera's focus point for photos imported before it was read (Sony α1 and A7S III raws and JPEGs), from the few KB of each file that hold it, on a background job with a row in the activity stack. Without `ids`, every photo in the library not looked at yet; with `ids`, those photos, looked at again. Photos that have a point keep it. No undo step and no sidecar write. `wait: true` returns when all are read (scripts)",
|
||
super::always,
|
||
read_points
|
||
),
|
||
cmd!(
|
||
query "focus.pump",
|
||
"Read Focus Points in the Background",
|
||
[],
|
||
None,
|
||
"{pace?: pause | light | normal} → {active, running?: {done, total, found}, last?, lookedAt} — cheap to call every frame (the app does): takes in what the background focus-point reader has read and commits it in batches; reads nothing new while paused and rests between files when light. Starts the reader by itself once per library opening when photos are left to look at",
|
||
super::always,
|
||
pump
|
||
),
|
||
]
|
||
}
|