Cortar y redimensionar imágenes utilizando PHP, jQuery y AJAX

En este artículo veremos cómo subir imágenes al servidor, cortarlas y redimensionarlas utilizando PHP y AJAX. En un artículo anterior ya vimos cómo subir imágenes y recortarlas utilizando un popup box. Obtuve una gran respuesta por vuestra parte, pero muchos me solicitásteis el volver a publicar el artículo sobre el recorte de imágenes y redimensionamiento sin el popup box ni ventanas modales, para que se puede reproducir fielmente en tabletas y dispositivos móviles.

En este artículo veremos cómo subir imágenes y recortarlas en la misma página sin tener que utilizar una ventana modal. Utilizaremos la librería GD de PHP para redimensionar las imágenes, y el plugin de jQuery, AJAX Form, para subir las imágenes. También le daremos uso al plugin Imgareaselect para cortar la imagen y a PHP para guardar la imagen una vez esté redimensionada y cortada.

Resumiendo, esto será lo que utilicemos:

  • Librería jQuery: Librería base para soportar otros plugins de jQuery
  • Boostrap: La utilizaremos para crear diseños alucinantes y responsives
  • imgareaselect: La utilizaremos para cortar imágenes. Puedes descargarla desde aquí
  • Ajax Form: La utilizaremos para subir las imágenes del usuario al servidor. Puedes descargarla desde aquí.

Estos son los archivos que participarán en el tutorial de cortado de imágenes

  • index.php: Este fichero es el responsable de crear todo el diseño HTML y mostrar la imagen recortada
  • profile.php: Este fichero es el responsable de toda la funcionalidad del lado del servidor, como recortar la imagen y guardarla.
  • dist: Es una carpeta. La utilizaremos para albergar todas las librerías.

Subida, cortado y redimensionamiento de imágenes con PHP y AJAX

Paso 1: Antes que nada tenemos que incluir todas las librerías necesarias para que esto funcione, como son las de jQuery y Bootstrap. Introduce el siguiente código dentro de la sección head de tu archivo index.php.

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="dist/jquery.imgareaselect.js" type="text/javascript"></script>
<script src="dist/jquery.form.js"></script>
<link rel="stylesheet" href="dist/imgareaselect.css">

Paso 2: Crearemos un div para mostrar la imagen y una opción para modificarla.

<div class="col-sm-2"><img class="img-circle" id="avatar-edit-img" height="128" data-src="default.jpg"  data-holder-rendered="true" style="width: 140px; height: 140px;" src="default.jpg"/></div>
        <div class="col-sm-10"><a type="button" class="btn btn-primary" id="change-pic">Change Image</a>
</div>

Aquí mostraremos la imagen default.jpg cuando no haya nada como imagen por defecto.

Paso 3: Ahora crearemos el div para subir y recortar la imagen.

<div id="changePic" class="" style="display:none">
                  <form id="cropimage" method="post" enctype="multipart/form-data" action="profile.php">
            <label>Upload your image</label><input type="file" name="photoimg" id="photoimg" />
            <input type="hidden" name="hdn-profile-id" id="hdn-profile-id" value="1" />
            <input type="hidden" name="hdn-x1-axis" id="hdn-x1-axis" value="" />
            <input type="hidden" name="hdn-y1-axis" id="hdn-y1-axis" value="" />
            <input type="hidden" name="hdn-x2-axis" value="" id="hdn-x2-axis" />
            <input type="hidden" name="hdn-y2-axis" value="" id="hdn-y2-axis" />
            <input type="hidden" name="hdn-thumb-width" id="hdn-thumb-width" value="" />
            <input type="hidden" name="hdn-thumb-height" id="hdn-thumb-height" value="" />
            <input type="hidden" name="action" value="" id="action" />
            <input type="hidden" name="image_name" value="" id="image_name" />
            
            <div id='preview-avatar-profile'>
          </div>
          <div id="thumbs" style="padding:5px; width:600"></div>
          </form>
              <div class="modal-footer">
                  <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                  <button type="button" id="btn-crop" class="btn btn-primary">Crop & Save</button>
              </div>
      </div>

Paso 4: Necesitamos implementar algo de jQuery para mostrar el div del recorte de la imagen cuando se haga clic en el botón change pic

jQuery('#change-pic').live('click', function(e){
    e.preventDefault();
    
     jQuery('#changePic').show();
     jQuery('#change-pic').hide();
    
  });

Paso 5: Ahora utilizaremos el plugin de jQuery, AJAX Form para hacer submit del formulario y mostrar la imagen para el proceso de recorte en una ventana modal de bootstrap.

jQuery('#photoimg').live('change', function() 
{ 
jQuery("#preview-avatar-profile").html('');
jQuery("#preview-avatar-profile").html('Uploading....');
jQuery("#cropimage").ajaxForm(
{
target: '#preview-avatar-profile',
success:    function() { 
        jQuery('img#photo').imgAreaSelect({
        aspectRatio: '1:1',
        onSelectEnd: getSizes,
    });
    }
}).submit();
});

