Самый простой способ, который я нашел для решения этой проблемы, хотя я не знаю, как 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
И это становится очень просто, не требуя многократного сохранения всего изображения в каждой записи отмены. В качестве бонуса, когда пользователи копируют и вставляют слои, это едва ли занимает больше памяти, если / пока они не внесут изменения в этот вставленный слой. Это в основном предоставляет вам систему экземпляров для изображений. В качестве еще одного бонуса, когда пользователь создает прозрачный слой, скажем, 2000x2000 пикселей, но он рисует лишь небольшую часть изображения, как, скажем, просто 100x100 пикселей, который также едва занимает какую-либо память, потому что пустые / прозрачные плитки не должны хранить любые пиксели, только пару нулевых указателей. Это также ускоряет компоновку с такими прозрачными слоями, потому что вам не нужно альфа-смешивать пустые фрагменты изображения и просто пропустить их. В этих случаях он также ускоряет фильтры изображений, поскольку они также могут просто пропускать пустые плитки.
Что касается действий PS, это немного другой подход. Там вы можете использовать некоторые сценарии, чтобы указать, какие действия нужно выполнить, но вы можете связать их с приведенным выше, чтобы эффективно кэшировать только измененные части изображения. Смысл этого подхода состоит в том, чтобы избежать необходимости глубокого копирования всего изображения снова и снова и увеличивать использование памяти для кэширования предыдущих состояний изображения для отмены без необходимости возиться с записью отдельной логики отмены / повторения для всех видов различные операции, которые могут произойти.