Skip to content

Commit f4160f9

Browse files
committed
feat: discover standard tesseract installs
1 parent ccb1948 commit f4160f9

3 files changed

Lines changed: 34 additions & 2 deletions

File tree

docs/snow-shot-alignment-plan.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Pin、截图历史、二维码、可选 OCR/翻译、滚动截图和 FFmpeg 录
3939
| 历史 | 缩略图、相对时间、关键词搜索、来源筛选(含 Selection、Scrolling、Full screen 和 Pinned)、展开、单项动作、批量删除和键盘导航选择已具备;300 条真实记录默认仅渲染 5 条预览,重启截图与内存复核通过 | 暂无未覆盖的 P1 工作流差距;继续保留长期增长观察 | P1(完成) |
4040
| 设置主页 | 分组页面、深浅主题、状态反馈和面向 Capture/Library/Record/App 的任务导航已具备;深浅主题语义前景色在背景和面板上均由自动测试保证至少 4.5:1 对比度;深色/浅色 980x760、浅色 520x640 和深浅色最小 420x420 的 Release 原生截图复核通过;设置探针现在可按零基显示器索引定位目标 DPI | 150%/200% 缩放下的最终实机复核仍需完成 | P1 |
4141
| 保存 | PNG/JPEG/WebP 导出、快速保存、项目 sidecar、默认目录和命名配置已具备;设置页的 `Check folder` 与新目录选择都会先验证当前目录能创建、同步并清理私有探针文件;首选历史目录失效时,选择、全屏和 Pin 快速保存会回退到托管目录并同步历史索引 | 不同 Windows profile 下的目录权限和命名仍需手工复核 | P2 |
42-
| 高级能力 | OCR、翻译、滚动截图和录屏、环境检查及失败恢复已具备;录屏停止请求现在有独立 `Stopping` 状态,收尾期间禁用重复停止/暂停/切换目标;设置页的 `Test service` 只在用户显式点击且配置 HTTPS 端点时发送固定短语,并仅显示返回长度;`recognition-acceptance` 默认只读报告 OCR/翻译依赖,显式 `--ocr-image``--translation-text` 才会执行真实链路并仅写入长度元数据;生产录屏后端的显示器、窗口、区域与暂停/恢复/停止已由 `recording-acceptance` 验收探针生成 MP4 并通过 `ffprobe` | 翻译真实端点与 UI 成功态仍需验收,完整录屏 UI 手工矩阵仍需执行 | P2 |
42+
| 高级能力 | OCR、翻译、滚动截图和录屏、环境检查及失败恢复已具备;OCR 保留 `FLASH_SHOT_TESSERACT` 覆盖,同时自动识别 Windows 常见 Tesseract 安装路径;录屏停止请求现在有独立 `Stopping` 状态,收尾期间禁用重复停止/暂停/切换目标;设置页的 `Test service` 只在用户显式点击且配置 HTTPS 端点时发送固定短语,并仅显示返回长度;`recognition-acceptance` 默认只读报告 OCR/翻译依赖,显式 `--ocr-image``--translation-text` 才会执行真实链路并仅写入长度元数据;生产录屏后端的显示器、窗口、区域与暂停/恢复/停止已由 `recording-acceptance` 验收探针生成 MP4 并通过 `ffprobe` | 翻译真实端点与 UI 成功态仍需验收,完整录屏 UI 手工矩阵仍需执行 | P2 |
4343

4444
## 4. 实施阶段
4545

