É muito comum a necessidade de salvar imagens para atender alguma regra de negócio específica. Existem formas simples de se fazer isso sem utilizar nenhuma biblioteca de terceiros, porém esta não é a mais recomendada visto que não possui os artifícios necessários para tratar tais fotos.

Este artigo tem como principal objeto mostrar na prática como utilizar a biblioteca WideImage para tratar essas imagens de forma eficaz e sem muito código, por outro lado o Jquery Uploadify vai nos ajudar a tornar todo esse processo dinâmico e rápido.

WideImage do PHP

A Biblioteca WideImage é famosa e muito utilizado, visto que seus recursos tornar o trabalho com imagens muito simples e ao mesmo tempo complexo, funcionalmente falando. Com apenas 1 linha nós conseguimos cortar, redimensionar e salvar. É por isso que aconselhamos fortemente o uso de bibliotecas de renome (como é o caso do WideImage) para realizar tal tarefa, não há necessidade de se “reinventar a roda”. Na seção links deste artigo, você encontrar o link para o site oficial do WideImage onde você poderá realizar o download e estudar mais afundo esta biblioteca.

Confira os cursos de PHP da DevMedia

Quando você fizer o download de toda biblioteca, verá que há diversos arquivos nesta, e é óbvio que todos devem estar em uma pasta do seu projeto. Porém apenas o arquivo WideImage.php deverá ser chamado para que a biblioteca seja carregada. Você verá mais exemplos adiante.

jQuery Uploadify

Este plugin desenvolvido em jQuery torna o processo de upload de arquivos em geral (não apenas fotos) um tanto quanto bonito e eficaz. Isso porque todo o processo é feito dinamicamente via JavaScript retornando uma resposta em tempo real ao usuário, coisa que não aconteceria se você utilizasse apenas um input file comum.

Ele será utilizado em nosso exemplo para enviar a foto para uma pasta temporária, assim o WideImage poderá capturar a foto desta pasta temporária e tratá-la salvando em uma pasta definitiva. Na seção de links deste artigo você encontrará o link para o site oficial do uploadify onde você poderá baixá-lo e estudá-lo.

Só para deixar claro, o Uploadify possui duas versões: HTML5 e Flash. Utilizaremos nos exemplos abaixo a versão em Flash.

Na prática

Depois de uma breve explicação sobre as duas ferramentas que serão utilizadas no exemplo, podemos então introduzir o nosso estudo de caso.

Nosso exemplo será baseado no seguinte estudo de caso: temos que salvar imagens de banners enviados pelo usuário. Cada banner corresponde à um registro no banco com Id e Descrição, porém na nossa aplicação teremos uma foto para cada banner de acordo com o seu Id. Exemplo: O banner de Id 341 tem uma foto 341.jpg.

Primeiro vamos definir nosso formulário para envio do Banner, conforme a Listagem 1.

