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(原图与处理后图片)的生命周期。 - 响应用户界面事件(加载按钮、保存按钮、切换滤镜)。
- 关键流程 :
- 用户点击加载 -> 调用
FilePickerMgr-> 获取路径。 - 通过
MainThreadDispatcher异步加载图片到ImageData。 - 加载成功后,自动触发当前
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 处理的通用逻辑。
- 工作流程 :
- 初始化 :通过
ShaderDataMgr加载指定的 Shader 并创建 Material。 - 参数同步 :
ApplyParametersToShader()方法遍历所有参数字段,将 C# 变量的值映射到 Shader 的 Uniform 变量(如_BlurSize,_EdgeColor)。 - 执行渲染 :调用
Graphics.Blit,将输入纹理通过 Material 渲染到输出 RenderTexture。
- 初始化 :通过
- 扩展性 :新增滤镜只需继承
ImageProcessor,添加[ProcessorInfo]特性定义元数据,编写特定的 Shader 逻辑即可,无需修改 UI 代码。
3.4 命令管理系统 (ParamCommandMgr)
实现了标准的命令模式 (Command Pattern),提供专业级的编辑体验。
- 结构 :维护
UndoStack和RedoStack。 - 操作 :
- 每次参数改变(如拖动滑块结束),创建一个
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 的运行时权限请求。
- PC/Editor : 使用
- 统一接口 :上层业务代码只需调用
OpenFilePickerAsync,无需关心底层平台差异。
3.6 资源与线程管理
- ShaderDataMgr :
- 提供多重加载策略:先查缓存 -> 再试内置 Shader -> 尝试 Resources 加载 -> 尝试变体名称。
- 解决打包后 Shader 丢失或命名不一致的问题。
- MainThreadDispatcher :
- 由于文件 IO 和某些 Unity API 必须在主线程执行,该组件维护一个动作队列,确保异步任务的结果安全地回传到主线程更新 UI 或纹理。
- ImageData :
- 封装
Texture2D,强制确保纹理可读(isReadable = true)以便进行 CPU 端编码保存。 - 实现
IDisposable接口,显式管理纹理内存,防止泄漏。
- 封装
4. 关键业务流程
4.1 滤镜处理流程
- 用户在 UI 上调整参数(例如:增加模糊度)。
FloatSliderControl捕获输入,调用ParamCommandMgr.ExecuteParameterChange。- 命令管理器记录旧值和新值,执行新值。
- 触发
ParameterInfo.OnValueChangedEvent。 ParameterUIController接收到事件,调用processor.SetParameter。- 处理器更新 Material 的 Shader 属性。
- 触发延迟预览(防抖动),调用
Graphics.Blit重新渲染图像。 - 更新
displayImage显示结果。
4.2 图片保存流程
- 用户点击"保存"。
ImageAppController调用FilePickerMgr.OpenSaveFileDialogAsync。- 根据平台弹出保存对话框或准备相册保存路径。
- 用户确认路径后,回调
OnFileSaved。 ImageExporter将ImageData中的纹理编码为 PNG/JPG 字节流。- 异步写入文件或保存到系统相册。
- 反馈保存结果给用户。