SUBIR, VALIDAR, RECORTAR... IMÁGENES
Subir imagen:

  • comentario 1: prestar atencion en que para mandar el contenido de FILE en AJAX debemos declarar objeto formdata y cargar el elemento [0] del array.
  • comentario 2: si la devolución del AJAX es Éxito....
  • comentario 3: agregamos el tiempo para que no lo tome del cache.
  • Comentario 4: colocamos la reticula (no olvidar de la div reticula justo antes de cerrar body) en el centro de la imagen y la hacemos arrastrable (debe incluirse jquery-ui.min.js o si no falla draggable. Para que recortar funcione, la clase IMAGICK debe estar registrada en PHP. Para esto, abrir el cPanel, ir a Seleccionar versión de PHP y tildar la casilla de Imagick. Ser cuidadso con cambiar el nombre del script PHP de AJAX y del directorio donde se guardan las imagenes subidas y el blanco.gif asimismo con las dimensiones de la imagenfinal que deben asignarse en lugar de los 155x155 del test (incluida la div reticulo y los tamaños en procesar).
Redimensionar imagen

comentario 5: enviamos por AJAX las coordenadas que nos da reticulo en stop de draggable (que se usan para crop) y despues escondemos la reticula y los controles de recorte
En este ejemplo el archivo img-upload/temporario.jpg contiene primero a nivel del upload y luego se sobreescribe con el crop, pero al subir otro se lo sobreescribe.
Para guardarlo con otro nombre es necesario agregar (con otro botón) con la función copy( "img-upload/temporario.jpg" , "img-upload/nuevo.jpg"); o en lugar de img-upload el directorio correspondiente
						
1) Scripts Javascript

<script type="text/javascript" src="../scripts/jquery-3.6.4.min.js"></script>
<script type="text/javascript" src="../scripts/jquery-ui.min.js"></script>
<script>
	$(document).ready(function(){
		$("#recortar").css("display", "none");		// paso 2 no accesible.....
		$("#terminar").css("display", "none");		// paso 3 no accesible.....
		//subir foto por ajax
		 $("input[name='archivo']").on("change", function(){    //es la forma de indicar el FILE
		    $("#recortar").css("display", "none");		// paso 2 no accesible..... se repite aca si hay opcion a recargar otra foto
		    $("#terminar").css("display", "none");		// paso 3 no accesible.....
			
			var formData = new FormData($("#formulario")[0]);	 //carga todos los datos del form en array
            var ruta = "tec-php-manejar-imagenes-procesar.php?accion=SF";        //ruta del script uploader
			$("#esperando").css("visibility", "visible");		 // esperando.....
			$.ajax({
                url: ruta,
                type: "POST",
                data: formData,        //datos del form declarado
                contentType: false,
                processData: false,
                success: function(datos){
					if(datos.indexOf('Exito') == 0){
						$("#test").attr('src', 'img-upload/temporario.jpg?' + new Date().getTime());  // para que el server lo tome como <> y no lo tome de cache
						$("#msg").html(' ');                       //borra los mensajes anteriores
						$("#esperando").css("visibility", "hidden");   //desaparece esperando....
						$("#reticula").css("top", Math.max(0, ( $('#test').position().top)) + "px");
						$("#reticula").css("left", Math.max(0, ( $('#test').position().left)) + "px");
						$("#reticula").draggable();
						$("#reticula").css("display","block");
						$("#x").val(Math.max(0, ( $('#reticula').position().left- $('#test').position().left)));
						$("#y").val(Math.max(0, ( $('#reticula').position().top - $('#test').position().top)));
						$("#recortar").css("display", "block");		// paso 2  accesible.....
					}else{
						$("#esperando").css("visibility", "hidden");
						$("#msg").html(datos);
					}
                } //fin datos
            }); // fin ajax
        });  // fin on change 
		
		$('#reticula').draggable({
    		stop: function(event, ui){
				$("#x").val(Math.max(0, ( $('#reticula').position().left- $('#test').position().left)));
				$("#y").val(Math.max(0, ( $('#reticula').position().top - $('#test').position().top)));
			}
		}); //fin draggable
		$("#recortarok").click(function(evento){
			x = $("#x").val();
			y = $("#y").val();
            var ruta = "tec-php-manejar-imagenes-procesar.php?accion=CI";
			$("#esperando").css("visibility", "visible");
			$.ajax({
                url: ruta,
                type: "POST",
                data: 'x=' + escape(x) + '&y=' + escape(y),    //mando las coordenadas del inicio del crop
                success: function(datos){
					if(datos.indexOf('Exito') == 0){
						$("#test").attr('src', 'img-upload/temporario.jpg?' + new Date().getTime());  // para que el server lo tome como <> y no lo tome de cache
						$("#msg").html(' ');
						$("#esperando").css("visibility", "hidden");
						$("#reticula").css("display","none");				// borra control crop
						$("#recortar").css("display","none");				// paso 2 no accesible.....
						$("#terminar").css("display","block");				// paso 3  accesible.....
					}else{
						$("#esperando").css("visibility", "hidden");
						$("#msg").html(datos);
					}
                } //fin datos
            }); // fin ajax
		}); //fin recortar
		$("#asociarimagen").click(function(evento){
			//cid = $("#colorN").val();
            var ruta = "tec-php-manejar-imagenes-procesar.php?accion=AS";
			$("#esperando").css("visibility", "visible");
			$.ajax({
                url: ruta,
                type: "POST",
                data: 'cid=definitiva',
                success: function(datos){
					if(datos.indexOf('Exito') == 0){
						$("#msg").html(' ');
						$("#esperando").css("visibility", "hidden");
						$("#test").attr('src', 'img-upload/blanco.gif');  // vuelvo a blanco
						$("#msg").html("Se ha asociado la imagen");
					}else{
						$("#esperando").css("visibility", "hidden");
					}
                } //fin datos
            }); // fin ajax
		}); //fin asociar

	});				   			
	</script>

