图像处理滤镜应用 - 技术说明文档

8 阅读5分钟

1. 项目概述

本项目是一个基于 Unity 引擎开发的跨平台图像处理与滤镜应用。它允许用户加载本地图片,实时应用多种基于 GPU Shader 的后处理效果(如卡通化、高斯模糊等),并通过动态生成的 UI 界面调整参数。程序支持撤销/重做操作,并提供了完善的文件保存与分享功能,能够无缝运行于 Unity 编辑器、PC (Windows/Mac) 以及移动端 (Android/iOS)。

核心特性

  • 实时滤镜预览:利用 GPU 加速,参数调整即时生效。
  • 动态 UI 生成:基于 C# 反射和特性(Attributes)自动构建参数控制面板。
  • 完善的命令系统:支持多步撤销(Undo)和重做(Redo)。
  • 跨平台文件交互:抽象化的文件选择器,适配各平台原生对话框及相册权限。
  • 稳健的资源管理:自定义 Shader 加载策略,确保打包后资源不丢失;严格的内存清理机制。

2. 系统架构设计

程序采用分层架构,主要包含 控制层 (Controller)核心逻辑层 (Core Logic)视图层 (View/UI)基础设施层 (Infrastructure)

2.1 架构图解

graph TD
User[用户] --> ImageAppController[ImageAppController]

subgraph "控制层(Controller)"
    ImageAppController --> ParamCommandMgr[ParamCommandMgr]
    ImageAppController --> FilePickerMgr[FilePickerMgr]
    ImageAppController --> ParameterUIController[ParameterUIController]
end

subgraph "核心逻辑层(Core)"
    ImageAppController --> ImageData(ImageData)
    ImageAppController --> ImageProcessor[ImageProcessor]
    ImageProcessor --> ToonProcessor[ToonProcessor]
    ImageProcessor --> GaussianBlurProcessor[GaussianBlur]
    ImageProcessor --> ProcessorFactory[ProcessorFactory]
end

subgraph "视图层(View)"
    ParameterUIController --> UIControls[动态UI控件]
    ImageAppController --> ImageViewer[ImageViewer]
end

subgraph "基础设施(Infra)"
    FilePickerMgr --> IFilePicker[接口抽象]
    IFilePicker --> StandaloneFilePicker(PC/Editor 实现)
    IFilePicker --> MobileFilePicker[Mobile 实现]
    ImageProcessor --> ShaderDataMgr[ShaderDataMgr]
    ImageAppController --> MainThreadDispatcher[主线程调度器]
    ImageAppController --> ImageExporter[图像导出/分享]
end

3. 核心模块详解

3.1 应用程序控制器 (ImageAppController)

作为程序的入口和协调者,负责管理应用的生命周期。

  • 职责
    • 初始化各个单例管理器(Shader, Command, FilePicker)。
    • 协调图像加载、处理、保存的流程。
    • 管理 ImageData(原图与处理后图片)的生命周期。
    • 响应用户界面事件(加载按钮、保存按钮、切换滤镜)。
  • 关键流程
    1. 用户点击加载 -> 调用 FilePickerMgr -> 获取路径。
    2. 通过 MainThreadDispatcher 异步加载图片到 ImageData
    3. 加载成功后,自动触发当前 ImageProcessor 进行处理。

3.2 动态参数与 UI 系统

这是本程序最灵活的部分,实现了代码即配置

A. 参数定义 (ParameterAttribute)

开发者只需在 ImageProcessor 子类中定义字段并添加特性,即可自动生成 UI。

  • 特性示例
    • [FloatParameter("模糊强度", Min=0, Max=20)] -> 生成滑块。
    • [ColorParameter("边缘颜色")] -> 生成颜色选择器。
    • [DropdownParameter("模式", "A", "B", "C")] -> 生成下拉菜单。
    • [BoolParameter("启用开关")] -> 生成开关 Toggle。

