Самый простой способ я нашел, чтобы решить эту проблему, хотя я не знаю, как Adobe решает его, чтобы использовать постоянную структуру данных, например, так:

Вы думаете о изображение как набор графических фрагментов, скажем, 64x64 пикселей каждый, и они получают собранный мусор или подсчет ссылок (например: используя shared_ptr
в C++).
Теперь, когда пользователь вносит изменения в фоновое изображении, вы создаете новую версию, пока неглубокое копирование немодифицированных плиток:

Все, кроме тех темные плиток мелкие скопировано на такое изменение. И когда вы делаете это таким образом, вся ваша система отката сводится к следующему:
before user operation:
store current image in undo stack
on undo/redo:
swap image at top of undo stack with current image
И становится очень легко, как, что, не требуя полное изображение будет храниться снова и снова в каждом отменить запись. В качестве бонуса, когда пользователи копируют и вставляют слои, он едва занимает больше памяти, если/до тех пор, пока они не вносят изменения в этот вставленный слой. Он в основном предоставляет вам систему instancing для изображений. Еще один бонус, когда пользователь создает прозрачный слой, скажем, 2000x2000 пикселей, но они только рисуют немного изображения, например, говорят только 100x100 пикселей, что также едва ли берет память, потому что пустые/прозрачные плитки не должны хранить любые пиксели, только пару нулевых указателей. Он также ускоряет компоновку с такими прозрачными слоями, потому что вам не нужно альфа-смешивать пустые фрагменты изображений и просто пропустить их. Он также ускоряет фильтрацию изображений в тех случаях, так как они также могут просто пропускать пустые плитки.
Что касается действий PS, это немного другой подход. Там вы можете использовать некоторые скрипты, чтобы указать, какие действия выполнять, но вы можете связать их с приведенным выше, чтобы эффективно кэшировать только измененные части изображения. Весь смысл этого подхода состоит в том, чтобы избежать необходимости глубокой копии всего изображения снова и снова и взорвать использование памяти для кэширования предыдущих состояний изображения для отмены, не прибегая к написанию отдельной логики отмены/повтора для всех видов различные операции, которые могут произойти.
Зачем закрывать? Это обман или что-то еще? За закрытием должны следовать комментарии –
Посмотрите на [эту SO-нить] (http://stackoverflow.com/questions/3541383/undo-redo-implementation/3542670#3542670). – Lazer