Canvas: nova classe para manipulação e redimensionamento de imagens com PHP

Quase 3 anos, 144 comentários e dezenas de e-mails depois resolvi atualizar e dar o devido valor à minha classe de manipulação e redimensionamento de imagens com PHP. A antiga m2brimagem agora virou canvas e, em breve, contará com um site próprio.

Nessa nova versão, dei uma revisada geral no código e adicionei novas funcionalidades.

A primeira grande mudança foi o nome: m2brimagem não era lá muito amigável. Além disso, chega de receber e-mails na agência (m2brnet) solicitando suporte e ajuda com a classe. O nome ainda não é final, então, caso você tenha alguma ideia bacana deixa-a registrada nos comentários lá em baixo.

Agora falando da parte técnica, a classe canvas apresenta as seguintes novas funcionalidades:

  • Encadear métodos
  • Carregar imagens sem extensão de imagens
  • Carregar imagens diretamente de um formulário, utilizando apenas o arquivo temporário do PHP
  • Carregar imagens externas, via URL (vai depender do seu servidor)
  • Criar uma nova imagem “vazia”, apenas com cor de preenchimento
  • Adicionar legendas com posições fixas, assim como já acontecia com marcas d’água (topo_centro, baixo_esquerda etc.)
  • Adicionar cor de fundo nas legendas
  • Adicionar/configurar cores passando como parâmetro um valor hexadecimal

Pra quem quiser testar

Segue o link para download do arquivo fonte. Lembrando que não garanto o funcionamento completo, então evite usar em sistemas em produção.

Novos exemplos de uso

Todos os exemplos deste artigo utilizam a chamada da classe. Pra evitar repetição no texto, vou mostrar apenas uma vez aqui:

require_once( 'canvas.php' );
$img = new canvas();

Continua sendo válido carregar imagens no próprio construtor:

$img = new canvas( 'imagem.jpg' );

Carregar e redimensionar, utilizando o método preenchimento

$img->carrega( 'cats.jpg' )
  ->hexa( '#FF005C' )
  ->redimensiona( 400, 200, 'preenchimento' )
  ->grava();

Notem a utilização do encadeamento de métodos, tornando o código muito mais elegante e legível. O método redimensiona, que antes recebia o tipo como string, agora recebe este parâmetro na forma de constantes. ‘fill’ passou a ser ‘preenchimento’. O tipo padrão ainda é o redimensionamento simples, distorcendo caso sejam passados ambos largura e altura.

Quando só é passado um valor, altura ou largura, a classe calcula automaticamente o valor ausente na proporção. E, pra finalizar, também é possível redimensionar por porcentagem, bastando acrescentar o símbolo % nas dimensões.

Criar uma imagem nova

$img->hexa( '#ff0000' )
  ->novaImagem( 300, 300 )
  ->hexa( '#fff' )
  ->legenda( 'FLAMENGO', 20, 'meio', 'centro', '#000', true, 'Aller_Bd.ttf' )
  ->grava();

Este novo método permite a criação de uma nova imagem “do zero”. Você passa uma cor de fundo através dos métodos hexa ou rgb e utiliza a função novaImagem com os parâmetros largura e altura. No exemplo também adiciono um texto no centro da imagem - mais abaixo falo das novidades do método legenda.

Carregar imagem utilizando uma URL

$img->carregaUrl( 'http://www.google.com.br/intl/en_com/images/srpr/logo1w.png' )
  ->redimensiona( 200, 100, 'crop' )
  ->grava();

Muita gente pediu isso via comentários ou e-mail, então decidi implementar, mesmo sendo um pouco contra. :) As funções de criação de imagem do php/gd já permitem por natureza carregar um endereço externo (imagecreatefromjpeg, imagecreatefrompng etc.), no entanto, por questões de segurança, seu servidor provavelmente vai ter desabilitado este acesso (como no caso aqui do mediatemple).

Ainda aconselho desenvolver uma outra função para salvar imagens externas e carregar a imagem normalmente na classe canvas.

Legendas com posição fixa (experimental)

$img->carrega( 'cats.jpg' )
  ->redimensiona( 400, 400, 'crop' )
  ->hexa( '#000' )
  ->legenda( 'LOL Catz!', 20, 'meio', 'centro', '#FF005C', true, 'Aller_Bd.ttf' )
  ->grava();

O método marcaFixa, de autoria do leitor Giolvani, fez grande sucesso. A ideia foi duplicada para as legendas. Agora, também é possível passar as posições topo, meio e baixo - esquerda, centro e direita nas coordenadas X e Y da legenda. Ainda não está funcionando 100%, eu acho, principalmente com fontes truetype. A função marcaFixa, aliás, passou a ser private e agora é chamada na própria marca() - basta passar os parâmetros X e Y como strings.

