Photoshop撤消系统

时间:2009-04-04 12:58:00

标签: drawing photoshop undo

这个问题可能适用于一般的绘图系统。我想知道如何在PS中实现撤消功能。程序是否在每次操作之前拍摄画布的快照?如果是这样,这不会导致巨大的内存需求吗?我查看了Command模式,但我不太清楚它是如何应用于绘图的。

此致 门诺

5 个答案:

答案 0 :(得分:12)

它被称为command pattern。实现它对任何类型的编辑器都很有用。

Photoshop在原始图像上应用堆叠变换。一个操作一个命令。撤消时,它只是取消应用转换。所以它只保留原始版本和最新版本,但我想它可能只是为了性能而缓存最后几个版本。

答案 1 :(得分:4)

由于某些操作是不可逆的,并且正如你所说每次拍摄整个图像都是不可能的,那么我能看到的唯一其他选择就是一堆增量。 delta是在操作之前包含修改的像素的掩码集。当然,许多操作可能是可逆的,因此可以优化它们的增量。

答案 2 :(得分:4)

我不确定Adobe Photoshop如何实现undo,但Apple Shake合成应用程序中的Paint节点很容易解释:

  • 每个行程存储为一系列点,以及一些信息,如描边颜色,画笔大小等。
  • 绘制一个笔划时,会对当前图像进行更改。
  • 每个x笔画(我认为10)当前图像被缓存到内存中。
  • 撤消时,会重新绘制上一个缓存图像上的最后~9个字符。

这有两个问题:

  • 当您撤消10次以上时,必须重新计算整个图像。有数千次击打可能会导致几秒钟的停顿。
  • 使用Shake,您可以保存包含笔划信息的设置文件,而不是实际的像素值。然后意味着每次重新打开“绘制”节点或渲染图像时都必须重新计算整个图像(但这并不像撤消图像那么大)。

嗯,还有第三个问题,就是Shake非常多,并且在很多方面都很难实现,Paint节点让其中一个失败了 - 所以我不确定这个实现有多好,但我不能想象Photoshop太不相似(虽然更好地优化)。

答案 3 :(得分:0)

我发现解决这个问题的最简单方法,虽然我不知道Adobe如何处理它,但是使用持久数据结构,如下所示:

enter image description here

您将图像视为图像切片的集合,例如每个64x64像素,并且它们会被垃圾收集或引用计数(例如:在C ++中使用shared_ptr)。

现在,当用户对图像图块进行更改时,您将创建一个新版本,同时浅层复制未修改的图块:

enter image description here

除了那些黑色瓷砖之外的所有东西都是在这样的变化时被轻易复制的。当你这样做时,你的整个撤销系统归结为:

before user operation:
    store current image in undo stack
on undo/redo:
    swap image at top of undo stack with current image

这样就变得非常容易,而不需要在每个撤销条目中反复存储整个图像。作为用户复制和粘贴图层时的奖励,除非/直到他们对该粘贴图层进行更改,否则几乎不会占用更多内存。它基本上为您提供了图像的实例化系统。作为另一个奖励,当用户创建一个透明层,例如,2000x2000像素,但他们只绘制一点点图像,比如说只有100x100像素,这也几乎不占用任何内存,因为空/透明瓷砖不必须存储任何像素,只有几个空指针。它还可以加快与这种大多数透明图层的合成速度,因为您不必对空图像图块进行alpha混合,只需跳过它们即可。在这些情况下,它也可以加速图像过滤器,因为它们同样可以跳过空的瓷砖。

对于PS动作,这是一种不同的方法。在那里,您可以使用某些脚本来指示要执行的操作,但您可以将其与上述操作结合使用,以有效地仅缓存图像的修改部分。这种方法的重点是避免不得不一遍又一遍地深度复制整个图像并炸掉内存使用来缓存图像的先前状态以进行撤消,而不必为各种类型编写单独的撤销/重做逻辑。可能发生的不同操作。

答案 4 :(得分:-2)

Photoshop使用历史记录来跟踪他们的操作。这些也可以作为撤消,因为您可以随时回溯历史。您可以在首选项中设置历史记录的大小。

我还建议您查看 Adob​​e Version Cue作为回溯撤消或版本的工具,它仅用于此唯一目的。 http://en.wikipedia.org/wiki/Adobe_Version_Cue