Comparación de filtros en flash

En este tutorial, crearemos un programa de filtro que permitirá al usuario aplicar diferentes filtros a una imagen, cambiar los niveles de intensidad y comparar las imágenes originales y filtradas. También utilizaremos componentes para nuestros controles..




Breve descripción

Habrá tres capas: una para el ActionScript, otra para el texto y los componentes y la última para la imagen. El programa compilado contendrá dos imágenes ya que una se creará en tiempo de ejecución. La versión en tiempo de ejecución tendrá filtros aplicados. Además, se creará una máscara en tiempo de ejecución que se usará para mostrar / ocultar partes de la imagen filtrada.

Supongo que ya tiene un conocimiento básico de Flash y ActionScript 3.0. Sin embargo, seguiré intentando mantener cada paso lo más claro posible..

Nota: A lo largo de este tutorial usaré referencias débiles al agregar escuchas de eventos. Para obtener más información sobre referencias débiles, consulte esta publicación de blog.

Paso 1

Crear un nuevo documento ActionScript 3.0. Establezca el tamaño del escenario en 600 x 500 px. He elegido este tamaño ya que la imagen que usaré se ajustará cómodamente a estas dimensiones.

Paso 2

Cree las tres capas mencionadas anteriormente (a saber, "acciones", "texto y componentes" e "imagen (original)"). Bloquee la capa de "acciones" ya que no agregará nada a esa capa aparte de ActionScript.

Paso 3

Seleccione la capa "texto y componentes" y agregue el texto estático "Filtro" e "Intensidad" en la esquina superior izquierda.

Etapa 4

Vaya al panel Componentes y arrastre cinco botones y dos controles deslizantes al escenario. Básicamente puedes colocarlos como quieras..

Proporcione a los botones valores de "Predeterminado", "Desenfoque", "Relieve", "Brillo" y "Negativo". Luego dales los nombres de instancia de "default_btn", "blur_btn", "emboss_btn", "brightness_btn" y "negative_btn".

Asigne al control deslizante de intensidad un nombre de instancia de "intensidad_sld", luego nombre el control deslizante de máscara "máscara_sld".

Nota: no es muy importante dónde colocar el control deslizante de máscara, ya que usaremos ActionScript para volver a colocarlo más adelante.

Terminología: a lo largo de este tutorial puedo referirme indistintamente a "deslizador de máscara" o "máscara_sld". Lo mismo ocurre con el control deslizante de intensidad y con la intensidad..

Paso 5

Ahora puede bloquear la capa "texto y componentes". A continuación, seleccione la capa "imagen (original)" e importe la imagen que desea usar. Voy a usar una foto de un diente de león..

Paso 6

Seleccione la imagen y conviértala en un símbolo de Clip de película. Lo he llamado "diente de león", pero puede ser lo que quieras. Asegúrese de que el punto de registro esté en la esquina superior izquierda. Vaya a la vista "Avanzado" y marque "Exportar para ActionScript". La "Exportación en el fotograma 1" debe ser verificada automáticamente. Para la clase, ingrese "PhotoDandelion" y deje la clase base como "flash.display.MovieClip".

Paso 7

Asigne a la nueva imagen Clip de película el nombre de instancia "photoOriginal". Ahora puedes bloquear la capa "imagen (original)".

Paso 8 - Fundamentos del filtro

Flash le permite aplicar filtros similares a los de Photoshop. Puede aplicar filtros desde el panel Propiedades o mediante ActionScript. Estos son algunos de los filtros básicos que proporciona Flash: biselado, difuminado, sombra, brillo, etc..

Usando ActionScript podemos aplicar un filtro a cualquier DisplayObject a través de su propiedad "filtros". El valor asignado a la propiedad "filtros" debe ser una matriz. También puedes aplicar más de un filtro..

 // Aplicando un filtro de desenfoque a un DisplayObject. var bFilter: BlurFilter = nuevo BlurFilter (); var arrFilters: Array = [bFilter]; displayObj.filters = arrFilters;

Paso 9 - Filtros de convolución

Flash también admite filtros de convolución que pueden realizar efectos más avanzados, como brillo, detección de bordes, relieve, etc..

