Você está na página 1de 31

Capítulo 9.

Clipping e Masking (Recorte e mascaramento)

Às vezes você não quer ver uma imagem inteira; por exemplo, você pode querer desenhar uma imagem
como se fosse visto através de binóculos ou um buraco de fechadura; tudo fora do limite das oculares ou
buraco da fechadura será invisível. Ou, você pode querer criar um clima mostrando uma imagem como
se viu por meio de uma cortina translúcida. O SVG realiza esses efeitos com “clipping and masking” -
recorte e mascaramento.

9.1 de recorte em um Path

Quando você cria um documento SVG, você estabelece a sua janela especificando a largura e altura da
área que você está interessado, e esta área torna-se automaticamente a sua área de recorte; qualquer coisa
tirada fora destes limites não será exibida. Você pode estabelecer um recorte em sua própria área com o
elemento <clipPath>.
Aqui é o caso mais simples: o estabelecimento de uma área de clip retangular. Dentro do elemento
<clipPath> estará o elemento <rect> que usaremos para o recorte. O retângulo em si não é exibido; nós
só usaremos as suas coordenadas. Assim, estamos livres para adicionar quaisquer estilos de
preenchimento ou borda que desejamos nos elementos dentro do <clipPath>.
No objeto a ser recortado nós adicionamos uma propriedade de estilo “clip-path” cujo valor referencia o
elemento <clipPath>. Observe que a propriedade é hifenizada e sem letras maiúsculas; o elemento é não
hifenizado e possui letras maiúsculas. No exemplo abaixo, o objeto que está sendo recortado é uma
versão pequena da imagem do gato, do Capítulo 1.

<defs>
<clipPath id="rectClip">
<rect id="rect1" x="15" y="15" width="40" height="45" style="stroke: gray; fill: none;"/>
</clipPath>
</defs>
<!-- clip para retângulo -->
<use xlink:href="minicat.svg#cat" style="clip-path: url(#rectClip);"/>
<!--referência, para mostrar imagem inteira com recorte e área delineada-->
<g transform="translate(100,0)">
<use xlink:href="#rect1"/> <!-- mostra o recorte do retângulo -->
<use xlink:href="minicat.svg#cat"/>
</g>

Como o nome <clipPath> implica, você pode juntar a qualquer caminho arbitrário. Com efeito, o
elemento <clipPath> pode conter qualquer número de formas básicas, elementos <path>, ou elementos
<Text>. O exemplo a seguir mostra um grupo de formas cortadas para um caminho curvo e o mesmo
grupo de formas cortadas pelo texto.

<defs>
<clipPath id="curveClip">
<path id="curve1" d="M5 55 C 25 5, 45 -25, 75 55, 85 85, 20 105, 40 55 Z" style="stroke: black; fill: none;"/>
</clipPath>
<clipPath id="textClip">
<text id="text1" x="20" y="20" transform="rotate(60)" style="font-size: 48pt; stroke: black; fill:
none;">CLIP</text>
</clipPath>
<g id="shapes">
<rect x="0" y="50" width="90" height="60" style="fill: #999;"/>
<circle cx="25" cy="25" r="25" style="fill: #666;"/>
<polygon points="30 0 80 0 80 100" style="fill: #ccc;"/>
</g>
</defs>
<!-- desenha clip-path com curva -->
<use xlink:href="#shapes" style="clip-path: url(#curveClip);" />
<g transform="translate(100,0)">
<use xlink:href="#shapes"/>
<use xlink:href="#curve1"/> <!-- show clip path -->
</g>
<!-- desenha clip-path com texto -->
<g transform="translate(0,150)">
<use xlink:href="#shapes" style="clip-path: url(#textClip);"/>
</g>
<g transform="translate(100,150)">
<use xlink:href="#shapes"/>
<use xlink:href="#text1"/>
</g>

Para ajudá-lo a ver melhor as áreas, o SVG desenha antes o caminho de recorte acima da figura inteira;
você vê isso na metade direita da figura. As coordenadas para os caminhos de clipes anteriores foram
especificadas em coordenadas do usuário. Se você deseja expressar coordenadas em termos de caixa
delimitadora do objeto, em seguida, defina “clipPathUnits” para “objectBoundingBox” (o padrão é
“userSpaceOnUse”). O exemplo seguinte utiliza um caminho de grampo que vai produzir uma janela
circular (ou oval) em qualquer objeto em que é aplicado.
<defs>
<clipPath id="circularPath" clipPathUnits="objectBoundingBox">
<circle cx="0.5" cy="0.5" r="0.5"/>
</clipPath>
<g id="shapes">
<rect x="0" y="50" width="100" height="50" style="fill: #999;"/>
<circle cx="25" cy="25" r="25" style="fill: #666;"/>
<polygon points="30 0 80 0 80 100" style="fill: #ccc;"/>
</g>
<g id="words">
<text x="0" y="19" style="font-size: 12;">
<tspan x="0" y="19">If you have form'd a circle</tspan>
<tspan x="12" y="33">to go into,</tspan>
<tspan x="0" y="47">Go into it yourself</tspan>
<tspan x="12" y="61">and see how you would do.</tspan>
<tspan x="50" y="80">&#xad;William Blake</tspan>
</text>
</g>
</defs>
<use xlink:href="#shapes" style="clip-path: url(#circularPath);" />
<use xlink:href="#words" transform="translate(110,0)"
style="clip-path: url(#circularPath);"/>
Na Figura abaixo, as figuras geométricas estão em uma caixa delimitadora quadrada, de modo que o
recorte aparece circular. O texto é delimitado por uma área retangular, de modo que a área de recorte
parece ser uma forma oval.

Especificar um retângulo de recorte para as tags <marker> e <symbol> com a propriedade de estilo clip.
O seu valor é em número de quatro espaços separados que especificam os retângulos que formam os
limites superior, direito, inferior e esquerdo. Isso define o retângulo de corte para coincidir com o
marcador ou símbolo de viewBox, em vez de sua janela.

9.2 Masking

Uma máscara em SVG é exatamente o oposto da máscara que você usa para uma festa a fantasia. Com
uma máscara de festa a fantasia, as partes que são opacas escondem seu rosto; as partes que são
translúcidas deixam as pessoas ver o seu rosto vagamente, e os furos (que são transparentes) deixam
as pessoas verem o seu rosto claramente. Uma máscara SVG, por outro lado, transfere a sua
transparência para o objeto que ela mascara. Onde a máscara é opaca, os pixels opacos do objeto são
mascarados. Onde a máscara é translúcida, assim é o objeto, e as partes transparentes da máscara fazem
as partes correspondentes do objeto mascarado, invisíveis.

Você usa o elemento <mask> para criar uma máscara. Você pode especificar as dimensões da máscara
com os atributos (x, y, width, height). Estas dimensões são em termos do “objectBoundingBox”
mascarado. Se você quer que as dimensões sejam em termos de coordenadas de espaço do usuário,
defina “maskUnits” para “userSpaceOnUse”.

Entre as tags de início <mask> e término </mask> podem existir quaisquer formas básicas, textos ou
caminhos que você deseja usar como máscara. As coordenadas sobre estes elementos são expressos
no espaço do usuário por coordenadas padrão. Se você deseja usar a “objectBoundingBox” para o
conteúdo da máscara, defina “maskContentUnits” como “objectBoundingBox”. (O padrão é
“userSpaceOnUse”).
A questão torna-se então: como SVG determina a transparência, ou valor alfa de uma a máscara?
Sabemos que cada pixel é descrito por quatro valores: os valores de cor, vermelho, verde e azul, e sua
opacidade. Embora à primeira vista pareça lógico utilizar apenas o valor de opacidade, o SVG decide
usar todas as informações de que dispõe em vez de jogar informações de distância de três quartos de um
pixel. SVG utiliza esta fórmula:

