Intro
Um belo dia você acorda, toma um café preto e uma aspirina e decide colocar as fotos da festa de ontem na internet. Aquela, que fez você ter de tomar uma aspirina e o café preto.
Você tem na sua frente um bom editor de textos, um Apache com PHP, um browser e 60 fotos para botar no ar. Melhor fazer de uma vez, antes que a vontade passe.
Possibilidades
Para ser rápido, você pensa em botar as fotos uma em cima da outra, separadas por um <br />, e era isso. Mas aí você tem de aturar os amigos reclamando que a página demora um século para abrir e tem muita rolagem.
Também pode fazer o resize direto no HTML, forçando o IMG tag para 160x120px, e as suas fotos demorariam igual para carregar e ficariam com uma aparência pior que a sua neste momento.
A última maluquice seria fazer thumbnails (miniaturas) das fotos num editor gráfico, e criar um link para a foto em tamanho natural. Genial! Mas fazer thumbnails de 60 imagens??? E quando os outros mandarem as fotos deles para serem incluídas, você vai fazer tudo de novo? Larry Wall já disse que o bom programador é meio preguiçoso. Faça bem feito para não ter de fazer de novo.
A Solução
Aí então, você lembra de, um dia, ter lido em algum lugar que o PHP trabalha com imagens. Bem lembrado. Neste artigo você vai aprender a criar thumbnails em realtime com o PHP e a biblioteca GD.
Para isso tenha certeza de que o seu PHP foi compilado com suporte a GD 2.0.1 (no win32 é padrão. No *nix, --with-gd[=DIR]) e que ele está sendo carregado no PHP.INI. Se você está hospedando o seu site numa empresa de host, peça gentilmente para o admin habilitar o GD2 no PHP.INI. Não compromete em nada a performance do server e dá uma possibilidade a mais para os clientes.
O script vai receber a imagem da qual o thumbnail deve ser gerado pela querystring, com o endereço completo da imagem no servidor. Uma IMG tag vai ficar mais ou menos assim:
<img src="thumb.php?dir/imagem.jpg">
Explicações dadas, vamos ao que interessa: show me the code...
Código-Fonte
<?PHP
/** Arquivo: thumb.php
* Autor: Mauricio Wolff .:. organiKa
* baseado no trabalho de Michael Bailey
***/
// Constantes: variaveis que não mudam em todo o programa
// path do win2k. no unix, mude de 'd:/path' para '/home/usuario/www'
define(PATH_IMG, 'd:/www/artigos/thumb');
define(MAX_WIDTH, 160);
define(MAX_HEIGHT, 120);
# Pega onde está a imagem
$image_file = str_replace('..', '', $_SERVER['QUERY_STRING']);
$image_path = PATH_IMG . '/'.$image_file;
# Carrega a imagem
$img = null;
$extensao = strtolower(end(explode('.', $image_path)));
if ($extensao == 'jpg' || $extensao == 'jpeg') {
$img = @imagecreatefromjpeg($image_path);
} else if ($extensao == 'png') {
$img = @imagecreatefrompng($image_path);
// Se a versão do GD incluir suporte a GIF, mostra...
} else if ($extensao == 'gif') {
$img = @imagecreatefromgif($image_path);
}
// Se a imagem foi carregada com sucesso, testa o tamanho da mesma
if ($img) {
// Pega o tamanho da imagem e proporção de resize
$width = imagesx($img);
$height = imagesy($img);
$scale = min(MAX_WIDTH/$width, MAX_HEIGHT/$height);
// Se a imagem é maior que o permitido, encolhe ela!
if ($scale < 1) {
$new_width = floor($scale*$width);
$new_height = floor($scale*$height);
// Cria uma imagem temporária
$tmp_img = imagecreatetruecolor($new_width, $new_height);
// Copia e resize a imagem velha na nova
imagecopyresized($tmp_img, $img, 0, 0, 0, 0,
$new_width, $new_height, $width, $height);
imagedestroy($img);
$img = $tmp_img;
}
}
// Cria uma imagem de erro se necessário
if (!$img) {
$img = imagecreate(MAX_WIDTH, MAX_HEIGHT);
imagecolorallocate($img,204,204,204);
$c = imagecolorallocate($img,153,153,153);
$c1 = imagecolorallocate($img,0,0,0);
imageline($img,0,0,MAX_WIDTH,MAX_HEIGHT,$c);
imageline($img,MAX_WIDTH,0,0,MAX_HEIGHT,$c);
imagestring($img, 2, 12, 55, 'erro ao carregar imagem',$c1 );
}
// Mostra a imagem
header('Content-type: image/jpeg');
imagejpeg($img);
?>
Comentários
Agora que você já saciou a sede de código, prepare uma xícara de café (ou JoltCola... eu nunca tomei, não posso falar) e vamos analisar o código como faria Jack, por partes...
<?php
// Constantes: variaveis que não mudam em todo o programa
// path do win2k. no unix, mude de 'd:/path' para '/home/usuario/www'
define(PATH_IMG, 'd:/www/artigos/thumb');
define(MAX_WIDTH, 160);
define(MAX_HEIGHT, 120);
?>
Primeiro, a definição de algumas constantes. PATH_IMG aponta para o diretório onde estãos os arquivos de imagem no servidor. Apenas imagens neste ou nos seus subdiretórios serão mostradas. Não é um primor de segurança, mas funciona muito bem.
MAX_WIDTH e MAX_HEIGHT definem o tamanho máximo em pixels para os thumbnails. Se a imagem já possuir um tamanho menor que estes, ela não é alterada. Proporções serão mantidas, pois se a largura (width) for reduzida por 3, a altura (height) será reduzida na mesma razão.
<?php
# Pega onde está a imagem
$image_file = str_replace('..', '', $_SERVER['QUERY_STRING']);
$image_path = PATH_IMG . '/'.$image_file;
# Carrega a imagem
$img = null;
$extensao = strtolower(end(explode('.', $image_path)));
if ($extensao == 'jpg' || $extensao == 'jpeg') {
$img = @imagecreatefromjpeg($image_path);
} else if ($extensao == 'png') {
$img = @imagecreatefrompng($image_path);
// Se a versão do GD incluir suporte a GIF, mostra...
} else if ($extensao == 'gif') {
$img = @imagecreatefrompng($image_path);
}
?>
O local físico da imagem é passada na query string, como explicado nos comentários. Para prever o acesso de imagens fora do local especificado na constante, quaisquer ".." são suprimidos da query string, e ½ dos "h4x0rs" eliminados ( $image_file = str_replace('..', '', $_SERVER['QUERY_STRING']);).
Em seguida, a extensão do arquivo é checada para se definir qual função do GD será usada para a imagem em questão. O GD pode criar imagens a partir de: gif, jpeg, png, wbmp, xbm, xpm... etc. Neste script você vai encontrar suporte para gif, jpeg e png, e isso deve bastar. Caso precise acrescentar, ponha mais um elseif e resolvido!
Se a extensão não for reconhecida ou o arquivo não existir, a variável $img vai ficar vazio e isso vai gerar um erro. O @ antes das funções previne que erros sejam mostrados se a função imagecreatefrom... não conseguir criar a imagem. Essa mesma técnica pode ser usada em extract, se o argumento passado não for um array.
Se você tentar utilizar este script para gerar o thumbnail de um .gif e obtiver o erro: "Warning: ImageCreateFromGif: No GIF read support in this PHP build"
Não se desespere! Isso acontece porque na versão 1.6 o GD deixou de oferecer suporte a .gif, já que a dona Unisys tem a patente do algoritmo de compressão usado nos gifs e quer $$$ por isso.
Existem várias alternativas para contornar este problema. Em distribuições Linux como o Debian você pode baixar pacotes RPM do GD patched, você mesmo pode aplicar o patch no gd.c, baixar patches na internet (tente http://www.webofsin.com/gd-1.8.3-gif.patch) ou usar programas externos para converter os .gifs em .pngs (gif2png, mogrify, ImageMagick, netPBM).
<?php
// Se a imagem foi carregada com sucesso, testa o tamanho da mesma
if ($img) {
// Pega o tamanho da imagem e proporção de resize
$width = imagesx($img);
$height = imagesy($img);
$scale = min(MAX_WIDTH/$width, MAX_HEIGHT/$height);
}
?>
imagesx() e imagesy() retornam a largura e altura da imagem respectivamente. A proporção de redimensionamento é obtida com o tamanho máximo permitido dividido pelo tamanho real da imagem. Ele é calculado para a largura (width) e altura (height), mas somente o menor valor deles é usado. Usando a mesma razão para altura e largura, a proporção é mantida.
<?php
// Se a imagem é maior que o permitido, encolhe ela!
if ($scale < 1) {
$new_width = floor($scale*$width);
$new_height = floor($scale*$height);
// Cria uma imagem temporária
$tmp_img = imagecreatetruecolor($new_width, $new_height);
// Copia e resize a imagem velha na nova
imagecopyresized($tmp_img, $img, 0, 0, 0, 0,
$new_width, $new_height, $width, $height);
imagedestroy($img);
$img = $tmp_img;
}
?>
Se a proporção de redimensionamento ($scale) for maior ou igual a 1, a imagem não precisa ser alterada, já é menor que um thumbnail. Caso contrário, a imagem precisa ser reduzida na razão da variável $scale. O tamanho do thumbnail é calculado multiplicando-se o tamanho real da imagem pelo valor de $scale.
Usando esses valores de largura e altura, criamos uma nova imagem temporária usando a função imagecreatetruecolor(). Se você não estiver usando GD 2.0+, use a função imagecreate() (os seus jpegs podem ficar medonhos, use 2.0+).
A imagem original vai agora ser redimensionada para o tamanho da temporária. Podemos então liberar o arquivo da imagem e renomear a temporária para $img.
<?php
// Cria uma imagem de erro se necessário
if (!$img) {
$img = imagecreate(MAX_WIDTH, MAX_HEIGHT);
imagecolorallocate($img,204,204,204);
$c = imagecolorallocate($img,153,153,153);
$c1 = imagecolorallocate($img,0,0,0);
imageline($img,0,0,MAX_WIDTH,MAX_HEIGHT,$c);
imageline($img,MAX_WIDTH,0,0,MAX_HEIGHT,$c);
imagestring($img, 2, 12, 55, 'erro ao carregar imagem',$c1 );
}
Se a extensão não for reconhecida ou o arquivo não for encontrado, uma imagem de erro será gerada. Ela será um quadrado cinza com um X cinza o cortando e a frase 'erro ao carregar a imagem' em preto, mas também pode ser uma imagem de erro previamente criada.
A função imagestring escreve texto na imagem. Os seus parâmetros, apesar de não parecerem fazer sentido algum, são muito fáceis de entender. Em ordem: $img é a imagem na qual a string será escrita (handle); 2 é o tamanho da letra, variando de 1 a 5; 12 é a coordenada x da base esquerda da string, enquanto que 55 corresponde à base inferior; 'erro ao carregar a imagem' - surpresa!!! - é a string em si, que será escrita; $c1 é a cor alocada para s string, definida logo acima, em RGB.
<?php
// Mostra a imagem
header('Content-type: image/jpeg');
imagejpeg($img);
?>
Finalmente, mostra a imagem. Pode ser usado o parâmetro opcional int(quality) da função imagejpeg, para controlar a qualidade da imagem mostrada. O parâmetro varia de 0 a 100, sendo o seu default 75.
E a imagem grande?
Como você pode ver, nem é preciso tanta cafeína assim para gerar thumbnails em PHP. Agora, só falta o gran-finale do artigo: e como linkar as imagens em tamanho natural?
para isso precisaremos de:
uma página listando as imagens de um diretório
algumas imagens maiores que 160x120px
um pouco de xhtml e css
Listando as imagens
A nossa aventura termina com uma página xhtml simples, com código PHP embutido, que lerá as imagens do diretório padrão de imagens e mostrará uma lista de thumbnails. <!doctype html public "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>.: Lista Imagens :.</title>
<meta name="author" content="mauricio wolff :aka: mauwolff" />
<style type="text/css" media="all">
<!--
body, p { font-family: arial, sans-serif; font-size: 12px; }
image { border: 0; display: block; clear: both; margin: 15px; text-align: center;}
-->
</style>
</head>
<body>
<?php
// Abre o diretório atual para leitura de imagens...
if ($handle = opendir('.')) {
while (false !== ($file = readdir($handle))) {
// Só carrega as imagens que tiverem extensões esperadas
if (strtolower(substr($file,-4,4)) == '.jpg' ||
strtolower(substr($file,-4,4)) == '.gif' ||
strtolower(substr($file,-4,4)) == '.png' ||
strtolower(substr($file,-5,5)) == '.jpeg') {
$alt = 'clique para ver a imagem no tamanho original...';
echo '<a href="'.$file.'" target="_blank"><img src="thumb.php?'.$file.'" alt="'.$alt.'" /></a>'."\n";
}
}
closedir($handle);
}
?>
</body>
</html>
Simples, não? O css define a apresentação do xhtml, que somente terá uma lista de thumbnails a mostrar. As imagens automaticamente não terão borda alguma, estarão centralizadas na página e serão listadas uma abaixo a outra. Com CSS isso é facilmente alterável, sem mexer no html ou usar gambiarras como <br />.
O código php somente abre o diretório atual, lista todos os arquivos do tipo desejado e monta os links para as imagens grandes. Se você criar um arquivo de texto vazio e renomeá-lo para teste.gif, verá a imagem de erro.
Para você ter uma idéia da economia: um arquivo de 18.809 bytes ficou com 2.941 bytes, e outro de 287.005 bytes ficou com 3.257 bytes (1,13% do tamanho).
Conclusão
Claro que, normalmente, é melhor usar uma classe de template, deixar o seu código mais modular, não misturar apresentação e lógica... mas este é um exemplo funcional do que se pode fazer com meia-dúzia de linhas e algumas fotos...
Bom... já foi um exercício. Agora aproveite os exemplos, refine um pouco o código e, depois de botar as fotos da festa no ar, volte pra cama. Aproveite a ressaca... :)
base64: SGFwcHkgY29kaW5nIQ==
Sobre o autor
Mauricio Wolff é o fundador, criador, programador e fazedor de cafézinho da organiKa.com.br. Gosta de PHP, XML, CSS, Sânscrito, Vedanta, Cinema, Artes, Kung-Fu, Física e História. Sim, ele gosta de bastante coisa... é casado e tem uma filha.
Fonte: http://www.clubedainformatica.com.br/