Как мне изменить размер изображения с помощью PIL и сохранить его соотношение сторон?

StackOverflow https://stackoverflow.com/questions/273946

Вопрос

Есть ли очевидный способ сделать это, которого мне не хватает?Я просто пытаюсь сделать миниатюры.

Это было полезно?

Решение

Определите максимальный размер. Затем вычислите коэффициент изменения размера, взяв min (maxwidth / width, maxheight / height) .

Правильный размер: oldsize * ratio .

Конечно, для этого есть и библиотечный метод: метод Image.thumbnail .
Ниже приведен (отредактированный) пример из документации PIL .

import os, sys
import Image

size = 128, 128

for infile in sys.argv[1:]:
    outfile = os.path.splitext(infile)[0] + ".thumbnail"
    if infile != outfile:
        try:
            im = Image.open(infile)
            im.thumbnail(size, Image.ANTIALIAS)
            im.save(outfile, "JPEG")
        except IOError:
            print "cannot create thumbnail for '%s'" % infile

Другие советы

Этот скрипт изменит размер изображения (somepic.jpg) с помощью PIL (Python Imaging Library) до ширины 300 пикселей и высоты, пропорциональной новой ширине. Он делает это, определяя, какой процент 300 пикселей имеет исходную ширину (img.size [0]), а затем умножая исходную высоту (img.size [1]) на этот процент. Изменить " базовую пропускную способность " на любой другой номер, чтобы изменить ширину изображений по умолчанию.

from PIL import Image

basewidth = 300
img = Image.open('somepic.jpg')
wpercent = (basewidth/float(img.size[0]))
hsize = int((float(img.size[1])*float(wpercent)))
img = img.resize((basewidth,hsize), Image.ANTIALIAS)
img.save('sompic.jpg') 

Я также рекомендую использовать метод миниатюр PIL, потому что он избавляет вас от всех проблем с соотношением.

Однако есть один важный намек:Заменить

im.thumbnail(size)

с

im.thumbnail(size,Image.ANTIALIAS)

по умолчанию PIL использует изображение.БЛИЖАЙШИЙ фильтр для изменения размера, что приводит к хорошей производительности, но низкому качеству.

Основываясь на @tomvon, я закончил использовать следующее:

Ширина изменения размера:

new_width  = 680
new_height = new_width * height / width 

Изменение размера:

new_height = 680
new_width  = new_height * width / height

Тогда просто:

img = img.resize((new_width, new_height), Image.ANTIALIAS)

PIL уже имеет возможность обрезать изображение

img = ImageOps.fit(img, size, Image.ANTIALIAS)
from PIL import Image

img = Image.open('/your iamge path/image.jpg') # image extension *.png,*.jpg
new_width  = 200
new_height = 300
img = img.resize((new_width, new_height), Image.ANTIALIAS)
img.save('output image name.png') # format may what u want ,*.png,*jpg,*.gif

Если вы пытаетесь сохранить такое же соотношение сторон, то не измените ли вы размер на какой-то процент от исходного размера?

Например, половина оригинального размера

half = 0.5
out = im.resize( [int(half * s) for s in im.size] )
from PIL import Image
from resizeimage import resizeimage

def resize_file(in_file, out_file, size):
    with open(in_file) as fd:
        image = resizeimage.resize_thumbnail(Image.open(fd), size)
    image.save(out_file)
    image.close()

resize_file('foo.tif', 'foo_small.jpg', (256, 256))

Я использую эту библиотеку:

pip install python-resize-image

Мой ужасный пример.

Функция получает файл наподобие: " pic [0-9a-z]. [extension] " ;, изменяет их размер до 120x120, перемещает секцию в центр и сохраняет в " ico [0-9a-z]. [extension ] " ;, работает с портретной и альбомной ориентацией:

def imageResize(filepath):
    from PIL import Image
    file_dir=os.path.split(filepath)
    img = Image.open(filepath)

    if img.size[0] > img.size[1]:
        aspect = img.size[1]/120
        new_size = (img.size[0]/aspect, 120)
    else:
        aspect = img.size[0]/120
        new_size = (120, img.size[1]/aspect)
    img.resize(new_size).save(file_dir[0]+'/ico'+file_dir[1][3:])
    img = Image.open(file_dir[0]+'/ico'+file_dir[1][3:])

    if img.size[0] > img.size[1]:
        new_img = img.crop( (
            (((img.size[0])-120)/2),
            0,
            120+(((img.size[0])-120)/2),
            120
        ) )
    else:
        new_img = img.crop( (
            0,
            (((img.size[1])-120)/2),
            120,
            120+(((img.size[1])-120)/2)
        ) )

    new_img.save(file_dir[0]+'/ico'+file_dir[1][3:])