Puedes definir los parámetros de la imagen dentro de la función callback que está en success.

Paso 6: Ahora cortamos la imagen y llamamos al método save de AJAX para guardar la imagen en el disco duro del usuario.

//call on crop iamge button
jQuery('#btn-crop').live('click', function(e){
  e.preventDefault();
  params = {
            targetUrl: 'profiles/saveAvatarTmp/',
            action: 'profiles_controller_saveAvatarTmp',
      x_axis: jQuery('#hdn-x1-axis').val(),
      y_axis : jQuery('#hdn-y1-axis').val(),
      x2_axis: jQuery('#hdn-x2-axis').val(),
      y2_axis : jQuery('#hdn-y2-axis').val(),
      thumb_width : jQuery('#hdn-thumb-width').val(),
      thumb_height:jQuery('#hdn-thumb-height').val()
        };
    saveCropImage(params);
  });
  //make ajax request to PHP for save image
function saveCropImage(params) {
    jQuery.ajax({
        url: siteurl + params['targetUrl'],
        cache: false,
        dataType: "html",
        data: {
            action: params['action'],
            id: jQuery('#hdn-profile-id').val(),
       t: 'ajax',
                w1:params['thumb_width'],
                x1:params['x_axis'],
                h1:params['thumb_height'],
                y1:params['y_axis'],
                x2:params['x2_axis'],
                y2:params['y2_axis']
        },
        type: 'Post',
       // async:false,
        success: function (response) {
        jQuery('#changePic').hide();
          jQuery('#change-pic').show();
        jQuery(".imgareaselect-border1,.imgareaselect-border2,.imgareaselect-border3,.imgareaselect-border4,.imgareaselect-border2,.imgareaselect-outer").css('display', 'none');
        
        jQuery("#avatar-edit-img").attr('src', response);
        jQuery("#preview-avatar-profile").html('');
        jQuery("#photoimg").val('');
        AlertManager.showNotification('Image cropped!', 'Click Save Profile button to save image.', 'success');
        
        
        },
        error: function (xhr, ajaxOptions, thrownError) {
            alert('status Code:' + xhr.status + 'Error Message :' + thrownError);
        }
    });
  }

Paso 7: Definimos el método controlador/acción en profile.php

/*********************************************************************
   Purpose      : update image.
   Parameters       : null
   Returns      : integer
   ***********************************************************************/
  public function changeAvatar() {
    global $current_user;
    $loggedInId = $current_user->ID;
    $post = isset($_POST) ? $_POST: array();
    $max_width = "500"; 
    $userId = isset($post['hdn-profile-id']) ? intval($post['hdn-profile-id']) : 0;
    $path = get_theme_root(). 'imagesuploadstmp';

    $valid_formats = array("jpg", "png", "gif", "bmp","jpeg");
    $name = $_FILES['photoimg']['name'];
    $size = $_FILES['photoimg']['size'];
    if(strlen($name))
    {
    list($txt, $ext) = explode(".", $name);
    if(in_array($ext,$valid_formats))
    {
    if($size<(1024*1024)) // Image size max 1 MB
    {
    $actual_image_name = 'avatar' .'_'.$userId .'.'.$ext;
    $filePath = $path .'/'.$actual_image_name;
    $tmp = $_FILES['photoimg']['tmp_name'];
    
    if(move_uploaded_file($tmp, $filePath))
    {
    $width = $this->getWidth($filePath);
      $height = $this->getHeight($filePath);
      //Scale the image if it is greater than the width set above
      if ($width > $max_width){
        $scale = $max_width/$width;
        $uploaded = $this->resizeImage($filePath,$width,$height,$scale);
      }else{
        $scale = 1;
        $uploaded = $this->resizeImage($filePath,$width,$height,$scale);
      }
    $res = $this->Profile->saveAvatar(array(
            'userId' => isset($userId) ? intval($userId) : 0,
                        'avatar' => isset($actual_image_name) ? $actual_image_name : '',
            ));
            
    //mysql_query("UPDATE users SET profile_image='$actual_image_name' WHERE uid='$session_id'");
    echo "<img id='photo' class='' src='".getCustomAvatar($userId, true).'?'.time()."' class='preview'/>";
    }
    else
    echo "failed";
    }
    else
    echo "Image file size max 1 MB"; 
    }
    else
    echo "Invalid file format.."; 
    }
    else
    echo "Please select image..!";
    exit;
    
    
  }

Paso 8: Guardamos la ruta de la imagen dentro de la base de datos

/*********************************************************************
   Purpose      : save avatar.
   Parameters       : $options 
   Returns      : true/false
   ***********************************************************************/
  function saveAvatar($options){
      //update sql

    }

Fuente: phpflow.com

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP