10

Мне нужно изменить размер и обрезать изображение до определенной ширины и высоты. Я смог построить метод, который создаст квадратную миниатюру, но я не уверен, как применить это, когда желаемый эскиз не является квадратным.Охват App Engine для определенной ширины и высоты

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 

Если есть лучший способ сделать это, пожалуйста, дайте мне знать. Любая помощь будет принята с благодарностью.

Вот диаграмма, поясняющая желаемый процесс. crop_diagram

Спасибо,

Kyle

ответ

17

У меня была аналогичная проблема (ваш скриншот был очень полезным). Это мое решение:

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

Спасибо. Это именно то, что я искал. –

+0

большое спасибо за код, работает потрясающе! – goggin13

+0

thx! точно, что я искал – fceruti

2

Вы можете указать оба heightиwidth параметров resize - это не изменит соотношение сторон (вы не можете сделать это с помощью GAE-х images модуля), но он гарантирует, что каждое из двух измерений будет <= соответствующее значение, которое вы укажете (на самом деле, каждый будет точно равен указанному вами значению, другой будет <=).

Я не уверен, почему вы обрезаете сначала и изменяете размер позже - кажется, что вы должны делать что-то наоборот ... изменяйте размер так, чтобы как можно больше оригинального изображения «соответствовало», затем обрезайте, чтобы обеспечить точный результат измерения. (Таким образом, вы не использовали бы исходные предоставленные значения высоты и ширины для изменения размера - вы бы масштабировали их так, чтобы ни одно из полученных изображений не было «потеряно», иначе «пусто», если я правильно понимаю ваши требования). Поэтому, возможно, я не понимаю, что вам нужно, - можете ли вы привести пример (URL-адрес изображения, как он выглядит перед обработкой, как он должен следить за обработкой, а также детали параметров, которые вы должны пройти) ?

+0

Спасибо, Алекс, скажем, например, у меня есть изображение шириной 500 пикселей и высотой 300 пикселей. Я хотел бы, чтобы обрезанное изображение (миниатюра) имело ширину 150 пикселей и высоту 100 пикселей. Я считаю, что вы правы в изменении размера. Я уверен, что вся функция довольно проста. Я просто борюсь с кодом. Вот ссылка на диаграмму, описывающую процесс. http://farm3.static.flickr.com/2543/4205690696_b3821a12e9_o.gif –