【问题标题】:What's the best way to implement an "undo" feature in photo editing application?在照片编辑应用程序中实现“撤消”功能的最佳方式是什么?
【发布时间】:2017-08-30 03:58:59
【问题描述】:

显然,存储更改历史数组需要大量内存……这就是我的应用程序的工作方式,但似乎有一种更聪明的方法可以做到这一点。

ArrayList<Photo> photoHistory = new ArrayList<>();
photoHistory.add(originalPhoto);
photoHistory.add(change1);
photoHistory.add(change2);

// bad implementation - lots of memory

也许只存储原始视图模型和当前视图模型并记录使用的方法/过滤器?那么当用户点击“撤消”时,它会采用所做的更改总数并再次将所有更改减去一?这似乎也非常低效。

我想我只是在寻找有关如何实现软件应用程序的一般“撤消”功能的建议。

【问题讨论】:

  • 计算更改前后的增量,即应用到新版本以逆转更改的增量。历史就是那些三角洲。对于全滤镜,这可能是全图,但对于像红眼滤镜这样的东西,它只是眼睛,即小得多。
  • 好吧,如果您只想拥有一个通用的撤消功能,@AndyTurner 链接的命令模式是一个很好的模式。然而,在图形应用场景中让它变得相当复杂的是 undo 方法本身(需要将其添加到每个命令中)。在命令中实现撤消可能并不那么容易。正如您所提到的 - 您可以保留已执行命令的列表,并在撤消最后一个命令时重新应用以前的命令。不过,这可能效率很低。所以,总结一下——在一般情况下,命令模式是可以的,但可能不是图形编辑器中的最佳选择。

标签: java undo undo-redo


【解决方案1】:

以下是 GIMP 如何实现它的提示:

GIMP 的撤消实现相当复杂。许多操作需要很少的撤消内存(例如,更改图层的可见性),因此您可以在它们退出撤消历史记录之前执行它们的长序列。某些操作(例如更改图层可见性)会被压缩,因此连续多次执行这些操作只会在撤消历史记录中产生一个点。但是,还有其他操作可能会消耗大量撤消内存。大多数过滤器都是由插件实现的,因此 GIMP 核心无法有效地知道发生了什么变化。因此,除了在操作之前和之后记住受影响层的全部内容外,没有其他方法可以实现 Undo。在这些操作退出撤消历史记录之前,您可能只能执行一些此类操作。

Source

因此,要尽可能优化,您必须根据要撤消的操作执行不同的操作。显示或隐藏图层可以在可以忽略不计的空间中表示,但过滤整个图像可能需要存储整个图像的另一个副本。但是,如果您只过滤图像的一部分(或在图像的一小部分中绘制),您可能只需要存储这部分图像。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-17
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 2021-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多