src/docs/flow-image-translation.md
Smart 分段回退策略。STranslate/ViewModels/ImageTranslateWindowViewModel.cs
ExecuteAsync(Bitmap):图片翻译窗口主执行命令。ApplyLayoutAnalysis(OcrResult):按分段模式生成 OcrLayoutBlock。GenerateTranslatedImage(IReadOnlyList<OcrLayoutBlock>, BitmapSource?):擦除原文并覆盖译文。RefreshSelectableOcrWords():在原文标注图和译文结果图之间切换图片文本选中数据源。STranslate/Views/ImageTranslateWindow.xaml / ImageTranslateCompactWindow.xaml
Standalone:原独立窗口,保留服务、语言、文本框和完整工具栏。Compact:无标题精简窗口,图片区贴回截图选区,底部预留悬浮核心按钮区。STranslate/Core/Screenshot.cs
GetScreenshotCaptureAsync():调用 ScreenGrabber.CaptureWithRegionAsync,截图时直接回传选区物理坐标,无需事后反推。padImage: false,关闭 ScreenGrab 对 <64px 小截图的背景画布 padding 扩展,保证 bitmap.Size == 选区物理尺寸,避免贴回时 Viewbox 把 padding 图缩放导致原始内容缩小;其他窗口模式保留默认 padding 行为。STranslate/Core/OcrLayoutAnalyzer.cs
AnalyzeBlocks(OcrResult, LayoutAnalysisMode):分段逻辑入口。Auto / Provider / Smart / NoMerge:图片翻译分段策略。STranslate/Core/OcrLayoutBlock.cs
STranslate/Core/ImageTranslateTextOverlayLayout.cs
STranslate/Services/OcrService.cs
GetImageTranslateOcrServices() / GetImageTranslateOcrServiceOrDefault():图片翻译 OCR 服务筛选和兜底。STranslate/Services/TranslateService.cs
ImageTranslateService:图片翻译专用翻译服务。STranslate.Plugin/IOcrPlugin.cs
IOcrPlugin.SupportBoxPoints()、OcrRequest、OcrResult、BoxPoint。IScreenshot.GetScreenshotCaptureAsync() 调用 ScreenGrabber.CaptureWithRegionAsync,截图时即回传选区物理坐标;精简窗口优先按该坐标贴回选区,仅异常情况下回退到光标附近定位。Settings.ImageTranslateWindowMode 决定使用 ImageTranslateWindow 还是 ImageTranslateCompactWindow 承载同一个 ImageTranslateWindowViewModel。ImageTranslateWindowViewModel.ExecuteAsync(bitmap) 清空旧状态,缓存 _sourceImage 并显示原图。OcrService.GetImageTranslateOcrSvcOrDefault()。候选服务必须实现 IOcrPlugin,并让 SupportBoxPoints() 返回 true。OcrRequest(data, Settings.OcrLanguage, bitmap.Width, bitmap.Height),插件必须返回图片像素坐标 BoxPoints。Utilities.PrepareOcrResult();如果插件只填充结构化 Regions,宿主会投影出兼容的 OcrContents。OcrWordBuilder.CreateFromOcrContents(_lastOcrResult.OcrContents) 生成原文选中块。ApplyLayoutAnalysis() 生成 OcrLayoutBlock,并把分析后的块投影回 OcrResult.OcrContents,供标注图、复制和结果文本复用。TranslateService.ImageTranslateService,该服务必须是 ITranslatePlugin,词典类服务不会进入图片翻译翻译列表。OcrLayoutBlock.Text 并发执行语言检测和翻译;翻译成功后用 ImageTranslateTextOverlayLayout.NormalizeOverlayText() 收敛空白,再回写到对应 block。LineBoxPoints 擦除原文,再按覆盖策略绘制译文。Settings.IsImTranShowingAnnotated 控制显示标注图还是结果图;图片文本选中同步切换为原文块或译文块。Standalone 是默认模式,保留当前可缩放、可调整大小的独立窗口。Compact 使用无标题、不可缩放、非任务栏、完全透明窗口,窗口本身无背景色;屏幕上只看到截图内容 + 悬浮按钮条(按钮条自带半透明胶囊背景)。ImageTranslateCompactWindowPlacement.CreateLayout,返回窗口矩形、图片偏移、按钮条位置与 ToolbarSide(Below/Above/Overlay),由 ImageTranslateCompactWindow.ApplyLayoutToVisualTree 换算成 DIP 应用到 ImageZoom 与按钮条 Border。Esc、点击窗口外部或再次触发图片翻译关闭;右键菜单和窗口内部文字选择不会触发外部关闭。Settings.IsImTranShowingTextControl 只影响独立窗口。Auto:默认模式。OCR 返回结构化 Regions 时使用 Provider 段落;没有结构化分段时回退 Smart。Provider:只使用服务商结构化 Regions -> Paragraphs -> Lines;缺失结构化分段时退化为 NoMerge,不自行猜段落。Smart:本地智能分段。适用于只返回扁平 OcrContents 但有坐标框的 OCR。NoMerge:保留 OCR 原始块,适合用户希望逐块翻译或服务商块已经足够稳定的场景。Smart 只在宿主内部生效,不改变插件接口和外部枚举。
BuildLineSegments() 先按 Y 位置恢复视觉行,并按横向间距拆成行内 segment。File Explorer Add-ons File Locksmith 这类同一行跨单元格误合并。BuildLayoutRegions() 按列/区域相似度聚合,避免不同栏之间链式吞并。AnalyzeRegion() 在 region 内合并 paragraph;普通段落、PDF 连续行、多列正文和英文断词续行继续使用原段落合并规则。TableLike:至少多行、多列、多个视觉行有横向 peers,并且列左边缘或中心点在多行重复对齐。TableLike region 内禁止跨视觉行继续追加为同一 paragraph,所以功能列表、表格单元格默认按每个视觉行/单元项独立翻译。图片翻译对 OCR 插件的要求比普通 OCR 更高:
IOcrPlugin.SupportBoxPoints() 并返回 true。BoxPoints。OcrResult.OcrContents,宿主会用 Smart 分段。OcrResult.Regions。paragraph=true 获取 paragraphs_result.words_result_idx,再把对应 words_result 行组装成 OcrRegion -> OcrParagraph -> OcrContent。OcrResult.OcrContents 仍是兼容旧插件和旧调用链的扁平结果;结构化插件可以同时填充它,也可以只填充 Regions。OcrRequest.PixelWidth / PixelHeight 换算成图片像素坐标后再写入 BoxPoints。Auto 模式下,结构化 OCR 的 Provider 段落优先级高于本地 Smart,所以插件返回的 Regions 会直接影响分段粒度。插件侧应尽量让 Paragraphs 表示真实语义段落或表格单元项,而不是把整列/整表合成一个 paragraph。
OcrLayoutBlock.LineBoxPoints,尽量只擦除原文行;缺少行框时退回 block 外接框。ImageZoom 使用 OcrWords 模拟图片上的文本选中。OcrWords 来自原始 OCR 坐标和原文文本。OcrWords 来自翻译后的 OcrLayoutBlock,复制时拿到的是译文。ServiceSettings.ImageTranslateOcrSvcID,由图片翻译窗口的 OCR 选择写入。ServiceSettings.ImageTranslateSvcID,由图片翻译窗口的翻译服务选择写入。Settings.ImageTranslateWindowMode 控制图片翻译结果使用独立窗口或精简窗口,默认 Standalone。Settings.LayoutAnalysisMode 是分段模式配置,默认 Auto,序列化支持 auto、provider、smart、noMerge;旧未知值归一为 Auto。Settings.IsImTranShowingAnnotated 控制标注图/结果图显示。Settings.IsImTranShowingTextControl 控制图片翻译窗口文本区域显示。Settings.ImageTranslateSourceLang / ImageTranslateTargetLang 控制图片翻译语言。Settings.ShowImageTranslateItemInNotifyIconMenu 控制托盘菜单是否显示图片翻译入口。Helper.PromptConfigureService() 弹出配置提示并定位到 OcrPage。_snackbar.ShowWarning("NoTranslateService")。ImageTranslateWindowViewModel logger。LanguageDetectionFailed。TaskCanceledException,当前实现不额外弹提示。STranslate/ViewModels/ImageTranslateWindowViewModel.csSTranslate/Views/ImageTranslateCompactWindow.xamlSTranslate/Core/Screenshot.csSTranslate/Core/OcrLayoutAnalyzer.csSTranslate/Core/OcrLayoutBlock.csSTranslate/Core/ImageTranslateTextOverlayLayout.csSTranslate/Core/LayoutAnalysisModeJsonConverter.csSTranslate/Services/OcrService.csSTranslate/Services/TranslateService.csSTranslate.Plugin/IOcrPlugin.csTests/STranslate.Tests/OcrLayoutAnalyzerTests.csTests/STranslate.Tests/ImageTranslateTextOverlayLayoutTests.csOcrLayoutAnalyzer,并补 OcrLayoutAnalyzerTests。ImageTranslateTextOverlayLayout,并补 ImageTranslateTextOverlayLayoutTests。OcrResult.Regions,并确保每个 OcrContent 有图片像素坐标 BoxPoints。OcrService.IsImageTranslateOcrService() / GetImageTranslateOcrServices()。ImageTranslateWindowViewModel.OnTransFilter() 或 TranslateService.ImageTranslateService 相关逻辑。RefreshSelectableOcrWords()、OcrWordBuilder 或 ImageZoom 的选区逻辑。ImageTranslateCompactWindow 的 PlaceForCapture / PlaceOnPhysicalWindowBounds,选区物理坐标由 Screenshot.GetScreenshotCaptureAsync 经 ScreenGrab CaptureWithRegionAsync 直接回传。ImageTranslateCompactWindowPlacement.CreateLayout,并补 ImageTranslateCompactWindowPlacementTests 对应场景;按钮条尺寸/间距常量在 ImageTranslateCompactWindow(ToolbarWidth/GapH/GapV/WindowMargin)。