10

J'ai besoin de redimensionner et de recadrer une image à une largeur et une hauteur spécifiques. J'ai été capable de construire une méthode qui créera une vignette carrée, mais je ne sais pas comment l'appliquer, quand la vignette souhaitée n'est pas carrée.Recadrage du moteur d'applications à une largeur et à une hauteur spécifiques

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 

S'il y a une meilleure façon de le faire s'il vous plaît faites le moi savoir. Toute aide serait grandement appréciée.

Voici un diagramme expliquant le processus souhaité. crop_diagram

Merci,

Kyle

Répondre

17

J'ai eu un problème similaire (votre capture d'écran était très utile). C'est ma solution:

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

Merci. C'est exactement ce que je cherchais. –

+0

merci beaucoup pour le code, fonctionne génial! – goggin13

+0

thx! exactement ce que je cherchais – fceruti

2

Vous pouvez spécifier les heightetwidth paramètres à resize - il ne changera pas le rapport d'aspect (vous ne pouvez pas le faire avec le module de GAE images), mais il s'assurera que chacune des deux dimensions est <= la valeur correspondante que vous spécifiez (en fait, l'un sera exactement égal à la valeur que vous spécifiez, l'autre sera <=). Je ne suis pas sûr de savoir pourquoi vous recadrez d'abord et redimensionnez plus tard - il semble que vous devriez faire les choses dans l'autre sens ... redimensionner de sorte que la plupart de l'image originale "s'adapte" comme c'est faisable, puis recadrer pour assurer la dimension résultante exacte. (Ainsi, vous n'utiliseriez pas les valeurs originales fournies de hauteur et de largeur pour le redimensionnement - vous les augmenteriez pour qu'aucune image résultante ne soit "gaspillée", alias "vide", si je comprends bien vos besoins). Alors peut-être que je ne comprends pas exactement ce dont vous avez besoin - pourriez-vous donner un exemple (les URL d'une image avant le traitement, la façon dont elle devrait être traitée et les détails des paramètres que vous allez passer) ?

+0

Merci Alex, Dis par exemple J'ai une image qui a une largeur de 500px et une hauteur de 300px. Je voudrais que l'image recadrée (vignette) ait une largeur de 150 pixels et une hauteur de 100 pixels. Je crois que vous avez raison de redimensionner d'abord. Je suis sûr que toute la fonction est assez simple, je viens de me battre avec le code. Voici un lien vers un diagramme décrivant le processus. http://farm3.static.flickr.com/2543/4205690696_b3821a12e9_o.gif –