2008-11-07 23 views
266

¿Hay alguna manera obvia de hacer esto que me falta? Solo estoy tratando de hacer miniaturas.¿Cómo cambio el tamaño de una imagen usando PIL y mantengo su relación de aspecto?

+7

Dado que esta cuestión es bastante antiguo, pero útil, y la almohada es más bien prefiere, para un tutorial basado en la almohada echar un vistazo a esto: http : //pillow.readthedocs.org/en/latest/handbook/tutorial.html#create-jpeg-thumbnails – Wtower

+1

He creado una pequeña biblioteca para cambiar el tamaño de las imágenes, puede ser de alguna ayuda: https://github.com/ charlesthk/python-resize-image – Charlesthk

Respuesta

326

Define un tamaño máximo. Luego, calcule una proporción de cambio de tamaño tomando min(maxwidth/width, maxheight/height).

El tamaño correcto es oldsize*ratio.

Por supuesto, también hay un método de biblioteca para hacer esto: el método Image.thumbnail.
A continuación se muestra un ejemplo (editado) del PIL documentation.

import os, sys 
import Image 

size = 128, 128 

for infile in sys.argv[1:]: 
    outfile = os.path.splitext(infile)[0] + ".thumbnail" 
    if infile != outfile: 
     try: 
      im = Image.open(infile) 
      im.thumbnail(size, Image.ANTIALIAS) 
      im.save(outfile, "JPEG") 
     except IOError: 
      print "cannot create thumbnail for '%s'" % infile 
+58

** Comentario de [Randy Syring] (http://stackoverflow.com/users/182111/randy-syring) **: Agregue 'Image.ANTIALIAS' a la llamada' thumbnail() '. Es muy recomendable en los documentos y, siendo esta la mejor respuesta, se deben seguir las mejores prácticas. En otras palabras: reemplace 'im.thumbnail (size)' por 'im.thumbnail (size, Image.ANTIALIAS)'. – Anne

+2

Como dice, el ejemplo era de la documentación pil, y ese ejemplo (todavía) no usa el indicador antialias. Como probablemente sea lo que la mayoría de la gente quiera, lo agregué. – gnud

+2

PIL establece la altura de la nueva imagen con el tamaño dado (128 aquí) y calcula el ancho para mantener la relación de aspecto. ¿Hay alguna manera de arreglar el ancho en lugar de la altura? quizás pregunte esto en otra pregunta. – eugene

9

Si intenta mantener la misma relación de aspecto, ¿no cambiaría el tamaño en algún porcentaje del tamaño original?

Por ejemplo, la mitad del tamaño original

half = 0.5 
out = im.resize([int(half * s) for s in im.size]) 
+7

Podría ser que las imágenes fueran de diferentes tamaños y se requiera que el tamaño del tamaño sea del tamaño uniforme – Steen

136

Este script cambiar el tamaño de una imagen (somepic.jpg) usando PIL (Python Imaging Library) a una anchura de 300 píxeles y una altura proporcional a la nueva anchura . Lo hace determinando qué porcentaje es 300 píxeles del ancho original (img.size [0]) y luego multiplicando la altura original (img.size [1]) por ese porcentaje. Cambia el "ancho de base" a cualquier otro número para cambiar el ancho predeterminado de tus imágenes.

from PIL import Image 

basewidth = 300 
img = Image.open('somepic.jpg') 
wpercent = (basewidth/float(img.size[0])) 
hsize = int((float(img.size[1])*float(wpercent))) 
img = img.resize((basewidth,hsize), Image.ANTIALIAS) 
img.save('sompic.jpg') 
+2

Si está utilizando este script en Zope como método externo, necesitará la línea "de PIL import Image" para evitar conflictos de espacios de nombres con la "Imagen" de Zope. – tomvon

+1

gracias por el 'PIL.Image.ANTIALIAS' –

+0

Este código me da un archivo de salida de 0 bytes' '' sompic.jpg'''. ¿Por qué pasó esto? Estoy usando Python 3.x –

46

También recomiendo utilizar el método de miniaturas de PIL, ya que elimina todas las molestias de la relación.

Una pista importante, sin embargo: Sustituir

im.thumbnail(size) 

con

im.thumbnail(size,Image.ANTIALIAS) 

por defecto, PIL utiliza el filtro Image.NEAREST de cambio de tamaño que se traduce en un buen rendimiento, pero de mala calidad.

13

PIL ya tiene la opción de recortar una imagen

img = ImageOps.fit(img, size, Image.ANTIALIAS) 
+10

Eso solo recorta la imagen, no mantiene la relación de aspecto. – Radu

1

Mi fea ejemplo.

Función obtener archivo como: "pic [0-9a-z]. [Extensión]", cambiar el tamaño a 120x120, mover la sección al centro y guardar en "ico [0-9a-z].[Extensión]", funciona con vertical y horizontal:

def imageResize(filepath): 
    from PIL import Image 
    file_dir=os.path.split(filepath) 
    img = Image.open(filepath) 

    if img.size[0] > img.size[1]: 
     aspect = img.size[1]/120 
     new_size = (img.size[0]/aspect, 120) 
    else: 
     aspect = img.size[0]/120 
     new_size = (120, img.size[1]/aspect) 
    img.resize(new_size).save(file_dir[0]+'/ico'+file_dir[1][3:]) 
    img = Image.open(file_dir[0]+'/ico'+file_dir[1][3:]) 

    if img.size[0] > img.size[1]: 
     new_img = img.crop((
      (((img.size[0])-120)/2), 
      0, 
      120+(((img.size[0])-120)/2), 
      120 
     )) 
    else: 
     new_img = img.crop((
      0, 
      (((img.size[1])-120)/2), 
      120, 
      120+(((img.size[1])-120)/2) 
     )) 

    new_img.save(file_dir[0]+'/ico'+file_dir[1][3:]) 
17

Basado en @tomvon, he terminado utilizando la siguiente: anchura

Cambio de tamaño:

new_width = 680 
new_height = new_width * height/width 

Cambiar el tamaño de altura:

new_height = 680 
new_width = new_height * width/height 

Entonces solo:

img = img.resize((new_width, new_height), Image.ANTIALIAS) 
+4

Tus variables están mezcladas. Su publicación dice redimensionar el ancho, y luego cambia el tamaño de la altura. Y en la llamada 'resize', ¿estás usando' new_width' tanto para alto como para ancho? – Zachafer

+0

Sugirió una solución para eso @ Zachafer – Mohammad

2
from PIL import Image 
from resizeimage import resizeimage 

def resize_file(in_file, out_file, size): 
    with open(in_file) as fd: 
     image = resizeimage.resize_thumbnail(Image.open(fd), size) 
    image.save(out_file) 
    image.close() 

resize_file('foo.tif', 'foo_small.jpg', (256, 256)) 

puedo utilizar esta biblioteca:

pip install python-resize-image 
8
from PIL import Image 

img = Image.open('/your iamge path/image.jpg') # image extension *.png,*.jpg 
new_width = 200 
new_height = 300 
img = img.resize((new_width, new_height), Image.ANTIALIAS) 
img.save('output image name.png') # format may what u want ,*.png,*jpg,*.gif 
Cuestiones relacionadas