Outra novidade nas legendas é a possibilidade de adicionar uma cor de fundo. É o quinto parâmetro do método legenda(), podendo ser uma cor hexadecimal como string ou um array com as cores RGB. Aliás, tô achando que o legenda() está com muitos parâmetros. Talvez seja melhor separar em legenda normal e truetype, o que acham?

Filtros

Pesquisando por métodos de blur, de conversão para preto e branco etc. acabei descobrindo a função nativa imagefilter() - é curioso como sempre tem alguma coisa nova no PHP pra descobrir.

O método recebe como parâmetro, além do tipo de filtro, a quantidade de vezes que ele será aplicado. Algumas opções de filtragem possuem parâmetros extras. Aqui segui o padrão da função original: arg1, arg2, arg3 e arg4. Mais detalhes no manual da imagefilter().

canvasimagefilter()Descrição
blurIMG_FILTER_GAUSSIAN_BLUR“Embaça” a imagem, com desenfoque gaussiano.
blur2IMG_FILTER_SELECTIVE_BLUR“Embaça” a imagem, com desenfoque seletivo.
brilhoIMG_FILTER_BRIGHTNESSAltera o brilho da imagem, definido através do parâmetro arg1.
cinzasIMG_FILTER_GRAYSCALEConverte a imagem para tons de cinza.
contrasteIMG_FILTER_CONTRASTAltera o contraste da imagem, definido através do parâmetro arg1
colorirIMG_FILTER_COLORIZEConverte a imagem para tons da cor especificada. Arg1, arg2 e arg3 corrspondem às cores R, G e B - e o arg4 é o canal alfa.
edgeIMG_FILTER_EDGEDETECTDestaca os traços da imagem.
embossIMG_FILTER_EMBOSS“Acimenta” (ugh) a imagem.
negativoIMG_FILTER_NEGATEInverte todas as cores da imagem.
pixelIMG_FILTER_PIXELATEPixeliza a imagem. Arg1 é o tamanho do bloco (pixel) e arg2 é o modo de pixelização (avançado - true, ou normal - false). só funciona com PHP 5.3 ou superior
ruidoIMG_FILTER_MEAN_REMOVALAdiciona ruído, aplicando um efeito do tipo rascunho.
suaveIMG_FILTER_SMOOTHSuaviza a imagem conforme o valor especificado em arg1.

Confira alguns exemplos:

Blur

$img->carrega( 'cats.jpg' )
  ->redimensiona( '50%' )
  ->filtra( 'blur', 20 )
  ->grava();

Cor

$img->carrega( 'cats.jpg' )
  ->redimensiona( '50%' )
  ->filtra( 'colorir', 1, 255, 0, 92, 60 )
  ->grava();

Negativo

$img->carrega( 'cats.jpg' )
  ->redimensiona( '50%' )
  ->filtra( 'negativo', 2, 4 )
  ->grava();

Emboss

$img->carrega( 'cats.jpg' )
  ->redimensiona( '50%' )
  ->filtra( 'emboss' )
  ->grava();

Ruído

$img->carrega( 'cats.jpg' )
  ->redimensiona( '50%' )
  ->filtra( 'ruido', 2 )
  ->grava();

Exemplo combinando várias opções da classe canvas

$img->carrega( 'cats.jpg' )
  ->redimensiona( '40%', '', 'crop' )
  ->filtra( 'colorir', 1, 255, 70, 60, 40 )
  ->flip()
  ->hexa( '#fff' )
  ->gira( 45 )
  ->filtra( 'ruido', 1, 3 )
  ->marca( 'marca.png', 'topo', 'esquerda' )
  ->legenda( 'Criado automaticamente em '. date( 'd/m/Y H:i:s' ), 5, 'baixo', 'direita', '#000' )
  ->legenda( 'Lol Catz!', 20, 'topo', 'direita', '#ff9900', true, 'Aller_Bd.ttf' )
  ->grava();

Participando

Fique a vontade para, utilizando os comentários, sugerir melhorias e novas funcionalidades. Antes de indicar qualquer erro, verifique os seguintes problemas abaixo:

  • seu servidor está configurado com PHP 4 e a classe requer PHP 5;
  • a extensão GD não está habilitada no seu servidor;
  • o diretório no qual você está tentando salvar as imagens não possui permissão de escrita;
  • no caso de retornar as imagens direto na tela, o script está retornando alguma coisa antes da imagem, um texto, um código perdido - o que não pode acontecer;
  • o PHP do seu servidor não foi compilado com freetype (para o uso de fontes truetype) ou com suporte à função imagefilter();
  • o formulário que envia a imagem, sendo esse o caso, está sem o enctype=”multipart/form-data”.

Espero que curtam e que divirtam-se utilizando esta classe da mesma forma que foi divertido para mim desenvolvê-la.