Na continuação desta posta, venho agora falar-vos de sombras.
O Imagick tem uma instrução própria para gerar sombras, shadowImage, que aceita quatro parâmetros: opacidade, sigma, x e y. Uma das vantagens mais fascinantes é que, se a imagem passada tiver transparência, a sombra segue o contorno da mesma. Ideal para usar com botões, ícones…
No entanto, a instrução tem várias armadilhas. Logo a abrir, a instrução não aplica a sombra à imagem, gera uma sombra isolada a partir da imagem, o que nos obriga, logo à partida, a uma composição posterior:
// criar um novo objecto Imagick para a sombra,
// que é um clone da imagem original
$sombra = $img->clone();
// como vamos sombrear, precisamos definir qual é
// a cor da sombra, via cor de fundo da imagem
// esta função aceita as cores de várias maneiras:
// "black", "#000000", "rgb(0, 0, 0)" ou "cmyk(0, 0, 0, 100)"
$sombra->setImageBackgroundColor("black");
// finalmente, vamos aplicar a sombra
// opacidade: 60%; sigma: 2; posição: 5, 5
$sombra->shadowImage(60, 2, 5, 5);
// neste momento já temos a sombra, vamos compor
// a imagem original por cima
$sombra->compositeImage($img, Imagick::COMPOSITE_OVER, 0, 0);
Não esquecer que o sombreado irá gerar imagens com transparência parcial, pelo que que as técnicas discutidas nos cantos arredondados – conversão para PNG ou composição sobre um fundo sem transparência – devem ser aplicadas.
Outra armadilha é o valor do sigma: à primeira vista, pode parecer que é o esborratamento da sombra, algo como shadow blur dos pacotes de edição de imagem, mas, ao brincar com o parâmetro, chegamos à conclusão que é isso, mas não só. Veremos, também, que os valores de x e y acabam por ser completamente descartados. Em teoria, estes valores posicionam a sombra; na prática, ao fazer a composição da imagem original, o eixo referencial é perdido, e a sombra acaba por ir dar sempre ao mesmo lado. Vejam o que mudaria com as seguintes instruções:
// alteração do sigma - comparem com o original $sombra->shadowImage(60, 20, 5, 5); // alteração de x - teoricamente, a imagem ficaria com // muito mais sombra à direita do que por baixo $sombra->shadowImage(60, 20, 50, 5);
Na prática, mudar o x e o y não resulta em alterações visíveis e o valor do sigma altera tanto o esborratamento, que era o pretendido, como o posicionamento da sombra, e consequente tamanho final da imagem. Além disso, como é fácil de verificar, é impossível gerar sombras noutras posições que não a sudeste que estamos a ver em todas as imagens. O que é necessário é descartar os valores de x e y na geração da sombra, e usá-los depois na composição, para situar a sombra onde queremos. Será possível, inclusivamente, simular um halo com o sombreado.
// valores iniciais
$opacidade = 60;
$sigma = 4;
$x = 10;
$y = 10;
// criar a sombra como clone
$sombra = $img->clone();
// definir a cor de fundo
$sombra->setImageBackgroundColor("black");
// gerar a sombra, com x e y a zeros
$sombra->shadowImage($opacidade, $sigma, 0, 0);
// criar uma nova imagem para compor tudo
$resultado = new imagick();
// definir o tamanho da nova imagem a partir do
// tamanho da sombra mais o posicionamento da sombra
// que é pedido
$resultado->newImage($shadow->getImageWidth() + $x,
$shadow->getImageHeight() + $y,
'transparent'
);
// Compor a sombra
// As contas do posicionamento em x e y referem-se à posição
// que queremos que a sombra tenha
// Isto é, se queremos a sombra a sair 10 pixels abaixo e à
// esquerda, temos que mover a sombra 10 pixels e compensar
// o valor do sigma - reparem que, se o deslocamento for
// negativo, a sombra fica na origem (quem mexe é a imagem
// original abaixo)
$resultado->compositeImage($shadow,
Imagick::COMPOSITE_OVER,
(($x < 0) ? 0 : $x) - $sigma * 2,
(($y < 0) ? 0 : $y) - $sigma * 2
);
// finalmente, vamos compor a imagem original, precisamente
// com o mesmo género de contas, mas ao contrário - reparem
// que as verificações do deslocamento são as inversas do
// que foi feito para a sombra
$resultado->compositeImage($img,
Imagick::COMPOSITE_OVER,
(($x > 0) ? 0 : -$x) + $sigma * 2,
(($y > 0) ? 0 : -$y) + $sigma * 2
);
Um exemplo com a sombra noutra posição:
// valores iniciais $opacidade = 60; $sigma = 4; $x = -10; $y = 10;
Para fazer um halo, basta que o deslocamento seja 0, 0:
// valores iniciais $opacidade = 60; $sigma = 4; // aumentei o sigma para se ver melhor o halo $x = 0; $y = 0; // também mudei a cor para "darkred"