2) HTML necesario

	<style>
		.textonormal{
			width:460px; 
			height:450px; 
			display:block; 
			z-index:100; 
			background-color:#ffffff; 
			opacity: 1; 
			padding:10px; 
			border:#666 solid 1px; 
			overflow:auto; 
			box-shadow: 8px 8px 10px grey; 
			text-align:center;
		}
		.dato{
			border:#ccc solid 1px; 
			float:left; 
			margin-left:30px; 
			padding:10px; 
			height:350px; 
			width:370px;
		}
		.divtest{
			width:370px; 
			height:200px; 
			text-align: center; 
			border:#ccc 1px solid; 
			overflow:scroll;
		}
		.segundo{
			padding-top:15px; 
			float:left;
		}
		.equis{
			padding-top:10px; 
			float:left; 
			margin-right:10px; 
			width:50px;
		}
		.reticula{
			width:155px; 
			height:155px; 
			border:#000000 dotted 2px; 
			position:absolute; 
			display:none; 
			z-index:101; 
			cursor: move;  
		}

	</style>
<div id="caja" class="textonormal" >
	<div id="datos" class="dato"> 
		<form method="post" id="formulario" enctype="multipart/form-data"> 
			<div style="margin-bottom:10px; ">
				Subir una imagen (tamaño máximo:500K SOLO jpg ) 
			</div>
			<div> 
				1°    
				<input name="archivo" type="file"  accept=".jpg,.gif" style="height:24px; ">
				<span id="esperando" style="visibility: hidden; ">
				<img src="esperando.gif" width="16" height="16" />
				</span>
			</div>
			<div style="margin-bottom:10px; margin-top:20px; text-align:center;" id="msg">
				 
			</div>
			</form>
			<div id="divtest" class="divtest">
				<img src="img-upload/blanco.gif" id="test" />
			</div>
			<div id="recortar">
				<div class="segundo">
					2° Seleccionar area          X = 
				</div>
				<div  class="equis">
					<input name="x" type="text" id="x" style="border:none; width:50px; " />
				</div>
				<div class="segundo">
					Y = 
				</div>
				<div class="segundo">
					<input name="y" type="text" id="y" style="border:none; width:50px; " />
				</div>
				<div class="segundo" style="margin-left:10px;" >
					<input name="Recortar" type="button" value="Recortar"  id="recortarok" />
				</div>
			</div><!-- Fin recortar datos-->
			<div style="clear:both"></div>  
			<div id="terminar">
				<div style=" float:left; margin-left:10px;"> 
					<input name="Asociar" type="button" value="Guardar"  id="asociarimagen"/>
				</div>
				<div style="float:left; margin-left:10px; width:200px; border:#ccc solid 1px; margin-top:3px; ">
					<a href="img-upload/definitiva.jpg" target="_blank">Ver imagen recortada y guardada</a>
				</div>
			</div>
	</div>   <!-- Fin datos-->
