Crop image with Javascript

Asked

Viewed 3,291 times

26

I need to upload a photo and then put it in a modal for the user to make a proportional cutout 4/3 a short web search found this jQuery plugin jCrop.

He seems to provide me with the coordinates to crop the images, but I don’t idea of how to integrate it with PHP. If anyone has a practical example it will be very welcome.

  • I don’t know if it’s possible to do this with Javascript. I think the most you can do is take the dimensions you want (using JS) of the image and send it to the server to process it. But I’m not sure, better wait for someone who knows more to say.

  • Yes, @gabrielhof. But the question is how to pass the coordinates to PHP.

  • 3

    Just as a reference, that other library allows you to crop an image in arbitrary formats, not only rectangular. Here is a example in jsFiddle

2 answers

15


To crop the photo you need to use an extension PHP that manipulates images, the best known are GD and Imagemagick.

Simple implementation for PHP 5 >=5.5 using GD

$ini_filename = 'imagens/img.jpg'; // path da imagem
$im = imagecreatefromjpeg($ini_filename); // criando instancia jpeg

//definindo coordenadas de corte
$to_crop_array = array('x' =>20 , 'y' => 20, 'width' => 200, 'height'=> 200); 
$thumb_im = imagecrop($im, $to_crop_array); // recortando imagem

imagejpeg($thumb_im, 'imagens/new_img.jpg', 100); // salvando nova instancia

Example based on


jQuery Picture Cut

If you want I recommend this plugin jQuery is very simple to implement and full features both client-side and server-side implementations.

HTML

<div id="container_image"></div>

Javascript

$("#container_image").PictureCut({                    
    InputOfImageDirectory       : "image",
    PluginFolderOnServer        : "/jquery.picture.cut/",
    FolderOnServer              : "/uploads/",    
    EnableCrop                  : true,
    CropWindowStyle             : "Bootstrap",              
});

Server side implementation

Demo

Documentation

  • 1

    Very interesting this jQuery Picture Cut, seems to solve all my needs

  • 1

    Congratulations Vinicius, your explanation was very good.

14

Initial settings

As it comes to a jQuery plugin we need the call to the library somewhere in our HTML. In addition, we will also need to include the jCrop source file with its required style sheet and images.

<link href="css/jquery.Jcrop.css" rel="stylesheet" type="text/css" />
<script src="js/jquery.min.js"></script>
<script src="js/jquery.Jcrop.js"></script>

This way you can already use jCrop in its most basic form:

<img src="imagem.jpg" width="634" height="340" id="jcrop" />
<script type="text/javascript">
$(function(){ 
    $('#jcrop').Jcrop(); 
});
</script>

In the above example, ‘#jcrop’ is the ID attribute of the Crop target image. You can use any type of jQuery selector (classes, sub-elements etc.) by applying the Crop frontend to various img elements.

The plugin works only on the client, on the application interface. Crop itself has to be done on the server.

Processing Crop with PHP First let’s understand how jCrop works. Its marking method in the image returns an array with the dimensions and positioning of Crop. It has some events, here we will use the two main: onChange and onSelect. onChange executes any function at the time the markup is changed and onSelect executes any function at the time the selection is in progress.

Therefore, we will use, for now, the function exibePreview in both cases. What it does is update a preview of the final Crop result, and store variables for upload and processing on the server.

function exibePreview( c )
{
    // c.x, c.y, c.x2, c.y2, c.w, c.h
};

The function receives the array c, the one with the dimensions and coordinates of Crop. The values of the array are:

w width (width) of Crop h height (height) of Crop X1 and x2 horizontal Crop positions in the image Y1 and Y2 vertical Crop positions in the image Note that this is where jCrop’s work ends. Values should be processed in PHP. In our example, as I mentioned earlier, the displayPreview function will record the positions in inputs of type Hidden in the shipping form.

function exibePreview( c )
{
    // campos hidden que armazenam os valores
    $('#x').val(c.x);
    $('#y').val(c.y);
    $('#x2').val(c.x2);
    $('#y2').val(c.y2);
    $('#w').val(c.w);
    $('#h').val(c.h);
};

In addition, it must update the preview of the cropped image. For this we will need the original image size. If you are using the same image format, just use the same values always. In our case, as the image is sent via form, we use the getimagesize function of php to return the width (index 0 of the return array) and the height (index 1). They are necessary to calculate the positioning of Crop. The idea is to create a div with Crop dimensions, masking the original image.

function exibePreview(c)
{
    var rx = 100 / c.w;
    var ry = 100 / c.h;

    // atualiza CSS do preview para refletir o tamanho da imagem enviada 
    // e o posicionamento do crop
    $('#preview').css({
        width: Math.round(rx * <?php echo $imagesize[0]; ?>) + 'px',
        height: Math.round(ry * <?php echo $imagesize[1]; ?>) + 'px',
        marginLeft: '-' + Math.round(rx * c.x) + 'px',
        marginTop: '-' + Math.round(ry * c.y) + 'px'
    });

    // campos hidden que armazenam os valores
    $('#x').val(c.x);
    $('#y').val(c.y);
    $('#x2').val(c.x2);
    $('#y2').val(c.y2);
    $('#w').val(c.w);
    $('#h').val(c.h);
}

