В Python, Python Image Library 1.1.6, как я могу расширить холст без изменения размера?
Я, вероятно, искал неправильную вещь в справочнике, но я ищу, чтобы взять объект изображения и расширить его, не изменяя размер (растягивая/скрещивая) исходное изображение.
Пример игрушки: представьте синий прямоугольник, 200 x 100, затем я выполняю некоторую операцию, и у меня есть новый объект изображения 400 x 300, состоящий из белого фона, на котором покоится синий прямоугольник 200 x 100. Бонус, если я могу контролировать, в каком направлении это расширяется, или новый цвет фона и т.д.
По существу, у меня есть образ, к которому я буду добавлять итеративно, и я не знаю, какой размер он будет в самом начале.
Я предполагаю, что мне удастся захватить оригинальный объект, создать новый, чуть больший объект, вставить оригинал там, нарисовать немного больше, а затем повторить. Похоже, что это может быть дорогостоящим. Однако я думал, что для этого будет функция, так как я предполагаю, что это обычная операция. Возможно, я ошибался.
Ответы
Ответ 1
Функция ImageOps.expand расширит изображение, но добавит столько же пикселей в каждом направлении.
Лучший способ - просто создать новое изображение и вставить:
newImage = Image.new(mode, (newWidth,newHeight))
newImage.paste(srcImage, (x1,y1,x1+oldWidth,y1+oldHeight))
Если производительность является проблемой, сделайте исходное изображение больше, чем нужно, и обрезайте его после завершения рисования.
Ответ 2
Основываясь на ответах на interjays:
#!/usr/bin/env python
from PIL import Image
import math
def resize_canvas(old_image_path="314.jpg", new_image_path="save.jpg",
canvas_width=500, canvas_height=500):
"""
Resize the canvas of old_image_path.
Store the new image in new_image_path. Center the image on the new canvas.
Parameters
----------
old_image_path : str
new_image_path : str
canvas_width : int
canvas_height : int
"""
im = Image.open(old_image_path)
old_width, old_height = im.size
# Center the image
x1 = int(math.floor((canvas_width - old_width) / 2))
y1 = int(math.floor((canvas_height - old_height) / 2))
mode = im.mode
if len(mode) == 1: # L, 1
new_background = (255)
if len(mode) == 3: # RGB
new_background = (255, 255, 255)
if len(mode) == 4: # RGBA, CMYK
new_background = (255, 255, 255, 255)
newImage = Image.new(mode, (canvas_width, canvas_height), new_background)
newImage.paste(im, (x1, y1, x1 + old_width, y1 + old_height))
newImage.save(new_image_path)
resize_canvas()
Ответ 3
Вы можете подумать о другом подходе к своему изображению... выстроить его из плиток фиксированного размера. Таким образом, поскольку вам нужно расширить, вы просто добавляете новые плитки изображений. Когда вы закончите все свои вычисления, вы можете определить окончательный размер изображения, создать пустое изображение этого размера и вставить в него плитки. Это должно уменьшить объем копирования, на который вы смотрите, для выполнения задачи.
(Вероятно, вы захотите инкапсулировать такое черепичное изображение в объект, который спрятал бы аспекты черепицы из других слоев кода, конечно.)