algorithm - 内存有限时位图编辑器的快速撤消/重做?

标签 algorithm design-patterns optimization undo

我正在尝试为移动设备(即 Photoshop 的受限版本)编写位图编辑器。用户的文档由大约 4 个位图组成,每个位图的大小约为 1000x500。

我想要一个尽可能简单的强大且高效的撤消/重做系统。我的目标是大约 ~0.2 秒来撤消或重做编辑。我正在寻找有关我当前预期方法的一些反馈或一些我可以使用的新想法。我认为我所拥有的太复杂了,所以我对继续前进持谨慎态度,所以只要知道这是我能做的最好的事情就很好了。

我已经为我的撤消/重做系统尝试了使用命令模式和备忘录模式的组合。到目前为止,我得出的一些结论是:

  1. 我没有足够的内存,而且在许多情况下,我无法以足够快的速度将内存写入磁盘以使用备忘录来支持对上一个命令的“未执行”操作,例如如果用户非常快地完成几个单独的绘画笔画,我将无法存储代表用户绘画内容的位图而不让用户等待它们被保存。

  2. 如果我将文档恢复到其初始状态并重播除最后一个命令之外的所有命令以实现撤消,即使在执行少量命令后,这也太慢了,例如重放 10 次绘画笔画或 5 次涂抹笔画需要大约 1 秒,这太慢了。

  3. 我可以通过在后台定期将整个文档保存到磁盘并在回放命令之前恢复到此检查点来绕过前一点。要撤消比上一个检查点更早的内容,我们会重新加载在此之前的检查点并重播命令。

方法 2 和 3 工作正常,除了随着添加更多层而保存整个文档变得越来越慢,而且它已经很慢了 4 个位图(大约 5 - 10 秒等待)。因此,我需要修改 3,以便我只保存自上次以来更改的内容。

由于许多命令仅在一层上运行,因此仅保存自上次检查点以来已修改的层是有意义的。例如,如果我有 3 个初始层,我在其中指示了可能保存检查点的位置,我的命令堆栈可能看起来像这样。

(Checkpoint1: Save layer 1, 2 and 3.)
Paint on layer 1
Paint on layer 1
(Checkpoint2: Save layer 1. Reuse saved layers 2 and 3 from Checkpoint1.)
Paint on layer 2
Paint on layer 2
(Checkpoint3: Save layer 2. Reuse saved layers 1 and 3 from Checkpoint2.)
Paint on layer 3
Paint on layer 3
Flip layer 3 horizontally.
(Checkpoint4: Save layer 3. Reuse saved layers 1 and 2 from Checkpoint3.)
Resize layer 1, 2 and 3.
(Checkpoint5: Save layer 1, 2, 3.)

在编辑过程中,我会跟踪自上一个检查点以来修改了哪些图层。当我恢复检查点时,我只恢复已更改的层,例如为了在修改第 2 层和第 3 层后恢复 Checkpoint4,我从磁盘重新加载第 2 层和第 3 层的备份。添加检查点时,我只保存到目前为止已修改的图层。我可以让所有这一切基本上是自动的,除非在我的界面中需要有一些地方,用户被迫等待检查点被保存,因为我一次只能在内存中保留一个图层的大约 1 个临时副本。

你怎么看?它比我希望的要复杂得多,但我看不到任何其他方式。我可以使用任何其他有用的模式来让我的生活更轻松吗?

最佳答案

以下内容对于使用图像的层和撤消缓冲区可能很方便:

  • 保留最新的图像作为图像
  • 以前的版本存储为与下一个版本的异或运算,然后(假设并非所有内容都以相同的方式更改或更改)使用简单的压缩算法(如游程编码)进行压缩

这样有以下优点

  • 以前的版本可以很容易地合并(将它们异或)。

这可能不适用于:

  • 颜色调整(色调、亮度等)
  • 坐标变换(裁剪、变形等)

关于algorithm - 内存有限时位图编辑器的快速撤消/重做?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3901430/

相关文章:

algorithm - 寻找变密度三角剖分的非结构化网格生成算法

c++ - 使用 C++ 的 OOP 设计模式

java - 如何在 OOP 中为 API 或框架设计一个健壮的 Status 类?

c++ - 排序几乎已排序的大文件

algorithm - 这个优化算法的正式名称?

python - 查找未排序数据的路径

algorithm - 如果 f ≠ ω(g),是否 f = O(g)?

arrays - 左/右旋转数组后最长递增子数组的长度

ios - 预加载网络数据时的 NSNotification 或 Delegate

javascript - 从 UI/UX 开发中抛弃 jQuery