Motore di app che ritaglia una larghezza e un'altezza specifiche
Domanda
Devo ridimensionare e ritagliare un'immagine su una larghezza e un'altezza specifiche. Sono stato in grado di costruire un metodo che creerà una miniatura quadrata, ma non sono sicuro di come applicarlo, quando la miniatura desiderata non è quadrata.
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
Se c'è un modo migliore per farlo per favore fammelo sapere. Qualsiasi aiuto sarebbe molto apprezzato.
Ecco un diagramma che spiega il processo desiderato.
Grazie,
Kyle
Soluzione
Ho avuto un problema simile (il tuo screenshot è stato molto utile). Questa è la mia soluzione:
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()
Altri suggerimenti
Puoi specificare entrambi height
e width
parametri a resize
- non cambierà le proporzioni (non puoi farlo con Gae images
modulo), ma assicurerà che ciascuna delle due dimensioni sia <=
Il valore corrispondente specificato (in effetti, uno sarà esattamente uguale al valore specificato, l'altro sarà <=
).
Non sono sicuro del motivo per cui stai ritagliando prima e ridimensionando in seguito - sembra che dovresti fare le cose al contrario ... Ridimensionare in modo che la stessa immagine originale "si adatti" a fattibile, quindi fissi per assicurarti dimensione risultante esatta. (Quindi non useresti i valori originali forniti di altezza e larghezza per il ridimensionamento: li ridimensioneresti in modo che nessuna immagine risultante sia "sprecata" aka "vuota", se capisco correttamente le tue esigenze). Quindi forse non capisco esattamente cosa hai bisogno: potresti fornire un esempio (URL a un'immagine come guarda prima dell'elaborazione, su come dovrebbe occuparsi dell'elaborazione e i dettagli dei parametri che passeresti) ?