Depois que lançamos o Gallery, recebi diversas questões de pessoas interessadas em saber como o sistema funcionava “por baixo do capô”, como manipulava as imagens enviadas, etc.
O principal que faz com que o sistema funcione é a biblioteca GD, uma biblioteca que serve para manipular imagens, e que está presente na maioria das instalações de PHP atualmente.
Para ajudar aqueles que têm vontade de usar GD, resolvi começar a postar aqui alguns códigos de coisas bacanas que usam a biblioteca. Hoje vou deixar aqui para vocês um código que serve para criar um mosaico de imagens, como este.
Basicamente é um script onde você define uma pasta que contém as imagens a serem utilizadas para gerar o mosaico, e então o script pega as imagens, redimensiona, sorteia suas posições dentro do mosaico, e gera numa pasta de saída uma imagem png com seu mosaico.
Todas as características do mosaico podem ser alteradas modificando algumas variáveis do script.
Segue então o código:
<?php function imagecreatefromwhatever($image) { $info = pathinfo($image); $extension = strtolower($info['extension']); switch($extension) { case "jpg": return imagecreatefromjpeg($image); break; case "jpeg": return imagecreatefromjpeg($image); break; case "png": return imagecreatefrompng($image); break; case "gif": return imagecreatefromgif($image); break; default: return imagecreatefromjpeg($image); } } //diretório de onde pegar as imagens $input_dir = "imagens/"; //diretório onde salvar o mosaico $output_dir = "mosaicos/"; //tamanho aproximado do mosaico final $mosaic_size = array(1280,800); $mosaic_proportion = $mosaic_size[0]/$mosaic_size[1]; //cor de fundo do mosaico $mosaic_background = array( "red" => "255", "green" => "255", "blue" => "255" ); ob_start(); $d = dir($input_dir); $extensions = array("jpg","jpeg","png","psd","gif"); while(false !== ($entry = $d->read())) { if($entry != "." && $entry != "..") { $info = pathinfo($entry); $ext = strtolower($info['extension']); $name = $info['filename']; if(in_array($ext,$extensions) && $striped == 0) { $photos[] = $entry; } } } //quanto maior o número de fotos, mais reduzidas elas ficarão no mosaico $number_of_photos = count($photos); $reduce_factor = 0.5; //o trecho abaixo calcula as posições possíveis das imagens dentro do mosaico $actual_x = 0; $actual_y = 0; $possible_positions[] = array("x" => 0, "y" => 0); foreach($photos as $thephoto): list($image_width, $image_height, $image_type, $image_attr) = getimagesize($input_dir.$thephoto); $image_res_width = round($image_width*$reduce_factor); $image_res_height = round($image_height*$reduce_factor); $actual_x = $actual_x + $image_res_width; if(($actual_x+$image_res_width) > $mosaic_size[0]) { $actual_y = $actual_y + $image_res_height; $actual_x = 0; } $possible_positions[] = array("x" => $actual_x, "y" => $actual_y); endforeach; //definir posições máximas das imagens no mosaico para criar imagem true color no tamanho final arsort($possible_positions); foreach($possible_positions as $position): $final_positions[] = $position; endforeach; $max_image_position = $final_positions[0]; //cria imagem true color que será o mosaico em si, já com as dimensões calculadas acima $mosaic = imagecreatetruecolor($max_image_position["x"], $mosaic_size[1]); //preenche a imagem com uma cor de fundo $background_alloc = imagecolorallocate($mosaic,$mosaic_background["red"],$mosaic_background["green"],$mosaic_background["blue"]); imagefill($mosaic,0,0,$background_alloc); //sorteia as posições dentro do mosaico para que nunca fique igual shuffle($possible_positions); $i=0; foreach($photos as $thephoto): list($image_width, $image_height, $image_type, $image_attr) = getimagesize($input_dir.$thephoto); $image_res_width = round($image_width*$reduce_factor); $image_res_height = round($image_height*$reduce_factor); $handler = imagecreatefromwhatever($input_dir.$thephoto); $actual_x = $possible_positions[$i]["x"]; $actual_y = $possible_positions[$i]["y"]; imagecopyresampled($mosaic , $handler, $actual_x, $actual_y, 0, 0, $image_res_width, $image_res_height, $image_width, $image_height); $i++; endforeach; //salva a imagem final do mosaico imagepng($mosaic); $output_buffer = ob_get_contents(); $output_filename = substr(uniqid(sha1(md5(base64_encode(rand(0,100)*time()+microtime()*1000)))),0,10).".png"; $output_handler = fopen($output_dir.$output_filename,"a+"); fwrite($output_handler,$output_buffer); fclose($output_handler); ob_clean(); ?>
Aqui vai uma lista de algumas variáveis que você deve/pode alterar:
input_dir: A pasta de onde pegar as imagens (não se esqueça da barra no final “/”)
output_dir: A pasta onde salvar o mosaico
mosaic_size: Width,height do mosaico. Aqui vale uma observação: a largura do mosaico vai variar dependendo de quantas imagens você tiver para formá-lo e também de qual o tamanho delas. A altura, no entanto, será fixa.
reduce_factor: O padrão é 0.5, o que significa que as imagens serão reduzidas a 50% do seu tamanho original
Basicamente é isso, o script faz um bocado de cálculos e exige um bocado de processamento no servidor, então é bom tomar cuidado quando o utiliza. Está longe de ser perfeito, você pode por exemplo usar fórmulas matemáticas para calcular a área total do mosaico e redimensionar as figuras para que todas caibam dentro desta área direitinho, que tal?
Fica aí este script para que você estude um pouco sobre GD, e tome gosto pela coisa. Na documentação no próprio site do PHP tem bastante informação a respeito. Pretendo postar mais sobre o assunto futuramente.
Até mais!
No começo da função poderia usar:
——————–
case:”jpg”
case:”jpeg”
return imagecreatefromjpeg($image);
——————–
visto que os dois direcionam pro mesmo resultado.
Na hora de definir o nome do arquivo percebi um pouco de fanatismo, me parece um pouco exagerado… rs
Abraços
Obrigado pela partilha.
Para usar a gd as imagens têm de estar no meu servidor ?
E se as minhas imagens não estiverem no meu servidor mas eu tiver uma array com o url de cada uma.
Seria possivél fazer esta classe funcionar? Com o php eu consigo fazer um echo de todas elas no meu html … tenho centenas de thumbs 50x50px mas gostaria q o meu visitante pudesse descarregar um mosaico com todas elas.
Rui, dependendo do servidor é possível utilizar imagens externas com o gd, acho que depende da configuração do PHP permitir o carregamento de arquivos externos. Se o seu servidor não permite este processo será necessário baixar a imagem para seu servidor para depois montar o mosaico.