Los filtros de convolución solo se pueden aplicar a través de ActionScript y también requieren el uso de matrices que describan cómo deben efectuarse los colores para cada píxel. La matriz necesita estar en una matriz.

 // Valor predeterminado var matrixDefault: Array = [0, 0, 0, 0, 1, 0, 0, 0, 0]; // Brighter var matrixBrighter: Array = [0, 0, 0, 0, 2, 0, 0, 0, 0]; // Más oscuro var matrixDarker: Array = [0, 0, 0, 0, 0.5, 0, 0, 0, 0]; // Relieve var matrixEmboss: Array = [-1, -1, 0, -1, 1, 1, 0, 1, 1];

El valor central es el píxel actual y los valores circundantes son los píxeles vecinos. El valor predeterminado es 1; aumentar este valor hará que la imagen sea más brillante. Disminuirlo hará que sea más oscuro. Tener valores negativos en la parte superior izquierda y valores positivos en la parte inferior derecha (o viceversa) crea un efecto de relieve.

Usando ActionScript, podemos aplicar un filtro de convolución de la siguiente manera:

 // La siguiente matriz iluminará la imagen. var matrixBrighter: Array = [0, 0, 0, 0, 2, 0, 0, 0, 0]; var matrixCol: Number = 3; // Número de columna var matrixRow: Número = 3; // Número de filas var cvFilter: ConvolutionFilter = new ConvolutionFilter (matrixCol, matrixRow, matrixBrighter); var arrFilters: Array = [cvFilter]; displayObj.filters = arrFilters;

Para obtener más información sobre el filtro de convolución, consulte este artículo de Adobe Flash.

Paso 10

Ahora vamos a escribir el código ActionScript. Seleccione el primer cuadro de la capa de "acciones" y vaya al panel Acciones.

Paso 11

Normalmente me gusta mantener el texto consistente en todo el programa. Así que aquí está el código para configurar el texto (Verdana) para todos los componentes globalmente.

 importar fl.managers.StyleManager; formato var: TextFormat = new TextFormat ("Verdana", 10, 0x000000); StyleManager.setStyle ("textFormat", formato);

Paso 12

Ahora vamos a crear una copia de la foto (para aplicar filtros) y colocarla en la misma ubicación que la foto original. Voy a usar la versión B, ya que quiero aplicar una máscara después del filtro. Con la versión A, si aplica un filtro de desenfoque, puede notar que el desenfoque excede la máscara. Eso es porque el filtro está aplicando su efecto después de la máscara..

Más adelante, enmascararemos "photoWrapper" y solo aplicaremos los filtros a "photoEffected".

 / * // Version A var photoEffected: PhotoDandelion = new PhotoDandelion (); photoEffected.x = photoOriginal.x; photoEffected.y = photoOriginal.y; addChild (photoEffected); * / // Versión B var photoWrapper: Sprite = new Sprite (); photoWrapper.x = photoOriginal.x; photoWrapper.y = photoOriginal.y; var photoEffected: PhotoDandelion = new PhotoDandelion (); photoWrapper.addChild (photoEffected); addChild (photoWrapper);

Paso 13

A continuación, cree la línea que separará la foto filtrada y original. Usaremos una forma para dibujar una línea. Coloque la línea en la mitad inferior de la foto, luego trace la línea de abajo hacia arriba.

 var compareLine: Shape = new Shape (); compareLine.x = photoOriginal.x + photoOriginal.width / 2; compareLine.y = photoOriginal.y + photoOriginal.height; compareLine.graphics.lineStyle (2, 0x999999, 1, true); compareLine.graphics.moveTo (0, 0); compareLine.graphics.lineTo (0, -photoOriginal.height); addChild (compareLine);

Paso 14

Recordarás que tenemos un deslizador de máscara. Usando ActionScript, podemos colocarlo debajo de la foto y estirarlo para que su ancho sea el mismo que el ancho de la foto. La configuración de los valores "máximo" y "ancho" al ancho de la foto ayuda a crear una proporción de 1: 1. Por lo tanto, no necesitaremos crear ninguna conversión a escala más adelante. Además, centraremos la flecha en el deslizador..

 mask_sld.x = photoOriginal.x; mask_sld.y = photoOriginal.y + photoOriginal.height; mask_sld.minimum = 0; mask_sld.maximum = photoOriginal.width; mask_sld.value = photoOriginal.width / 2; mask_sld.width = photoOriginal.width;

Paso 15