B. UI 控制器 (ParameterUIController)

  • 反射机制:启动时扫描当前处理器的字段,读取 ParameterAttribute
  • 动态实例化:根据属性类型(Float, Color, Int 等),从预制体池中实例化对应的 ParameterUIControl(如 FloatSliderControl, ColorPickerControl)。
  • 数据绑定:UI 控件的值变化会自动触发 ParamCommandMgr 记录命令,并更新处理器中的字段值,进而驱动 Shader 更新。

3.3 图像处理引擎 (ImageProcessor)

所有滤镜的基类,封装了 Shader 处理的通用逻辑。

  • 工作流程
    1. 初始化:通过 ShaderDataMgr 加载指定的 Shader 并创建 Material。
    2. 参数同步ApplyParametersToShader() 方法遍历所有参数字段,将 C# 变量的值映射到 Shader 的 Uniform 变量(如 _BlurSize, _EdgeColor)。
    3. 执行渲染:调用 Graphics.Blit,将输入纹理通过 Material 渲染到输出 RenderTexture。
  • 扩展性:新增滤镜只需继承 ImageProcessor,添加 [ProcessorInfo] 特性定义元数据,编写特定的 Shader 逻辑即可,无需修改 UI 代码。

3.4 命令管理系统 (ParamCommandMgr)

实现了标准的命令模式 (Command Pattern),提供专业级的编辑体验。

  • 结构:维护 UndoStackRedoStack
  • 操作
    • 每次参数改变(如拖动滑块结束),创建一个 ParameterChangeCommand 压入撤销栈。
    • 执行 Undo() 时,弹出栈顶命令,调用其 Undo() 方法恢复旧值,并将命令压入重做栈。
    • 支持批量命令(BatchCommand)和重置命令(ResetAllCommand)。

3.5 跨平台文件系统 (FilePickerMgr & IFilePicker)

解决了 Unity 在不同平台文件 IO 的差异性问题。

  • 工厂模式FilePickerFactory 根据编译符号(UNITY_ANDROID, UNITY_STANDALONE_WIN 等)动态创建具体的实现类。
  • 实现策略
    • PC/Editor: 使用 StandaloneFileBrowser 插件或 EditorUtility 调用系统原生文件对话框。
    • Mobile: 使用 NativeGallery 调用系统相册,并自动处理 Android/iOS 的运行时权限请求。
  • 统一接口:上层业务代码只需调用 OpenFilePickerAsync,无需关心底层平台差异。

3.6 资源与线程管理

  • ShaderDataMgr
    • 提供多重加载策略:先查缓存 -> 再试内置 Shader -> 尝试 Resources 加载 -> 尝试变体名称。
    • 解决打包后 Shader 丢失或命名不一致的问题。
  • MainThreadDispatcher
    • 由于文件 IO 和某些 Unity API 必须在主线程执行,该组件维护一个动作队列,确保异步任务的结果安全地回传到主线程更新 UI 或纹理。
  • ImageData
    • 封装 Texture2D,强制确保纹理可读(isReadable = true)以便进行 CPU 端编码保存。
    • 实现 IDisposable 接口,显式管理纹理内存,防止泄漏。

4. 关键业务流程

4.1 滤镜处理流程

  1. 用户在 UI 上调整参数(例如:增加模糊度)。
  2. FloatSliderControl 捕获输入,调用 ParamCommandMgr.ExecuteParameterChange
  3. 命令管理器记录旧值和新值,执行新值。
  4. 触发 ParameterInfo.OnValueChangedEvent
  5. ParameterUIController 接收到事件,调用 processor.SetParameter
  6. 处理器更新 Material 的 Shader 属性。
  7. 触发延迟预览(防抖动),调用 Graphics.Blit 重新渲染图像。
  8. 更新 displayImage 显示结果。

4.2 图片保存流程

  1. 用户点击“保存”。
  2. ImageAppController 调用 FilePickerMgr.OpenSaveFileDialogAsync
  3. 根据平台弹出保存对话框或准备相册保存路径。
  4. 用户确认路径后,回调 OnFileSaved
  5. ImageExporterImageData 中的纹理编码为 PNG/JPG 字节流。
  6. 异步写入文件或保存到系统相册。
  7. 反馈保存结果给用户。