Listagem 1. Definição do Formulário para Envio do Banner


  <!--INICIO cad_banner.php -->
  <?php
  require_once "controller_banner.php";
   
  if (isset($_GET['acao']) && $_GET['acao'] == 'inserir')
      $acao = 'inserir';
  else if (isset($_GET['acao']) && $_GET['acao'] == 'editar') {
      $acao = 'editar';
      $pojoBanner = ControllerBanner::getInstance()->BuscarPorCOD(strip_tags(trim($_GET['cod_banner'])));
  }
  else
      echo "<script type='text/javascript'>history.back();</script>";
   
  if (isset($_POST['salvar'])) {
   
      if ($acao == "inserir")
          $pojoBanner = new PojoBanner();
      
   
      $pojoBanner->setDescricao(strip_tags(trim($_POST['descricao'])));
      $pojoBanner->setFoto($_POST['text_foto']);
   
   
  //INSERE OU SALVA DEPENDENDO DA ACÃO
      if ($acao == "inserir") {
   
          if (ControllerBanner::getInstance()->Inserir($pojoBanner)) {
   
              echo "<script type='text/javascript'> alert('Registro salvo com sucesso');</script>";
          }
          else
              echo "<script type='text/javascript'> alert('O Registro não pode ser inserido');</script>";
      }
   
      else if ($acao == "editar") {
          if (ControllerBanner::getInstance()->Editar($pojoBanner)) {
              echo "<script type='text/javascript'> alert('Registro salvo com sucesso');</script>";
          }
          else
              echo "<script type='text/javascript'> alert('O Registro não pode ser alterado');</script>";
      }
      else
          echo "Nenhuma Ação foi Selecionada";
  } // fim do salvar
  ?>
  <div id="tabs">
      <ul>
          <li><a href="#tabs-1">Cadastro/Edição de Banner</a></li>
      </ul>
      <div id="tabs-1">
          <div class="containerError hidden">
              <h3>Erros Encontrados</h3>
          </div>
          <form action="" enctype="multipart/form-data" method="post" name="form_cad_banner" id="form_cad_banner">     
   
              <label for="descricao">Descrição*:</label><input placeholder="Informe a Descrição" type="text" name="descricao" id="descricao" value="<?php
              if (isset($pojoBanner)) {
                  echo $pojoBanner->getDescricao();
              }
              ?>" /><br />                        
   
              <input type="file" class="enviar_foto" id="enviar_foto" name="enviar_foto" />
   
  <?php
  $file = "";
   
  if ($acao == 'editar') {
   
      if (file_exists("fotos_banners/" . $pojoBanner->getCod_banner() . "_original.jpg"))
          $file = "fotos_banners/" . $pojoBanner->getCod_banner() . "_original.jpg";
   
  }
  ?>
   
  <input type='hidden' name='text_foto' id='text_foto' value='<?php echo $file; ?>' /><br />
   
              <div class="acoes">
                  <input type="submit" name="salvar" value="Salvar" />
                  <input type="reset" name="cancelar" value="Cancelar" onclick="dialogoConfirm('Cancelar', 'Deseja cancelar ?')" />                    
              </div>
   
   
      </div>        
  </form>            
  </div>
  <!--FIM cad_banner.php-->

O formulário acima não tem mistério algum, mais atente a alguns pontos importantes:

  1. O campo text_foto é quem vai armazenar o nome da foto que será colocada na pasta temporária que falamos no inicio do artigo. Isso porque o text_foto é passado pelo objeto PojoBanner assim o WideImage pode identificar onde está a foto para tratá-la.
  2. É sempre bom guardamos a foto original enviada pelo usuário antes de fazer qualquer alteração. Por padrão podemos utilizar a nomenclatura: id_original.jpg, ou seja, se o banner tiver ID 354 a foto original ficará 354_original.jpg.
    Vamos agora definir o Uploadify que será responsável por “setar” o valor ao campo text_foto, conforme a Listagem 2.
  3. No input file a classe “enviar_foto” é quem vai dizer que ali vai ser configurado um Uploadify e todo mecanismo funcionará.

Listagem 2. Definição do jQuery Uploadify


  if ($('.enviar_foto').length) {
          $('.enviar_foto').uploadify({
              'uploader': '../../js/uploadify/uploadify.swf',
              'script': '../../js/uploadify/uploadify.php',
              'cancelImg': '../../js/uploadify/cancel.png',
              'folder': '../../js/uploadify/tempfiles',
              'auto': true,
              'removeCompleted': false,
              'fileExt': '*.jpg;*.jpeg;*.JPG;*.JPEG',
              'fileDesc': 'JPG|JPEG',
              'buttonText': 'Enviar Foto',
              'onComplete': function(event, ID, fileObj, response, data) {
                  $('#text_foto').attr("value", fileObj.name);
              }
          });
      }

Atente aos seguintes pontos:

  1. A nossa pasta temporária é a tempfiles, é lá que o WideImage vai buscar as imagens que serão tratadas e salvas.
  2. No “onComplete” do Uploadify, pegamos o nome do objeto que esta sendo salvo no tempfiles e setamos no text_foto.
  3. As propriedades e opções do uploadify podem ser encontradas em detalhes no seu site oficial.