Ahora vamos a crear la función y asignar el evento para el control deslizante de máscara. Queremos que la "línea de comparación" siga el control deslizante de máscara. El ancho de "PhotoMask" debe cambiar de acuerdo con el control deslizante de la máscara cada vez que se arrastra. Sé que aún no hemos abordado "photoMask", pero ese es el siguiente paso.

 import fl.events.SliderEvent; function maskSliderDrag (evt: SliderEvent): void compareLine.x = evt.target.value + evt.target.x; photoMask.width = evt.target.value;  mask_sld.addEventListener (SliderEvent.THUMB_DRAG, maskSliderDrag, false, 0, true);

Paso 16

Como se mencionó anteriormente, "photoMask" se usará para enmascarar "photoWrapper" en lugar de "photoEffected". Como va a ser una máscara rectangular, usaremos una forma. Establezca la posición y la dimensión del rectángulo de la misma manera que "photoOriginal". Asegúrese de rellenar la forma con un color (puede ser de cualquier color) o la máscara podría no funcionar como se esperaba. A continuación, establezca "photoMask" como máscara de photoWrapper y el ancho de la máscara al "valor" del control deslizante de máscara.

 var photoMask: Shape = new Shape (); photoMask.x = photoOriginal.x; photoMask.y = photoOriginal.y; photoMask.graphics.beginFill (0xff9900); photoMask.graphics.drawRect (0, 0, photoOriginal.width, photoOriginal.height); photoMask.graphics.endFill (); addChild (photoMask); photoWrapper.mask = photoMask; photoMask.width = mask_sld.value;

Paso 17

Necesitamos una forma de almacenar el último botón pulsado, que almacenaremos en "activeFilter". Esto será utilizado más tarde por el control deslizante de intensidad.

 var activeFilter: Button;

Paso 18

A continuación vamos a pasar al control deslizante de intensidad. Definimos la función "cambio de intensidad" que se llamará cada vez que se arrastre el control deslizante de intensidad. La función enviará un evento (es decir, un clic del ratón) en función del último botón presionado. También asignaremos el evento e inicialmente deshabilitaremos el control deslizante..

 función currentChange (evt: SliderEvent): void activeFilter.dispatchEvent (new MouseEvent (MouseEvent.CLICK));  intensity_sld.addEventListener (SliderEvent.THUMB_DRAG, intensidadChange, falso, 0, verdadero); intensity_sld.enabled = false;

Paso 19

Ahora vamos a definir las funciones de filtro. Las funciones de filtro "por defecto" y "negativo" son similares, ya que ambas deshabilitan el control deslizante de intensidad y, por lo tanto, no necesitan actualizar las propiedades del control deslizante. Para "desenfoque", "relieve" y "brillo", todos deben volver a habilitar el control deslizante de intensidad. Además, utilizan la propiedad "valor" para determinar la intensidad del filtro. Además, cada filtro tiene su propio valor "máximo" único, por lo que debemos recalcular el "snapInterval". La propiedad "valor" también se recalcula ya que me gustaría que el control deslizante se reinicie a mitad de camino entre el mínimo y el máximo. Solo necesitamos establecer las propiedades del control deslizante de intensidad cuando el "activeFilter" no es igual al objetivo actual.

 function default_btnHandler (evt: MouseEvent): void var matrixDefault: Array = [0, 0, 0, 0, 1, 0, 0, 0, 0]; var conv: ConvolutionFilter = nuevo ConvolutionFilter (3, 3, matrixDefault); photoEffected.filters = [conv]; activeFilter = evt.target como Button; intensity_sld.enabled = false;  function blur_btnHandler (evt: MouseEvent): void if (activeFilter! = evt.target) intensity_sld.maximum = 30; intensidad_sld.snapInterval = (intensidad_sld.maximum - intensidad_sld.minimum) / 40; intensidad_sld.valor = intensidad_sld.maximum / 2;  var blurX: Number = intensity_sld.value; var blurY: Number = intensity_sld.value; photoEffected.filters = [nuevo BlurFilter (blurX, blurY, BitmapFilterQuality.HIGH)]; activeFilter = evt.target como Button; intensity_sld.enabled = true;  función emboss_btnHandler (evt: MouseEvent): void if (activeFilter! = evt.target) intensity_sld.maximum = 4; intensidad_sld.snapInterval = (intensidad_sld.maximum - intensidad_sld.minimum) / 40; intensidad_sld.valor = intensidad_sld.maximum / 2;  var matrixEmboss: Array = [-intensity_sld.value, -intensity_sld.value, 0, -intensity_sld.value, 1, intensity_sld.value, 0, intensity_sld.value, intensidad_sld.value]; var conv: ConvolutionFilter = nuevo ConvolutionFilter (3, 3, matrixEmboss); photoEffected.filters = [conv]; activeFilter = evt.target como Button; intensity_sld.enabled = true;  función brightness_btnHandler (evt: MouseEvent): void if (activeFilter! = evt.target) intensity_sld.maximum = 6; intensidad_sld.snapInterval = (intensidad_sld.maximum - intensidad_sld.minimum) / 40; intensidad_sld.valor = intensidad_sld.maximum / 2;  var matrixBrightness: Array = [0, 0, 0, 0, current_sld.value, 0, 0, 0, 0]; var conv: ConvolutionFilter = nuevo ConvolutionFilter (3, 3, matrixBrightness); photoEffected.filters = [conv]; activeFilter = evt.target como Button; intensity_sld.enabled = true;  function negative_btnHandler (evt: MouseEvent): void var matrixNegative: ColorMatrixFilter = nuevo ColorMatrixFilter ([- 1, 0, 0, 0, 255, 0, -1, 0, 0, 0, 255, 0, 0, -1, 0, , 255, 0, 0, 0, 1, 0]); photoEffected.filters = [matrixNegative]; activeFilter = evt.target como Button; intensity_sld.enabled = false; 

