Быстрая отмена / повтор для редактора растровых изображений, когда память ограничена? - PullRequest
12 голосов
/ 10 октября 2010

Я пытаюсь написать редактор растровых изображений для мобильного устройства (то есть ограниченную версию Photoshop). Документ пользователя состоит из ~ 4 растровых изображений размером около 1000x500 каждая.

Мне нужна надежная и эффективная система отмены / повтора, максимально простая. Я стремлюсь примерно на ~ 0,2 с отменить или повторить редактирование. Мне нужны отзывы о моем нынешнем подходе или о новых идеях, которые я могу использовать. Я думаю, что то, что у меня есть, слишком сложно, поэтому я осторожен в продолжении, поэтому просто знать, что это лучшее из того, что я мог сделать, было бы хорошо.

Я экспериментировал с комбинациями использования шаблона Command и Memento для моей системы отмены / возврата. Вот некоторые выводы, к которым я пришел:

  1. У меня недостаточно памяти, и я не могу записать память на диск достаточно быстро, чтобы использовать память для поддержки операции «неисполнение» предыдущей команды во многих ситуациях, например, если пользователь делает несколько отдельных мазков очень быстро, я не смогу хранить растровые изображения, представляющие то, что пользователь закрасил, не заставляя пользователя ждать их сохранения.

  2. Если я восстановлю документ в его начальном состоянии и воспроизведу все команды, кроме последней, которая должна была отменить, это будет слишком медленно даже после небольшого количества команд, например, воспроизведение 10 мазков или 5 мазков занимает ~ 1 с, что слишком вяло.

  3. Я могу обойти предыдущую точку, периодически сохраняя весь документ в фоновом режиме на диск и восстанавливая эту контрольную точку перед воспроизведением команд. Чтобы отменить дальше, чем последняя контрольная точка, мы перезагружаем контрольную точку перед этим и воспроизводим команды.

Подход 2 с 3 работает хорошо, за исключением того, что сохранение всего документа становится все медленнее и медленнее, поскольку добавляется больше слоев, и это уже медленно с 4 растровыми изображениями (ожидание ~ 5 - 10 секунд). Поэтому мне нужно изменить 3, чтобы сохранить только то, что изменилось с прошлого раза.

Поскольку многие команды работают только на одном слое, имеет смысл сохранять только те слои, которые были изменены с момента последней контрольной точки. Например, мой стек команд может выглядеть так, если у меня есть 3 начальных слоя, где я указал, где могут быть сохранены контрольные точки.

(Checkpoint1: Save layer 1, 2 and 3.)
Paint on layer 1
Paint on layer 1
(Checkpoint2: Save layer 1. Reuse saved layers 2 and 3 from Checkpoint1.)
Paint on layer 2
Paint on layer 2
(Checkpoint3: Save layer 2. Reuse saved layers 1 and 3 from Checkpoint2.)
Paint on layer 3
Paint on layer 3
Flip layer 3 horizontally.
(Checkpoint4: Save layer 3. Reuse saved layers 1 and 2 from Checkpoint3.)
Resize layer 1, 2 and 3.
(Checkpoint5: Save layer 1, 2, 3.)

Во время редактирования я отслеживаю, какие слои были изменены со времени предыдущей контрольной точки. Когда я восстанавливаю контрольную точку, я восстанавливаю только те слои, которые изменились, например, чтобы восстановить Checkpoint4 после изменения слоев 2 и 3, я перезагружаю резервные копии слоев 2 и 3 с диска. При добавлении контрольной точки я сохраняю только слой, который был изменен до сих пор. Я могу сделать все это в основном автоматически, за исключением того, что в моем интерфейсе должны быть места, где пользователь вынужден ждать сохранения контрольных точек, потому что я могу хранить только 1 временную копию слоя в памяти за раз.

Что ты думаешь? Это гораздо сложнее, чем хотелось бы, но я не вижу другого пути. Есть ли другие полезные шаблоны, которые я могу использовать, чтобы облегчить мне жизнь?

Ответы [ 2 ]

1 голос
/ 18 марта 2011

Одним из подходов является сохранение определенных «кадров» в виде полных кадров, а других - в качестве команды, необходимой для создания кадра из предыдущего.Вы намекаете на это в своем # 2.Может быть полезно сохранить некоторые кадры в памяти.

Уловка, которая может помочь сбалансировать производительность с пространством / временем, доступным для хранения полных кадров, заключается в отбрасывании некоторой доли «старых» кадров, так чтов любой момент времени вы можете отменить состояния, например, от 1, 2, 4, 8, 16, 32 и 64 операций назад.Отмена одной или двух операций потребует простого чтения кадра.Для отмены трех потребуется прочитать контрольную точку и повторить одну операцию.Для отмены пяти потребуется прочитать контрольную точку и повторить три операции.Для отмены тридцати трех потребуется прочитать контрольную точку и повторить 31 операцию.

Для повышения плавности приложения в некоторых случаях может быть полезно пересчитать кадры контрольных точек в фоновом режиме во время операции отмены.Например, после отмены семнадцати операций можно в фоновом режиме начать работу по вычислению состояний на 48, 40 и 36 шагов назад от начальной точки, так что, если кто-то захочет вернуться дальше, он уже выполнит некоторые изработа.Обратите внимание, что можно отбросить кадры, которые вернулись назад на 1, 2, 4, 8 или 16 операций, поскольку их можно воссоздать, воспроизводя команды вперед из текущего состояния.

1 голос
/ 11 октября 2010

Это может быть полезно для слоев и отмены буферов с помощью изображений:

  • Сохранить последнее изображение как изображение
  • Предыдущие версии сохраняются как xor со следующей версией, а затем (при условии, что не все изменилось или изменилось таким же образом) сжимаются с использованием простого алгоритма сжатия (например, кодирование длины серии)

Это имеет следующие преимущества

  • предыдущие версии могут быть легко объединены (xor их вместе).

Это может не работать с:

  • настройки цвета (оттенок, яркость и т. Д.)
  • преобразования координат (обрезка, морфинг и т. Д.)
...