(0.2125 * red value +


0.7154 * green value +
0.0721 * blue value) *
opacity value

Onde todos os valores são números de ponto flutuante na gama de 0 a 1. Você deve estar surpreso que
as proporções não são iguais, mas se você olhar para vermelho, verde, e azul, totalmente saturado, o
verde parece ser a mais brilhante, o vermelho e azul mais escuro. Quanto mais escura a cor, tanto menor
será o valor alfa resultante, e a menor opacidade o objeto será mascarado.

O exemplo a seguir cria um texto preto e um círculo preto mascarado por um quadrado vermelho,
verde, azul, e branco totalmente opaco. O texto e o círculo são agrupados e o grupo usa uma
propriedade de estilo de máscara para fazer referência a máscara apropriada.

<defs>
<mask id="redmask" x="0" y="0" width="1" height="1" maskContentUnits="objectBoundingBox">
<rect x="0" y="0" width="1" height="1" style="fill: #f00;"/>
</mask>
<mask id="greenmask" x="0" y="0" width="1" height="1" maskContentUnits="objectBoundingBox">
<rect x="0" y="0" width="1" height="1" style="fill: #0f0;"/>
</mask>
<mask id="bluemask" x="0" y="0" width="1" height="1" maskContentUnits="objectBoundingBox">
<rect x="0" y="0" width="1" height="1" style="fill: #00f;"/>
</mask>
<mask id="whitemask" x="0" y="0" width="1" height="1" maskContentUnits="objectBoundingBox">
<rect x="0" y="0" width="1" height="1" style="fill: #fff;"/>
</mask>
</defs>
<!-- mostra a cor para mostrar o brilho relativo (luminance) -->
<rect x="10" y="10" width="50" height="50" style="fill: #f00;"/>
<rect x="70" y="10" width="50" height="50" style="fill: #0f0;"/>
<rect x="130" y="10" width="50" height="50" style="fill: #00f;"/>
<rect x="190" y="10" width="50" height="50" style="fill: #fff; stroke: black;"/>
<g style="mask: url(#redmask); font-size: 14pt; text-anchor: middle;">
<circle cx="35" cy="115" r="25" style="fill: black;"/>
<text x="35" y="80">Red</text>
</g>
<g style="mask: url(#greenmask); font-size: 14pt; text-anchor: middle;">
<circle cx="95" cy="115" r="25" style="fill: black;"/>
<text x="95" y="80">Green</text>
</g>
<g style="mask: url(#bluemask); font-size: 14pt; text-anchor: middle;">
<circle cx="155" cy="115" r="25" style="fill: black;"/>
<text x="155" y="80">Blue</text>
</g>
<g style="mask: url(#whitemask); font-size: 14pt; text-anchor: middle;">
<circle cx="215" cy="115" r="25" style="fill: black;"/>
<text x="215" y="80">White</text>
</g>

9.3 Estudo de Caso - Mascaramento de gráfico

O exemplo a seguir acrescenta uma imagem JPG para a imagem que foi construída na Seção 8.10.
Como você pode ver (reduzida para economizar espaço e em escala de cinza para evitar o uso de tinta de
cor), a imagem obscurece a curva dentro da elipse principal, e o céu azul invade horrivelmente na seção
de vermelho pálido.

<defs>
<font-face font-family="bakbatn">
<font-face-src>
<font-face-uri xlink:href="kfont.svg#kfont-defn"/>
</font-face-src>
</font-face>
</defs>
<!-- desenha a elipse e o texto -->
<use xlink:href="ksymbol.svg#ksymbol"/>
<image xlink:href="kwanghwamun.jpg" x="72" y="92" width="160" height="120"/>

A solução é desvanecer-se para fora das bordas da imagem, o que pode ser feito facilmente usando um
gradiente radial como uma máscara. Aqui está o código para ser adicionado à seção <defs> do
documento:
<radialGradient id="fade">
<stop offset="0%" style="stop-color: white; stop-opacity: 1.0;"/>
<stop offset="85%" style="stop-color: white; stop-opacity: 0.5;"/>
<stop offset="100%" style="stop-color: white; stop-opacity: 0.0;"/>
</radialGradient>
<mask id="fademask">
<rect x="72" y="92" width="160" height="120" style="fill: url(#fade);"/>
</mask>

Então adicione a máscara referenciando com uma tag <image>

<image xlink:href="kwanghwamun.jpg" x="72" y="92" width="160" height="120" style="mask: url(#fademask);"/>

Utilizando menos parte da imagem pode melhorar substancialmente o gráfico como um todo.
Capítulo 10 – Filtros

Os capítulos anteriores deram-nos uma base para a criação de gráficos que transmitem informações com
grande precisão e detalhe. Se você vai a um piquenique na primavera, você quer um mapa preciso.
Quando você olha no jornal para os gráficos que descrevem a previsão do tempo, quer "apenas os fatos."
Se você for solicitado mais tarde para descrever o dia do piquenique, ninguém quer uma recitação
precisa das estatísticas meteorológicas. Da mesma forma, ninguém quer ver um gráfico de uma flor
composto por vetores puros, totalmente desprovida da qualidade de transmitir qualquer calor ou
charme.

Os gráficos são frequentemente concebidos para evocar sentimentos ou estados de humor, tanto quanto
eles são feitos para transmitir informação. Artistas que trabalham com gráficos de bitmap têm muitas
ferramentas à sua disposição para adicionar tais efeitos; eles podem produzir sombras borradas,
seletivamente engrossar linhas finas ou adicionar texturas a partes do desenho, fazer um objeto parecer
estar em relevo ou chanfrado, etc.

10.1 Como os filtros funcionam

Embora o SVG não seja uma linguagem de descrição de bitmap, ele ainda permite que você use algumas
destas mesmas ferramentas. Quando um programa visualizador de SVG processa um objeto gráfico, ele
irá processá-lo para algum dispositivo de saída de bitmap; em algum momento o programa irá converter
a descrição matemática do objeto para um conjunto adequado de pixels que aparecem no dispositivo de
saída.
Agora vamos dizer que você use o elemento SVG <filter> para especificar um conjunto de operações que
exibirá um objeto com uma sombra embaçada ligeiramente deslocada para o lado, e anexar esse filtro a
um outro objeto:

<filter id="drop-shadow">
<!-- operação de filtro aqui -->
</filter>
<g id="spring-flower"
style="filter: url(#drop-shadow);"/>
<!-- desenho da flor, aqui -->
</g>

Porque a flor usa um filtro no seu estilo de apresentação, o SVG não tornará a flor diretamente para o
gráfico final. Em vez disso, o SVG irá processar os pixels da flor em um bitmap temporário. As
operações especificadas pelo filtro serão aplicadas a essa área temporária e o resultado será traduzido para
o gráfico final.
10.2 Criando um Drop Shadow

No capítulo 4, no ponto 4.3.5, criamos uma sombra projetada por compensação de uma elipse cinza
debaixo de uma elipse em cores. Funcionou, mas não era elegante. Vamos investigar uma forma de criar
uma sombra mais bonita com um filtro.

10.2.1 Estabelecer limites do filtro

O elemento <filter> tem atributos que descrevem a região de recorte para um filtro. Você especifica os
atributos (x, y, width, height) em termos da percentagem da caixa delimitadora do objeto filtrado. (Esse
é o padrão.) Qualquer parte da saída resultante que está fora dos limites não serão exibidos. Se você está
pretendendo aplicar um filtro para muitos objetos, você pode querer omitir esses atributos
completamente e tomar os valores padrão de x igual a -10%, Y igual a -10%, largura igual a 120%, e
altura igual a 120%. Isto dá espaço extra para filtros - como a sombra que estamos construindo – que
produzem saída maior do que a sua entrada.

