Recorte del motor de aplicaciones a un ancho y altura específicos
Pregunta
Necesito cambiar el tamaño y recortar una imagen a un ancho y altura 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.
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 hacer esto, hágamelo saber. Cualquier ayuda sería muy apreciada.
Aquí hay un diagrama que explica el proceso deseado.
Gracias,
Kyle
Solución
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()
Otros consejos
Puedes especificar ambos height
y width
parámetros resize
- No cambiará la relación de aspecto (no puedes hacer eso con Gae's images
módulo), pero asegurará que cada una de las dos dimensiones sea <=
El valor correspondiente que especifique (de hecho, uno será exactamente igual al valor que especifique, el otro será <=
).
No estoy seguro de por qué estás recortando primero y cambia de tamaño más tarde, parece que debes hacer las cosas al revés ... cambiar el tamaño para que gran parte de la imagen original "se ajuste" como sea factible, luego recorte para asegurarte para asegurarte Dimensión exacta resultante. (Por lo tanto, no usaría los valores originales de altura y ancho para el cambio de tamaño: los escalaría para que ninguna de las imágenes resultantes se "desperdicie" también conocida como "en blanco", si entiendo sus requisitos correctamente). Entonces, tal vez no entiendo exactamente lo que necesita: ¿podría proporcionar un ejemplo (URL a una imagen tal como se ve antes del procesamiento, cómo debería cuidar el procesamiento y los detalles de los parámetros que estaría pasando) ?