docs/windows-manual-acceptance.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ cargo run --release --bin settings-ui-acceptance -- light 520 640 target/ui-acce
141141
| 2026-08-10 | `current-scroll-portable-20260810` | 当前主线滚动截图专项测试 19 项通过;Release `scroll-acceptance` 通过 6 帧、5 个 90 像素重叠区的确定性拼接,输出 96x630,像素校验和为 `2267123376996061824`;最新 Windows 便携包结构、SHA-256、隔离 profile 启动冒烟、fixture 和安装器配置校验均通过。 | 待执行 | 滚动截图可从选区工具栏的更多操作启动,支持手动追加、辅助滚动追加、失败重试、完成拼接和导出;便携包 `target/portable-current/FlashShot-0.1.0-windows-x86_64.zip` 的 SHA-256 为 `b1f0cf1fd09373bf5c6870f756affcd64b2cdb2d67acbaebae1338641e677d6a`(见同目录 `.sha256`,校验值完整记录在文件中)。真实滚动 UI、150%/200% 缩放、双屏和完整录屏 UI 手工矩阵仍待执行。 |
142142
| 2026-08-10 | `current-environment-followup` | 当前 Release 环境探针通过:检测到单块 `DISPLAY1`(2560x1440、DPI 96、scale 1.0),FFmpeg 9.0 可用并支持 `gdigrab`、窗口和区域输入;Tesseract 5.5.3 已安装并通过 `FLASH_SHOT_TESSERACT` 指向 `C:\Program Files\Tesseract-OCR\tesseract.exe`;识别就绪探针的 `--require-ocr` 门禁通过。 | 待执行 | 机器可读证据位于 `target/windows-acceptance-environment-20260810-followup.json``target/ui-acceptance/recognition-acceptance-ocr-ready.json``target/ui-acceptance/recognition-acceptance-ocr-ready-default.json`。翻译端点未配置;OCR/翻译真实 UI、150%/200% 缩放、双屏和完整录屏 UI 仍不标记为通过。 |
143143
| 2026-08-10 | `current-ocr-fixture` | Release `recognition-acceptance` 使用含文字的 `settings-current-dark-520x640.png` 执行完整 PNG -> Tesseract OCR;schema 3 报告中 `ocr.available``ocr_exercise.passed``--require-ocr` 均通过,识别文本只保留长度元数据(391 个字符)。 | 待执行 | 报告位于 `target/ui-acceptance/recognition-acceptance-ocr-fixture.json`。这证明本地 OCR 调用链可用,不替代含文字选区的真实 UI 复核、翻译服务失败后重试或滚动截图手工矩阵。 |
144+
| 2026-08-10 | `current-ocr-auto-discovery` | OCR 可执行文件发现现在保留 `FLASH_SHOT_TESSERACT` 覆盖,并自动尝试 Windows 常见安装路径;在未设置该环境变量且 `tesseract` 不在 PATH 的当前机器上,Release `recognition-acceptance --require-ocr --ocr-image` 自动发现 `C:\Program Files\Tesseract-OCR\tesseract.exe`,schema 4 的 OCR 检查与真实 PNG -> Tesseract 练习均通过,文本长度为 391。 | 待执行 | 报告位于 `target/ui-acceptance/recognition-acceptance-ocr-auto-discovery.json`。这关闭了本机 OCR 依赖配置缺口,但不替代含文字选区的真实 UI 复制与翻译服务手工矩阵。 |
144145
| 2026-08-10 | `current-scroll-acceptance-20260810` | 当前 Release `scroll-acceptance` 重新通过 6 帧、5 个 90px 重叠区的确定性滚动拼接,输出 96x630,像素校验和为 `2267123376996061824`| 待执行 | 报告位于 `target/ui-acceptance/scroll-acceptance-20260810-current3.json`;这确认滚动截图的重叠匹配、失败可重试和最终拼接链路可用,但真实目标应用滚动 UI、150%/200% 缩放和双屏仍需手工矩阵。 |
145146
| 2026-08-10 | `current-ui-acceptance-4` | 当前 Release 设置页按 Capture、Library、Record、App 顺序串行生成深色/浅色 520x640 截图,并额外复核深色 Library 420x420 最小窗口;100% DPI 下导航、主动作、状态栏和滚动内容均保持可达,没有发现文字截断或控件重叠。 | 待执行 | 截图证据位于 `target/ui-acceptance/settings-current4-dark-capture-520x640.png``settings-current4-dark-library-520x640.png``settings-current4-light-record-520x640.png``settings-current4-light-app-520x640.png``settings-current4-dark-library-420x420.png`;150%/200% 缩放、双屏和覆盖层真实交互仍需手工矩阵。 |
146147
| 2026-08-10 | `current-release-gates-4` | 当前 Release 工作区全目标构建通过;`scroll-acceptance` 通过 6 帧、5 个 90px 重叠区,`recognition-acceptance --require-ocr --ocr-image` 通过真实 PNG -> Tesseract 调用链(schema 3,文本长度 371)。 | 待执行 | 报告位于 `target/ui-acceptance/scroll-acceptance-20260810-current4.json``target/ui-acceptance/recognition-acceptance-ocr-current4.json`;翻译端点未配置,滚动/OCR 的真实 UI 手工矩阵仍需执行。 |

src/ocr.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ const TESSERACT_PATH_ENV: &str = "FLASH_SHOT_TESSERACT";
1616
const TESSERACT_LANGUAGE_ENV: &str = "FLASH_SHOT_OCR_LANGUAGE";
1717
const OCR_COMMAND_TIMEOUT: Duration = Duration::from_secs(20);
1818

19+
#[cfg(windows)]
20+
const WINDOWS_TESSERACT_PATHS: [&str; 2] = [
21+
r"C:\Program Files\Tesseract-OCR\tesseract.exe",
22+
r"C:\Program Files (x86)\Tesseract-OCR\tesseract.exe",
23+
];
24+
1925
/// Read-only local OCR readiness information used before the user begins a capture workflow.
2026
#[derive(Clone, Debug, Eq, PartialEq)]
2127
pub struct OcrSupport {
@@ -144,8 +150,21 @@ fn wait_for_child(child: &mut Child, timeout: Duration) -> io::Result<()> {
144150
}
145151
}
146152

153+
/// Selects an explicit executable override, common Windows install paths, or PATH lookup.
147154
fn executable_path() -> OsString {
148-
std::env::var_os(TESSERACT_PATH_ENV).unwrap_or_else(|| OsString::from("tesseract"))
155+
if let Some(configured) = std::env::var_os(TESSERACT_PATH_ENV).filter(|value| !value.is_empty())
156+
{
157+
return configured;
158+
}
159+
#[cfg(windows)]
160+
if let Some(installed) = WINDOWS_TESSERACT_PATHS
161+
.iter()
162+
.map(Path::new)
163+
.find(|path| path.is_file())
164+
{
165+
return installed.as_os_str().to_owned();
166+
}
167+
OsString::from("tesseract")
149168
}
150169

151170
fn language() -> String {
@@ -245,6 +264,18 @@ mod tests {
245264
assert_eq!(OCR_COMMAND_TIMEOUT, Duration::from_secs(20));
246265
}
247266

267+
#[cfg(windows)]
268+
#[test]
269+
fn common_windows_tesseract_paths_are_absolute_and_executable_named() {
270+
assert!(super::WINDOWS_TESSERACT_PATHS.iter().all(|path| {
271+
let path = Path::new(path);
272+
path.is_absolute()
273+
&& path
274+
.file_name()
275+
.is_some_and(|name| name.eq_ignore_ascii_case("tesseract.exe"))
276+
}));
277+
}
278+
248279
#[test]
249280
fn completed_ocr_processes_are_reaped_before_the_deadline() {
250281
let mut command = if cfg!(windows) {

0 commit comments

Comments
 (0)