Photoshop 撤消系统

发布于 2024-07-16 21:44:57 字数 137 浏览 9 评论 0原文

这个问题可能适用于一般的绘图系统。 我想知道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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

2024-07-23 21:44:57

它称为命令模式。 它的实现很简单,对任何类型的编辑器都很有用。

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.

五里雾 2024-07-23 21:44:57

由于某些操作是不可逆的,并且正如您所说,每次都对整个图像进行快照是不可能的,因此我能看到的唯一其他选择就是一堆增量。 增量是包含操作之前修改的像素的一组掩模。 当然,许多操作可能是可逆的,因此可以优化它们的增量。

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.

平定天下 2024-07-23 21:44:57

我不确定 Adob​​e Photoshop 如何实现撤消,但 Apple Shake 合成应用程序非常容易解释:

  • 每个描边都存储为一系列点,以及一些信息,例如描边颜色、画笔大小等。
  • 当您绘制描边时,就会进行更改在当前图像上。
  • x 笔画(我认为是 10 次)当前图像就会缓存到内存中。
  • 当您撤消时,它会在上一个缓存图像上重新绘制最后约 9 个笔画。

这样做有两个问题:

  • 当你撤消超过 10 次时,它必须重新计算整个图像。 如果有数千次敲击,这可能会导致几秒钟的暂停。
  • 使用 Shake,您可以保存设置文件,其中包含笔划信息 - 而不是实际的像素值。 那么意味着每当您重新打开 Paint 节点或渲染图像时,您都必须重新计算整个图像(但是,问题不像撤消那么大)。

好吧,还有第三个问题,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:

  • Each stoke is stored as a series of points, along with some information like stroke-color, brush-size etc.
  • When you draw a stoke, the changes are made on the current image.
  • Every x strokes (10 I think) the current image is cached into memory.
  • When you undo, it redraws the last ~9 stokes on the previous cached image.

There are two problems with this:

  • When you undo more than 10 times, it has to recalculate the whole image. With thousands of strokes this can cause a several second pause.
  • With Shake, you save the setup file, containing the stroke information - not the actual pixel values. Then means you have to recalculate the whole image whenever you reopen the Paint node, or render the image (not nearly as big a problem as the undo thing, however).

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).

血之狂魔 2024-07-23 21:44:57

我发现解决这个问题的最简单方法是使用持久数据结构,尽管我不知道 Adob​​e 如何解决它,如下所示:

在此处输入图像描述

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

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

< img src="https://i.sstatic.net/syaYe.jpg" alt="在此处输入图像描述">

在进行此类更改时,除了那些深色瓷砖之外的所有内容都会被浅复制。 当你这样做时,你的整个撤消系统可以归结为:

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 动作,这是一种不同的方法。 在那里,您可以使用一些脚本来指示要执行的操作,但您可以将其与上面的脚本结合起来,以有效地仅缓存图像的修改部分。 这种方法的重点是避免一遍又一遍地深度复制整个图像,并增加内存使用量来缓存图像的先前状态以进行撤消,而不必为各种情况编写单独的撤消/重做逻辑。可能发生的不同操作。

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:

enter image description here

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:

enter image description here

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:

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

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.

橙幽之幻 2024-07-23 21:44:57

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

我还建议您将 Adob​​e 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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文