PHP é à quinta-feira – Upload de uma Imagem
Boas. Ao nível de direitos sobre o código, devo remeter-vos para o meu primeiro artigo desta rubrica.
Nesta semana apresento-vos uma função cujo objectivo é receber uma imagem e redimensioná-la, caso necessário, com possibilidade de manter transparência caso a original a possua. Também podem redimensioná-la de forma a manter a sua proporção ou não.
<?php function saveImage($file,$newfile,$maxwidth = 250,$maxheight = 250,$proportional = true) { $original = $file['tmp_name'];//-- Original Image $ext_tmp = getimagesize($original); switch($ext_tmp[2]) { case 1 : $ext = "gif"; break; case 2 : $ext = "jpg"; break; case 3 : $ext = "png"; break; default : $ext = "jpg"; } switch ($ext) { case 'png' : $header = "image/png"; break; case 'gif' : $header = "image/gif"; break; case 'jpg' : case 'jpeg' : default : $header = "image/jpeg"; } header('Content-type: '.$header); list($width, $height) = getimagesize($original); if ($proportional) { if ($width < $maxwidth && $height < $maxheight) { $newwidth = $width; $newheight = $height; } else { if ($width < $height) { if ($height >= $maxheight) { $size = round($height/$maxheight,2); $newwidth = round($width/$size); $newheight = round($height/$size); } else { $size = round($width/$maxwidth,2); $newwidth = round($width/$size); $newheight = round($height/$size); } } else { if ($width >= $maxwidth) { $size = round($width/$maxwidth,2); $newwidth = round($width/$size); $newheight = round($height/$size); } else { $size = round($height/$maxheight,2); $newwidth = round($width/$size); $newheight = round($height/$size); } } } } else { $newwidth = $maxwidth; $newheight = $maxheight; } $img = imagecreatetruecolor($newwidth, $newheight); switch ($ext) { case 'png' : { $image = imagecreatefrompng($original); $transparency = true; } break; case 'gif' : { $image = imagecreatefromgif($original); $transparency = true; } break; case 'jpg' : case 'jpeg' : default : { $image = imagecreatefromjpeg($original); $transparency = false; } break; } if($transparency) { if ($ext == "png") { imagealphablending($img, false); $colorTransparent = imagecolorallocatealpha($img, 0, 0, 0, 127); imagefill($img, 0, 0, $colorTransparent); imagesavealpha($img, true); } elseif ($ext == "gif") { $trnprt_indx = imagecolortransparent($image); if ($trnprt_indx >= 0) { $trnprt_color = imagecolorsforindex($image, $trnprt_indx); $trnprt_indx = imagecolorallocate($img, $trnprt_color['red'], $trnprt_color['green'], $trnprt_color['blue']); imagefill($img, 0, 0, $trnprt_indx); imagecolortransparent($img, $trnprt_indx); } } } else { imagefill($img, 0, 0, imagecolorallocate($img, 255, 255, 255)); } imagecopyresampled($img, $image, 0, 0, 0, 0, $newwidth, $newheight, $width, $height); switch ($ext) { case 'png' : { if (imagepng($img, $newfile)) { //header('Content-Type: text/html; charset=iso-8859-1'); return true; } } break; case 'gif' : { if (imagegif($img, $newfile)) { //header('Content-Type: text/html; charset=iso-8859-1'); return true; } } break; case 'jpg' : case 'jpeg' : default : { if (imagejpeg($img, $newfile, 90)) { //header('Content-Type: text/html; charset=iso-8859-1'); return true; } } break; } //header('Content-Type: text/html; charset=iso-8859-1'); return false; } ?>
Modo de utilização:
É bastante simples e intuitivo, segue um exemplo de como pegar numa imagem de que se fez upload através de um formulário para 150x150 px, mantendo as proporções da imagem.
<?php $file = $_FILES['imagem']; $newfile = “/caminho/para/imagem.png”;//-- Estou a supôr que é .png, podemos e devemos obviamente determinar se o é antes de lhe dar o nome que vai ter no servidor. if (saveImage($file,$newfile,150,150)) echo “OK”; else echo “ERRO”; ?>
NOTA: A função só aceita imagens .jpg, .jpeg, .gif e .png
Qualquer dúvida ou sugestão, estão completamente à vontade.
Como vou entrar em exames, etc., se quiserem enviar as vossas propostas para esta rubrica, agradeço, pois será difícil escrevê-la até ao final de Julho.
Este artigo tem mais de um ano
Excelente dica. No entanto convém lembrar que o PHP necessita da GD Library para que estas funções funcionem.
Aproveito para indicar um pequeno tutorial para adicionar uma compilação do PHP com a GD Lybrary, para Mac. Para Linux deve funcionar exactamente da mesma forma.
http://macoshelp.blogspot.com/2008/02/adding-gd-library-for-mac-os-x-leopard.html
Cumprimentos e mais uma vez, parabéns pelo excelente artigo!
Obrigado pela explicação, excelente post.
Obrigado Bruno
Aquela parte ali de redimensionar dá-me a sensação de a ter visto de forma mais simplificada, mas também não li atentamente para perceber o que faz ao concreto.
Eu por acaso estava a pensar (o que não significa que irei fazer, também estou em exames) escrever um artigo para aqui. Como é que posso enviar a minha proposta/artigo para esta rubrica? O que preciso de enviar?
Basta enviar o código, uma descrição e uma forma de uso, para o email do Pplware(está no menu em cima, “Contacto”)
Bom trabalho. Apenas um ou dois pequenos reparos: o segundo switch case é desnecessário uma vez que poderias fazer a atribuição do formato de imagem ao header logo no primeiro switch. No segundo switch, o 4º caso (jpeg) está redundante porque a variável ext nunca tomará o valor “jpeg”.
Continua o óptimo trabalho que tens feito até aqui e já agora, aproveito para te desejar boa sorte para os exames. 😉
Obrigado pelos vossos comentários, e aproveito para dizer que, obviamente, as funções que aqui coloco podem ter redundâncias, nem sempre considerar todas as hipóteses e até mesmo código não optimizado. Tal acontece porque algumas destas funções já as desenvolvi há muito tempo, e por vezes são adicionadas funcionalidades após a construção inicial (como foi o caso da transparência).
Aproveitei esta rubrica para dar a conhecer código que muitas vezes uso ou pode ser útil para quem programa em PHP. Sei que no início andei à procura de muita coisa que ando aqui a colocar e o meu objectivo é ajudar essas pessoas, assim como também obter dicas sobre como melhorar partes do código ou até alternativas ao mesmo.
Obrigado novamente.
Em ColdFusion, bastaria uma linha!
cffile action=”upload” filefield=”form.clip” destination=”c:\Websites\testfolder\subfolder\#form.writer#\” accept=”audio/mpeg” nameconflict=”MakeUnique”
Pois, mas falta a parte do redimensionamento que te acrescentaria um bom número de linhas ao código bem como referências externas ao projecto, embora o nº total de linhas seja sempre inferior às do PHP… 😀 No entanto estou bastante curioso em relação ao ColdFusion uma vez que a nível profissional só desenvolvo em ASP.NET e PHP e essa plataforma está a ganhar cada vez mais terreno. Tenho que experimentar isso um dia destes 😀
Está a ganhar terreno? Espantosas notícias me dás, eu que tive de abandonar essa linguagem maravilhosa (e simples!!!) por causa dos custos envolvidos.
Pode ser que a “moda” (cá nunca o foi) volte…
Quanto ao redimensionamento, existem tags para o efeito pelo que, novamente, apenas seria precisa uma linha para passar os parâmetros.
Relativamente ao redimensionamento, não seria apenas 1 linha de código (acredito que gostes muito de ColdFusion, mas daí a fazer-se tudo com 2 linhas já é exagerado até para os menos cépticos)… Podes confirmar aqui uma das maneiras de efectuar o que foi apresentado nesta rubrica para PHP: http://www.scottpinkston.org/blog/index.cfm/2007/7/13/Image-Uploads-and-Resizing-with-ColdFusion-8
Contudo, se souberes essa maneira das 2 linhas agradecia que postasses, porque até fiquei curioso. No entanto, não hajam dúvidas que é muito mais simples do que PHP ou até ASP.NET. Mas isso é tudo muito relativo, porque adicionas uma classe ao projecto e chamas o método com uma linha de código também. Uma coisa é ser mais fácil, outra coisa é teres de acrescentar uma classe com funcionalidades que não vêm na API. Mas admito que é de louvar o ColdFusion trazer funcionalidades actualmente fulcrais já implementadas.
Quanto ao ganho de terreno, eu nunca disse que era cá (aliás isso é tão impensável, que eu admito que nem sequer conheço um único site português que apresente páginas desenvolvidas em ColdFusion). Por isso é que até fiquei com a ideia de que desenvolvias para empresas estrangeiras. Basta ires à página de customers da Adobe que usam ColdFusion e vês que são só empresas internacionais de grande envergadura. Se fossemos a olhar apenas aos custos, vias por exemplo os sites dos nossos bancos portugueses feitos em PHP ao invés de ASP…
Se por outro lado és trabalhador independente, já deverias saber que o ColdFusion estaria fora de questão antes de sequer pegares nele.
Por cá tens a Roche Farmacêutica.
A questão das duas linhas de código é verdadeira pelo seguinte: é certo que haveria que desenvolver o código do redimensionamento mas a “filosofia” do ColdFusion é a utilização de tags como no HTML (existe um modo de “script”, também).
Os tags podem ser “incorporados” na instalação do CF, bastando, depois, chamá-los como qualquer outro. Para além disto, existem bibliotecas de tags (que podes equiparar, de certa forma, a funções) não te cabendo a ti, utilizador comum, percebê-los. Apenas tens de colocar determinado ficheiro numa certa pasta e invocá-lo posteriormente.
Ou seja, quando chegasse a altura de escreveres, efectivamente o teu código, o redimensionamento implicaria, de facto, uma só linha, contribuindo para uma grande limpeza no código.
Uma das grandes vantagens do CF é que não há necessidade de explicitamente incorporar ficheiros para incluir funções. Desde que os ficheiros dos tags estejam na pasta certa, tudo está acessível como se fosse uma função nativa.
Outra das vantagens é que existe “normalização”, ou seja, uma query feita por mim ou por um programador em Marte, é feita da mesma forma, usando o mesmo código. Isto permite muito maior facilidade na compreensão de código alheio (maravilha para o “open source”, não?).
Mas… enquanto não houver um servidor ColdFusion gratuito, a coisa não descolará…
Obrigado pelo esclarecimento. É de facto uma plataforma deveras impressionante para sites a serem desenvolvidos em tempo crítico. Mas lá está, apenas viável para quem esteja disposto a pagar pelo alojamento. Lentamente, pode ser que isso ainda venha a mudar.
Seria melhor se tivesse mais explicações sobre cada parte do código pelo menos, tal como comentários, etc.
Cumps
Boas ,
Uma função útil para qualquer programador (principiante ou não) já que não vamos estar a decorar todas as funções que criamos/utilizamos .
Permite-me que adicione 2 dicas :
Para que o upload de um ficheiro (imagem ou não) seja possível o formulário tem de ter a seguinte enctype:
enctype=”application/x-www-form-urlencoded”
Ou vão andar passar o resto do dia a tentar fazer o debug do PHP o resto do dia quando o erro reside no bom velho HTML .
Outra, esta já no PHP:
Para verificar se o existe um ficheiro a enviar e tratar utilizo o seguinte :
if($_FILES[‘NOME_DO_CAMPO_DE_FICHEIRO’][‘error’] != 4){
/*
… codigo para upload/tratamento do ficheiro …
*/
}
pode servir de condição para evocar a função ou ser adicionada na própria função
Cumprimentos.
Keep Going !