裁剪与除尘
裁剪工具和橡皮擦工具以两个独立面板的形式位于单帧工具栏。裁剪面板负责几何变换——纵横比、方向、90° 旋转、精细校正和翻转。橡皮擦面板负责瑕疵去除——手动修复笔刷、红外(IR)自动除尘、AI 修复(MI-GAN)以及本地 AI 灰尘与毛发检测。本页描述的所有功能均在本地运行;图像数据不会上传至任何地方。
裁剪与变换
裁剪面板在点击单帧工具栏中的裁剪工具后打开。图像上的裁剪框是实时的:拖动任意边或角可调整大小,拖动框内可平移。拖动时按住 Shift 可锁定纵横比。按 Enter(或点击框外)确认裁剪;按 Esc 放弃更改。
纵横比下拉菜单允许将裁剪框约束为固定比例。预设按胶片格式分组:
- 原始 —— 无约束,裁剪框可为任意形状(预设 id
"original",ratio: null)。 - 135 —— 36 × 24(3:2)。
- 120 —— 6 × 4.5(4:3)、6 × 6(1:1)、6 × 7、6 × 8、6 × 9。
- 大画幅 —— 4 × 5、5 × 7、8 × 10。
- 屏幕 · 打印 —— 1 × 1、16 × 9、16 × 10、8.5 × 11。
选择预设后,裁剪框立即吸附到该比例。若随后手动调整框的大小,纵横比将变为 "custom"(仅在激活时显示于下拉菜单中)。保存在 CropRect 的 aspect 字段中(预设 id 字符串)。
方向按钮(横向/纵向图标)交换约束比例的宽高——例如将横向 3:2 的框切换为纵向 2:3。当前方向存储于 CropRect 的 orientation: "landscape" | "portrait" 字段。
变换行包含四个图标按钮:
- 向左旋转(⌘/Ctrl [)—— 将图像逆时针旋转 90°。每次点击使
rot90减 1(模 4);范围为 0–3 个顺时针四分之一圈。 - 向右旋转(⌘/Ctrl ])—— 顺时针旋转 90°,使
rot90加 1(模 4)。 - 水平翻转 —— 将图像左右镜像,切换
flipH。 - 垂直翻转 —— 上下镜像,切换
flipV。
翻转与旋转相互关联:后端按照翻转先于四分之一圈旋转的顺序执行(flip_h → flip_v → rot90 顺时针),因此对已旋转的图像进行翻转时会正确切换对应轴,不影响旋转计数。
校正滑块提供 −45° 至 +45° 的精细旋转调整,步进 0.1°,双击数值可重置为 0。该值存储于 CropRect 的 angle 字段。它以源图像中心为轴对其进行亚像素旋转(在裁剪框采样之前),不影响裁剪框尺寸。
重置按钮将所有裁剪设置清除为全帧原始状态:rect 恢复为 {x:0, y:0, w:1, h:1},rot90 归零,flipH/flipV 设为 false,angle 清零,aspect 恢复为 "original"。不影响任何其他显影参数。
每张图像写入磁盘的完整裁剪数据模型(CropRect)包含:rect(归一化矩形,x、y、w、h 各在 0–1 范围内)、aspect(预设 id 字符串)、orientation、rot90(0–3)、flipH(布尔值)、flipV(布尔值)和 angle(度数)。通过 api.saveCrop() 持久化。
深入原理
方向变换顺序(convert.rs):后端方向处理流程为 flip_h → flip_v → rot90 顺时针四分之一圈旋转。前端 transforms.ts 与此保持一致,确保 GPU 预览覆盖层与渲染输出完全匹配。当 rot90 为奇数(1 或 3)时,在显示视图上沿某轴翻转,等价于在预旋转图像上沿另一轴翻转,因此 flipOrient() 同时对 rot90 mod 4 取反以保持显示裁剪框对齐:rot90_new = (4 − rot90) % 4,并切换对应的 flipH/flipV 标志。
归一化矩形数学:rotateRectCW(r) 将 {x, y, w, h} 映射为 {x: 1−y−h, y: x, w: h, h: w},rotateRectCCW 映射为 {x: y, y: 1−x−w, w: h, h: w}。校正 angle 以裁剪窗口采样前源图像中心为轴旋转,因此裁剪框始终对应旋转后的坐标空间。传递给后端的格式为:image_crop: [x, y, w, h](归一化四元组)、rot90、flip_h、flip_v 和 angle。
手动橡皮擦笔刷
橡皮擦面板从单帧工具栏打开。手动笔刷允许在单个灰尘斑点或划痕上涂抹,随即完成修复(或通过 MI-GAN——详见下文)。
笔刷大小滑块设置归一化到图像宽度的笔刷半径,范围 0.005(极小)至 0.2(大)。显示值为半径占图像宽度的百分比。也可在图像上滚动鼠标滚轮实时调整笔刷大小。每次点击或拖动记录一个 DustStroke:归一化点的折线加半径 r。按 ⌘Z(macOS)撤销最后一笔。笔迹存储于 DustEdits.strokes,通过 api.saveDust() 持久化。
在正常模式下,每次笔迹在松开指针时即在 GPU 预览中实时修复。修复区域以内容感知克隆算法根据周围纹理混合融合。
显示修复点复选框(字段 showSpots)在每个已提交笔迹的质心处显示橡皮擦图标标记,便于查看并点击删除单个斑点。点击标记可立即删除对应笔迹。
缩放到区域按钮启动框选缩放:在图像上拖动矩形可将该区域放大以便精细操作。放大后按钮变为重置视图以返回全图。
重置按钮清除所有手动笔迹(DustEdits.strokes → [])并重置 AI 已应用标志。不影响红外去除或自动除尘设置。
深入原理
笔迹模型(dust.ts):DustStroke 的结构为 { points: DustPoint[], r: number },其中每个 DustPoint 为 { x: number, y: number }(在显示图像归一化坐标空间中,两轴均在 0–1 范围内),r 为归一化到显示图像宽度的笔刷半径。笔迹质心(strokeCentroid())为所有点的算术平均值,作为修复点标记的锚点。传递给后端的格式:每条笔迹序列化为 { points: [[x,y], …], r }(二元组,非对象),通过 api.ts 中的 wireDust() 处理。单点删除使用 removeStrokeAt(dust, i),按索引过滤笔迹数组并清除 aiApplied,使待处理的 MI-GAN 蒙版须重新应用。屏幕像素半径 = r × 图像宽度像素 × 缩放系数。
AI 填充(MI-GAN)
启用 AI 填充(MI-GAN)复选框后,笔刷切换为蒙版模式。笔迹不再实时修复,而是在图像上显示为半透明红色叠加层,精确标示将被修复的区域。满意后点击 AI 擦除运行 MI-GAN——一个机器修复模型,根据周围上下文重建蒙版区域的像素。该模型在本地运行,图像数据不会离开您的计算机。
AI 擦除按钮仅在存在未提交笔迹且当前蒙版尚未应用时可用。处理期间显示旋转指示器并标注"擦除中…"。运行成功后,aiApplied 置为 true,按钮变为非激活状态。添加或删除任意笔迹均会清除 aiApplied 并重新启用按钮,以便对新蒙版应用处理。撤销(⌘Z)会删除最后一笔并同时清除已应用标志。
深入原理
状态机(dust.ts):DustEdits.brushMigan 控制 GPU 预览是绘制实时修复还是蒙版叠加层。addStroke() 和 undoStroke() 均会重置 aiApplied = false,确保蒙版在更改后不会显示为"已完成"。"AI 擦除"分发 aiErase 事件,由父视图处理,向 MI-GAN 后端命令传入当前笔迹列表。setBrushMigan() 在模式切换时也会清除 aiApplied。
红外(IR)除尘
部分专用胶片扫描仪在 R、G、B 三通道之外还额外采集一个近红外通道。由于卤化银颗粒对红外光几乎透明,而灰尘和划痕会强烈散射红外光,因此该通道能以几乎不损失图像质量的方式提供近乎完美的除尘蒙版。
当加载的扫描包含红外平面时,去除灰尘(红外)开关可用。点击可开启或关闭红外除尘;当前状态以"开"或"关"标签显示在旁边。红外除尘激活时,灵敏度滑块(0–100,默认 50)控制将红外通道用作蒙版的激进程度。值越高去除越多(包括更细小的灰尘),但存在截断颗粒级真实细节的风险;值越低则越保守。两个字段均存储于 DustEdits.irRemoval(enabled 和 sensitivity),并作为 irRemoval 参数传递给后端渲染。
当扫描没有红外通道时,按钮被禁用并显示"即将推出"标签(提示文字为"需要红外扫描通道")。红外除尘依赖扫描仪:支持 ICE 功能的尼康 Coolscan 及美能达 Scan Multi 扫描仪可生成含红外通道的 TIFF 文件;大多数平台式扫描仪和数码单反扫描不具备此功能。
深入原理
传输格式(api.ts):红外状态通过 irRemoval: IrRemoval 参数({ enabled: boolean, sensitivity: number })传递给每次渲染调用。后端将红外平面用作修复合成的 Alpha 蒙版,根据红外信号强度按灵敏度值缩放,对重建(无尘)像素与原始像素进行混合。EraserPanel 上的 hasIr 属性由父视图在探测已加载图像的通道数后设置。
AI 灰尘与毛发自动去除
AI 灰尘与毛发去除子面板运行本地机器学习检测器,自动查找整张图像中的灰尘斑点和毛发,然后使用与手动 AI 填充相同的 MI-GAN 模型进行修复。所有处理均在本地完成——模型下载一次后存储在您的设备上,图像不会上传。
首次打开此面板时,OpenEnlarge 会检查 AI 模型是否已安装。若未安装,将显示下载提示及大致模型大小(MB)。点击下载 AI 模型进行下载,进度条实时显示进度。安装完成后,面板显示灵敏度滑块(0–100,默认 50)和检测并去除按钮。
灵敏度滑块控制检测器将像素标记为瑕疵的激进程度。值越高,检测到的斑点越多、越小;值越低,仅标记明显瑕疵。滑块在松开指针时提交(非拖动过程中),触发检测和修复的重新运行。灵敏度存储于 DustEdits.autoDust.sensitivity。
点击检测并去除对当前图像运行完整的检测与修复流程。处理期间按钮显示旋转指示器并被禁用。完成后,提示消息报告去除的不重复斑点数量(若图像干净则提示"未发现灰尘")。切换状态 DustEdits.autoDust.enabled 控制自动修复是否在主预览中显示。自动检测到但希望保留的斑点,可在"显示修复点"叠加层中点击排除——这些排除项存储于 DustEdits.autoDustExclusions。
深入原理
API(api.ts):api.autodustStatus() 返回 { installed: boolean, downloadBytes: number }。api.downloadAutodust() 触发模型下载;进度通过 Tauri 事件 autodust://download-progress({ received, total } 字节)流式传输。检测运行完成后,后端发出 autodust://result,携带 { count: number }——去除的不重复斑点数。autodustInstalled store(store.ts)在面板挂载间缓存安装状态,避免下载提示重复出现。DustEdits 中的自动除尘状态:autoDust: { enabled: boolean, sensitivity: number };排除点:autoDustExclusions: DustPoint[](每个为归一化 { x, y } 质心,通过 addExclusion() 添加)。