Exemplo de filtragem de objetos de exibição: bancada do filtro

Flash Player 9 e posterior, Adobe AIR 1.0 e posterior

O Filter Workbench fornece uma interface de usuário para aplicar filtros diferentes em imagens e outros conteúdos visuais e para visualizar o código resultante que pode ser usado para gerar o mesmo efeito no ActionScript. Além de fornecer uma ferramenta para experimentar filtros, esse aplicativo demonstra as seguintes técnicas:

  • Criação de ocorrências de vários filtros

  • Aplicação de vários filtros em um objeto de exibição

Para obter os arquivos de aplicativo desse exemplo, consulte www.adobe.com/go/learn_programmingAS3samples_flash_br . Os arquivos do aplicativo Filter Workbench estão localizados na pasta Amostras/FilterWorkbench. O aplicativo consiste nos seguintes arquivos:

Arquivo

Descrição

com/example/programmingas3/filterWorkbench/FilterWorkbenchController.as

Classe que fornece a principal funcionalidade do aplicativo, incluindo a alternância do conteúdo para os filtros aplicados e a aplicação de filtros no conteúdo.

com/example/programmingas3/filterWorkbench/IFilterFactory.as

Interface que define métodos comuns que são implementados por cada classe padrão de filtro. Essa interface define a funcionalidade comum que a classe FilterWorkbenchController usa para interagir com classes individuais de filtro padrão.

Na pasta com/example/programmingas3/filterWorkbench/:

BevelFactory.as

BlurFactory.as

ColorMatrixFactory.as

ConvolutionFactory.as

DropShadowFactory.as

GlowFactory.as

GradientBevelFactory.as

GradientGlowFactory.as

Conjunto de classes, cada uma delas implementa a interface IFilterFactory. Cada uma dessas classes permite criar e definir valores para um único tipo de filtro. Os painéis de propriedade de filtro do aplicativo usam essas classes padrão para criar ocorrências de filtros específicos, que a classe FilterWorkbenchController recupera e aplica no conteúdo da imagem.

com/example/programmingas3/filterWorkbench/IFilterPanel.as

Interface que define métodos comuns implementados pelas classes que definem os painéis da interface de usuário usados para manipular valores de filtro no aplicativo.

com/example/programmingas3/filterWorkbench/ColorStringFormatter.as

Classe de utilitário que inclui um método para converter um valor de cor numérico em um formato de string hexadecimal

com/example/programmingas3/filterWorkbench/GradientColor.as

Classe que serve como objeto de valor, combinando em um único objeto os três valores (cor, alfa e proporção) associados a cada cor em GradientBevelFilter e GradientGlowFilter

Interface de usuário (Flex)

FilterWorkbench.mxml

O arquivo principal que define a interface de usuário do aplicativo.

flexapp/FilterWorkbench.as

Classe que gera a funcionalidade da interface de usuário do aplicativo principal; essa classe é usada como a classe code-behind do arquivo MXML do aplicativo.

Na pasta flexapp/filterPanels:

BevelPanel.mxml

BlurPanel.mxml

ColorMatrixPanel.mxml

ConvolutionPanel.mxml

DropShadowPanel.mxml

GlowPanel.mxml

GradientBevelPanel.mxml

GradientGlowPanel.mxml

Conjunto de componentes MXML que gera a funcionalidade de cada painel usado para definir opções para um único filtro.

flexapp/ImageContainer.as

Um objeto de exibição que serve como contêiner da imagem carregada na tela

flexapp/controls/BGColorCellRenderer.as

Renderizador de célula personalizado usado para alterar a cor de fundo de uma célula no componente DataGrid

flexapp/controls/QualityComboBox.as

Controle personalizado que define uma caixa combinada que pode ser usada na configuração de qualidade de diversos painéis de filtro.

flexapp/controls/TypeComboBox.as

Controle personalizado que define uma caixa combinada que pode ser usada na configuração de tipo de diversos painéis de filtro.

Interface de usuário (Flash)

FilterWorkbench.fla

O arquivo principal que define a interface de usuário do aplicativo.

flashapp/FilterWorkbench.as

Classe que gera a funcionalidade da interface de usuário do aplicativo principal; essa classe é usada como a classe document do arquivo FLA do aplicativo.