Enfim vamos definir o WideImage que receberá esses dados e realizará o tratamento, conforme a Listagem 3.

Listagem 3. Usando o WideImage


  <?php
   
  require_once CAMINHO_RAIZ . "conexao.php";
  require_once CAMINHO_RAIZ . "geralog.php";
  require_once CAMINHO_RAIZ . "wideimage/WideImage.php";
  require_once CAMINHO_RAIZ . "controller_pagina.php";
  require_once CAMINHO_RAIZ . "converterData.php";
  require_once "pojo_banner.php";
   
  class DaoBanner {
   
      public static $instance;
   
      private function __construct() {
          //
      }
   
      public static function getInstance() {
          if (!isset(self::$instance))
              self::$instance = new DaoBanner();
   
          return self::$instance;
      }
   
      public function getNextID() {
          try {
              $sql = "SELECT Auto_increment FROM information_schema.tables WHERE table_name='banner'";
              $result = Conexao::getInstance()->query($sql);
              $final_result = $result->fetch(PDO::FETCH_ASSOC);
              return $final_result['Auto_increment'];
          } catch (Exception $e) {
              print "Ocorreu um erro ao tentar executar esta ação, foi gerado um LOG do mesmo, tente novamente mais tarde.";
              GeraLog::getInstance()->inserirLog("Erro: Código: " . $e->getCode() . " Mensagem: " . $e->getMessage());
          }
      }
   
      public function Inserir(PojoBanner $banner) {
          try {
              $sql = "INSERT INTO banner (             
                  descricao) 
                  VALUES (         
                  :descricao)";
   
              $p_sql = Conexao::getInstance()->prepare($sql);
   
              $p_sql->bindValue(":descricao", $banner->getDescricao());
                              
              if ($p_sql->execute()) {
   
                  $foto = $banner->getFoto();            
   
                  $lastid = Conexao::getInstance()->lastInsertId('cod_banner');
                  $caminho = CAMINHO_RAIZ . "fotos_banners/";
                  $caminho_old = CAMINHO_RAIZ . "js/uploadify/tempfiles/";
   
                  if (!empty($foto)) {
                      //Foto Original deve ser guardada
                      WideImage::load($caminho_old . $foto)->saveToFile($caminho . $lastid . "_original.jpg");
   
                      $w = 500;
                      $h = 500;
                      WideImage::load($caminho_old . $foto)->resize($w, $h, 'outside')->crop('50% - ' . ($w / 2), '50% - ' . ($h / 2), $w, $h)->saveToFile($caminho . $lastid . "_" . $w . "_" . $h . ".jpg");
                  }
   
                  return true;
              }
          } catch (Exception $e) {
              print "Ocorreu um erro ao tentar executar esta ação, foi gerado um LOG do mesmo, tente novamente mais tarde.";
              GeraLog::getInstance()->inserirLog("Erro: Código: " . $e->getCode() . " Mensagem: " . $e->getMessage());
          }
      }
   
      private function populaBanner($row) {
          $pojo = new PojoBanner();
          $pojo->setCod_banner($row['cod_banner']);
          $pojo->setDescricao($row['descricao']);
          return $pojo;
      }
   
  }
  ?>

A explicação do código acima é bem simples: A foto é carregada no WideImage através do método load, depois redimensionada com o resize (de acordo com o tamanho definido nas variáveis $w e $h), cortada nas pontas dando prioridade ao seu centro e por fim salva. Perceba também que logo de inicio salvamos a foto original sem nenhuma alteração, apenas trocando seu nome.

No código acima o nome da imagem segue esse padrão: id_W_H.jpg, ou seja, se o banner tem tamanho 500x500 e id 300 seu nome será 300_500_500.jpg, isso facilita na identificação da mesma, pois podemos ter a mesma foto em diversos tamanhos.

Links

WideImage - http://wideimage.sourceforge.net

Uploadify - http://www.uploadify.com/