</div>	<!-- Fin caja-->

<div id="reticula" class="reticula"> </div>

3) Script PHP llamado por AJAX

<?
$accion= $_GET["accion"];
switch ($accion) {
	case"SF":					// subir foto
		$maxbytes=800000;		//tamaño máximo validado que se deja subir
		$maxancho=1000;			//max ancho que valido para la original
		$maxalto=800;			//max alto que valido para la original
		$minancho=155;			// tamaño de la imagen final
		$minalto=155;			// tamaño de la imagen final
		$carpeta = "img-upload/";
		if (isset($_FILES["archivo"])){				// si viene algo del form
			$file = $_FILES["archivo"];				//cargo en $file la info
			$nombre = $file["name"];				// nombre
			$tipo = $file["type"];					//tipo
			$ruta_provisional = $file["tmp_name"];	//ruta temporaria
 			$size = $file["size"];					//tamaño					
			if (strlen($nombre)<>0 || strlen($ruta_provisional)<>0){
				$dimensiones = getimagesize($ruta_provisional);
			   	$width = $dimensiones[0];			//ancho en elemento 0 del vector 
 			    $height = $dimensiones[1];			//alto en elemento 1 del vector
				//***************comienzo validación********************************
			    if ($tipo != 'image/jpg' && $tipo != 'image/jpeg'){
     				 echo "Error, el archivo no es reconocido como una imagen jpg"; 
    			}else if ($size > $maxbytes){
    				echo "Error, el tamaño máximo permitido es de: " . $maxbytes/1024 . " Kb";
   				}else if ($width > $maxancho || $height > $maxalto){
     				echo "Error, la anchura y la altura maxima permitida es " . $maxancho ." X " . $maxalto . " px";
   				}else if($width < $minancho || $height < $minalto){
   					 echo "Error, la anchura y la altura mínima permitida es " . $minancho ." X " . $minalto . " px";
    			//***************FIN validación**************************************
				}else{
				  	$img_original = imagecreatefromjpeg($ruta_provisional);	//creo la imagen desde el temporal subido
					$x_prop = $minancho / $width;				//proporción de reduccion ancho
					$y_prop = $minalto / $height;				//proporción de reduccion alto
					if (($x_prop * $height) < $minalto){			// si reduzco altura y quedo chico
						$ancho_final = ceil($y_prop * $width);
						$alto_final = $minalto;
					}else{
						$alto_final = ceil($x_prop * $height);
						$ancho_final = $minancho;
					}
					$src = "img-upload/temporario.jpg";			//ruta donde grabo la imagen redimensionada
					$tmp=imagecreatetruecolor($ancho_final,$alto_final);	// imagen en blanco del nuevo tamaño
					imagecopyresampled($tmp,$img_original,0,0,0,0,$ancho_final, $alto_final,$width,$height);  
												// copiamos la nueva imagen
					imagedestroy($img_original);				//libero memoria
					$calidad=95;
					imagejpeg($tmp,$src,$calidad);				//Se graba la imagen final 
					unlink($ruta_provisional);				// borro la imagen anterior
    				echo "Exito";					
   					}
			}else{
				echo "No se eligió imagen";
			}
   		} 
		break;
		case"CI":  // crop image
			$minancho=155;			// tamaño de la imagen final
			$minalto=155;			// tamaño de la imagen final
			$x = $_POST["x"];
			$y = $_POST["y"];
			$src = "img-upload/temporario.jpg";
			$corte = new Imagick($src);
			$corte->cropImage($minancho,$minalto,$x,$y);
			$corte->writeImage($src);	// sobreescribimos el temporario
			echo "Exito";
   			break;
		case"AS":  // guardo imagen 
			$cid = $_POST["cid"];    // mandamos siempre en test definitiva.jpg en produccion $cid lleva el nombre
			$nuevaimagen= $cid . ".jpg";
			$src = "img-upload/temporario.jpg";
			copy ( $src , "img-upload/" . $nuevaimagen );
			echo "Exito";
   			break;
}
?>


						
					
© IQSystems 2023