quarta-feira, 3 de agosto de 2011

Upload e Recorte de imagens com PHP & jQuery


Hoje vou ensinar você como utilizar o plug-in Image Area Select plugin de Michal Wojciechowski, para criar uma interface bastante intuitiva onde o usuário possa escolher uma área da fotografia, fazer o recorte e então fazer utilizar upload da imagem sendo ela JPG, GIF ou PNG.

Requisitos

Resumo de funcionamento

1. Vamos usar uma variável de sessão para guardar um nome randômico para o arquivo (neste caso o timestamp). Depois, guardamos a extensão do arquivo para ser passado através do script para assegurarmos de que ele irá lidar com o tipo certo da imagem.
//Apenas grava o novo timestamp caso a variavel esteja vazia.
if (strlen($_SESSION['random_key'])==0){
    $_SESSION['random_key'] = strtotime(date('Y-m-d H:i:s')); //Grava o timestamp para uma variavel de sessão
    $_SESSION['user_file_ext']= "";
}
Nota: Uma vez que a thumbnail foi criada, setamos a variável de sessão igual a nada, vazia. Isso permite que uma nova imagem seja enviada com um novo nome.
2. Capturamos, renomeamos e redimencionamos a imagem carregada. Nesta parte, fazemos a validação do arquivo que foi feito o upload para validar se o mime type da imagem corresponde com a extensão do arquivo para fazer deste um sistema mais seguro.
foreach ($allowed_image_types as $mime_type => $ext) {
    //Faz um loop pelos mime types permitidos e se eles baterem com a imagem que foi enviado o loop é interrompido.
    //Se tudo estiver ok, ele prossegue e verifica o tamanho do arquivo.
    if($file_ext==$ext && $userfile_type==$mime_type){
        $error = "";
        break;
    }else{
        $error = "Somente imagens <strong>".$image_ext."</strong> são aceitas para o upload";
    }
}
//Verifica se o tamanho do arquivo tem um tamanho permitido.
if ($userfile_size > ($max_file*1048576)) {
    $error.= "Imagens devem ser menores que ".$max_file."MB em seu tamanho";
}
3. Ainda no passo anterior, pegamos as cordenadas (x1,y1,x2,y2) utilizando o Image Area Select plugin e mandamos os detalhes para o servidor.
Descrição das coordenadas
  • x1, y1 = Coordenadas do topo esquerdo da área de seleção.
  • x2, y2 = Coordenadas da parte inferior direta a partir da seleção.
  • width = Largura do recorte.
  • height = Altura do recorte.
Estas são as coordenadas que são manipuladas pelo plugin, como você pode ver mais a frente. Optei por um aspect ratio de 1:1 (Largura e altura de 100px) no modo de visualização quando estamos selecionando a área de recorte da imagem.
Nota: Utilizando o cálculo php mais a frente, faz o script muito mais dinâmico. Tudo o que você deve fazer é setar a altura e a largura do seu thumbnail e o script vai calcular os tamanhos de ratio/preview para você!
$(window).load(function () {
    $("#thumbnail").imgAreaSelect({ aspectRatio: "1:thumb_height/thumb_width", onSelectChange: preview });
});
A função a seguir roda quando fazemos nossa seleção. Ela pega a área exata da seleção e coloca dentro da área de preview. A segunda função popula os hidden fields que serão passados para o servidor.
function preview(img, selection) {
    var scaleX =  / selection.width;
    var scaleY =  / selection.height; 

    $('#thumbnail + div > img').css({
        width: Math.round(scaleX * ) + 'px',
        height: Math.round(scaleY * ) + 'px',
        marginLeft: '-' + Math.round(scaleX * selection.x1) + 'px',
        marginTop: '-' + Math.round(scaleY * selection.y1) + 'px'
    });
    $('#x1').val(selection.x1);
    $('#y1').val(selection.y1);
    $('#x2').val(selection.x2);
    $('#y2').val(selection.y2);
    $('#w').val(selection.width);
    $('#h').val(selection.height);
}
Essa função não é obrigatória, mas ajuda a verificar se o usuário fez um recorte. No nosso caso, a seleção é obrigatória. O formulário é submetido e se os valores existirem (ou se a seleção for feita), prosseguimos.
$(document).ready(function () {
    $("#save_thumb").click(function() {
        var x1 = $("#x1").val();
        var y1 = $("#y1").val();
        var x2 = $("#x2").val();
        var y2 = $("#y2").val();
        var w = $("#w").val();
        var h = $("#h").val();
        if(x1=="" || y1=="" || x2=="" || y2=="" || w=="" || h==""){
            alert("Você precisa fazer uma seleção!");
            return false;
        }else{
            return true;
        }
    });
});
4. Finalmente, pegamos as novas coordenadas e geramos uma nova e redimencionada thumbnail.
if (isset($_POST["upload_thumbnail"])) {
    //Pega as novas coordenadas para recortar a imagem.
    $x1 = $_POST["x1"];
    $y1 = $_POST["y1"];
    $x2 = $_POST["x2"]; // Não é obrigatório
    $y2 = $_POST["y2"]; // Não é obrigatório
    $w = $_POST["w"];
    $h = $_POST["h"];
    //Escala a imagem para 100px por 100px
    $scale = $thumb_width/$w;
    $cropped = resizeThumbnailImage($thumb_image_location, $large_image_location,$w,$h,$x1,$y1,$scale);
    //Recarrega a imagem para ver a thumbnail
    header("location:".$_SERVER["PHP_SELF"]);
    exit();
}
Dê uma olhada na demo e faça o download do código completo funcionando.
Ao longo do tempo testamos o script no Firefox 2 e 3Internet Explorer 6 e 7 e no Safari 3.1.2, resultados muito bons, o único problema que encontramos foi quando fizemos o upload de um gif transparente, os testes resultaram em uma thumbnail com o fundo preto.

Demo

Download

*
Este texto é uma adaptação e tradução do texto PHP & jQuery image upload and crop v1.2.

Nenhum comentário:

Postar um comentário