Na pasta flashapp/filterPanels:

BevelPanel.as

BlurPanel.as

ColorMatrixPanel.as

ConvolutionPanel.as

DropShadowPanel.as

GlowPanel.as

GradientBevelPanel.as

GradientGlowPanel.as

Conjunto de classes que geram a funcionalidade de cada painel usado para definir opções para um único filtro.

Para cada classe, também existe um símbolo MovieClip associado na biblioteca do arquivo FLA do aplicativo principal, cujo nome corresponde ao nome da classe (por exemplo, o símbolo “BlurPanel” está vinculado à classe definida em BlurPanel.as). Os componentes que fazem parte da interface de usuário são posicionados e nomeados nesses símbolos.

flashapp/ImageContainer.as

Um objeto de exibição que serve como contêiner da imagem carregada na tela

flashapp/BGColorCellRenderer.as

Renderizador de célula personalizado usado para alterar a cor de fundo de uma célula no componente DataGrid

flashapp/ButtonCellRenderer.as

Renderizador de célula personalizado usado para incluir um componente de botão em uma célula no componente DataGrid

Conteúdo da imagem filtrada

com/example/programmingas3/filterWorkbench/ImageType.as

Essa classe serve como um objeto de valor que contém o tipo e a URL de um único arquivo de imagem no qual o aplicativo pode carregar e aplicar filtros. A classe também inclui um conjunto de constantes que representam os arquivos de imagem reais disponíveis.

images/sampleAnimation.swf,

images/sampleImage1.jpg,

images/sampleImage2.jpg

Imagens e outros conteúdos visuais nos quais os filtros são aplicados no aplicativo.

Como experimentar filtros do ActionScript

O aplicativo Filter Workbench foi desenvolvido para ajudar você a experimentar os diversos efeitos de filtro e gerar o código do ActionScript relevante para esse efeito. O aplicativo permite selecionar entre três arquivos diferentes que possuem conteúdo visual, incluindo imagens de bitmap e uma animação criada no Flash, além de permitir aplicar oito filtros diferentes do ActionScript na imagem selecionada, individualmente ou em combinação com outros filtros. O aplicativo inclui estes filtros:

  • Bisel (flash.filters.BevelFilter)

  • Desfoque (flash.filters.BlurFilter)

  • Matrix de cor (flash.filters.ColorMatrixFilter)

  • Convolução (flash.filters.ConvolutionFilter)

  • Sombra projetada (flash.filters.DropShadowFilter)

  • Brilho (flash.filters.GlowFilter)

  • Bisel de gradiente (flash.filters.GradientBevelFilter)

  • Brilho de gradiente (flash.filters.GradientGlowFilter)

Depois que o usuário seleciona uma imagem e um filtro a ser aplicado nessa imagem, o aplicativo exibe um painel com controles para definir as propriedades específicas do filtro selecionado. Por exemplo, a imagem a seguir mostra o aplicativo com o filtro de bisel selecionado:

À medida que o usuário ajusta as propriedades de filtro, a visualização é atualizada em tempo real. O usuário também pode aplicar vários filtros personalizando um filtro, clicando no botão Apply filter and add another, personalizando outro filtro, clicando no botão Apply filter and add another e assim por diante.

Existem alguns recursos e limitações nos painéis de filtro do aplicativo:

  • O filtro de matriz de cor inclui um conjunto de controles para manipular diretamente propriedades comuns de imagem, como brilho, contrastes, saturação e matiz. Além disso, é possível especificar valores personalizados de matriz de cor.

  • O filtro de convolução, que está disponível somente no ActionScript, inclui no conjunto de valores de matriz de convolução usados normalmente ou valores personalizados podem ser especificados. No entanto, enquanto a classe ConvolutionFilter aceita qualquer tamanho de matriz, o aplicativo Filter Workbench usa uma matriz 3 x 3 fixa, o tamanho de filtro usado com mais frequência.

  • Os filtros de mapa de deslocamento e de sombreador, disponíveis somente no ActionScript, não estão presentes no aplicativo Filter Workbench.

Criação de ocorrências de filtro

O aplicativo Filter Workbench inclui um conjunto de classes, uma para cada filtro disponível, que são usadas por painéis individuais para criar os filtros. Quando o usuário seleciona um filtro, o código do ActionScript associado ao painel de filtro cria uma ocorrência da classe de filtro de fábrica apropriada. Essas classes são conhecidas como classes de fábrica porque sua finalidade é criar ocorrências de outros objetos, assim como uma fábrica real cria produtos individuais.

Sempre que o usuário altera um valor de propriedade no painel, o código do painel chama o método adequado na classe de fábrica. Cada classe de fábrica inclui métodos específicos usados pelo painel para criar a ocorrência de filtro adequada. Por exemplo, se o usuário selecionar o filtro de desfoque, o aplicativo criará uma ocorrência de BlurFactory. A classe BlurFactory inclui um método modifyFilter() que aceita três parâmetros: blurX , blurY e quality , que são usados em conjunto para criar a ocorrência de BlurFilter desejada:

private var _filter:BlurFilter; 
 
public function modifyFilter(blurX:Number = 4, blurY:Number = 4, quality:int = 1):void 
{ 
    _filter = new BlurFilter(blurX, blurY, quality); 
    dispatchEvent(new Event(Event.CHANGE)); 
}

Por outro lado, se o usuário selecionar o filtro de convolução, esse filtro dará uma flexibilidade muito maior e, consequentemente, terá um conjunto maior de propriedades para controlar. Na classe ConvolutionFactory, o código a seguir é chamado quando o usuário seleciona um valor diferente no painel de filtro:

private var _filter:ConvolutionFilter; 
 
public function modifyFilter(matrixX:Number = 0,  
                                                matrixY:Number = 0,  
                                                matrix:Array = null,  
                                                divisor:Number = 1.0,  
                                                bias:Number = 0.0,  
                                                preserveAlpha:Boolean = true,  
                                                clamp:Boolean = true,  
                                                color:uint = 0,  
                                                alpha:Number = 0.0):void 
{ 
    _filter = new ConvolutionFilter(matrixX, matrixY, matrix, divisor, bias, preserveAlpha, clamp, color, alpha); 
    dispatchEvent(new Event(Event.CHANGE)); 
}

Observe que, em cada caso, quando os valores de filtro são alterados, o objeto de fábrica envia um evento Event.CHANGE para notificar os ouvintes que os valores do filtro foram alterados. A classe FilterWorkbenchController, que realmente aplica os filtros no conteúdo filtrado, ouve esse evento para recuperar uma nova cópia do filtro e reaplicá-lo no conteúdo filtrado quando necessário.

A classe FilterWorkbenchController não precisa conhecer os detalhes específicos de cada classe de fábrica de filtro - ela só precisa saber que o filtro foi alterado e acessar uma cópia do filtro. Para dar suporte a isso, o aplicativo inclui uma interface, IFilterFactory, que define o comportamento que uma classe de fábrica de filtro precisa fornecer para que a ocorrência de FilterWorkbenchController do aplicativo possa fazer seu trabalho. A classe IFilterFactory define o método getFilter () que é usado na classe FilterWorkbenchController:

function getFilter():BitmapFilter;

Observe que a definição do método da interface getFilter() especifica o retorno de uma ocorrência de BitmapFilter, em vez de um tipo específico de filtro. A classe BitmapFilter não define um tipo específico de filtro. Em vez disso, BitmapFilter é a classe básica a partir da qual todas as classes de filtro são criadas. Cada classe de fábrica de filtro define uma implementação específica do método getFilter() que retorna uma referência ao objeto de filtro criado. Por exemplo, veja uma versão abreviada do código-fonte da classe ConvolutionFactory:

public class ConvolutionFactory extends EventDispatcher implements IFilterFactory 
{ 
    // ------- Private vars ------- 
    private var _filter:ConvolutionFilter; 
    ... 
    // ------- IFilterFactory implementation ------- 
    public function getFilter():BitmapFilter 
    { 
        return _filter; 
    } 
    ... 
}

Na implementação da classe ConvolutionFactory do método getFilter() , é retornada uma ocorrência de ConvolutionFilter, embora nenhum objeto que chame getFilter() saiba necessariamente disso - de acordo com a definição do método getFilter() seguida por ConvolutionFactory, qualquer ocorrência de BitmapFilter deve ser retornada, a qual pode ser uma ocorrência de qualquer classe de filtro do ActionScript.

Aplicação de filtros em objetos de exibição

Conforme explicado antes, o aplicativo Filter Workbench usa uma ocorrência da classe FilterWorkbenchController (a partir daqui mencionada como “ocorrência do controlador”), que realmente aplica os filtros no objeto visual selecionado. Antes de aplicar um filtro, a ocorrência do controlador precisa saber em qual imagem ou conteúdo visual o filtro deve ser aplicado. Quando o usuário seleciona uma imagem, o aplicativo chama o método setFilterTarget() na classe FilterWorkbenchController, transmitindo uma das constantes definidas na classe ImageType:

public function setFilterTarget(targetType:ImageType):void 
{ 
    ... 
    _loader = new Loader(); 
    ... 
    _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, targetLoadComplete); 
    ... 
}

Usando essas informações, a ocorrência do controlador carrega o arquivo designado, armazenando-o em uma variável da ocorrência chamada _currentTarget assim que o carregamento termina:

private var _currentTarget:DisplayObject; 
 
private function targetLoadComplete(event:Event):void 
{ 
    ... 
    _currentTarget = _loader.content; 
    ... 
}

Quando o usuário seleciona um filtro, o aplicativo chama o método setFilter() da ocorrência do controlador, dando ao controlador uma referência ao objeto de fábrica de filtro relevante, armazenado em uma variável da ocorrência chamada _filterFactory .

private var _filterFactory:IFilterFactory; 
 
public function setFilter(factory:IFilterFactory):void 
{ 
    ... 
     
    _filterFactory = factory; 
    _filterFactory.addEventListener(Event.CHANGE, filterChange); 
}

Observe que, conforme descrito anteriormente, a ocorrência do controlador não sabe o tipo de dados específico da ocorrência de fábrica de filtro fornecida; ela só sabe que o objeto implementa a ocorrência de IFilterFactory, indicando que tem um método getFilter() e envia um evento change ( Event.CHANGE ) quando o filtro é alterado.

Quando o usuário altera as propriedades no painel do filtro, a ocorrência do controlador descobre que o filtro foi alterado por meio do evento change da fábrica de filtro, que chama o método filterChange() da ocorrência do controlador. Esse método, por sua vez, chama o método applyTemporaryFilter() :

private function filterChange(event:Event):void 
{ 
    applyTemporaryFilter(); 
} 
 
private function applyTemporaryFilter():void 
{ 
    var currentFilter:BitmapFilter = _filterFactory.getFilter(); 
     
    // Add the current filter to the set temporarily 
    _currentFilters.push(currentFilter); 
     
    // Refresh the filter set of the filter target 
    _currentTarget.filters = _currentFilters; 
     
    // Remove the current filter from the set 
    // (This doesn't remove it from the filter target, since  
    // the target uses a copy of the filters array internally.) 
    _currentFilters.pop(); 
}

A aplicação do filtro no objeto de exibição ocorre no método applyTemporaryFilter() . Primeiro, o controlador recupera uma referência ao objeto de filtro chamando o método getFilter() da fábrica de filtro.

var currentFilter:BitmapFilter = _filterFactory.getFilter();

A ocorrência do controlador tem uma variável da ocorrência de Array chamada _currentFilters , na qual são armazenados todos os filtros que foram aplicados no objeto de exibição. A próxima etapa é adicionar o filtro recém atualizado a essa matriz:

_currentFilters.push(currentFilter);

Em seguida, o código atribui a matriz dos filtros à propriedade filters do objeto de exibição, que realmente aplica os filtros na imagem:

_currentTarget.filters = _currentFilters;

Finalmente, como esse filtro adicionado recentemente ainda é o filtro de “trabalho”, ele não deve ser aplicado permanentemente no objeto de exibição e, por isso, é removido da matriz _currentFilters :

_currentFilters.pop();

A remoção desse filtro da matriz não afeta o objeto de exibição filtrado porque um objeto de exibição cria uma cópia da matriz de filtros quando esta é atribuída à propriedade filters e usa essa matriz interna em vez da original. Desse modo, todas as alterações feitas na matriz dos filtros não afetam o objeto de exibição até que a matriz seja novamente atribuída à propriedade filters do objeto de exibição.