El fundido cruzado perfecto

25

Me resulta difícil describir este problema en palabras, por eso hice un video (45 segundos) para ilustrarlo. Aquí hay una vista previa de las preguntas, échale un vistazo en Vimeo: http://vimeo.com/epologee/perfect-crossfade

Usando un fundido cruzado lineal, la imagen resultante tendrá una 'caída' en la transparencia.  ¿Cómo puedo prevenir esto?

La cuestión de crear un fundido cruzado o una disolución perfecta de dos imágenes o formas se me ha repetido en varios campos durante la última década. Primero en edición de video, luego en animación Flash y ahora en programación iOS. Cuando comienzas a buscarlo en Google, hay muchas soluciones alternativas por encontrar, pero realmente quiero resolver esto sin un truco esta vez.

El resumen:
¿Cuál es el nombre de la técnica o curva que se aplicará en dos mapas de bits semitransparentes del mismo color, si desea que la transparencia resultante coincida con el original de cualquiera de ellos?

¿Existe una función (matemática) para calcular los valores necesarios de transparencia parcial / alfa durante el desvanecimiento?

¿Existen lenguajes de programación que tengan estas funciones como un preajuste, similar al ease in, ease outoease in out funciones que se encuentran en ActionScript o cacao?

Actualización: además del video, hice un proyecto de muestra (requiere Xcode y iOS SDK) y lo publiqué en github. Muestra la misma animación que el video pero esta vez con cuadrados: https://github.com/epologee/StackOverflow-Example-Code

epologee
fuente
77
No sé nada al respecto, pero +1 para el video.
sebastiangeiger
Depende de cómo se implemente el operador superior. Ver en.wikipedia.org/wiki/Alpha_channel
artistoex
Estoy de acuerdo, @artistoex, hay algo en eso sobre el operador, ¡gracias por el enlace! Sin embargo, si la respuesta está enterrada allí en algún lugar, no la
veo
La representación matemática del operador sobre conduce a una ecuación. Ejemplo sobre operador: C = alfa * c1 + (alfa-1) * c2 produce alfa = (C + c2) / (c1 + c2) (C es el resultado de mezclar los dos colores c1, c2). Esto significa que para este operador no existe una función que satisfaga su condición.
artistoex
Para C = alpha1 * c1 + alpha2 * c2 (0 <= alpha1, alpha2 <= 1), existe dicha función: alpha1 = (C-alpha2 * c2) / c1.
artistoex

Respuestas:

3

Me temo que eso no es posible. Así se calcula la transparencia cuando se superponen dos objetos: http://en.wikipedia.org/wiki/Alpha_compositing

Composición alfa

Uno de los objetos debe tener una opacidad de 1 si no desea que se vea el área de superposición.

b123400
fuente
3

No sé cuál podría ser el nombre en el ámbito de la edición de video, pero llamaría a la curva una curva S o curva sigmoidea . Debería ser muy sencillo producir el fundido cruzado que está buscando en iOS utilizando la función de sincronización kCAMediaTimingFunctionEaseInEaseOut de Core Animation . Simplemente anime la alphapropiedad de dos vistas en direcciones opuestas (una 0-> 1, una 1-> 0) usando esa función de temporización:

[UIView beginAnimations:@"crossfade" context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
view1.alpha = 0.0;
view2.alpha = 1.0;
[UIView commitAnimations];

Nota: Realmente debería usar los métodos de animación basados ​​en bloques en lugar de los métodos de conveniencia de UIView. Utilicé los métodos de UIView anteriores porque es muy fácil de entender y fácil de escribir desde la memoria. Sin embargo, usar bloques no es mucho más difícil.

Anexo: Si no le gusta UIViewAnimationEaseInOut, puede crear su propia función de temporización como se describe en Timing, Timespaces y CAAnimation . Eso es un poco más avanzado que la animación simple ilustrada arriba, pero te da todo el control que deseas.

Caleb
fuente
¡Sigmoideo! Eso ya está un paso más cerca, ¡gracias! El código que proporciona no funciona de inmediato, ya que setAnimationCurve toma un parámetro diferente que kCAMediaTimingFunctionEaseInEaseOut. ¿Podrías haber querido decir UIViewAnimationCurveEaseInOut? Sin embargo, el problema con esa curva es el mismo (caída en el medio), porque en cualquier punto en el tiempo, los dos valores alfa en una suma simple serán iguales 1.0, donde como en mi curva ajustada manualmente, debe excederse 1.0para obtener los resultados deseados .
epologee
Ahora veo ... tienes razón sobre la constante: he actualizado el código en la respuesta. También he agregado un enlace a documentos que explican cómo crear sus propias funciones de temporización.
Caleb
Hago mis animaciones con bloques, pero la esencia es la misma. Las curvas integradas todavía no se aplican, debido a su simetría, pero el apéndice allanó el camino a una CAMediaTimingFunction personalizada que coincidía con la que utilicé en el video de After Effects. Lo problemático es que no hay una curva sigmoidea que se ajuste a cada escenario , los diferentes niveles iniciales de opacidad requerirán diferentes posiciones bezier para deshacerse de la 'caída'. Debe haber algo que me falta.
epologee
Hola @Caleb, publiqué un proyecto de muestra en GitHub (ver publicación). El tiempo personalizado es útil, pero si cambia el initialTransparencyvalor, no sirve de nada. ¿No tienes idea de qué probar a continuación?
epologee
2
Unos pedacitos más para ayudar a las búsquedas de Google; los programadores de gráficos llaman al gráfico que estás hablando un "paso suave". Los programadores altamente matemáticos a menudo lo llaman un "interpolador de hermitas". Y una ecuación simple para calcular uno sin trigonometría es: "3t ^ 2 - 2t ^ 3".
Trevor Powell
1

En gráficos de computadora, este tipo de función se llama smoothstep . Cuando se usa para fundido cruzado, determina el valor alfa global para la composición.

Si las imágenes de entrada tienen un canal alfa, primero debe asegurarse de que el alfa esté premultiplicado . Luego, puede hacer la composición de fundido cruzado directamente, utilizando el paso suave alphaen cada canal [ X = A*alpha + B*(1-alpha)], y esperar resultados razonables.

tormenta
fuente
0

Puede usar la función de disminución exponencial:

Alpha1(time) = 1 - exp(-time / (0.2 * transitionTime)); // fade in
Alpha2(time) = 1 - Alpha1(time); // fade out

Su gráfico se parece más a:

Alpha1(time) = sin(time * 0.5 * pi / transitionTime); // fade in
Alpha2(time) = cos(time * 0.5 * pi / transitionTime); // fade out
Danny Varod
fuente
Gracias @Danny. En realidad, realizar la 1 - Alpha1(time)ecuación no se encargará de la inmersión, ya que dos imágenes combinadas de 0.5 alfa no darán como resultado una imagen compuesta con 1.0 alfa. Las curvas personalizadas que dibujé no se reflejan verticalmente.
epologee
1
El 1-alfa fue para la disminución exponencial, que creo que es más adecuado. Sin embargo, para las funciones sin / cos, por supuesto, sin (t) = sqrt (1-sqr (cos (t)), calcular cada una por separado debería ser más rápido.
Danny Varod
Si el problema fuera cómo se vería la función de una curva similar, su matemática es correcta. Sin embargo, el problema es cómo lidiar con la combinación de dos colores, por ejemplo, cómo obtener un 40% de azul + 40% de azul para obtener un 80% de azul.
epologee
Eso es fácil de hacer, pero daría como resultado una saturación de mal aspecto cuando la suma de colores> 100%.
Danny Varod