Autor Tema: Redimensionar imágenes con GD de forma proporcional (gdp v1.5)  (Leído 3440 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado WHK

  • 吴阿卡
  • Administrador
  • Aportador
  • *****
  • Mensajes: 555
  • Karma: +15/-3
  • Coder
    • Yahoo Instant Messenger - yan_uniko_102
    • Ver Perfil
    • WHK
    • Email
Hize una clase que permite el redimensionado de imágenes con opciones para guardar las proporciones del tamaño de la imágen. Soporta todos los formatos que aguanta php y no hace perdida de calidad ni pixelados como imagick.

Código: php [Seleccionar]
<?php
if($_SERVER['SCRIPT_FILENAME'] == __file__) exit; /* Not included */


class gdp{
var $lastError;
var $imageHandle;
var $imageSize;

function getImageHandle($filepath = false){
if($this->lastError)
return false;

if(!$filepath){
$this->lastError = 50; /* Necesita proporcionar mas datos */
return false;
}

/* Verifica si el archivo existe */
if(!file_exists($filepath)){
$this->lastError = 2; /* El archivo no existe */
return false;
}

/* Verifica si el archivo es una imágen o no */
if(!exif_imagetype($filepath)){
$this->lastError = 3; /* EL archivo no es una imágen */
return false;
}

/* Verifica si GD es capaz de cargar la imágen */
if(!$this->imageHandle =  imagecreatefromstring(file_get_contents($filepath))){
$this->lastError = 4; /* La imágen no pudo ser procesada */
return false;
}

/* Verifica si el sistema es capaz de obtener sus dimensiones */
if(!$this->imageSize = getimagesize($filepath)){
$this->lastError = 5; /* Fué imposible obtener sus propiedades */
return false;
}

}

function saveImageHandle($savepath = false, $makePathRecursive = true){
if($this->lastError)
return false;

if(!$savepath){
$this->lastError = 51; /* Necesita proporcionar mas datos */
return false;
}

/* Crea el directorio de forma recursiva si es necesario (php5 solamente) */
if(!is_dir(dirname($savepath))){
if(!mkdir(dirname($savepath), 0775, $makePathRecursive)){
$this->lastError = 6; /* No fué posible crear el directorio para guardar la imágen */
return false;
}
}

if(!imagejpeg($this->imageHandle, $savepath, 100)){
$this->lastError = 7; /* Imposible guardar imágen */
return false;
}

/* Guardado correctamente */
return true;

}

function copyImage($filepath = false, $savepath = false, $makePathRecursive = true){
if($this->lastError)
return false;

if((!$filepath) or (!$savepath)){
$this->lastError = 52; /* Necesita proporcionar mas datos */
return false;
}

$this->getImageHandle($filepath);
$this->saveImageHandle($savepath, $makePathRecursive);

if($this->lastError)
return false;
else
return true;
}

function sizeAspectRatio($w, $h, $maxW, $maxH){
/* Cast */
$w = (int)$w; $h = (int)$h; $maxW = (int)$maxW; $maxH = (int)$maxH;
/* Matris con el nuevo tamaño */
$newSize = array(
'oldW' => (int)$w,
'oldH' => (int)$h,
'w' => (int)$w,
'h' => (int)$h,
'maxW' => (int)$maxW,
'maxH' => (int)$maxH,
'%newW' => (((int)$maxW * 100) / (int)$w),
'%newH' => (((int)$maxH * 100) / (int)$h),
);

/* Calcula el redimensionado principal */

/* El ancho necesita ser redimensionado */
if($w > $maxW){

/* Establece el nuevo valor para el ancho */
$newSize['w'] = $maxW;

/* Establece el nuevo valor para la altura */
$newSize['h'] = (($h * $newSize['%newW']) / 100); // Float
}

/* El alto necesita ser redimensionado */
if($h > $maxH){

/* Establece el nuevo valor para la altura */
$newSize['h'] = $maxH;

/* Establece el nuevo valor para el ancho */
$newSize['w'] = (($w * $newSize['%newH']) / 100); // Float
}

/* Redundancia para evitar una recursividad (disminuye el uso de CPU) */
/* El ancho necesita ser redimensionado */
if(($newSize['w'] > 0) and ($newSize['w'] > $maxW) or (($newSize['w'] == 0) and ($w > $maxW))){ // Calculo de valores flotantes

/* Establece el nuevo valor para el ancho */
$newSize['w'] = $maxW;

/* Establece el nuevo valor para la altura */
$newSize['h'] = (($h * $newSize['%newW']) / 100); // Float
}

/* Recalcula el porcentaje de redimensionado total (no es el aspecto de radio) */
$newSize['%newW'] = (($newSize['w'] * 100) / $w);
$newSize['%newH'] = (($newSize['h'] * 100) / $h);

/* Cast (transforma los valores Flotantes a Integers) */
$newSize = array(
'oldW' => (int)$newSize['oldW'],
'oldH' => (int)$newSize['oldH'],
'w' => (int)$newSize['w'],
'h' => (int)$newSize['h'],
'maxW' => (int)$newSize['maxW'],
'maxH' => (int)$newSize['maxH'],
'%newW' => $newSize['%newW'], // Valor flotante
'%newH' => $newSize['%newH'] // Valor flotante
);
return $newSize;
}

function resize($filepath = false, $savepath = false, $maxW = false, $maxH = false, $makePathRecursive = true){
if($this->lastError)
return false;

if((!$filepath) or (!$savepath) or (!$maxW) or (!$maxH)){
$this->lastError = 53; /* Necesita proporcionar mas datos */
return false;
}

$this->getImageHandle($filepath);
if($this->lastError)
return false;

/* Calcula el redimensionado manteniendo la relación de aspecto */
$newSize = $this->sizeAspectRatio((int)$this->imageSize[0], (int)$this->imageSize[1], (int)$maxW, (int)$maxH);
print_r($newSize); exit;
/* Redimensiona la imágen */
if(((int)$this->imageSize[0] > (int)$maxW) or ((int)$this->imageSize[1] > (int)$maxH)){
$handleOutImg = imagecreatetruecolor((int)$newSize['w'], (int)$newSize['h']);
imagecopyresampled($handleOutImg, $this->imageHandle, 0, 0, 0, 0, (int)$newSize['w'], (int)$newSize['h'], (int)$this->imageSize[0], (int)$this->imageSize[1]);
imagedestroy($this->imageHandle);
$this->imageHandle = $handleOutImg;
}

/* Guarda la imágen */
$this->saveImageHandle($savepath, $makePathRecursive);
if($this->lastError)
return false;

/* Guardado correctamente */
return $newSize;
}
}


Uso:
Código: php [Seleccionar]
<?php
$this->gdp = new gdp();
if(!$this->gdp->resize(
$_POST['files']['photo']['tmp_name'],
'/var/www/uploads/galerias/'.($outpath = md5(microtime()).'.jpg'),
700,
700
) and ($this->gdp->lastError)){

/* Argumentos faltantes? esto no debería pasar jamás, pero de todas formas se controlará */
if(($this->gdp->lastError > 49) and ($this->gdp->lastError < 60))
$lastError = 'Hubo un error al intentar guardar la imágen. Contáctese con su Administrador.';

/*
* El archivo se ha enviado pero el servidor no la ha guardado.
* Generalmente sucede debido al mod security del apache con alguna regla de seguridad que evitó
* el guardado de un archivo potencialmente peligroso.
* También sucede cuando se está utilizando algún antivirus en el servidor y se ha detectado
* algún código malicioso.
* De todas formas no debería causar mayor problema debido a que no se guardará el archivo original
* sino que se procesará su duplicado evitando la subida de códigos o binarios arbitrários.
* En este caso dicha regla o antivirus queda obsoleto para este procesamiento.
**/
elseif($this->gdp->lastError == 2)
$this->lastError = 'El archivo enviado no pudo ser procesado. Contáctese con el Administrador.';

elseif($this->gdp->lastError == 3)
$this->lastError = 'El archivo proporcionado no es una imágen.';

elseif(($this->gdp->lastError == 4) or ($this->gdp->lastError == 5))
$this->lastError = 'La imágen proporcionada está corrupta.';

elseif($this->gdp->lastError == 6)
$this->lastError = 'No fué posible crear el directorio para guardar la fotografía. Contáctese con su Administrador.';

elseif($this->gdp->lastError == 7)
$this->lastError = 'Fué imposible guardar la imágen. Contáctese con su Administrador.';

else
$this->lastError = 'Hubo un error al intentar guardar la imágen. Contáctese con su Administrador.';
}else
echo 'Imágen guardada: '.$outpath;


No te guarda un cuadrado de 700x700 sino que establece el ancho y alto máximo manteniendo las proporciones.
Si el directorio de la fotografía a guardar no existe la creará, si no deseas que la haga entonces ponle false después del valor de la altura máxima así:

Código: php [Seleccionar]
<?php
if(!$this->gdp->resize(
$_POST['files']['photo']['tmp_name'],
'/var/www/uploads/galerias/'.($outpath = md5(microtime()).'.jpg'),
700,
700,
false
) and ($this->gdp->lastError)){
...


Además está asegurado para que nadie pueda subirte una shell o algún archivo malicioso, en otras palabras es seguro.

Yo en lo personal prefiero redimensionar con GD en ves de Imagick porque la calidad de redimensionado con imágenes HD queda mejor y para el trabajo que estoy haciendo es indispensable.

Saludos  :xb:
« Última Modificación: marzo 23, 2012, 04:47:35 pm por WHK »
Mi WEB - The Hacktivism is not a crime - Si no lo hago yo, que lo hagan otros -
Si has encontrado útil este articulo recuerda que puedes ayudarnos con tu donación voluntaria la cual ayudará al staff y a la mantención del foro.

Desconectado raul338

  • Recién llegado
  • *
  • Mensajes: 3
  • Karma: +0/-0
  • :D
    • Ver Perfil
Re:Redimensionar imágenes con GD de forma proporcional
« Respuesta #1 : marzo 17, 2012, 11:34:16 am »
Me parece perfecto! :D No lo probe todavia, pero no entiendo esta linea...

$newSize['w'] = (int)$this->galleryMaxWidth;

De donde sale galleryMaxWidth? Y porque no es la misma forma en la que comprobas el ancho que con la altura? :P

Desconectado WHK

  • 吴阿卡
  • Administrador
  • Aportador
  • *****
  • Mensajes: 555
  • Karma: +15/-3
  • Coder
    • Yahoo Instant Messenger - yan_uniko_102
    • Ver Perfil
    • WHK
    • Email
Re:Redimensionar imágenes con GD de forma proporcional
« Respuesta #2 : marzo 19, 2012, 09:33:43 am »
Tienes toda la razón, esque solo publiqué una función y no la clase completa, de todas formas el viernes pasado la actualizé bastante, asi que ahi la publiqué completa y está muy comodo y fácil de usar.
De hecho esta clase es parte del framework FDC que estoy actualizando :p
Mi WEB - The Hacktivism is not a crime - Si no lo hago yo, que lo hagan otros -

Desconectado WHK

  • 吴阿卡
  • Administrador
  • Aportador
  • *****
  • Mensajes: 555
  • Karma: +15/-3
  • Coder
    • Yahoo Instant Messenger - yan_uniko_102
    • Ver Perfil
    • WHK
    • Email
Re:Redimensionar imágenes con GD de forma proporcional (gdp v1.4)
« Respuesta #3 : marzo 21, 2012, 12:38:03 pm »
Acabo de actualizar la clase, reparé un error en una variable ausente y aprobeché de separar la función que realiza el cálculo de relación de aspecto al momento de redimensionar la imágen, de esta forma podemos realizar cálculos sin la necesidad de cargar nada:

Código: php [Seleccionar]
<?php
$gdp = new gdp();
print_r($gdp->sizeAspectRatio(500, 1000, 100, 100));
/*
Array (
   [w]   =>  50,
   [h]   => 100
)
*/


Le das el ancho, alto original de la imágen y cuando debería ser el ancho y alto máximo que debería tener. Te debuelve el ancho y alto de la nueva imágen manteniendo las proporciones de ancho y alto, o sea que no va a estirar la imágen resultante.

Saludos.
Mi WEB - The Hacktivism is not a crime - Si no lo hago yo, que lo hagan otros -


. . . . . . . .