2009-04-14 22 views
8

Necesito cambiar el tamaño de una imagen a un tamaño fijo. Pero tiene que mantener los factores entre el ancho y la altura.Redimensionar/recortar/rellenar una imagen en un tamaño fijo

decir que quiero cambiar el tamaño de una imagen de 238 (w) X 182 (h) a 210/150

Lo que hago ahora es:

Original width/target width = 1.333333 
Original Height/target Height = 1.213333 

Ahora tomo el factor más pequeño.

Ahora siempre tengo el ancho correcto desde 238/1.333333 = 210. Pero la altura sigue siendo 160.

¿Cómo puedo obtener la altura hasta 160 sin arruinar la imagen?

¿Necesito recortar? ¿Si es así, cómo?

Respuesta

22

Esta solución es básicamente la misma que la de Can Berk Güder, pero después de haber dedicado un tiempo a escribir y comentar, me apetecía publicar.

Esta función crea una miniatura que es exactamente tan grande como el tamaño que le da. La imagen se redimensiona para adaptarse mejor al tamaño de la miniatura. Si no se ajusta exactamente en ambas direcciones, se centra en el thumnail. Los extensos comentarios explican lo que sucede. el uso

function thumbnail_box($img, $box_w, $box_h) { 
    //create the image, of the required size 
    $new = imagecreatetruecolor($box_w, $box_h); 
    if($new === false) { 
     //creation failed -- probably not enough memory 
     return null; 
    } 


    //Fill the image with a light grey color 
    //(this will be visible in the padding around the image, 
    //if the aspect ratios of the image and the thumbnail do not match) 
    //Replace this with any color you want, or comment it out for black. 
    //I used grey for testing =) 
    $fill = imagecolorallocate($new, 200, 200, 205); 
    imagefill($new, 0, 0, $fill); 

    //compute resize ratio 
    $hratio = $box_h/imagesy($img); 
    $wratio = $box_w/imagesx($img); 
    $ratio = min($hratio, $wratio); 

    //if the source is smaller than the thumbnail size, 
    //don't resize -- add a margin instead 
    //(that is, dont magnify images) 
    if($ratio > 1.0) 
     $ratio = 1.0; 

    //compute sizes 
    $sy = floor(imagesy($img) * $ratio); 
    $sx = floor(imagesx($img) * $ratio); 

    //compute margins 
    //Using these margins centers the image in the thumbnail. 
    //If you always want the image to the top left, 
    //set both of these to 0 
    $m_y = floor(($box_h - $sy)/2); 
    $m_x = floor(($box_w - $sx)/2); 

    //Copy the image data, and resample 
    // 
    //If you want a fast and ugly thumbnail, 
    //replace imagecopyresampled with imagecopyresized 
    if(!imagecopyresampled($new, $img, 
     $m_x, $m_y, //dest x, y (margins) 
     0, 0, //src x, y (0,0 means top left) 
     $sx, $sy,//dest w, h (resample to this size (computed above) 
     imagesx($img), imagesy($img)) //src w, h (the full size of the original) 
    ) { 
     //copy failed 
     imagedestroy($new); 
     return null; 
    } 
    //copy successful 
    return $new; 
} 

Ejemplo:

$i = imagecreatefromjpeg("img.jpg"); 
$thumb = thumbnail_box($i, 210, 150); 
imagedestroy($i); 

if(is_null($thumb)) { 
    /* image creation or copying failed */ 
    header('HTTP/1.1 500 Internal Server Error'); 
    exit(); 
} 
header('Content-Type: image/jpeg'); 
imagejpeg($thumb); 
+0

en realidad esta secuencia de comandos no cambia el tamaño de la imagen original. ¿Eso también es posible? – sanders

+1

Este script hace una copia de la imagen original. Cuando remuestree una imagen, tendrá que hacer una copia. Mi uso de ejemplo destruye la imagen original (imagedestroy ($ i)). Si desea sobrescribir el archivo de imagen, simplemente escriba $ pulgar en el archivo "img.jpg" en el ejemplo. – gnud

+0

