Photoshop 撤消系统
这个问题可能适用于一般的绘图系统。 我想知道PS中的撤消功能是如何实现的。 程序是否在每次操作之前拍摄画布快照? 如果是这样,这不会导致巨大的内存需求吗? 我研究过命令模式,但我不太明白它如何应用于绘图。
问候, 门诺
The question probably applies to drawing systems in general. I was wondering how the undo functionality is implemented in PS. Does the program take snapshots of the canvas before each operation? If so, wouldn't this lead to huge memory requirements? I've looked into the Command pattern, but I can't quite see how this would be applied to drawing.
Regards,
Menno
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
它称为命令模式。 它的实现很简单,对任何类型的编辑器都很有用。
Photoshop 对原始图像应用堆叠变换。 一项操作一项命令。 当您撤消时,它只是不应用转换。 所以它只保留原始版本和最新版本,但我想它可能只是为了性能而缓存最后几个版本。
It's called the command pattern. It's simple to implement as useful for any sort of editor.
Photoshop applies stacked transformations upon the original image. One opetation one command. It simply unapplies the transformation when you undo. So it just keeps the original and latest versions, but I guess it might cache the last few versions just for performance.
由于某些操作是不可逆的,并且正如您所说,每次都对整个图像进行快照是不可能的,因此我能看到的唯一其他选择就是一堆增量。 增量是包含操作之前修改的像素的一组掩模。 当然,许多操作可能是可逆的,因此可以优化它们的增量。
Since some operations will be non-reversable and as you say snapshoting the entire image every time would be out of the question then the only other alternative I can see would be a stack of deltas. A delta being the set of masks containing the modified pixels prior to the operation. Of course many operations may be reversable so their deltas could be optimised.
我不确定 Adobe Photoshop 如何实现
撤消
,但 Apple Shake 合成应用程序非常容易解释:x
笔画(我认为是 10 次)当前图像就会缓存到内存中。这样做有两个问题:
好吧,还有第三个问题,Shake 存在严重错误,并且在许多方面实施得很差,Paint 节点就是其中之一 - 所以我不确定这是一个多么好的实施,但我无法想象 Photoshop太不相似了(尽管远优化得更好)。
I'm not sure how Adobe Photoshop implements
undo
, but the Paint node within Apple Shake compositing application is pretty easy to explain:x
strokes (10 I think) the current image is cached into memory.There are two problems with this:
Well, there is a third problem, that being Shake is horribly buggy and poorly implemented in many areas, the Paint node beign one of them - so I'm not sure how good an implementation this is, but I can't imagine Photoshop being too dissimilar (albeit far better optimised).
我发现解决这个问题的最简单方法是使用持久数据结构,尽管我不知道 Adobe 如何解决它,如下所示:
您将图像视为一个集合图像块,例如每个 64x64 像素,并且它们被垃圾收集或引用计数(例如:在 C++ 中使用
shared_ptr
)。现在,当用户对图像图块进行更改时,您可以创建一个新版本,同时浅层复制未修改的图块:
< img src="https://i.sstatic.net/syaYe.jpg" alt="在此处输入图像描述">
在进行此类更改时,除了那些深色瓷砖之外的所有内容都会被浅复制。 当你这样做时,你的整个撤消系统可以归结为:
这样就变得超级简单,不需要将整个图像一遍又一遍地存储在每个撤消条目中。 作为一个额外的好处,当用户复制和粘贴图层时,它几乎不需要更多的内存,除非/直到他们对粘贴的图层进行更改。 它基本上为您提供了一个图像实例化系统。 另一个好处是,当用户创建一个透明图层(例如 2000x2000 像素)但他们只绘制图像的一小部分(例如仅 100x100 像素)时,这也几乎不需要任何内存,因为空/透明图块不会占用任何内存。必须存储任何像素,只有几个空指针。 它还可以加快与此类大部分透明图层的合成速度,因为您不必对空图像图块进行 Alpha 混合,只需跳过它们即可。 在这些情况下,它还可以加快图像过滤器的速度,因为它们同样可以跳过空的图块。
至于 PS 动作,这是一种不同的方法。 在那里,您可以使用一些脚本来指示要执行的操作,但您可以将其与上面的脚本结合起来,以有效地仅缓存图像的修改部分。 这种方法的重点是避免一遍又一遍地深度复制整个图像,并增加内存使用量来缓存图像的先前状态以进行撤消,而不必为各种情况编写单独的撤消/重做逻辑。可能发生的不同操作。
The easiest way I've found to solve this problem, though I don't know how Adobe tackles it, is to use a persistent data structure, like so:
You think of an image as a collection of image tiles, say 64x64 pixels each, and they get garbage collected or reference counted (ex: using
shared_ptr
in C++).Now when the user makes changes to an image tile, you create a new version while shallow copying the unmodified tiles:
Everything except those dark tiles are shallow copied upon such a change. And when you do it that way, your entire undo system boils down to this:
And it becomes super easy like that without requiring the entire image to be stored over and over in each undo entry. As a bonus when users copy and paste layers, it barely takes any more memory unless/until they make changes to that pasted layer. It basically provides you an instancing system for images. As yet another bonus, when a user creates a transparent layer that's, say, 2000x2000 pixels but they only paint a little bit of the image, like say just 100x100 pixels, that also barely takes any memory because the empty/transparent tiles don't have to store any pixels, only a couple of null pointers. It also speeds up compositing with such mostly-transparent layers, because you don't have to alpha blend the empty image tiles and can just skip over them. It also speeds up image filters in those cases as well since they can likewise just skip over the empty tiles.
As for PS actions, that's a bit of a different approach. There you might use some scripting to indicate what actions to perform, but you can couple it with the above to efficiently cache only modified portions of the image. The whole point of this approach is to avoid having to deep copy the entirety of the image over and over and blow up memory usage to cache previous states of an image for undoing without having to fiddle with writing separate undo/redo logic for all kinds of different operations that could occur.
Photoshop 使用历史记录来跟踪他们的操作。 这些也可以用作撤消,因为您可以随时返回历史记录。 您可以在首选项中设置历史记录的大小。
我还建议您将 Adobe Version Cue 作为一种用于回顾撤消或版本的工具,它内置于套件中的目的就是为了这个目的。 http://en.wikipedia.org/wiki/Adobe_Version_Cue
Photoshop uses History to track their actions. These also serve as Undo as you can go back in history at any point. You can set the size of history in preferences.
I also suggest you look into Adobe Version Cue as a tool for retrospect undo or versions, it's built into the suite for that sole purpose. http://en.wikipedia.org/wiki/Adobe_Version_Cue