2012-02-01 3 views
11

В настоящее время я использую:Изменение размера изображения с сохранением пропорций И ​​создание портретных и ландшафтных изображений одинакового размера?

os.chdir(album.path) 
    images = glob.glob('*.*') 

    # thumbs size 
    size = 80,80 

    for image in images: 
     #create thumb 
     file, ext = os.path.splitext(image) 
     im = Image.open(os.path.join(album.path,image)) 
     im.thumbnail(size, Image.ANTIALIAS) 
     thumb_path = os.path.join(album.path, 'thumbs', file + ".thumb" + ".jpeg") 
     im.save(thumb_path) 

Хотя это работает, я в конечном итоге с различными размерами изображениями (некоторые из них портрета, а некоторые пейзажи), но я хочу, чтобы все изображения, чтобы иметь точный размер. Может быть, разумная обрезка?

UPDATE:

Я не против кадрирования небольшой части изображения. Когда я сказал, осмысленное кадрирование я имею в виду что-то вроде этого алгоритму:

if image is portrait: 
    make width 80px 
    crop the height (will be more than 80px) 
else if image is landscape: 
    make height 80px 
    crop the width to 80px (will be more than 80px) 
+0

Рассмотрим чтение руководств. Метод 'thumnail' * означает *, чтобы сохранить аспект изображения. Очевидно, вы не можете иметь оба, поскольку не все изображения имеют одинаковое соотношение сторон. Рассмотрите возможность использования 'resize', если вы хотите перемасштабировать, не сохраняя соотношение. –

+1

Он мог бы сделать их того же размера, если бы захотел сделать посадку, которая выложила бы лишнюю область с постоянным цветом. Это позволило бы 4x3 или 16x9 или любому аспектному изображению соответствовать заданному размеру 80x80 – jdi

+0

К сожалению, нет стандартного способа определения «разумного» для обрезки. Похоже, вы хотите всегда обрезать квадрат с изображения, что означает, что вы рискуете отрезать части, которые вы действительно хотели сохранить. –

ответ

18

Вот мой взять на себя делать мягкие, пригодную для изображения:

#!/usr/bin/env python 

from PIL import Image, ImageChops 

F_IN = "/path/to/image_in.jpg" 
F_OUT = "/path/to/image_out.jpg" 

size = (80,80) 

image = Image.open(F_IN) 
image.thumbnail(size, Image.ANTIALIAS) 
image_size = image.size 

thumb = image.crop((0, 0, size[0], size[1])) 

offset_x = max((size[0] - image_size[0])/2, 0) 
offset_y = max((size[1] - image_size[1])/2, 0) 

thumb = ImageChops.offset(thumb, offset_x, offset_y) 
thumb.save(F_OUT) 

Сначала он использует операцию миниатюр, чтобы довести изображение до исходных границ и сохранить его. Затем он выгружает его обратно, чтобы на самом деле заполнить размер ваших границ (поскольку, если исходное изображение не было квадратным, оно теперь будет меньше), и мы найдем правильный смещение, чтобы центрировать изображение. Изображение смещено к центру, поэтому вы получаете черное дополнение, но не обрезаете изображение.

Если вы не можете сделать действительно разумное предположение о правильном посещении центра, не теряя при этом возможных важных данных изображения по краям, подход с мягкой подгонкой будет работать лучше.

Update

Вот версия, которая может сделать любой центр кадрирования или площадку подгонку.

#!/usr/bin/env python 

from PIL import Image, ImageChops, ImageOps 

def makeThumb(f_in, f_out, size=(80,80), pad=False): 

    image = Image.open(f_in) 
    image.thumbnail(size, Image.ANTIALIAS) 
    image_size = image.size 

    if pad: 
     thumb = image.crop((0, 0, size[0], size[1])) 

     offset_x = max((size[0] - image_size[0])/2, 0) 
     offset_y = max((size[1] - image_size[1])/2, 0) 

     thumb = ImageChops.offset(thumb, offset_x, offset_y) 

    else: 
     thumb = ImageOps.fit(image, size, Image.ANTIALIAS, (0.5, 0.5)) 

    thumb.save(f_out) 


source = "/path/to/source/image.JPG" 

makeThumb(source, "/path/to/source/image_padded.JPG", pad=True) 
makeThumb(source, "/path/to/source/image_centerCropped.JPG", pad=False) 
+0

Это действительно близко к тому, что мне нужно @jdi, спасибо! Как изменить его, чтобы нарезать и не вставлять прокладку? (даже теряя кусок изображения) – thyagx

+0

@thyagx - там я иду! – jdi

+1

Отлично, именно то, что мне нужно! Спасибо @jdi! – thyagx

2

Очевидно, что вам нужно будет обрезать или колодки изображения. Вы могли бы сделать что-то, как показано ниже, чтобы получить максимальные центрированной урожай в соответствии с соотношением сторон эскизов (непроверенных):

aspect = lambda size: float(size[0])/float(size[1]) 
sa = aspect(size) 
if aspect(im.size) > sa: 
    width = int(sa * im.size[1]) 
    left = (im.size[0] - width)/2 
    im = im.crop((left, 0, left + width, im.size[1])) 
else: 
    height = int(im.size[0]/sa) 
    top = (im.size[1] - height)/2 
    im = im.crop((0, top, im.size[0], top + height)) 
im.thumbnail(size, Image.ANTIALIAS) 
+0

В этом примере есть несколько ошибок. im.crop() не обрезается на месте.Он должен вернуть объект изображения самому себе. Аргументы для урожая должны быть короткими кортежами, поэтому вам нужно обернуть их в(). Вы отправляете поплавки в урожай. Нужно делать int (ширина) и int (высота). Кроме того, все это не обязательно, поскольку существует встроенный метод: 'im = ImageOps.fit (im, size, Image.ANTIALIAS, (0.5, 0.5))', который делает то же самое. – jdi

0

Если вы используете простые в эскизы вам необходимо установить crop в True и upscale в True всегда заполнить вверх пространство (имеют те же размеры).

Ex: делает IMAGE_2 вписывается в размеры IMAGE_1:

thumbnailer = get_thumbnailer(image_2) 
    thumbnail = thumbnailer.generate_thumbnail(thumbnail_options={ 
     'crop': True, 
     'upscale': True, 
     'size': image_1.size 
    }) 
    image_2 = thumbnail.image