Обрезка движка приложения до определенной ширины и высоты
Мне нужно изменить размер и обрезать изображение до определенной ширины и высоты. Мне удалось создать метод, который будет создавать квадратный эскиз, но я не уверен, как его применить, когда нужный эскиз не квадратный.
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
Если есть лучший способ сделать это, пожалуйста, дайте мне знать. Любая помощь будет принята с благодарностью.
Вот диаграмма, объясняющая желаемый процесс.
Спасибо,
рукав моря
2 ответа
У меня была похожая проблема (ваш скриншот был очень полезен). Это мое решение:
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()
Вы можете указать оба height
а также width
параметры для resize
- это не изменит соотношение сторон (вы не можете сделать это с GAE images
модуль), но он будет гарантировать, что каждое из двух измерений <=
соответствующее значение, которое вы указываете (на самом деле, одно будет точно равно указанному вами значению, другое будет <=
).
Я не уверен, почему вы сначала обрезаете, а потом изменяете размеры - кажется, что вы должны делать что-то наоборот... изменить размер так, чтобы оригинальное изображение "соответствовало", насколько это возможно, а затем обрезать, чтобы обеспечить точное результирующее измерение. (Таким образом, вы не будете использовать исходные значения высоты и ширины для изменения размера - вы бы масштабировали их так, чтобы ни одно из полученных изображений не было "потрачено впустую" или "пусто", если я правильно понимаю ваши требования). Поэтому, возможно, я не совсем понимаю, что вам требуется - не могли бы вы привести пример (URL-адреса изображения, как оно выглядит до обработки, как оно должно выглядеть после обработки, и подробности параметров, которые вы будете передавать)?