Esses atributos são, em termos de caixa delimitadora do objeto filtrado; especificamente, “filterUnits”
tem um valor de “objectBoundingBox” por padrão. Se você deseja especificar limites em unidades do
usuário, em seguida, defina o valor do atributo para “userSpaceOnUse”.

10.2.2 Usando feGaussianBlur para uma Drop Shadow

Entre as tags <filter> de início e fim são as primitivas de filtros que executam as operações que você
deseja. Cada primitiva tem uma ou mais entradas, e exatamente uma saída. Uma entrada pode ser o
gráfico original, especificado como “SourceGraphic”, o canal alfa (opacidade) do gráfico, especificado
como “SourceAlpha”, ou a saída de uma filtragem primitiva prévia. Você provavelmente irá utilizar a
fonte alfa com mais frequência, uma vez que evita as interações de alfa e cor, conforme descrito no
Capítulo 9, na Seção 9.2.

O exemplo abaixo é a nossa primeira tentativa de produzir uma sombra sobre a flor, usando o filtro
primitivo <FeGaussianBlur>. Nós especificamos “SourceAlpha” como sua entrada (no atributo), e a
quantidade de desfoque com o atributo “stdDeviation”. Quanto maior for esse número, maior será o
efeito de arrastamento. Se você dá dois números separados por espaços em branco como valor para
“stdDeviation”, o primeiro número é tomado como o “blur” na direção-x e o segundo, como o “blur”
na direção y.

<filter id="drop-shadow">
<feGaussianBlur in="SourceAlpha" stdDeviation="2"/>
</filter>
</defs>
<g id="flower" filter="url(#drop-shadow)">
<!-- drawing here -->
</g>
Não se surpreenda; lembre que o filtro retorna a saída, o qual é um canal alfa turvo, em vez do gráfico
fonte original. Poderíamos obter o efeito que queremos colocando a flor dentro da seção <defs> do
documento e mudar a nossa SVG para ler:

<use xlink:href="#flower" filter="url(#drop-shadow)" transform="translate(4, 4)"/>


<use xlink:href="#flower"/>

No entanto, isso exigiria SVG para executar todos os elementos que compõem a flor duas vezes. Em vez
disso, vamos adicionar mais primitivas de filtro, de modo que todo o trabalho possa ser tratado durante
o processamento.

10.2.3 Armazenando, Encadeando, Fundindo e Filtrando Resultados

<filter id="drop-shadow">
<feGaussianBlur in="SourceAlpha" stdDeviation="2" result="blur"/>
[1]
<feOffset in="blur" dx="4" dy="4" result="offsetBlur"/> [2]
<feMerge> [3]
<feMergeNode in="offsetBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>

[1] O atributo “resultado” especifica que o resultado desta primitiva pode ser referenciado mais tarde
pelo nome “blur”. Isto não é como um ID de XML; o nome que você dá é um nome local que é válido
apenas para a duração das primitivas contidos no atual <filter>.

[2] A primitiva <feOffset> leva a sua entrada, neste caso, o “blur” resultado do “Gaussian Blur”, a
compensar os valores dx e dy especificados, e armazena o bitmap resultante sob o nome “offsetBlur”.

[3] A primitiva <feMerge> inclui uma lista de elementos <feMergeNode>, cada um dos quais especifica
uma entrada. As entradas são empilhadas uma em cima da outra na ordem em que elas aparecerem.
Neste caso, queremos que o “offsetBlur” fique abaixo do “sourceGraphic” original.

Nós agora nos referimos a esta sequência do filtro “drop shadow”, onde o desenho original da flor, à
frente, produz uma imagem surpreendentemente agradável.

<g id="flower" filter="url(#drop-shadow)">


<!-- drawing here -->
</g>
Quando você começar a trabalhar com filtros, eu recomendo fortemente que você faça as coisas em
etapas, testando filtros, um de cada vez. Eu criei um grande número de resultados incrivelmente feios
durante tentativas fracassadas para descobrir como um filtro realmente funciona. Provavelmente vai
acontecer com você, também. Nós vamos mantê-lo como nosso pequeno segredo.

Da mesma forma, quando você aprender sobre filtros, você será tentado a aplicar muitos deles, tantos
quanto possível a um desenho, só para ver o que vai acontecer. Desde que a sua finalidade seja a
experimentação, vá em frente. Os filtros devem apoiar e melhorar a sua mensagem, não oprimi-la. O
uso criterioso de um ou dois filtros é uma bóia; uma flotilha de filtros quase sempre afunda a
mensagem.

10.3 Criando uma GlowingShadow (sombra incandescente)

A dropShadow funcionou bem na flor, mas parece totalmente inexpressiva quando aplicada em texto.

Em vez disso, nós gostaríamos de uma área de turquesa brilhante para cercar o texto, e podemos fazer
isso com a primitiva <feColorMatrix> para mudar de preto para uma cor diferente.

10.3.1 O elemento <feColorMatrix>

O elemento <feColorMatrix> permite alterar os valores de cor de uma forma muito generalizada. A
sequência de primitivas usadas para criar uma sombra turquesa incandescente é mostrado no exemplo a
seguir.

<filter id="glow">
<feColorMatrix type="matrix" [1]
values=
"0 0 0 0 0
0 0 0 0.9 0
0 0 0 0.9 0
0 0 0 1 0"/>
<feGaussianBlur stdDeviation="2.5" [2]
result="coloredBlur"/> [3]
<feMerge> [4]
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>

[1] O <feColorMatrix> é um primitivo muito versátil, o que lhe permite modificar qualquer um dos
valores de cor ou alfa de um pixel. Quando o atributo de tipo é igual à matriz, você deve definir o valor
para uma série de vinte números que descrevem a transformação.
Para configurar uma transformação que adiciona cor para os valores alfa, configure seus valores da
matriz do seguinte modo:
= valores
"0 0 0 0 vermelho
0 0 0 0 verde
0 0 0 0 azul
00010"

onde os valores de vermelho, verde e azul são números decimais que geralmente variam de zero a 1.
Neste exemplo, nós definimos o vermelho para zero, e os valores de verde e azul para 0,9, o que vai
produzir uma cor ciano brilhante.

Você vai notar que nós não especificamos em um atributo de entrada para este primitivo; o padrão
é a utilização do “SourceGraphic”. Também não colocamos um atributo de resultado para este
primitivo. Isto significa que a produção da operação matricial da cor está disponível apenas como a
entrada implícita para o próximo filtro primitivo. Se você utilizar este atalho, então a próxima primitiva
de filtro não deve ter um atributo.

[2] Agora que temos uma fonte de cor ciano, usamos “Gaussian Blur” para espalhá-la para fora.
[3] O borrão cor de ciano resultante é armazenado para referência futura como “coloredBlur”.
[4] Tal como no exemplo anterior, usamos <feMerge> para a saída do brilho baixo do objeto em
questão.
Com estes dois filtros, podemos melhorar a imagem:

<g id="flower" style="filter: url(#drop-shadow);">


<!-- desenho da flor -->
</g>
<text x="120" y="50" style="filter: url(#glow); fill: #003333; font-size:18;>Spring <tspan x="120"
y="70">Flower</tspan>
</text>

10.3.2 Mais sobre o elemento feColorMatrix

Começamos com o tipo mais geral da matriz de cores, onde você começa a especificar qualquer valor
que desejar. Há três outros valores para o atributo “type”. Cada um desses "Built-in" (construtores) de
matrizes de cor realiza uma tarefa visual específica e tem a sua própria maneira de especificar valores.

et ao u R h
O valor é um número único que informa quantos graus os valores de cor devem ser rodados. A
matemática utilizada para alcançar este, é muito semelhante àquela utilizada na transformação de
rotação, conforme descrito na Secção 5.5, do Capítulo 5.
A relação entre a rotação e a cor resultante não é de modo algum óbvio, como se mostra abaixo:

