App Engine裁剪到特定的宽度和高度

时间:2009-12-22 04:07:34

标签: google-app-engine resize image-manipulation resize-image dynamic-resizing

我需要调整大小并将图像裁剪为特定的宽度和高度。我能够构建一个可以创建方形缩略图的方法,但是当所需的缩略图不是正方形时,我不确定如何应用它。

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

谢谢,

凯尔

2 个答案:

答案 0 :(得分:16)

我遇到了类似的问题(截图非常有用)。这是我的解决方案:

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()

答案 1 :(得分:2)

您可以将height width参数指定给resize - 它不会改变宽高比(你不能用GAE的{{{ 1}}模块),但它将确保两个维度中的每一个都是images您指定的相应值(事实上,一个将完全等于您指定的值,另一个将是{{1} }})。

我不确定你为什么要先裁剪并稍后调整大小 - 看起来你应该做相反的事情......调整大小,以便原始图像尽可能地“适合”,然后裁剪以确保精确的尺寸。 (因此,您不会使用原始提供的高度和宽度值来调整大小 - 如果我正确理解您的要求,您可以将它们放大,以使得所有图像都不会被“浪费”,也就是“空白”。所以也许我不能确切地理解你的需求 - 你能提供一个例子(在处理之前看到的图像的URL,处理后应该如何看待的图像,以及你要传递的参数的细节) ?