10

Necesito cambiar el tamaño y recortar una imagen a un ancho y alto específicos. Pude construir un método que creará una miniatura cuadrada, pero no estoy seguro de cómo aplicar esto, cuando la miniatura deseada no es cuadrada.Recorte del motor de aplicación a un ancho y una altura específicos

def rescale(data, width, height): 
"""Rescale the given image, optionally cropping it to make sure the result image has the specified width and height.""" 
from google.appengine.api import images 

new_width = width 
new_height = height 

img = images.Image(data) 

org_width, org_height = img.width, img.height 

# We must determine if the image is portrait or landscape 
# Landscape 
if org_width > org_height: 
    # With the Landscape image we want the crop to be centered. We must find the 
    # height to width ratio of the image and Convert the denominater to a float 
    # so that ratio will be a decemal point. The ratio is the percentage of the image 
    # that will remain. 
    ratio = org_height/float(org_width) 
    # To find the percentage of the image that will be removed we subtract the ratio 
    # from 1 By dividing this number by 2 we find the percentage that should be 
    # removed from each side this is also our left_x coordinate 
    left_x = (1- ratio)/2 
    # By subtract the left_x from 1 we find the right_x coordinate 
    right_x = 1 - left_x 
    # crop(image_data, left_x, top_y, right_x, bottom_y), output_encoding=images.PNG) 
    img.crop(left_x, 0.0, right_x, 1.0) 
    # resize(image_data, width=0, height=0, output_encoding=images.PNG) 
    img.resize(height=height) 
# Portrait 
elif org_width < org_height: 
    ratio = org_width/float(org_height) 
    # crop(image_data, left_x, top_y, right_x, bottom_y), output_encoding=images.PNG) 
    img.crop(0.0, 0.0, 1.0, ratio) 
    # resize(image_data, width=0, height=0, output_encoding=images.PNG) 
    img.resize(width=witdh) 

thumbnail = img.execute_transforms() 
return thumbnail 

Si hay una mejor manera de hacerlo, háganmelo saber. Cualquier ayuda sería muy apreciada.

Aquí hay un diagrama que explica el proceso deseado. crop_diagram

Gracias,

Kyle

Respuesta

17

Tuve un problema similar (tu captura de pantalla fue muy útil). Esta es mi solución:

def rescale(img_data, width, height, halign='middle', valign='middle'): 
    """Resize then optionally crop a given image. 

    Attributes: 
    img_data: The image data 
    width: The desired width 
    height: The desired height 
    halign: Acts like photoshop's 'Canvas Size' function, horizontally 
      aligning the crop to left, middle or right 
    valign: Verticallly aligns the crop to top, middle or bottom 

    """ 
    image = images.Image(img_data) 

    desired_wh_ratio = float(width)/float(height) 
    wh_ratio = float(image.width)/float(image.height) 

    if desired_wh_ratio > wh_ratio: 
    # resize to width, then crop to height 
    image.resize(width=width) 
    image.execute_transforms() 
    trim_y = (float(image.height - height)/2)/image.height 
    if valign == 'top': 
     image.crop(0.0, 0.0, 1.0, 1 - (2 * trim_y)) 
    elif valign == 'bottom': 
     image.crop(0.0, (2 * trim_y), 1.0, 1.0) 
    else: 
     image.crop(0.0, trim_y, 1.0, 1 - trim_y) 
    else: 
    # resize to height, then crop to width 
    image.resize(height=height) 
    image.execute_transforms() 
    trim_x = (float(image.width - width)/2)/image.width 
    if halign == 'left': 
     image.crop(0.0, 0.0, 1 - (2 * trim_x), 1.0) 
    elif halign == 'right': 
     image.crop((2 * trim_x), 0.0, 1.0, 1.0) 
    else: 
     image.crop(trim_x, 0.0, 1 - trim_x, 1.0) 

    return image.execute_transforms() 
+0

Gracias. Eso es exactamente lo que estaba buscando. –

+0

muchas gracias por el código, ¡funciona increíble! – goggin13

+0

thx! exactamente lo que estaba buscando – fceruti

2

Puede especificar ambos heightywidth parámetros a resize - no va a cambiar la relación de aspecto (no se puede hacer eso con la GAE images módulo), pero se asegurará de que cada una de las dos dimensiones sea <= el valor correspondiente que especifique (de hecho, una será exactamente igual al valor que especifique, la otra será <=).

No estoy seguro de por qué está recortando primero y cambiando el tamaño más tarde - parece que debe hacer las cosas al revés ... cambie el tamaño para que la mayor parte de la imagen original "se adapte" como sea posible, luego recorte para asegurar la dimensión exacta resultante. (Por lo tanto, no usaría los valores originales de alto y ancho para el cambio de tamaño; los escalaría para que ninguna de las imágenes resultantes se "desperdicie", es decir, "en blanco", si entiendo sus requisitos correctamente). Así que tal vez no estoy entendiendo exactamente lo que necesita: ¿podría proporcionar un ejemplo (direcciones URL de una imagen tal como se ve antes del procesamiento, cómo debe verse después del procesamiento y detalles de los parámetros que aprobaría)? ?

+0

Gracias Alex, di por ejemplo Tengo una imagen que tiene un ancho de 500px y una altura de 300px. Me gustaría que la imagen recortada (miniatura) tenga un ancho de 150 px y una altura de 100 px. Creo que tu derecho a redimensionar primero. Estoy seguro de que toda la función es bastante simple. He estado luchando con el código. Aquí hay un enlace a un diagrama que describe el proceso. http://farm3.static.flickr.com/2543/4205690696_b3821a12e9_o.gif –

Cuestiones relacionadas