Ok gracias. ¿Qué pasa si quiero cambiar el tamaño de la imagen completa y no hacer solo una cosecha? – sanders

2

¿Tiene Imagick? Si es así se puede cargar la imagen con él y hacer algo como thumbnailimage()

No puede omitir cualquiera de los parámetros (altura o anchura) y va a cambiar el tamaño correctamente.

+0

así yo prefiero usar gd ya que eso es lo que estoy utilizando para todo. No sé si tengo imagemagick – sanders

+0

Aquí hay un ejemplo en imagick php: http: // arturito.net/2011/01/08/imagemagick-php-image-resizing-imagick-with-canvas/ –

0

Vas a tener que recortar 5 píxeles de la parte superior e inferior para llegar a su tamaño final, sin embargo, esto podría arruinar la imagen.

Realmente debe tener un objetivo de ancho o alto, luego ajuste la otra dimensión en la misma proporción.

+0

sí, pero la altura o el ancho pueden no coincidir con el valor requerido – sanders

+0

Tener tamaños de imagen específicos no es una buena idea cuando no tienen control completo sobre la fuente de las imágenes. Solo puedes escalarlos para que quepan. – cjk

10

Esto no recorta la imagen, pero deja espacio alrededor de la nueva imagen si es necesario, que creo que es un mejor enfoque (que recorte) al crear miniaturas.

$w = 210; 
$h = 150; 

$orig_w = imagesx($original); 
$orig_h = imagesy($original); 

$w_ratio = $orig_w/$w; 
$h_ratio = $orig_h/$h; 

$ratio = $w_ratio > $h_ratio ? $w_ratio : $h_ratio; 

$dst_w = $orig_w/$ratio; 
$dst_h = $orig_h/$ratio; 
$dst_x = ($w - $dst_w)/2; 
$dst_y = ($h - $dst_h)/2; 

$thumbnail = imagecreatetruecolor($w, $h); 

imagecopyresampled($thumbnail, $original, $dst_x, $dst_y, 
        0, 0, $dst_w, $dst_h, $orig_w, $orig_h); 
+0

Has probado esto ya que en mi ejemplo la altura sigue siendo de 160 px y no de 150, ya que debería ser – sanders

+0

sí, me funciona. –

+0

altura es 150 y el ancho es 196. por lo que hay un margen de 7px a la izquierda y derecha. –

1

Prefiero cambiar el tamaño de modo que la imagen esté dentro de su límite y luego complete las partes en blanco. Entonces, en el ejemplo anterior, cambiarías el tamaño para que la altura sea correcta y luego se llenaría (7 píxeles en cada extremo, creo) a la izquierda y a la derecha con un color de fondo.

1

Cambiar el tamaño de las imágenes desde una página web con PHP puede ser problemático. Las imágenes más grandes (que se aproximan a 2 + MB en el disco) pueden ser tan grandes que necesitan más de 32 MB de memoria para procesar.

Por esa razón, yo bien tienden a hacer desde un script basada en CLI, con un máximo al 128 MB de memoria disponible para ella, o una línea de comandos estándar, que también utiliza tanto como lo necesita.

# where to put the original file/image. It gets resized back 
# it was originally found (current directory) 
SAFE=/home/website/PHOTOS/originals 
# no more than 640x640 when finished, and always proportional 
MAXSIZE=640 
# the larger image is in /home/website/PHOTOS/, moved to .../originals 
# and the resized image back to the parent dir. 
cd $SAFE/.. && mv "$1" "$SAFE/$1" && \ 
    convert "$SAFE/$1" -resize $MAXSIZE\x$MAXSIZE\> "$1" 

'convert' es parte de las herramientas de línea de comandos de ImageMagick.

1

son estas miniaturas? si lo están, cosechar no es un gran problema. lo hacemos todo el tiempo Ni siquiera rehúso cultivar proporciones arbitrarias en las miniaturas cuadráticas paralizadas, arruinando por completo la imagen (sí, soy ese hardcore), si solo se ve bien. esta es la respuesta de un diseñador a una pregunta técnica, pero aún así. no temas la cosecha!

