Reducir una imagen con PHP y GD
Este simple script permite procesar una imagen, pudiendo ser usado tanto al subir la imagen para guardar una versión reducida de esta, o para emitir una versión ajustada a la medida solicitada leyendo desde una imagen mas grande.
Se requiere que la instalación de PHP tenga incorporada la librería GD.
Efecto Imagen Zoom: Una variante de este código podría usarse para hacer "Zoom" en una imagen muy alta resolución, programando adecuadamente el vector de desplazamiento sobre la imagen original y trayendo solo un área específica, esta técnica combinada con Ajax realiza el efecto de Zoom
Ejemplo de uso:
// IMAGEN ORIGINAL..EN ALTA RESOLUCION.
$fullName = '/anypath/image.jpg';
// OBTENER INFORMACION DE LA IMAGEN ORIGINAL.
list($ow, $oh, $xmime) = getimagesize($fullName);
$imageSize = filesize($fullName);
$mime = '';
if($xmime == 2) $mime = 'image/jpg';
if($xmime == 3) $mime = 'image/png';
// LEER LA IMAGEN ORIGINAL
$f = fopen($fullName,"r");
$imageData = fread($f, $imageSize);
fclose($f);
// HACER EL RESIZE A 160 x 120 px, con 70% de compresion JPEG
$r = new ImageResizer();
$newImage = $r->resize($imageData, 160, 120, 70, 'jpg', $ow, $oh);
// EMITIR LA IMAGEN
header('Content-type: '.$mime);
echo $newImage;
Si el ejemplo anterior estuviese alojado en una pagina PHP llamada:
http://miservidor/imagen.php
podríamos visualizar la imagen en una pagina HTML asi:
<html>
<img src='http://miservidor/imagen.php'>
</html>
Está demás decir que se pudiera programar el script para recibir argumentos y asi emitir la imagen en un formato especifico:
<html>
<img src='http://miservidor/imagen.php?w=320&h=200&c=50'>
</html>
El script podria recibir los argumentos pasados aqui y asi emitir la imagen en esa dimensión solicitada.
Por qué "a veces" es incorrecto hacer: "<img src='...' width=160 height=120 >" ?
Respuesta: Porque "a veces" la imagen original pesa 4 megas y no vas a querer tener en un website una imagen de 160x120 pixels que pese 4 megas, debido a que aunque estes solicitando esas medidas en tiempo de browsing (es decir al momento de presentarla) esa imagen pesara 4 megas, tardara en bajar al browser para finalmente ser presentada en una medida muy pequeña, aparte de quedar horrible por la fragmentación del pixelado, va a pesar mucho.
Código fuente:
- <?php
- /**
- * ImageResizer
- * a helper class to handle image resize.
- *
- * example usage:
- *
- * $fullName = '/anypath/image.jpg';
- * list($ow, $oh, $xmime) = getimagesize($fullName);
- * $imageSize = filesize($fullName);
- * $mime = '';
- * if($xmime == 2) $mime = 'image/jpg';
- * if($xmime == 3) $mime = 'image/png';
- *
- * $f = fopen($fullName,"r");
- * $imageData = fread($f, $imageSize);
- * fclose($f);
- *
- * $r = new ImageResizer();
- * $newImage = $r->resize($imageData, 160, 120, 70, 'jpg', $ow, $oh);
- * header('Content-type: '.$mime);
- * echo $newImage;
- *
- *
- * @author Christian Salazar <christiansalazarh@gmail.com>
- * @license NEW BSD.
- */
- class ImageResizer {
- /**
- * resize
- * resizes an image making it to fit into a rectangle
- *
- * @param mixed $image Binary raw image data.
- * @param mixed $dw destination viewport width
- * @param mixed $dh destination viewport height
- * @param mixed $q quality for jpg or png: 1 to 100.
- * @param mixed $imgtype desired output image type 'jpg' or 'png'
- * @param mixed $ow original image width
- * @param mixed $oh original image height
- * @return new image. you can echo it or use GD functions to handle it.
- */
- public function resize($image, $dw, $dh, $q, $imgtype, $ow, $oh){
- $im = imagecreatetruecolor($dw, $dh);
- $im_src = imagecreatefromstring($image);
- $_w = 0;
- $_h = 0;
- $this->_scaleVector($dw, $dh, 0.95, $ow, $oh, $_w, $_h);
- // displacement vector, this vector center the image.
- $dx = ($dw - $_w)/2;
- $dy = ($dh - $_h)/2;
- $fillcolor = imagecolorallocate($im,255,255,255);
- //$xcolor = imagecolorallocate($im, 200,200,200);
- imagefilledrectangle($im, 0,0,$dw, $dh, $fillcolor);
- //imagefilledrectangle($im, $dx,$dy, $dx + $_w, $dy + $_h, $xcolor);
- imagecopyresampled(
- $im, $im_src,
- $dx, $dy, 0, 0,
- $_w, $_h,
- $ow, $oh
- );
- if($imgtype == 'png')
- return imagepng($im, null, $q);
- return imagejpeg($im, null, $q);
- }
- /**
- * _scaleVector
- *
- *
- * @param mixed $dw | destination viewport:
- * @param mixed $dh | d = {w, h}
- * @param mixed $delta | delta: is a fixture measurement. max 1.
- * @param mixed $ow | original viewport to be scaled into "d":
- * @param mixed $oh | o = {w, h}
- * @param mixed $out_w
- * @param mixed $out_h
- * @access private
- * @author Christian Salazar H. <christiansalazarh@gmail.com>
- * @return void
- */
- private function _scaleVector($dw, $dh, $delta, $ow, $oh, &$out_w, &$out_h){
- $dR = $dw / $dh;
- if($dR >= 1){
- $out_w = $delta * $dw;
- $out_h = ($out_w * $oh) / $ow;
- }else{
- $out_h = $delta * $dh;
- $out_w = ($out_h * $ow) / $oh;
- }
- }
- }