Muitos de nós já tiveram o prazer de construir uma
aplicação web que requer a criação de thumbnails a partir de imagens que são
carregadas em tempo de execução. Thumbnails são dificilmente um assunto complicado,
mas eles são incomuns o suficiente para fazer com que cada vez que você
implemente um código para sua criação, esta pareça ser uma experiência
completamente nova.
A maneira mais fácil de produzir thumbnails para um
site é utilizar uma biblioteca pré-configurada, criada para este objetivo.
Existem algumas boas bibliotecas com este propósito, incluindo o PHP Thumbnailer
Class, que fornece maneiras bem simples
de como manipular imagens. Este tipo de bilbioteca, seja esta utilizada como
código ou como um plugin para outro software, vai além do que apenas produzir
thumbnails; ela também adiciona marcas d’água e facilmente habilita a rotação
programática da imagem de saída.
Usar o PHP Thumbnailer Class para criar thumbnails é
fácil:
include_once('libs/ThumbLib.inc.php');
$imagefile =
dirname(__FILE__) . '/sample.jpg';
PhpThumbFactory::create($imagefile)-resize(100,100)-show();
Este código cria um
objeto do thumbnail que contém a imagem-fonte, a redimensiona dentro de uma
área de 100×100, e a joga no browser com os cabeçalhos corretos.
Existe um outro
método bem útil, adaptiveResize(), que irá
redimensionar as imagens o máximo possível dentro das dimensões fornecidas,
para então cortá-las de maneira que elas preencham todo o tamanho desejado.

A diferença entre essas duas
imagens, fora a área de corte, é o resultado da escolha de qual lado da imagem
o algoritmo utilizará para redimensioná-la. No caso do resize(), a imagem-fonte é redimensionada de
maneira com que sua altura caiba na área de saída. Já no caso do adaptiveResize(), a imagem-fonte é redimensionada
de maneira com que sua largura caiba na área de saída.
Para simplificar os próximos
exemplos, irei mostrar somente o código que é como o resize(), no qual a imagem de saída é igual ou
menor do que as dimensões especificadas, e não precisam ser cortadas. Para
criar o código utilizando o adaptiveResize() você simplesmente precisa
redimensionar a imagem pelo lado oposto e utilizar um método de corte no
resultado.
Independentemente de qual estilo
de thumbnail sua aplicação necessite, o lado que você irá escolher é
determinado utilizando a comparação largura x altura da imagem.
Compreendendo o conceito de
proporção da imagem
Se você procura por uma função
que produza thumbnails para adicionar à sua aplicação, você provavelmente irá
encontrar algumas que simplesmente fazem tudo errado. Elas irão calcular o
tamanho do thumbnail baseando-se somente em uma dimensão da imagem original, ou
irão basear o tamanho de saída unicamente na orientação da imagem original.
Isso é incorreto, pois irá, na maioria das vezes, deixar algumas imagens do
thumbnail cortadas incorretamente.
Para determinar qual dimensão da
imagem original usar como base para redimensioná-la, você precisa comparar a
proporção da imagem original com a proporção do thumbnail.
A proporção de uma imagem é a
relação entre sua largura e sua altura. O valor real da proporção não é importante,
mas a comparação das proporções da imagem original com a imagem do thumbnail
gera a dimensão correta que deve ser utilizada para o redimensionamento.
Considere as duas imagens abaixo:

A imagem-fonte do topo tem uma
proporção de 2/3. Isto é facilmente convertido para a forma decimal ao dividir
a largura em pixels pela altura em pixels, (66 ÷ 100) ? 0.66. A imagem-fonte de baixo
tem uma proporção de 3/2, ou de (100 ÷
66) ? 1.5.
Para ambas as imagens, o tamanho
do thumbnail de saída é uma atípica faixa vertical. Se você é parecido comigo,
na maioria das vezes você acaba escrevendo thumbnails customizados de maneira
atípica. Mesmo assim, a proporção de ½ pode ser computada da mesma
maneira, (50 ÷ 100) = 0.5.
A surpresa é que, nos dois casos,
a proporção da imagem-fonte é maior do que a proporção do thumbnail, de modo
que ambos devem ser redimensionados para que sua largura seja igual à largura
do thumbnail, com a altura reduzida em igual proporção:
// Original values obtained from the top image
// can come from getimagesize(), imagesx()/imagesy(), or similar
$source_width = 66;
$source_height = 100;
$thumbnail_width = 50;
$thumbnail_height = 100;
// Compute aspect ratios
$source_ar = $source_width / $source_height;
$thumbnail_ar = $thumbnail_width / $thumbnail_height;
// Compute the output width and height based on the
// comparison of aspect ratios
if ($source_ar > $thumbnail_ar) {
// Use the thumbnail width
$output_width = $thumbnail_width;
$output_height = round($original_height
/ $original_width * $thumbnail_width);
}
else {
// Use the thumbnail height
$output_height = $thumbnail_height;
$output_width = round($original_width
/ $original_height * $thumbnail_height);
}
Se a altura e a largura do thumbnail são diferentes, a comparação entre a
proporção da imagem original com a do thumbnail irá nos contar qual lado deve
ser utilizado como ponto para o redimensionamento.
Idealmente, uma biblioteca de thumbnails fará toda a matemática para
você, mas caso você esteja preso escrevendo seu próprio código, é bom entender
os cálculos envolvidos.
Mesmo que você use uma biblioteca, é uma boa ideia considerar o chache.
Cache do thumbnail
preguiçoso
Bilbliotecas que
produzem thumbnails muitas vezes têm um método básico para criar suas imagens,
que gera a imagem de saída diretamente no browser. Isto não é um problema em
primeira instância, mas você não deve permitir que o PHP construa este
thumbnail em cada carregamento de página. Isso é um problema se você tem vários
thumbnails em uma página, o que geralmente acontece.
Utilizar o cache é
uma ótima idéia, mas é melhor se for utilizado de uma maneira que tire total
vantagem das capacidades do seu servidor web. Os códigos seguintes são gerados
a partir do uso no Apache, mas podem ser configurados de maneira a funcionar
com Lighttpd ou Nginx.
A ideia básica é
utilizar um padrão do front controller. Crie thumbnails via PHP para requisições
que não têm arquivos correspondentes, e então salve este arquivo no local especificado
para que o Apache o carregue diretamente – sem carregar o PHP – em pedidos
subsequentes.
Se você está usando um Framework PHP, como Lithium ou Zend Framework,
então você já colocou tudo no lugar, mas aqui estão algumas linhas básicas
.htaccess para permitir mod_rewrite para o padrão do
front controller:
RewriteEngine On
RewriteCond
%{REQUEST_FILENAME} !-f
RewriteCond
%{REQUEST_FILENAME} !-d
RewriteRule .
create_thumbnail.php [PT]
Se você está usando Apache 2.3, você pode utilizar
mod_dir e FallbackResource:
FallbackResource
create_thumbnail.php
Agora você precisa de um simples script PHP para
associar a URL requisitada no diretório do Thumbnail com o arquivo que deve ser
transformado em thumbnail.
<?php
include_once('libs/ThumbLib.inc.php');
// Set up the directories for the source and thumbnail images
$source_dir = '/var/www/test.vm2/htdocs/images/';
$thumb_dir = '/var/www/test.vm2/htdocs/thumbs/';
// Figure out where to load and save this image
$source_file = $source_dir . basename($_SERVER['REQUEST_URI']);
$output_file = $thumb_dir . basename($_SERVER['REQUEST_URI']);
// Serve the thumbnail and save it
PhpThumbFactory::create($source_file)->adaptiveResize(100,100)
->show()
->save($output_file);
?>
A coisa mais importante de se prestar atenção é
garantir que a saída da imagem vá diretamente para o browser ao salvá-la em
disco, senão o primeiro usuário que tentar carregar o thumbnail não conseguirá
ver nada.
Conclusão
Thumbnails são ocorrências comuns e simples de
gerenciar com alguns truques e uma boa biblioteca. Um bom entendimento de como
a matemática por trás dos códigos da biblioteca funcionam podem ajudar bastante
se você precisar produzir algo personalizado.
*
Texto original de Owen Winkler, disponível em http://phpadvent.org/2010/thumbnails-by-owen-winkler.