With the full Preview function, we can now update our jCrop call:

$('#jcrop').Jcrop({
    onChange: exibePreview,
    onSelect: exibePreview,
    aspectRatio: 1
});

Note the property aspectRatio, used to tie width and height of Crop, maintaining the ratio.

Everything’s OK at the front. Below you check the upload form code and the post-upload image processing script (validation and resizing to avoid giant Crop files).

<form name="frm-jcrop" id="frm-jcrop" method="post" action="index.php" enctype="multipart/form-data">
    <p>
        <label>Envie uma imagem:</label>
        <input type="file" name="imagem" id="imagem" />
        <input type="submit" value="Enviar" />
    </p>
</form>
// processa arquivo
$imagem     = isset( $_FILES['imagem'] ) ? $_FILES['imagem'] : NULL;
$img        = '';
// verifica se arquivo foi enviado para o servidor
if( $imagem['tmp_name'] )
{
    // move arquivo para o servidor
    if( move_uploaded_file( $imagem['tmp_name'], $imagem['name'] ) )
    {
        include( 'm2brimagem.class.php' );
        $oImg = new m2brimagem( $imagem['name'] );
        if( $oImg->valida() == 'OK' )
        {
            // redimensiona imagem para evitar arquivos grandes
            $oImg->redimensiona( '400', '', '' );
            $oImg->grava( $imagem['name'] );
            // retorna dimensões da imagem e configura variáveis para o jCrop
            $imagesize  = getimagesize( $imagem['name'] );
            $img        = '<img src="'.$imagem['name'].'" id="jcrop" '.$imagesize[3].' />';
            $preview    = '<img src="'.$imagem['name'].'" id="preview" '.$imagesize[3].' />';
        }
        else
        {
            // imagem inválida, exclui do servidor
            unlink( $imagem['name'] );
        }
    }
}

It’s almost ready. We have a form to upload the image, and all the javascript that will process Crop and update our preview. Missing the PHP code that will actually crop the sent image. For this we will use the class m2brimagem (read more about it here).

The processing will be done via AJAX/post, just to expedite the return to the user, but nothing prevents you from doing Crop in a resubmission form.

$('#btn-crop').click(function(){
    $.post( 'crop.php', {
        img:img, 
        x: $('#x').val(), 
        y: $('#y').val(), 
        w: $('#w').val(), 
        h: $('#h').val()
    }, function(){
        $('#div-jcrop').html( '<img src="'+img+'?'+Math.random()+'" width ="'+$('#w').val()+'" height ="'+$('#h').val()+'" />' );
    });
    return false;
});

Once processed, our form will display a new screen, with the option to crop and save a piece of the submitted image. In the example you can observe that, in addition to the image and the interface for Crop, we also show two additional windows: the preview, already commented previously; and a small debug, displaying the information and coordinates in real time (all this updated via displayPreview).

When clicking the save button, the user executes, via AJAX, the script below, once again using the m2brimagem class for processing. The script takes as parameter the starting point X and Y of Crop, in addition to its width and height, and creates the cropped version of the original image. After execution, our img element is updated. As in this case the final image has the same name as the original image, we use the "?" with a random number (Math.Random()) to avoid caching (this tip is very nice for image uploading systems).

if( $_SERVER['REQUEST_METHOD'] == 'POST' )
{
    include( 'm2brimagem.class.php' );
    $oImg = new m2brimagem( $_POST['img'] );
    if( $oImg->valida() == 'OK' )
    {
        $oImg->posicaoCrop( $_POST['x'], $_POST['y'] );
        $oImg->redimensiona( $_POST['w'], $_POST['h'], 'crop' );
        $oImg->grava( $_POST['img'] );
    }
}
exit;

Other options Maybe everything seems a little confusing looking at the codes so separately. Download the examples that you will understand better. On the plugin’s website you will find the complete documentation, in English, as well as other examples. One option I use a lot is to specify fixed width and height. When the user uploads an avatar, for example, it is worth limiting the size in jCrop (or else doing something proportional). The minSize and maxSize properties delimit the minimum and maximum Crop area.

$('#jcrop').Jcrop({
    onChange: exibePreview,
    onSelect: exibePreview,
    minSize     : [ 200, 200 ], 
    maxSize     : [ 200, 200 ],
    allowResize : false,
    addClass    : 'custom'
});

In the above example Crop will always have 200 200 pixels in dimension. In addition, we configure the allowResize property with false, to avoid resizing the selection. Another cool property is addClass, to define a custom style in the selection. In the example below the line gets a solid edge instead of the dotted.

.custom .jcrop-vline, .custom .jcrop-hline {
    background: #FF3366;
}

Source of the answer tutorial

Browser other questions tagged

You are not signed in. Login or sign up in order to post.