Nota: Para el filtro "negativo", he usado un ColorMatrixFilter que usa una matriz de 4 por 5 para aplicar transformaciones de color. Para obtener más información sobre ColorMatrixFilter, consulte este artículo de Adobe Flash.

Paso 20

Ahora asignemos cada uno de los botones a sus funciones correspondientes..

 default_btn.addEventListener (MouseEvent.CLICK, default_btnHandler, false, 0, true); blur_btn.addEventListener (MouseEvent.CLICK, blur_btnHandler, false, 0, true); emboss_btn.addEventListener (MouseEvent.CLICK, emboss_btnHandler, false, 0, true); brightness_btn.addEventListener (MouseEvent.CLICK, brightness_btnHandler, false, 0, true); negative_btn.addEventListener (MouseEvent.CLICK, negative_btnHandler, false, 0, true);

Paso 21 - Código final

He creado tres funciones adicionales: "applyConvolutionFilter", "activeFilterAndIntensityOnOff" y "setSliderProperties". Su propósito es reducir la codificación repetitiva en las funciones de filtro..

Su código completo final debe ser similar a este ...

 import fl.events.SliderEvent; importar fl.managers.StyleManager; formato var: TextFormat = new TextFormat ("Verdana", 10, 0x000000); StyleManager.setStyle ("textFormat", formato); var photoWrapper: Sprite = new Sprite (); photoWrapper.x = photoOriginal.x; photoWrapper.y = photoOriginal.y; var photoEffected: PhotoDandelion = new PhotoDandelion (); photoWrapper.addChild (photoEffected); addChild (photoWrapper); var compareLine: Shape = new Shape (); compareLine.x = photoOriginal.x + photoOriginal.width / 2; compareLine.y = photoOriginal.y + photoOriginal.height; compareLine.graphics.lineStyle (2, 0x999999, 1, true); compareLine.graphics.moveTo (0, 0); compareLine.graphics.lineTo (0, -photoOriginal.height); addChild (compareLine); mask_sld.x = photoOriginal.x; mask_sld.y = photoOriginal.y + photoOriginal.height; mask_sld.minimum = 0; mask_sld.maximum = photoOriginal.width; mask_sld.value = photoOriginal.width / 2; mask_sld.width = photoOriginal.width; function maskSliderDrag (evt: SliderEvent): void compareLine.x = evt.target.value + evt.target.x; photoMask.width = evt.target.value;  mask_sld.addEventListener (SliderEvent.THUMB_DRAG, maskSliderDrag); var photoMask: Shape = new Shape (); photoMask.x = photoOriginal.x; photoMask.y = photoOriginal.y; photoMask.graphics.beginFill (0xff9900); photoMask.graphics.drawRect (0, 0, photoOriginal.width, photoOriginal.height); photoMask.graphics.endFill (); addChild (photoMask); photoWrapper.mask = photoMask; photoMask.width = mask_sld.value; var activeFilter: Button; función currentChange (evt: SliderEvent): void activeFilter.dispatchEvent (new MouseEvent (MouseEvent.CLICK));  intensity_sld.addEventListener (SliderEvent.THUMB_DRAG, intensidadChange); intensity_sld.enabled = false; función applyConvolutionFilter (matrix: Array): void var cFilter: ConvolutionFilter = new ConvolutionFilter (3, 3, matrix); photoEffected.filters = [cFilter];  function activeFilterAndIntensityOnOff (btn: Button, intensityOnOff: Boolean): void activeFilter = btn; intensity_sld.enabled = intensidadOnOff;  función setSliderProperties (btn: Button, max: Number): void if (activeFilter! = btn) intensity_sld.maximum = max; intensidad_sld.snapInterval = (intensidad_sld.maximum - intensidad_sld.minimum) / 40; intensidad_sld.valor = intensidad_sld.maximum / 2;  function default_btnHandler (evt: MouseEvent): void var matrixDefault: Array = [0, 0, 0, 0, 1, 0, 0, 0, 0]; applyConvolutionFilter (matrixDefault); activeFilterAndIntensityOnOff (evt.target as Button, false);  function blur_btnHandler (evt: MouseEvent): void var btn: Button = evt.target as Button; setSliderProperties (btn, 30); var blurX: Number = intensity_sld.value; var blurY: Number = intensity_sld.value; photoEffected.filters = [nuevo BlurFilter (blurX, blurY, BitmapFilterQuality.HIGH)]; activeFilterAndIntensityOnOff (btn, true);  function emboss_btnHandler (evt: MouseEvent): void var btn: Button = evt.target como Button; setSliderProperties (btn, 4); var matrixEmboss: Array = [-intensity_sld.value, -intensity_sld.value, 0, -intensity_sld.value, 1, intensity_sld.value, 0, intensity_sld.value, intensidad_sld.value]; applyConvolutionFilter (matrixEmboss); activeFilterAndIntensityOnOff (btn, true);  function brightness_btnHandler (evt: MouseEvent): void var btn: Button = evt.target como Button; setSliderProperties (btn, 6); var matrixBrightness: Array = [0, 0, 0, 0, intensity_sld.value, 0, 0, 0, 0]; applyConvolutionFilter (matrixBrightness); activeFilterAndIntensityOnOff (btn, true);  function negative_btnHandler (evt: MouseEvent): void var matrixNegative: ColorMatrixFilter = nuevo ColorMatrixFilter ([- 1, 0, 0, 0, 255, 0, -1, 0, 0, 0, 255, 0, 0, -1, 0, , 255, 0, 0, 0, 1, 0]); photoEffected.filters = [matrixNegative]; activeFilterAndIntensityOnOff (evt.target as Button, false);  default_btn.addEventListener (MouseEvent.CLICK, default_btnHandler, false, 0, true); blur_btn.addEventListener (MouseEvent.CLICK, blur_btnHandler, false, 0, true); emboss_btn.addEventListener (MouseEvent.CLICK, emboss_btnHandler, false, 0, true); brightness_btn.addEventListener (MouseEvent.CLICK, brightness_btnHandler, false, 0, true); negative_btn.addEventListener (MouseEvent.CLICK, negative_btnHandler, false, 0, true);

Nota: Incluso puede ir más allá de lo que he hecho, como implementar una función central que abarque todos los filtros. Luego use "if if if" o "switch" para ejecutar el código necesario para el filtro correspondiente.

Conclusión

Hay muchas cosas que puedes hacer con los filtros, simplemente te he dado una breve introducción. Los filtros básicos en Flash son bastante buenos, ya que hay suficientes parámetros para jugar. Si no puede encontrar lo que está buscando, pruebe algunos de los otros filtros como ColorMatrixFilter, ConvolutionFilter, DisplacementMapFilter, etc. Puede que le sorprenda lo que encuentre. Sigue experimentando y lo más importante, diviértete.!

Gracias por tomarse el tiempo para ver este tutorial. Espero que hayas encontrado útil.