Изменение размера изображения с сохранением соотношения сторон И обеспечение одинакового размера портретных и альбомных изображений? - PullRequest
11 голосов
/ 02 февраля 2012

В настоящее время я использую:

    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)

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

ОБНОВЛЕНИЕ:

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

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)

Ответы [ 3 ]

18 голосов
/ 02 февраля 2012

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

#!/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)

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

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

Обновление

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

#!/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)
2 голосов
/ 02 февраля 2012

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

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 голосов
/ 06 августа 2015

Если вы используете easy-thumbnails, вам нужно установить crop в True и upscale в True, чтобы всегда заполнять пространство (иметь одинаковые размеры).* Пример: делает 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
...