Lfscoutinho 2 Posted April 4, 2011 Report Share Posted April 4, 2011 Boas, Aqui fica o trabalho feito por mim nos últimos dias. Espero que seja útil Pastebin: http://pastebin.com/WQbWed3m Nota: O ficheiro da classe tem de estar guardado como UTF-8 sem BOM ou ANSI. <?php /** * Luís Coutinho é um autodidacta com uma grande paixão pela programação. Esta * classe tem como único objectivo ser útil a quem precisa de criar e redimensionar * imagens, criar miniaturas, colocar marcas d'água em imagens e fazer upload de * imagens. * * Críticas e sugestões são bem-vindas. * * No caso de teres gostado desta classe e te tenha sido útil, podes sempre fazer * uma pequena contribuição monetária... Abaixo, segue o link para doações. * https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=SK9NXWHWLGGHW * * @author Luís Coutinho <Luis@lfscoutinho.net> * @link http://lfscoutinho.net * @version 1.0 * @package lfscoutinho */ /** * Imagem Lfscoutinho * A Imagem Lfscoutinho é uma classe que permite criar e redimensionar imagens, * criar miniaturas, colocar uma marca d'água, fazer upload, etc. Para além disso, * está adaptada para sites que estejam em vários idiomas. Os únicos requisitos * são: ter a função gettext e a biblitoteca GD activas no servidor. * * @property array $formatos Formatos autorizados * @property int $max_tamanho Tamanho máximo da imagem a ser carregada (em bytes) * @property int $max_largura Largura máxima da imagem a ser carregada (em pixels) * @property int $max_altura Altura máxima da imagem a ser carregada (em pixels) * @property int $qualidade Qualidade da imagem nova (0 a 100) * @property bool $redimensionar Indica se é possível redimensionar a imagem, caso as medidas sejam superiores às permitidas * @property bool $encriptarNome Indica se é para encriptar ou não o nome (de modo a não criar imagens com o mesmo nome) * @property null|string $destino Indica se é para mostrar ou carregar uma imagem. Se for null, mostra a imagem. Caso contrário, carrega-a * @property string $destinoImg Caminho de destino das imagens * @property string $destinoMini Caminho de destino das miniaturas * @property bool $colocarMarcaDagua Indica se é para colocar uma marca d'água ou não * @property array $marcaDagua Dados da marca d'água [src = caminho, posx = posição horizontal, posy = posição vertical] * @property array $imagemOriginal Imagem antiga * @property array $imagemNova Imagem nova * @property array $erros Erros que possam ocorrer * @property bool $mostrarErros Indica se é para mostrar os erros ou não, caso ocorram * * @package lfscoutinho * @subpackage classes */ class Imagem { private $formatos = array( IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_GIF ); private $formatosDesc = array( 'JPEG', 'PNG', 'GIF' ); private $max_tamanho = 100000; private $max_largura = 800; private $max_altura = 600; private $qualidade = 100; private $redimensionar = false; private $encriptarNome = true; private $destino = null; private $destinoImg = 'C:/wamp/www/imagem/fotos/'; private $destinoMini = 'C:/wamp/www/imagem/minis/'; private $colocarMarcaDagua = false; private $marcaDagua = array( 'src' => 'http://127.0.0.1/imagem/php.png', 'posx' => 0, 'posy' => 0 ); private $imagemOriginal; private $imagemNova; private $erros = array(); private $mostrarErros = true; /** * Método constructor. Neste método é possível alterar algumas propriedades * que estão atribuídas por defeito. * * @param int func_get_arg(0) Qualidade da imagem (0 - 100). Para usar o valor por defeito, colocar -1 * @param int func_get_arg(1) Tamanho máximo. Para usar o valor por defeito, colocar -1 * @param int func_get_arg(2) Largura máxima. Para usar o valor por defeito, colocar -1 * @param int func_get_arg(3) Altura máxima. Para usar o valor por defeito, colocar -1 * @param string|bool func_get_arg(4) Redimensionar automaticamente. Para usar o valor por defeito, colocar uma string vazia * @param string func_get_arg(5) Caminho de destino. Para usar o valor por defeito, colocar uma string vazia */ public function __construct() { // Qualidade if( func_num_args() > 0 && func_get_arg( 0 ) > -1 ) { $this->max_tamanho = (int) func_get_arg( 0 ); } // Tamanho máximo if( func_num_args() > 1 && func_get_arg( 1 ) > -1 ) { $this->max_tamanho = (int) func_get_arg( 1 ); } // Largura máxima if( func_num_args() > 2 && func_get_arg( 2 ) > -1 ) { $this->max_largura = (int) func_get_arg( 2 ); } // Altura máxima if( func_num_args() > 3 && func_get_arg( 3 ) > -1 ) { $this->max_altura = (int) func_get_arg( 3 ); } // Redimensionar if( func_num_args() > 4 && func_get_arg( 4 ) !== '' ) { $this->redimensionar = (bool) func_get_arg( 4 ); } // Caminho de destino if( func_num_args() > 5 && func_get_arg( 5 ) !== '' ) { $this->setDestino( (string) func_get_arg( 5 ) ); } } /** * Método que faz algumas verificações e atribuições em relação à imagem * * @param string $caminho Caminho de origem da imagem */ public function setImagem( $imagem ) { if( is_array( $imagem ) ) { if( $this->verificarFormato( $imagem['tmp_name'] ) ) { $this->imagemOriginal['caminho'] = $imagem['tmp_name']; $this->setNome( $imagem['name'] ); $this->setDestino( '' ); $this->setMedidas( $imagem['tmp_name'] ); $this->verificarTamanho( $imagem['size'] ); $this->verificarMedidas(); } } elseif( is_string( $imagem ) ) { if( $this->verificarFormato( $imagem ) ) { $this->imagemOriginal['caminho'] = $imagem; $this->setDestino( null ); $this->setMedidas( $imagem ); $this->redimensionar(); } } } /** * Método que define se é para encriptar o nome da imagem nova ou não * * @param bool $simOUnao true para encriptar e false para não encriptar */ public function setEncriptarNome( $simOUnao ) { if( is_bool( $simOUnao ) ) { $this->encriptarNome = $simOUnao; return true; } else { return false; } } /** * Método que define o nome da imagem nova * * @param string $nome Nome da imagem antiga */ public function setNome( $nome ) { if( $this->getEncriptarNome() ) { $this->imagemNova['nome'] = md5( $nome . microtime( true ) ) . $this->imagemOriginal['extensao']; } else { $this->imagemNova['nome'] = $nome; } } /** * Método que define as medidas da imagem original e, verifica ou não, se * são permitidas * * @param string $caminho Caminho da imagem original */ private function setMedidas( $caminho ){ list($largura, $altura) = getimagesize( $caminho ); $this->imagemOriginal['largura'] = $largura; $this->imagemOriginal['altura'] = $altura; } /** * Método que define os caminhos de destino das imagens/miniaturas. O valor * null, significa que é para mostrar uma imagem e não para fazer upload. Para * utilizar os caminhos por defeitos (tanto para imagens como miniaturas), * utiliza-se uma string vazia (''). E, para dizer se é para carregar uma * imagem ou uma miniatura atribui-se à variável $mini, false ou true, * respectivamente. O valor por defeito é false (carregar imagens). * * @param string $caminho Caminho de destino da imagem * @param bool $mini false para mudar o destino da imagem e true para mudar o destino da miniatura * @return bool Retorna true, se o caminho novo for definido. Caso contrário, false. */ public function setDestino( $caminho, $mini = false ){ if( $caminho === '' ) { if( $mini ) { $this->destino = $this->destinoMini; } else { $this->destino = $this->destinoImg; } $this->destino .= $this->getNome(); } elseif( $caminho && file_exists( $caminho ) ) { $this->destino = $caminho . $this->getNome(); } elseif( $caminho === null ) { $this->destino = null; } else { $this->erros[] = _('O caminho de destino não existe.'); return false; } return true; } /** * Método que define a colocação ou não da marca d'água. * * @param bool $simOUnao true para colocar e false para não colocar * @return bool Retorna true, se o valor for definido com sucesso. Caso contrário, false */ public function setColocarMarcaDagua( $simOUnao ) { if( is_bool( $simOUnao ) ) { $this->colocarMarcaDagua = $simOUnao; return true; } else { return false; } } /** * Método que define a imagem da marca d'água e as posições onde vai ser * colocada. As posições positivas alinham a imagem da esquerda para a direita * e de cima para baixo, já as posições negativas alinham a imagem da direita * para a esquerda e de baixo para cima. * * @param array $opcoes Opções da marca d'água [src = caminho, posx = posição horizontal, posy = posição vertical] * @return bool Retorna verdadeiro, se os valores forem definidos com sucesso. Caso contrário, false */ public function setMarcaDagua( $opcoes ) { if( is_array( $opcoes ) ) { if( isset( $opcoes['src'] ) && exif_imagetype( $caminho ) === IMAGETYPE_PNG ) { $this->marcaDagua['src'] = $opcoes['src']; } if( isset( $opcoes['posx'] ) && is_int( $opcoes['posx'] ) ) { $this->marcaDagua['posx'] = $opcoes['posx']; } if( isset( $opcoes['posy'] ) && is_int( $opcoes['posy'] ) ) { $this->marcaDagua['posy'] = $opcoes['posy']; } return true; } else { return false; } } /** * Método que retorna o objectivo de encriptar o nome da imagem nova * * @return bool Retorna true, se for para encriptar. Caso contrário, false. */ public function getEncriptarNome() { return $this->encriptarNome; } /** * Método que retorna o nome da imagem/miniatura nova * * @return string Retorna o nome da imagem/miniatura nova */ public function getNome() { return $this->imagemNova['nome']; } /** * Método que retorna o caminho de destino das imagens/miniaturas * * @return string Retorna o destino da imagem/miniatura */ public function getDestino() { return $this->destino; } /** * Método que retorna o objectivo de colocar a marca d'água * * @return bool Retornar true, se for para colocar a marca d'água. Caso contrário, false */ public function getColocarMarcaDagua() { return $this->colocarMarcaDagua; } /** * Método que verifica se há erros e, se necessário, mostra-os * * @return bool Retorna false, se não existirem erros. Caso contrário, retorna-os */ public function getErros() { if( $this->erros ) { $html = '<div id="errosImagem">'; foreach( $this->erros as $erro ) { $html.= "\n\t<p>{$erro}</p>"; } $html.= "\n</div>"; return $html; } else { return false; } } /** * Método que verifica se o ficheiro é uma imagem e se o formato é permitido * * @param string $caminho Caminho da imagem * @return bool Retorna verdadeiro, se o formato for permitido. Caso contrário, false */ public function verificarFormato( $caminho ) { $formato = exif_imagetype( $caminho ); if( $formato && in_array( $formato, $this->formatos ) ) { switch( $formato ) { case IMAGETYPE_JPEG : $this->imagemOriginal['extensao'] = '.jpg'; break; case IMAGETYPE_PNG : $this->imagemOriginal['extensao'] = '.png'; break; case IMAGETYPE_GIF : $this->imagemOriginal['extensao'] = '.gif'; break; } $this->imagemOriginal['formato'] = $formato; return true; } else { $this->erros[] = sprintf( _('Não é possível carregar ficheiros do formato escolhido. Os únicos formatos permitidos são: %s'), implode( ', ', $this->formatosDesc ) ); return false; } } /** * Método que verifica se o tomanho do ficheiro é permitido * * @param int $tamanho Tamanho do ficheiro * @return bool Retorna true, se o tamanho for permitido. Caso contrário, false */ public function verificarTamanho( $tamanho ) { if( $this->max_tamanho > $tamanho || $this->max_tamanho === 0 ) { return true; } else { $this->erros[] = sprintf( _('A imagem é muito grande. O tamanho da imagem deve ser, no máximo, %d KB.'), $this->max_tamanho ); return false; } } /** * Método que verifica se as medidas da imagem original (largura e altura) * são permitidas. Se não forem, verifica se é possível redimensionar a imagem. * * @return bool Retorna true, se as medidas forem permitidas ou se for possível redimensionar a imagem. Caso contrário, false */ public function verificarMedidas() { if( $this->redimensionar ) { $this->redimensionar(); } else { if( $this->max_largura && $this->imagemOriginal['largura'] > $this->max_largura ) { $this->erros[] = sprintf( _('A imagem é muito larga. A largura deve ter, no máximo, %d pixels.'), $this->max_largura ); return false; } if( $this->max_altura && $this->imagemOriginal['altura'] > $this->max_altura ) { $this->erros[] = sprintf( _('A imagem é muito alta. A altura deve ter, no máximo, %d pixels.'), $this->max_altura ); return false; } } $this->imagemNova['largura'] = $this->imagemOriginal['largura']; $this->imagemNova['altura'] = $this->imagemOriginal['altura']; return true; } /** * Método que calcula as medidas de uma imagem a ser redimensionada. No caso * de serem indicadas a largura e a altura, as medidas da nova imagem serão * essas. Se for indicada só a largura ou a altura, o redimensionamento será * feito com base nessa medida. E, se não for indicada nenhuma das medidas, * o redimensionamento será feito com base na medida maior. * * @param int $largura Largura da imagem * @param int $altura Altura da imagem */ public function redimensionar( $largura = 0, $altura = 0 ) { if( $largura === 0 && $altura === 0 ) { if( ( $this->max_largura && $this->imagemOriginal['largura'] > $this->max_largura ) || ( $this->max_altura && $this->imagemOriginal['altura'] > $this->max_altura ) ) { if( $this->imagemOriginal['largura'] > $this->imagemOriginal['altura'] ) { $largura = $this->max_largura; } else { $altura = $this->max_altura; } } else { // No caso de ser para mostrar a imagem (em vez de fazer upload) // e a imagem esteja dentro dos limites $largura = $this->imagemOriginal['largura']; $altura = $this->imagemOriginal['altura']; } } if( $largura && $altura === 0 ) { $altura = $this->imagemOriginal['altura'] * $largura / $this->imagemOriginal['largura']; } elseif( $largura === 0 && $altura ) { $largura = $this->imagemOriginal['largura'] * $altura / $this->imagemOriginal['altura']; } $this->imagemNova['largura'] = $largura; $this->imagemNova['altura'] = $altura; } /** * Cria o resource de uma imagem * * @param string $caminho Caminho da imagem original * @param string $formato Formato da imagem original * @return resource|bool Em caso de sucesso, retorna o resource da imagem. Caso contrário, false */ private function criarImagem( $caminho, $formato ) { if( $formato === IMAGETYPE_JPEG ) { $original = imagecreatefromjpeg( $caminho ); } elseif( $formato === IMAGETYPE_PNG ) { $original = imagecreatefrompng( $caminho ); } elseif( $formato === IMAGETYPE_GIF ) { $original = imagecreatefromgif( $caminho ); } return $original; } /** * Método que carrega ou mostra uma imagem * * @param resource $imagem Resource da imagem */ private function carregarOUmostrar( $imagem ) { if( $this->imagemOriginal['formato'] === IMAGETYPE_JPEG ) { imagejpeg( $imagem, $this->getDestino(), $this->qualidade ); } elseif ( $this->imagemOriginal['formato'] === IMAGETYPE_PNG ) { imagepng( $imagem, $this->getDestino(), round( $this->qualidade * 9 / 100 ) ); } elseif ( $this->imagemOriginal['formato'] === IMAGETYPE_GIF ) { imagegif( $imagem, $this->getDestino() ); } } /** * PNG ALPHA CHANNEL SUPPORT for imagecopymerge(); * This is a function like imagecopymerge but it handle alpha channel well!!! * * A fix to get a function like imagecopymerge WITH ALPHA SUPPORT * Main script by aiden dot mail at freemail dot hu * Transformed to imagecopymerge_alpha() by rodrigo dot polo at gmail dot com * * // Adicionei um pouco de código, de modo a que seja possível posicionar * // a imagem da esquerda para a direita e de baixo para cima. Para isso, * // basta utilizar medidas negativas */ function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x = 0, $src_y = 0, $src_w = 0, $src_h = 0, $pct = 100){ if(!isset($pct)){ return false; } $pct /= 100; // Get image width and height $w = imagesx( $src_im ); $h = imagesy( $src_im ); // Posicionar imagem da esquerda para a direita e de baixo para cima if( $dst_x < 0 ) { $dst_x = imagesx($dst_im) - $w - abs($dst_x) + 1; } if( $dst_y < 0 ) { $dst_y = imagesy($dst_im) - $h - abs($dst_y) + 1; } // Turn alpha blending off imagealphablending( $src_im, false ); // Find the most opaque pixel in the image (the one with the smallest alpha value) $minalpha = 127; for( $x = 0; $x < $w; $x++ ) for( $y = 0; $y < $h; $y++ ){ $alpha = ( imagecolorat( $src_im, $x, $y ) >> 24 ) & 0xFF; if( $alpha < $minalpha ){ $minalpha = $alpha; } } //loop through image pixels and modify alpha for each for( $x = 0; $x < $w; $x++ ){ for( $y = 0; $y < $h; $y++ ){ //get current alpha value (represents the TANSPARENCY!) $colorxy = imagecolorat( $src_im, $x, $y ); $alpha = ( $colorxy >> 24 ) & 0xFF; //calculate new alpha if( $minalpha !== 127 ){ $alpha = 127 + 127 * $pct * ( $alpha - 127 ) / ( 127 - $minalpha ); } else { $alpha += 127 * $pct; } //get the color index with new alpha $alphacolorxy = imagecolorallocatealpha( $src_im, ( $colorxy >> 16 ) & 0xFF, ( $colorxy >> 8 ) & 0xFF, $colorxy & 0xFF, $alpha ); //set pixel with the new color + opacity if( !imagesetpixel( $src_im, $x, $y, $alphacolorxy ) ){ return false; } } } // The image copy imagecopy($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $w, $h); } /** * Método que cria a imagem. Quando definido o modo de corte, a imagem será * cortada de modo a que fique proporcional. * * @param string $corte Modo de corte (horizontal (h) / vertical (v) / automático (a)) */ public function criar( $corte = null ) { if( $erros = $this->getErros() ) { if( $this->mostrarErros ) { echo $erros; } return false; } $dst_img = imagecreatetruecolor( $this->imagemNova['largura'], $this->imagemNova['altura'] ); $src_img = $this->criarImagem( $this->imagemOriginal['caminho'], $this->imagemOriginal['formato'] ); $src_w = $this->imagemOriginal['largura']; $src_h = $this->imagemOriginal['altura']; $dst_x = $dst_y = $src_x = $src_y = $dst_w = $dst_h = 0; $racio_original = $this->imagemOriginal['largura'] / $this->imagemOriginal['altura']; $racio_novo = $this->imagemNova['largura'] / $this->imagemNova['altura']; if( $corte === 'h' || ( $corte === 'a' && $racio_novo > $racio_original ) ) { $racio = $this->imagemNova['altura'] / $this->imagemOriginal['altura']; $dst_h = $this->imagemNova['altura']; $dst_w = $this->imagemOriginal['largura'] * $racio; $dst_x = ( $this->imagemNova['largura'] - $dst_w ) / 2; } elseif( $corte === 'v' || ( $corte === 'a' && $racio_novo < $racio_original ) ) { $racio = $this->imagemNova['largura'] / $this->imagemOriginal['largura']; $dst_w = $this->imagemNova['largura']; $dst_h = $this->imagemOriginal['altura'] * $racio; $dst_y = ($this->imagemNova['altura'] - $dst_h) / 2; } else { $dst_w = $this->imagemNova['largura']; $dst_h = $this->imagemNova['altura']; } imagecopyresampled( $dst_img, $src_img , $dst_x, $dst_y, $src_x, $src_y,$dst_w, $dst_h, $src_w, $src_h ); if( $this->getColocarMarcaDagua() ) { $src_im = $this->criarImagem( $this->marcaDagua['src'], IMAGETYPE_PNG ); $this->imagecopymerge_alpha( $dst_img, $src_im, $this->marcaDagua['posx'], $this->marcaDagua['posy'] ); imagedestroy( $src_im ); } $this->carregarOUmostrar( $dst_img ); imagedestroy( $dst_img ); imagedestroy( $src_img ); return true; } } ?> Exemplo1: Fazer upload de uma imagem <?php require_once'imagem.class.php'; $img = new Imagem(); $img->setImagem( $_FILES['imagem'] ); $img->criar(); ?> <html> <head> </head> <body> <form method="post" enctype="multipart/form-data"> <input type="file" name="imagem" /> <input type="submit" name="enviar" value="Enviar" /> </form> </body> </html> Exemplo 2: Redimensionar uma imagem para a largura indicada e carregá-la <?php require_once'imagem.class.php'; $img = new Imagem(); $img->setImagem( $_FILES['imagem'] ); $img->redimensionar( 400 ); $img->criar(); ?> Exemplo 3: Redimensionar uma imagem, criar uma miniatura e carregá-las <?php require_once'imagem.class.php'; $img = new Imagem(); $img->setImagem( $_FILES['imagem'] ); $img->redimensionar( 400 ); $img->criar(); $img->redimensionar( 100 ); $img->setDestino( '', true ); $img->criar(); ?> Exemplo 4: Redimensionar uma imagem utilizando o corte automático (redimensiona-a proporcionalmente) e carregá-la <?php require_once'imagem.class.php'; $img = new Imagem(); $img->setImagem( $_FILES['imagem'] ); $img->redimensionar( 400, 200 ); $img->criar( 'a' ); ?> Exemplo 5: Redimensionar uma imagem, adicionar uma marca d'água e carregá-la <?php require_once'imagem.class.php'; $img = new Imagem(); $img->setImagem( $_FILES['imagem'] ); $img->redimensionar( 400, 200 ); $img->setColocarMarcaDagua(true); $img->criar( 'a' ); ?> Exemplo 6: Carregar uma imagem, redimensioná-la e adicionar uma marca d'água (alinhando-a da esquerda para a direita e de baixo para cima) <?php require_once'imagem.class.php'; $img = new Imagem(); $img->setImagem( $_FILES['imagem'] ); $img->redimensionar( 400, 200 ); $img->setColocarMarcaDagua(true); $img->setMarcaDagua( array('posx' => -1, 'posy' => -1) ); $img->criar( 'a' ); ?> Exemplo 7: Criar uma imagem para mostrar, mas não carregar Nota: o ficheiro teste.php tem de estar como UTF-8 sem BOM ou AINSI. <html> <head> </head> <body> <img src="teste.php" /> </body> </html> <?php header("Content-type: image/jpeg"); require_once'imagem.class.php'; $img = new Imagem(); $img->setImagem( 'http://url_da_imagem.extensao' ); $img->redimensionar( 400, 200 ); $img->setColocarMarcaDagua( true ); $img->criar('a'); ?> 1 Report Link to post Share on other sites
yoda 126 Posted April 4, 2011 Report Share Posted April 4, 2011 Tens muita coisa que podes aprimorar, se tiver tempo mais tarde indico-as. before you post, what have you tried? - http://filipematias.info sense, purpose, direction Link to post Share on other sites
Lfscoutinho 2 Posted April 5, 2011 Author Report Share Posted April 5, 2011 Boas, Eu agradeço Link to post Share on other sites
vitoroli 0 Posted September 29, 2011 Report Share Posted September 29, 2011 Será possível ajudares-me a que seja possível com a tua classe adicionar a fotos original mais a miniatura com os tamanhos reduzidos? Link to post Share on other sites
taviroquai 55 Posted September 29, 2011 Report Share Posted September 29, 2011 Viva! Bastante trabalhinho Vou comentar apenas 1 método... não vi os outros... No método setImagem, estás a permitir array... acho que é muito inconsistente... quem lê a documentação inline, sem olhar para o código, fica sem preceber que tipo de array pode passar... imagina: array(array(array('imagem' => 'caminho relativo? absoluto?'))) ou array('caminho') Assim, acho que deves limitar apenas a string, não há dúvidas e funciona sempre. Ainda assim mudava setImagem para caminho ou setPath, tipo $image->setPath('path'); Cumps Link to post Share on other sites
tiko165 2 Posted December 9, 2014 Report Share Posted December 9, 2014 Muito tempo depois deste post, alguem comenta Ainda sem testar, parece-me uma função bastante aceitavel ao que se pretende. Possivelmente na data de hoje, muita coisa ja se pode melhorar, mas pelo que vi, eu gostei. Link to post Share on other sites
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now