2009-04-04 23 views
7

La pregunta probablemente se aplica a los sistemas de dibujo en general. Me preguntaba cómo se implementa la funcionalidad deshacer en PS. ¿El programa toma instantáneas del lienzo antes de cada operación? Si es así, ¿esto no llevaría a requisitos de memoria enormes? He analizado el patrón de Comando, pero no puedo ver cómo se aplicará esto al dibujo.Photoshop Undo System

Saludos, Menno

+0

¿Por qué cerrar? ¿Esto es un engaño o algo así? El cierre debe ir seguido de los comentarios –

+0

Eche un vistazo a [este subproceso SO] (http://stackoverflow.com/questions/3541383/undo-redo-implementation/3542670#3542670). – Lazer

Respuesta

12

Se llama el command pattern. Es simple de implementar como útil para cualquier tipo de editor.

Photoshop aplica transformaciones apiladas sobre la imagen original. Una operación, un comando. Simplemente deja de aplicar la transformación cuando se deshace. Así que solo conserva las versiones original y última, pero supongo que podría almacenar en caché las últimas versiones solo por el rendimiento.

+0

Lo he implementado en un editor WYSIWYG. Parece imposible al principio, pero una vez que comprendes el patrón, es realmente bastante fácil. –

+0

Esa es mi misma experiencia, pensé que nunca iba a funcionar, y que tenía que haber un secreto interno, pero una vez que terminé simplemente funcionó :) –

+0

En realidad, la versión actual es solo la versión existente y el historial de comandos es en realidad una lista de comandos invertidos. Al menos así es como lo haría un procesador de textos. – jmucchiello

4

Dado que algunas operaciones no serán reversibles y, como dices, la instantánea de toda la imagen sería imposible, entonces la única alternativa que puedo ver sería una pila de deltas. Un delta es el conjunto de máscaras que contiene los píxeles modificados antes de la operación. Por supuesto, muchas operaciones pueden ser reversibles por lo que sus deltas podrían ser optimizados.

+0

También Photoshop utiliza el disco duro para deshacer la información, por lo que no hay requisitos de memoria adicionales allí. – Joey

-2

Photoshop utiliza Historial para realizar un seguimiento de sus acciones. Estos también sirven como Deshacer ya que puede retroceder en la historia en cualquier punto. Puede establecer el tamaño del historial en las preferencias.

También sugiero que busque en Adobe Version Cue como una herramienta para deshacer o versiones retrospect, está integrado en el conjunto para ese único propósito. http://en.wikipedia.org/wiki/Adobe_Version_Cue

+0

Esta pregunta es sobre los detalles de implementación. – tmcw

4

no estoy seguro de cómo implementa Adobe Photoshop undo, pero el nodo de pintura dentro Apple Shake aplicación de composición es bastante fácil de explicar:

  • Cada Stoke se almacena como una serie de puntos, junto con alguna información como el color de trazo, tamaño de pincel, etc.
  • Cuando dibuja un pico, los cambios se realizan en la imagen actual.
  • Cada x golpes (10 creo) la imagen actual se almacena en caché en la memoria.
  • Al deshacer, vuelve a dibujar las últimas ~ 9 alimentaciones en la imagen almacenada en caché anterior.

Hay dos problemas con este:

  • Al deshacer más de 10 veces, tiene que volver a calcular toda la imagen. Con miles de golpes, esto puede causar una pausa de varios segundos.
  • Con Shake, guarda el archivo de instalación, que contiene la información de trazo, no los valores de píxel reales. Entonces significa que tiene que volver a calcular la imagen completa cada vez que vuelva a abrir el nodo Paint, o renderice la imagen (sin embargo, no es un problema tan grande como deshacer).

Bueno, hay un tercer problema, que al ser Shake tiene errores horribles y está mal implementado en muchas áreas, el nodo Paint es uno de ellos, así que no estoy seguro de qué tan buena implementación es, pero No puedo imaginarme que Photoshop sea muy diferente (aunque ahora mejor optimizado).

0

La manera más fácil que he encontrado para resolver este problema, aunque no sé cómo Adobe fuerza a él, es el uso de una estructura de datos persistentes, así:

enter image description here

Se piensa una imagen como una colección de mosaicos de imágenes, digamos 64x64 píxeles cada uno, y se obtiene la basura recogida o referencia contada (por ejemplo, usando shared_ptr en C++).

Ahora, cuando el usuario realiza cambios en un mosaico de imagen, se crea una nueva versión mientras copia superficial de las baldosas sin modificar:

enter image description here

Todo excepto aquellas tejas oscuras son poco profundas copiado en un cambio de este tipo. Y cuando lo haces de esa manera, su sistema de deshacer todo se reduce a esto:

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

y se hace muy fácil de esa manera, sin necesidad de toda la imagen a almacenar una y otra vez en cada entrada de deshacer. Como ventaja adicional, cuando los usuarios copian y pegan capas, apenas necesitan más memoria a menos que/hasta que realicen cambios en esa capa pegada. Básicamente, le proporciona un sistema de instancias para las imágenes. Como una ventaja adicional, cuando un usuario crea una capa transparente que es, por ejemplo, 2000x2000 píxeles, solo pinta un poco de la imagen, como por ejemplo 100x100 píxeles, que apenas toma memoria porque las casillas vacías/transparentes no tiene que almacenar cualquier píxel, solo un par de punteros nulos. También acelera la composición con esas capas en su mayoría transparentes, porque no tienes que mezclar alfa los mosaicos vacíos de la imagen y puedes omitirlos. También acelera los filtros de imagen en esos casos, ya que también pueden saltear las baldosas vacías.

En cuanto a las acciones de PS, ese es un enfoque un poco diferente. Allí puede usar algunas secuencias de comandos para indicar qué acciones realizar, pero puede acoplarlas con las de arriba para almacenar en caché solo las partes modificadas de la imagen. El objetivo de este enfoque es evitar tener que copiar en profundidad la totalidad de la imagen una y otra vez e inflar el uso de memoria para almacenar en caché los estados previos de una imagen para deshacer sin tener que jugar con la escritura de la lógica deshacer/rehacer para todo tipo de diferentes operaciones que podrían ocurrir