Простой метод для сохранения ограниченных соотношений и передачи максимальной ширины / высоты. Не самая красивая, но выполняет свою работу и легко понять:

def resize(img_path, max_px_size, output_folder):
    with Image.open(img_path) as img:
        width_0, height_0 = img.size
        out_f_name = os.path.split(img_path)[-1]
        out_f_path = os.path.join(output_folder, out_f_name)

        if max((width_0, height_0)) <= max_px_size:
            print('writing {} to disk (no change from original)'.format(out_f_path))
            img.save(out_f_path)
            return

        if width_0 > height_0:
            wpercent = max_px_size / float(width_0)
            hsize = int(float(height_0) * float(wpercent))
            img = img.resize((max_px_size, hsize), Image.ANTIALIAS)
            print('writing {} to disk'.format(out_f_path))
            img.save(out_f_path)
            return

        if width_0 < height_0:
            hpercent = max_px_size / float(height_0)
            wsize = int(float(width_0) * float(hpercent))
            img = img.resize((max_px_size, wsize), Image.ANTIALIAS)
            print('writing {} to disk'.format(out_f_path))
            img.save(out_f_path)
            return

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

Я пытался изменить размеры некоторых изображений для видео в режиме слайд-шоу, и поэтому я хотел не только одно максимальное измерение, но и максимальную ширину и максимальную высоту (размер видеокадра) .
И всегда была возможность портретного видео ...
Метод Image.thumbnail был многообещающим, но я не смог сделать его более масштабным.

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

from PIL import Image

def get_resized_img(img_path, video_size):
    img = Image.open(img_path)
    width, height = video_size  # these are the MAX dimensions
    video_ratio = width / height
    img_ratio = img.size[0] / img.size[1]
    if video_ratio >= 1:  # the video is wide
        if img_ratio <= video_ratio:  # image is not wide enough
            width_new = int(height * img_ratio)
            size_new = width_new, height
        else:  # image is wider than video
            height_new = int(width / img_ratio)
            size_new = width, height_new
    else:  # the video is tall
        if img_ratio >= video_ratio:  # image is not tall enough
            height_new = int(width / img_ratio)
            size_new = width, height_new
        else:  # image is taller than video
            width_new = int(height * img_ratio)
            size_new = width_new, height
    return img.resize(size_new, resample=Image.LANCZOS)

Если вы не хотите / не хотите открывать изображение с помощью Подушки, используйте это:

from PIL import Image

new_img_arr = numpy.array(Image.fromarray(img_arr).resize((new_width, new_height), Image.ANTIALIAS))

Я изменил размер изображения таким образом, и он работает очень хорошо

from io import BytesIO
from django.core.files.uploadedfile import InMemoryUploadedFile
import os, sys
from PIL import Image


def imageResize(image):
    outputIoStream = BytesIO()
    imageTemproaryResized = imageTemproary.resize( (1920,1080), Image.ANTIALIAS) 
    imageTemproaryResized.save(outputIoStream , format='PNG', quality='10') 
    outputIoStream.seek(0)
    uploadedImage = InMemoryUploadedFile(outputIoStream,'ImageField', "%s.jpg" % image.name.split('.')[0], 'image/jpeg', sys.getsizeof(outputIoStream), None)

    ## For upload local folder
    fs = FileSystemStorage()
    filename = fs.save(uploadedImage.name, uploadedImage)

Просто обновляю этот вопрос более современной оболочкой Эта библиотека обертывает Подушку (вилка PIL) https://pypi.org/project/python-resize-image/

Позволяет вам сделать что-то вроде этого: -

from PIL import Image
from resizeimage import resizeimage

fd_img = open('test-image.jpeg', 'r')
img = Image.open(fd_img)
img = resizeimage.resize_width(img, 200)
img.save('test-image-width.jpeg', img.format)
fd_img.close()

Куча других примеров в приведенной выше ссылке.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top