1

Creo que hay un poco de confusión .. Si sólo desea cambiar su tamaño, manteniendo la proporción original, la operación correcta es:

$ratio = $originalWidth/$originalHeight; 
if(//you start from the width, and want to find the height){ 
$newWidth = $x; 
$newHeight = $x/$ratio; 
}else if(//you start from the height, and want to find the width){ 
$newHeight = $x; 
$newWidth = $x * $ratio; 
} 

lo demás, si el prefijado newWidth y newHeight puedo ser cambiado, y la relación empírica es diferente de la relación original, el La única forma es recortar o agregar bordes al pulgar.

Si Your'e a tomar la forma del corte, esta función puede ayudarle a (i escribí hace años en 5 minutos, tal vez necesite una cierta mejora .. funciona únicamente con jpg, por ejemplo;):

function thumb_cut($nomeimage, $source_path, $destination_path, $new_width, $new_height){ 
     list($width, $height, $type, $attr) = getimagesize($source_path.$nomeimage); 
     if($type == 2){ 
     if($width > $new_width){ 
      $new_width = $width; 
      $new_height = $height; 
     } 
     $compression = 100; 
     $destimg = imagecreatetruecolor($new_width,$new_height) or die("Problems creating the image"); 
     $srcimg = ImageCreateFromJPEG($source_path.$nomeimage) or die("problem opening the image"); 
     $w = ImageSX($srcimg); 
     $h = ImageSY($srcimg); 
     $ro = $new_width/$new_height; 
     $ri = $w/$h; 
     if($ro<$ri){ 
      $par = "h"; 
     }else{ 
      $par = "w"; 
     } 
     if($par == "h"){ 
      $ih = $h; 
      $conv = $new_width/$new_height; 
      $iw = $conv*$ih; 
      $cw = ($w/2)-($iw/2); 
      $ch = ($h/2)-($ih/2); 
     }else if($par == "w"){ 
      $iw = $w; 
      $conv = $new_height/$new_width; 
      $ih = $conv*$iw; 
      $cw = ($w/2)-($iw/2); 
      $ch = ($h/2)-($ih/2); 
     } 
     ImageCopyResampled($destimg,$srcimg,0,0,$cw,$ch,$new_width,$new_height,$iw,$ih) or die("problems with resize"); 
     ImageJPEG($destimg,$destination_path.$nomeimage,$compression) or die("problems with storing new image"); 
     } 
    } 
2

Sólo un consejo para la generación de miniaturas rápida y de alta calidad a partir de las imágenes grandes: (from the php.net site)

Si lo hace la generación de miniaturas en dos etapas:

  1. De original a imagen intermedia con el doble de las dimensiones finales, utilizando un redimensionar rápida
  2. A partir de la imagen intermedia a la miniatura final utilizando un nuevo muestreo de alta calidad

entonces esto puede ser mucho más rápido; el cambio de tamaño en el paso 1 es de calidad relativamente baja para su tamaño, pero tiene suficiente resolución adicional que en el paso 2 la calidad es aceptable, y la imagen intermedia es lo suficientemente pequeña como para volver a muestrearla de gran calidad (que funciona bien con un tamaño 2: 1) procede muy rápido.

+0

Gracias por su adición. ¿Tienes algún código de muestra? ¿Cómo encajaría esto en el código de gnut? – sanders

+0

ver el enlace php en mi publicación –

1

La técnica consiste en:

  1. cambiar el tamaño de la imagen para que coincida con una dimensión mientras que la otra excede las dimensiones deseadas
  2. la imagen tamaño deseado llevar desde el centro de la imagen redimensionada.

Por último, si usted tiene dudas acerca de cómo hacer los cálculos de cambio de tamaño, recuerde que si las proporciones de origen como la de destino son iguales, esta relación se mantiene:

SourceWidth/SourceHeight = DestinationWidth/DestinationHeight 

Si conoces a tres parámetros, se puede calcule el cuarto fácilmente.

escribí un artículo sobre esto:
Crop-To-Fit an Image Using ASP/PHP

Cuestiones relacionadas