et a ur s
O atributo especifica valores em um único número no intervalo de zero a um. Quanto menor o
número, mais "lavadas" as cores serão, como se vê na figura.

aphlAo eTacniuml
Este filtro cria um canal alfa baseado na luminosidade de uma cor. A luminância é o "brilho" inerente
de uma cor, conforme descrito na Seção 9.2 no Capítulo 9. Na figura, a luminância dos quadrados de
cor é usada como um canal alfa para quadrados pretos sólidos. Quanto mais uma cor é iluminada,
menor transparência confere ao objeto filtrado. O atributo de valores é ignorado para este tipo.

10.4 O Filtro feImage

Até este ponto, nós usamos apenas o gráfico original ou seu canal alfa como entrada para um filtro. O
elemento SVG <feImage> permite que você use qualquer JPG, PNG ou SVG; ou um elementoSVG
com uma ID de atributo como entrada para um filtro. No exemplo abaixo, nós importamos uma
imagem de céu com uma nuvem, para usar como pano de fundo na foto da flor.
<defs>
<filter id="sky-shadow" filterUnits="objectBoundingBox">
<feImage xlink:href="sky.jpg" result="sky"/>
<feGaussianBlur in="SourceAlpha" stdDeviation="2" result="blur"/>
<feOffset in="blur" dx="4" dy="4" result="offsetBlur"/>
<feMerge>
<feMergeNode in="sky"/>
<feMergeNode in="offsetBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<g id="flower" style="filter: url(#sky-shadow)">
<!-- imagem da flor -->
</g>
<!-- mostra imagem original -->
<image xlink:href="sky.jpg" x="170" y="10" width="122" height="104"/>

Uma vez que estamos fazendo referência a uma imagem JPG, estende-se para encher a caixa
delimitadora do objeto filtrado. A figura a seguir mostra o resultado, com a imagem original do céu
mostrado à direita no seu verdadeiro tamanho.

10.5 O Filtro feComponentTransfer

O problema com o fundo é que é muito escuro. Usar o “saturate” não é a melhor resposta; ele aumenta
ou diminui todos os níveis de cor. O que precisamos fazer é aumentar o nível de verde e vermelho mais
do que o nível de azul, e o elemento <feComponentTransfer> nos permite fazer justamente isso.

Você ajusta os níveis de vermelho, verde, azul e alfa, colocando um elemento <feFuncR>,
<feFuncG>,<FeFuncB> e <feFuncA> dentro do <feComponentTransfer>. Cada um desses sub-
elementos podem especificar, independentemente, um atributo do tipo que diz como esse canal
particular deve ser modificado.

Para simular o efeito de um controle de brilho, você especifica a função linear, que coloca o atual valor
de cor C na fórmula: Inclinação * C + intersecção. A intersecção fornece um "valor base" para o
resultado; a inclinação é um fator de escala simples. O Exemplo a seguir usa um filtro que adiciona um
céu iluminado com a flor com “drop shadow”. Note-se que os canais vermelho e verde são ajustados de
forma diferente do que o canal azul. Este ilumina drasticamente o céu na figura anterior.
<filter id="brightness-shadow" filterUnits="objectBoundingBox">
<feImage xlink:href="sky.jpg" result="sky"/>
<feComponentTransfer in="sky" result="sky">
<feFuncB type="linear" slope="3" intercept="0"/>
<feFuncR type="linear" slope="1.5" intercept="0.2"/>
<feFuncG type="linear" slope="1.5" intercept="0.2"/>
</feComponentTransfer>
<feGaussianBlur in="SourceAlpha" stdDeviation="2" result="blur"/>
<feOffset in="blur" dx="4" dy="4" result="offsetBlur"/>
<feMerge>
<feMergeNode in="sky"/>
<feMergeNode in="offsetBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>

Um ajuste linear simples irá somar e multiplicar a mesma quantidade para cada valor de cor dentro de
um canal. Este não é o caso com a função gama, que coloca o valor corrente de cor C na fórmula:
amplitude * Cexpoente + offset. O deslocamento fornece um "valor base" para o resultado; a amplitude é
um fator de escala simples e o expoente faz com que o resultado seja uma linha curva em vez de uma
linha reta. Uma vez que o valor de cor é sempre entre zero e um, quanto maior for o seu expoente, tanto
menor será o valor modificado.
A figura a seguir mostra as curvas geradas com valores expoente de 0,6 (linha sólida) e 0,3 (linha
tracejada). Olhando para a linha tracejada, você pode ver que um baixo valor da cor original, como 0.1
será ampliada para 0,5, um aumento de 400%. Um valor original de 0,5, por outro lado, vai aumentar
apenas 80%, para 0,9.
Quando você especificar um filtro de gama, você define os atributos “amplitude”, “exponent”, e “offset”
para corresponder aos valores na fórmula anterior. O exemplo a seguir usa correção de gama para ajustar
o céu. Neste caso particular, as diferenças entre a figura a seguir e anterior são menores, mas existem
algumas imagens que podem ser melhoradas muito mais por um método do que pelo outro.

<feImage xlink:href="sky.jpg" result="sky"/>


<feComponentTransfer in="sky" result="sky">
<feFuncB type="gamma" amplitude="1" exponent="0.2" offset="0"/>
<feFuncR type="gamma" amplitude="1" exponent="0.707" offset="0"/>
<feFuncG type="gamma" amplitude="1" exponent="0.707" offset="0"/>
</feComponentTransfer>

O leitor pode ter observado que ambas as funções, “linear” e “gama” podem produzir valores de cor
maiores do que 1,0. A especificação SVG diz que isto não é um erro; após cada filtro primitivo, o
processador SVG vai fixar os valores para um intervalo válido.
Assim, qualquer valor maior do que 1,0 será reduzido para 1,0 e qualquer valor menor que zero será
definido como zero.

<FeComponentTransfer> tem outras opções para o atributo “type”. Por favor, note que você pode
misturar e combinar qualquer um destes; você pode corrigir os valores de vermelho, enquanto ilumina
os valores de verde com uma função linear.

ytiedn
A função de "não fazer nada". Isso permite que você declare explicitamente que um canal de cor deve
permanecer inalterado. (Este é o padrão se você não fornecer um elemento <feFuncX> para um canal
em particular.)

elbat
Permite dividir os valores de cor em uma série de intervalos iguais, cada um dos quais será
proporcionalmente dimensionado. Considere o seguinte remapeamento, que duplica o valor do menor
quarto da gama de cores, aperta o próximo quarto em um intervalo de um décimo, mantém o terceiro
quarto na exata proporção, então aperta o último quarto de valores nos restantes 15% da gama de cores:
Você deve especificar esse mapeamento para o canal verde, listando os pontos finais da gama remapeada
na tabela dos valores de atributos.
<feFuncG type="table" tableValues ="0.0, 0.5, 0.6, 0.85, 1.0"/>

Se você está dividindo o espectro de entrada em n seções diferentes, você deve fornecer n + 1 nos valores
da tabela, separados por espaços em branco ou vírgulas.

etcrsid
Permite dividir os valores de cor em uma série de intervalos iguais, cada um dos quais será mapeado para
um único valor de cor discreta. Considere o seguinte remapeamento, que mapeia o valor do menor
quarto da gama de cores para 0,125, define o próximo quarto, para 0,375, o terceiro quarto, para 0,625,
e quarto restante para 0,875. (Isto é, cada quarto do intervalo é mapeado para o seu ponto central.)

Você deve especificar esse mapeamento para o canal verde, listando os valores discretos, separados por
vírgulas ou espaços em branco, no atributo “tableValues”.

<feFuncG type="discrete" tableValues ="0.125 0.375 0.625 0.875"/>

Dividir o canal de entrada em n seções requer n entradas no atributo “tableValues”. Exceção: Se você
deseja remapear todos os valores de entrada para um único valor de saída, você deve colocar essa entrada
em “tableValues” duas vezes; Assim, para definir qualquer entrada de valor do canal de azul para 0,5,
você faria:
<feFuncB type="discrete" tableValues="0.5 0.5"/>

Se você quiser inverter a gama de valores de cor para um canal (isto é, alterar valores crescentes a partir
do mínimo para o máximo e para valores decrescentes a partir do máximo para o mínimo), utilizar o
seguinte:
<feFuncX type="table" tableValues="maximum minimum"/>

Normalmente, os valores para vermelho, verde ou azul correm em uma linha reta de zero a um, com 0
sendo nenhuma cor e 152 sendo 100% da cor. Isto é chamado um espaço de cor linear. Contudo,
quando o SVG calcula os valores de cor entre os limites de gradiente (como descrito no Capítulo 7, na
Seção 7.2), ele usa uma forma especial de representar a cor de tal forma que os valores não seguem uma
linha reta de zero a um. Esta representação é chamado de padrão RGB ou espaço de cor sRGB, e seu uso
pode fazer gradientes com aparência muito mais natural. A Figura a seguir mostra uma comparação. O
primeiro gradiente vai do preto ao verde, o segundo de vermelho para verde e para azul, e o terceiro de
preto para branco.

Por padrão, filtros aritméticos calculam quaisquer valores interpolados ( “In-between”) no espaço RGB
linear, por isso, se você aplicar um filtro a um objeto que tenha sido preenchido com um gradiente, você
terá resultados que não são os que você espera. A fim de obter o correto resultado, você deve dizer ao
filtro para fazer os seus cálculos no espaço sRGB adicionando uma “color-interpolation-filters='sRGB'“
no seu elemento <filter>. Alternativamente, você pode deixar o filtro sozinho e aplicar “color-
interpolation='linearRGB'” para o elemento <gradient>, ele usa o mesmo espaço de cor como padrão
para filtros.

10.6 O Filtro feComposite

Até agora, temos combinado os resultados de filtros usando <feMerge> para a camada de resultados
intermediários um sobre o outro. Vamos agora investigar o elemento <feComposite> muito mais geral.
Este elemento tem duas entradas, especificados com os atributos “in” e “in2”, e um “operator” que
conta como os dois devem ser combinados. Na sequência da explicação, vamos supor que você tenha
especificado in = "A" e in2 = "B".
<feComposite operator="over" in="A" in2="B"/>

Produz o resultado de camadas A mais B, exatamente como <feMergeNode> faz. De fato,


<feMergeNode> é realmente apenas um atalho conveniente para um elemento <feComposite> que
especifica uma operação “over”.
<feComposite operator="in" in="A" in2="B"/>

O resultado é a parte do “A” que está dentro dos limites do “B”. Não confunda o nome desse valor do
atributo com o atributo “in”.
<feComposite operator="out" in="A" in2="B"/>

O resultado é a parte de “A” que está fora dos limites de “B”.


<feComposite operator="atop" in="A" in2="B"/>

O resultado é a parte de “A” que está dentro de “B”, assim como a parte de “B” fora de “A”. Para
citar o artigo em que estes operadores foram definidos em primeiro lugar: "... o papel do “atop” na
tabela inclui o papel que está em cima da tabela, e tabela de outra forma; a área além da borda da tabela
está fora da imagem. "
"Imagens de composição digital," T. Porter, T. Duff, SIGGRAPH '84 Anais de conferências, Association
for Computing Machinery, Volume 18, Número 3, Julho de 1984.
<feComposite operator="xor" in="A" in2="B"/>

O resultado é a parte de “A” que está do lado de fora de “B”, em conjunto com a parte de “B” que está
fora de “A”.
<feComposite in="A" in2="B" operator="arithmetic" .../>

O máximo em flexibilidade. Você fornece quatro coeficientes, k1, k2, k3 e k4. O resultado para cada
pixel é calculado como:
k1 * A * B + k2 * A + k3 * B + k4

O operador aritmético é útil para fazer um efeito de "dissolve" (dissolver). Se vocês querem ter uma
imagem resultante que é “a% “ de uma imagem “A” e “b%” de uma imagem “B”, defina K1 e K4 como
zero, k2 como “a/100”, e K3 como “b/100”. Assim, fazendo uma mistura com 30% de A e 70% de B,
você pode usar isto:
<feComposite in="A" in2="B" result="combined" k1="0" k2="0.30" k3="0.70" k4="0"/>

Uso do <feComposite> “in” e “out”

<defs>
<filter id="sky-in" filterUnits="objectBoundingBox">
<feImage xlink:href="sky.jpg" result="sky"/>
<feComposite in="sky" in2="SourceGraphic" operator="in"/>
</filter>
<filter id="sky-out" filterUnits="objectBoundingBox">
<feImage xlink:href="sky.jpg" result="sky"/>
<feComposite in="sky" in2="SourceGraphic" operator="out"/>
</filter>
<g id="flower">
<!-- O gráfico da flor vem aqui -->
</g>
</defs>
<use xlink:href="#flower" transform="translate(10,10)" style="filter: url(#sky-in);"/>
<use xlink:href="#flower" transform="translate(170,10)" style="filter: url(#sky-out);"/>
10.7 O filtro <feBlend>

Mas espere, tem mais! Sim, os filtros oferecem ainda uma outra maneira de combinar imagens. O
elemento <FeBlend> requer duas entradas, especificados com os atributos “in” e “in2”, e um “mode”
que conta como as entradas para serem misturadas (blended). Os valores possíveis são: “normal”,
“multiply”, “screen”, “lighten”, e “darken”. Dadas as entradas com cores opacas <feBlend in = "A"
in2 = "B" mode = "m" />, a tabela a seguir mostra a cor do pixel resultante para cada modo:

Modo Efeito
normal somente B; isto é o mesmo que o operador “over” em <feMerge>.
multiply Como o nome sugere, o valor da cor resultante é o produto do valor da cor de A e valor
da cor de B. Isto tende a enfraquecer drasticamente as cores claras.
screen Adiciona os valores de cores em conjunto, em seguida, subtrai o seu produto. Isso tende
a fortalecer a luz das cores do que as cores mais escuras.
darken Pega o mínimo de A e B. Esta é a cor mais escura, daí o nome.
lighten Pega o máximo de A e B. Esta é a cor mais clara, daí o nome.

Note-se que o cálculo apropriado é feito de forma independente para cada um dos valores de vermelho,
verde, e azuis. Então, se fosse para você escurecer um quadrado vermelho puro, com valores RGB de
(100%, 0%, 0%) e um quadrado cinza com valores de RGB (50%, 50%, 50%), a cor resultante seria
(50%, 0%, 0%). Se as entradas não são opacas, então todos os modos, exceto no “screen”, atuam nas
transparências ao fazer os cálculos.

Finalmente, uma vez que o valor da cor é calculado, a opacidade do resultado é determinado pela
fórmula “1 - (1 - opacidade de A) * (1 - opacidade de B)”. Utilizando esta fórmula, dois itens opacos
ainda serão opacos; dois itens que são 50% opaco irão combinar com um que é 75% opaco.

A figura abaixo mostra o resultado da mistura de um sólido cinzento opaco (50%, 50%, 50%) barra
com quadrados de cores opacas a 50% que têm valores RGB de preto (# 000), amarelo (# ff0), vermelho
(# f00), verde médio brilhante (# 0C0) e azul escuro (# 009).
10.8 O filtro <feFlood> e <feTile>

Os elementos <feFlood> e <feTile> são "filtros utilitários". Muito parecido com <feOffset>, eles
permitem que você realize determinadas operações comuns dentro de uma série de primitivas de filtro
em vez de ter que criar elementos SVG extras em seu gráfico principal.

<feFlood> fornece uma área de cor sólida para uso em composição ou fusão. O usuário fornece o “flood-
fill-color” e “flood-fill-opacity”, e o filtro faz o resto.

<feTile> Transforma as entradas em ladrilhos e preenche, horizontal e verticalmente, a área especificada


no filtro. O tamanho do próprio ladrilho é especificado pelo elemento <feImage> usado como a entrada
para <feTile>.

O exemplo a seguir usa <feComposite> para cortar a área inundada e ladrilha até a forma da flor. A
imagem utilizada como ladrilho é mostrado para referência no canto superior direito.

<defs>
<filter id="flood-filter" x="0" y="0" width="100%" height="100%">
<feFlood flood-color="#993300" flood-opacity="0.8" result="tint"/>
<feComposite in="tint" in2="SourceGraphic" operator="in"/>
</filter>
<filter id="tile-filter" x="0" y="0" width="100%" height="100%">
<feImage xlink:href="cloth.jpg" width="32" height="32" result="cloth"/>
<feTile in="cloth" result="cloth"/>
<feComposite in="cloth" in2="SourceGraphic" operator="in"/>
</filter>
<g id="flower">
<!-- gráfico da flor aqui -->
</g>
</defs>
<use xlink:href="#flower" transform="translate(0, 0)" style="filter: url(#flood-filter);"/>
<use xlink:href="#flower" transform="translate(110,0)" style="filter: url(#tile-filter);"/>
<image xlink:href="cloth.jpg" x="220" y="10" width="32" height="32"/>
10.9 Efeitos de iluminação (Lighting)

Se você desenhar um círculo verde brilhante com SVG, parecerá um sinal de trânsito, brilhando por sua
própria luz e de alguma forma impresso na tela. Se você olhar para um círculo fora da tela, parece mais
"real", porque é iluminado por uma fonte de fora e tem alguma textura. Um círculo cortado de um
plástico verde não só é iluminado a partir do exterior, ele também tem destaques refletidos. Chamamos
a luz de uma fonte externa de “iluminação difusa” e os destaques que refletem fora de “iluminação
especular” da superfície, a partir do espéculo Latina, ou seja, do espelho.

A fim de alcançar estes efeitos, você deve especificar:


• O tipo de iluminação que você quer (<feDiffuseLighting> ou <feSpecularLighting>)
• O objeto que você deseja iluminar
• A cor da luz que você está usando
• O tipo de fonte de luz que você quer (<fePointLight>, <feDistantLight> ou <feSpotLight>) e sua
localização

Você especifica a localização de uma fonte de luz em três dimensões; isso significa que você vai precisar
de um valor-z, além de valor-x e valor-y. A relação entre os eixos x, y, e z é mostrada na figura abaixo; O
eixo z positivo é no sentido de "sair da tela", apontando para você.
Ambos os efeitos de iluminação usam o canal alfa do objeto que estão iluminando como um mapa de
relevo; valores alfa mais elevados são considerados como "levantados" acima da superfície do objeto.

10.9.1 A luz difusa

A melhor maneira de mostrar como o elemento <feDiffuseLighting> funciona é saltar para a direita
no próximo exemplo. Vamos acender uma luz amarela pálida em um círculo verde, texturizado com a
padrão de curva que usamos no Exemplo anterior.
<path id="curve" d="M 0 0 Q 5 20 10 10 T 20 20" [1] style="stroke: black; fill: none;"/>
<circle id="green-light" cx="50" cy="50" r="50" [2] style="fill: #060;"/>
<filter id="diff-light" color-interpolation-filters="sRGB" [3] x="0" y="0" width="100%" height="100%">
<feImage xlink:href="#curve" result="tile" [4] width="20" height="20"/>
<feTile in="tile" result="tile"/>
<feColorMatrix type="luminanceToAlpha" in="tile" [5] result="alphaTile"/>
<feDiffuseLighting in="alphaTile" [6] lighting-color="#ffffcc" surfaceScale="1" [7]
diffuseConstant="0.5" [8] result="diffuseOutput"> [9]
<fePointLight x="0" y="50" z="50"/> [10]
</feDiffuseLighting> [11]
<feComposite in="diffuseOutput" in2="SourceGraphic" [12] operator="in" result="diffuseOutput"/>
<feBlend in="diffuseOutput" in2="SourceGraphic" [13] mode="screen"/>
</filter>

[1] Define a curva que vai ser utilizada como ladrilho.


[2] Define o objeto que deve ser iluminado.
[3] Define o método de cor de interpolação e os limites para o filtro.
[4] Ladrilha a área do filtro com a imagem curva. Este será o nosso mapa de relevo ...
[5] ... então converte-o em um mapa alfa puro, denominado “alphaTile”.
[6] Esta área de ladrilhos é a entrada para o elemento <feDiffuseLighting>, que vamos iluminar com
uma luz amarela pálida, conforme especificado pelo atributo de iluminação de cor.
[7] O atributo “surfaceScale” conta a altura da superfície de um valor alfa de 1. (Especificamente, é o
fator pelo qual o valor alfa é multiplicado.)
[8] “diffuseConstant” é um fator multiplicativo que é utilizado na determinação do final dos valores
RGB de um pixel. Deve ter um valor maior do ou igual a zero; seu valor padrão é um. Quanto mais
brilhante a sua iluminação de cor, menor este número deve ser. A não ser queiramos uma imagem
desbotada.
[9] O resultado deste filtro será chamado “diffuseOutput”.
[10] Neste exemplo, estamos usando uma fonte de luz pontual, o que significa uma fonte que irradia
luz em todas as direções. Nós vamos posicioná-la no centro esquerdo da área que desejamos iluminar, e
configurá-lo em 50 unidades na frente da tela. Quanto mais longe do objeto você configurá-la, mais
uniformemente o objeto será iluminado.
[11] A extremidade do elemento <feDiffuseLighting>.
A entrada para esse filtro era um canal alfa; a saída é um bitmap RGB totalmente opaco; seu canal alfa é
igual a 1,0 em todos os pontos.
[12] Nós usamos <feComposite> no operador para o recorte de saída do filtro para os limites do gráfico
de origem (o círculo).
[13] Finalmente, usamos <feBlend> no modo “screen”, o que tende a aliviar a entrada, ao criar a
imagem final.
Uma vez que tudo isso é definido, a seguinte instrução ativa o filtro sobre o objeto desejado para
produzir a figura abaixo:
<Use xlink: href = "# verde-light" style = "filter: url (# diff-light);" />
10.9.2 Specular Lighting

A iluminação especular, por outro lado, dá destaques em vez de iluminação. O próximo exemplo mostra
como isso funciona.

<path id="curve" d="M 0 0 Q 5 20 10 10 T 20 20" [1] style="stroke: black; fill: none;"/>


<circle id="green-light" cx="50" cy="50" r="50" style="fill: #060;"/>
<filter id="spec-light" color-interpolation-filters="sRGB" [2] x="0" y="0" width="100%" height="100%">
<feImage xlink:href="#curve" result="tile" [3] width="20" height="20"/>
<feTile in="tile" result="tile"/>
<feColorMatrix type="luminanceToAlpha" in="tile" result="alphaTile"/>
<feSpecularLighting in="alphaTile" [4] lighting-color="#ffffcc" surfaceScale="1" [5] specularConstant="1" [6]
specularExponent="4" [7] result="specularOutput"> [8]
<feDistantLight elevation="25" azimuth="0"/> [9]
</feSpecularLighting> [10]
<feComposite in="specularOutput" in2="SourceGraphic" [11] operator="in" result="specularOutput"/>
<feComposite in="specularOutput" in2="SourceGraphic" [12] operator="arithmetic" k1="0" k2="1" k3="1"
k4="0"/>
</filter>

[1] Tal como no exemplo anterior, as primeiras seis linhas definem a curva e o círculo.
[2] A única diferença entre este e o exemplo anterior é o nome do filtro.
[3] Tal como no exemplo anterior, esta seção de ladrilha a curva em um canal alfa.
[4] Inicia a definição do filtro de <feSpecularLighting> e especifica a iluminação de cor para ser uma luz
amarelo-pálida.
[5] O atributo “surfaceScale” conta a altura da superfície de um valor alfa de 1. (Especificamente, é o
fator pelo qual o valor alfa é multiplicado).
[6] “specularConstant” é um fator multiplicativo que é utilizado na determinação final de valores RGB
de um pixel. Deve ter um valor maior ou igual a zero; seu valor padrão é um. Quanto mais brilhante a
sua iluminação de cor, menor este número deve ser.
[7] “specularExponent” é outro fator que é usado para determinar os valores RGB finais de um pixel.
Este atributo deve ter um valor de 1 a 128; o valor padrão é 1. Quanto maior esse número, mais
"brilhante" o resultado.
[8] O resultado deste filtro será chamado “specularOutput”.
[9] Neste exemplo, estamos usando uma fonte de luz distante, o que significa que o valor-z é
efetivamente infinito. A elevação diz o quão longe acima ou abaixo a luz está, da linha do horizonte, e o
“azimute” especifica o ângulo da luz no plano da tela - se é para a esquerda, direita, superior ou inferior
do objeto a ser iluminado.
[10] A extremidade do elemento <feSpecularLighting>.
[11] Nós usamos <feComposite> no operador para o clipe de saída do filtro para os limites do gráfico de
origem (o círculo).
[12] Finalmente, usamos <feComposite> como operador aritmético para fazer uma adição de “straight”
da iluminação no gráfico de origem.
<use xlink:href="#green-light" style="filter: url(#spec-light);"/>
Um terceiro tipo de fonte de luz, <feSpotLight>, é especificado com esses atributos: X, Y, e Z, a
localização dos holofotes (valor padrão é zero); “pointsAtX”, “pointsAtY”, e “pointsAtZ”, o lugar que o
foco está apontando para (valor padrão é zero); “specularExponent”, um valor que controla o foco para a
fonte de luz (valor padrão é um); e “limitingConeAngle”, que limita a região onde a luz é projetada. É o
ângulo entre o eixo luz do ponto e do cone. Assim, se você quer um grau 30 espalhada por todo o cone,
especifique o ângulo de 15. (O valor padrão é permitir disseminação ilimitada).

10.10 Acessando o fundo

Além das entradas de filtros de “SourceGraphic” e “SourceAlpha”, um objeto filtrado pode aceder a
parte da imagem que já está renderizada na tela quando invocar um filtro. Estas peças são chamadas
“BackgroundImage” (não BackgroundGraphic) e “BackgroundAlpha”. Para acessar essas entradas, o
objeto filtrado deve ser dentro de um container com atributo “enable-background” definido como
“new”.

<defs>
<filter id="blur-background">
<feGaussianBlur in="BackgroundAlpha" [1] stdDeviation="2" result="blur"/>
<feOffset in="blur" dx="4" dy="4" result="offsetBlur"/>
<feMerge>
<feMergeNode in="offsetBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<g enable-background="new"> [2]
<circle cx="30" cy="30" r="30" style="fill: #fff;"/> [3]
<rect x="0" y="0" width="60" height="60" style="filter: url(#blur-background); [4] fill: none; stroke:
blue;" />
</g>

[1] Isto é semelhante ao filtro de desfoque usado para sombras, exceto que a entrada é agora o
“BackgroundAlpha” em vez do “SourceAlpha”.
[2] Desde que o elemento <g> é um contêiner, é um candidato perfeito para colocar o “enable-
background”. Todos os filhos deste elemento terão acesso ao “backgroundAlpha” da imagem.
[3] Prestamos um círculo branco sobre a tela; este faz com que seja "invisível" contra um fundo branco.
[4] Vamos agora desenhar um retângulo e usar o filtro. O “BackgroundAlpha” que ele pega será circular,
por isso a figura abaixo mostra um quadrado com uma sombra circular. (Estranho, mas verdade!)
10.11 O elemento feMorphology

O elemento <feMorphology> permite "afinar" ou "engrossar" um gráfico. Você especifica um operador


com um valor de “erod” para afinar ou “dilate” para engrossar um gráfico. O atributo raio nos diz o
quanto as linhas devem ser afinadas ou dilatadas. É normalmente aplicado para canais alfa; no exemplo
abaixo nós afinamos e dilatamos um desenho de linha simples. Como você pode ver na figura, a erosão
pode causar estragos em um desenho com linhas finas.

<defs>
<g id="cat" stroke-width="2">
<!-- desenho do gato -->
</g>
<filter id="erode1">
<feMorphology operator="erode" radius="1"/>
</filter>
<filter id="dilate2">
<feMorphology operator="dilate" radius="2"/>
</filter>
</defs>
<use xlink:href="#cat"/>
<text x="75" y="170" style="text-anchor: middle;">Normal</text>
<use xlink:href="#cat" transform="translate(150,0)" style="filter: url(#erode1);"/>
<text x="225" y="170" style="text-anchor: middle;">Erode 1</text>
<use xlink:href="#cat" transform="translate(300,0)" style="filter: url(#dilate2);"/>
<text x="375" y="170" style="text-anchor: middle;">Dilate 2</text>

10.12 O elemento <feConvolveMatrix>

O elemento <feConvolveMatrix> permite calcular um novo valor de um pixel em termos de valores de


seus pixels vizinhos. Este filtro permite que você faça efeitos como desfoque, nitidez, entalhe e bisel. Ele
funciona através da combinação de um elemento de imagem com o seus pixels vizinhos para produzir
um valor de pixel resultante. Imagine que um pixel P e seus oito pixels vizinhos pixels (o caso usual que
é utilizado com este filtro):
ABC
DPE
FGH
Você, então, especifica uma lista de nove números no atributo “kernelMatrix”. Estes números dizem o
quanto a se multiplicar por cada pixel. Estes produtos serão somados. A soma pode bem vir a ser maior
do que um (se todos os fatores são positivos, por exemplo), portanto, à mesma intensidade, o resultado
é dividido pelo total dos fatores. Vamos dizer que você especifique estes nove números:

<feConvolveMatrix kernelMatrix="
012
345
6 7 8"/>

O novo valor de P então seria:

P' = ((0*A) + (1*B) + (2*C) + (3*D) + (4*P) + (5*E) + (6*F) + (7*G) + (8*H)) / (0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8)

<defs>
<filter id="emboss">
<feConvolveMatrix kernelMatrix="1 0 0
000
0 0 -1"/>
</filter>
<g id="flower">
<!-- Gráfico da flor -->
</g>
</defs>
<use xlink:href="#flower" style="filter: url(#emboss);"/>

Embora o tamanho da matriz padrão seja de três colunas por três linhas, você pode especificar qualquer
tamanho que você queira com o atributo “order”. Se você especificar a “order” = "4", então a matriz
exigirá dezesseis números (4 por 4) no atributo “kernelMatrix”. Uma matriz com três colunas e duas
fileiras seria especificada por “order” = "3 2" e exigiria seis números. Quanto maior a sua matriz de
núcleo, mais computação é necessária para produzir o resultado.

Para um pixel no meio de um gráfico, os vizinhos são fáceis de identificar. O que você faz com os pixels
das bordas do gráfico? Quem são seus vizinhos? Esta decisão é feita pela configuração que você dá ao
atributo “EdgeMode”. Se você definir o valor como “duplicate”, então <feConvolveMatrix> duplicará os
valores das bordas na direção necessária para produzir um vizinho. O valor “wrap” envolve em torno do
lado oposto para encontrar um vizinho. Por exemplo, o vizinho acima de um pixel na parte superior é o
elemento de imagem na parte inferior, e o vizinho para a esquerda de um pixel na extremidade esquerda
é o pixel correspondente na borda direita. O valor “none” irá fornecer um pixel preto transparente
(vermelho, verde, azul e valores alfa de zero) para quaisquer vizinhos desaparecidos.
O comportamento padrão do <feConvolveMatrix> é aplicar os cálculos para todos os canais, incluindo
alfa. Se você deseja aplicar cálculos apenas para os valores vermelhos, verdes e azuis, especifique
“preserveAlpha” como “true” (o valor padrão é “false”).

10.13 O elemento <feDisplacementMap>

Este filtro fascinante usa os valores de cor de sua segunda entrada para decidir quanto mover os pixels na
primeira entrada. Você especifica o canal de cor que deve ser usado para afetar a coordenada-x de um
pixel com o atributo “xChannelSelector”; o atributo “yChannelSelector” especifica o canal de cor usado
para afetar a coordenada-y. Os valores legais para estes seletores são "R", "L", "B", e "A" (para o canal
alfa). Você deve especificar a distância de deslocamento dos pixels; o atributo de escala dá o fator de
escala apropriado. Se não especificar este atributo, o filtro não vai fazer nada.

O exemplo a seguir cria um retângulo gradiente como a segunda entrada. O fator de deslocamento será
definido para dez, o canal vermelho vai ser utilizado como um deslocamento X, e o canal verde irá
ser utilizada como um deslocamento de Y. A figura em seguida mostra o resultado da aplicação deste
deslocamento a flor.

<defs>
<linearGradient id="gradient">
<stop offset="0" style="stop-color: #ff0000;" />
<stop offset="0.5" style="stop-color: #00ff00;"/>
<stop offset="1" style="stop-color: #000000;"/>
</linearGradient>
<rect id="rectangle" x="0" y="0" width="100" height="200" style="fill: url(#gradient);"/>
<filter id="displace">
<feImage xlink:href="#rectangle" result="grad"/>
<feDisplacementMap
scale="10"
xChannelSelector="R"
yChannelSelector="G"
in="SourceGraphic" in2="grad"/>
</filter>
<g id="flower">
<!-- Gráfico da flor -->
</g>
</defs>
<use xlink:href="#flower" style="filter: url(#displace);"/>
É possível utilizar o mesmo gráfico para ambas as entradas. Isto significa que um gráfico “displacement”
é controlado pela sua própria coloração. Este efeito, como está escrito no exemplo acima e apresentado
na figura anterior, pode ser muito excêntrico.

<defs>
<filter id="self-displace">
<feDisplacementMap
scale="10"
xChannelSelector="R"
yChannelSelector="G"
in="SourceGraphic" in2="SourceGraphic"/>
</filter>
<g id="flower">
<!-- Gráfico da flor -->
</g>
</defs>
<use xlink:href="#flower" style="filter: url(#self-displace);"/>

10.14 O elemento <feTurbulence>

O elemento <feTurbulence> permite produzir texturas artificiais para efeitos como mármore, nuvens,
etc., utilizando equações desenvolvidas por Ken Perlin. Você especifica estes atributos:

tipo
“turbulency” ou “fractalNoise”. O “fractalNoise” é mais suave na aparência.
baseFrequency
Quanto maior o número que você dá como valor para esse atributo, mais rapidamente haverá a
mudança de cores no resultado. Este número deve ser maior do que zero e inferior a um. Você também
pode dar dois números para este atributo; o primeiro será a frequência na direção-x e a segunda será a
frequência na direção-y.
numOctaves
Este é o número de funções de ruído que devem ser adicionados juntos quando for gerado o resultado
final. Quanto maior este número, mais refinado será a textura. O valor padrão é um.
seed
O valor inicial randomiza o gerador de números que este filtro usa. O valor padrão é zero; mude-o para
obter alguma variedade no resultado.
10,15 Filtro - Resumo e Referências

O elemento <filter> contém uma série de primitivas de filtro, cada uma das quais leva um ou mais
entradas e fornece um único resultado para uso com outros filtros. O resultado do último filtro na série
é processado no gráfico final. Você especifica as dimensões da tela para que o filtro se aplique com os
atributos x, y, largura e altura.

A tabela abaixo apresenta um resumo de referência dos filtros. Cada um dos elementos de filtro tem
primitivas um atributo “in” que dá a fonte para o primitivo, e pode também especificar os atributos x, y,
largura e altura. Os atributos padrão estão em negrito.

Elemento Atributos
<feBlend> in2="ceurosdn "
mode="normal " | "multiply" | "screen" | "darken" | "lighten"
<feColorMatrix> type="matrix" | "saturate" | "hueRotate" | "luminanceToAlpha"
values="ueslaxvirtm " | " -0)u1e(lavtoni rs " | "esrgdtao "
<feComponentTransfer> container for <feFuncR>, <feFuncG>, <feFuncB>, and <feFuncA>
elements.
<feFuncX > type="identity" | "table" | "discrete" | "linear" | "gamma"
tableValues="etcrsidofp,lbanv "
slope="pelosrani "
intercept="ceptrnial "
amplitude="edutplimag "
exponent="tenpoamxg "
offset="etsfaomg "
<feComposite> in2="ceurosdn "
operator="over" | "in" | "out" | "atop" | "xor" | "arithmetic"
<feComposite> Os seguintes atributos são usados com “arithmetic”:
o)çuãanitc( k1="i2*1norfcta "
k2="1niorfcta "
k3="2niorfcta "
k4="etsfovida "
<feConvolveMatrix> order="swornlumc " (default 3 by 3)
kernel="ueslav "
bias="uelavftso "
<feDiffuseLighting> Container para um elemento de fonte de luz.
surfaceScale="thgei " (default 1)
diffuseConstant="orctaf " (must be non-negative; default 1)
<feDisplacementMap> scale="orctafenmplsid " (default 0)
xChannelSelector="R" | "G" | "B" | "A"
yChannelSelector="R" | "G" | "B" | "A"
in2="utpniedcos "
<feFlood> flood-fill-color="onitcafpesrl "
flood-fill-opacity="0)1e(-luav "
<feGaussianBlur> stdDeviation="deaprsulb " (larger is blurrier; default 0)
<feImage> xlink:href="ceurosgaim "
<feMerge> container para elementos <feMergeNode>
<feMergeNode> in="ultesranidm
<feMorphology> operator="erode" | "dilate"
radius="usida-yr x "
radius="usida r "
<feOffset> dx="etsfxo " (default 0)
dy="etsfoy " (default 0)
<feSpecularLighting> Container for a light source element.
surfaceScale="thgei " (default 1)
specularConstant="orctaf " (must be non-negative; default 1)
specularExponent="tenpox " (range 1-128; default 1)
<feTile> Ladrilha a camada “in”
<feTurbulence> type="turbulence" | "fractalNoise"
baseFrequency="yucenqr-f x "
baseFrequency="uceynqrf "
numOctaves="egtrni "
seed="ebrumn "
<feDistantLight> azimuth="esrdg " (default 0)
elevation="esrgd " (default 0)
<fePointLight> x="etanidorc " (default 0)
y="aentidroc " (default 0)
z="aentidroc " (default 0)
<feSpotLight> x="etanidorc " (default 0)
y="aentidroc " (default 0)
z="aentidroc " (default 0)
pointsAtX="aentidroc " (default 0)
pointsAtY="aentidroc " (default 0)
pointsAtZ="aentidroc " (default 0)
specularConstant="lortcnusf " (default 1)
limitingConeAngle="esrgd "

Você também pode gostar