Меняем размер изображения в Python Pillow с обрезанием и изменением ширины и высоты
В Python есть много библиотек по работе с изображениями. Одна из самых известных библиотек — Pillow (ранее PIL). В этой статье будут рассмотрены примеры по изменению размеров картинки с помощью увеличения и уменьшения картинки, а так же обрезания.
Pillow не является стандартной библиотекой и устанавливается отдельно:
pip install pillow
Навигация по посту
- Получение размеров
- Изменение размера изображения с resize()
- Учет соотношения сторон
- Создание эскиза thumbnail
- Создание границ изображения с ImageOps.expand
Получение размеров
Для получения размера картинки мы должны открыть ее (создать объект класса Image) и получить атрибут ‘size’. Это можно сделать так:
from PIL import Image image_path = 'F:/hello.png' img = Image.open(image_path) # получаем ширину и высоту width, height = img.size print(width, height) # открываем картинку в окне img.show()
Изменение размера изображения с resize()
Для изменения ширины и высоты есть метод ‘resize’. Этот метод не изменяет текущую картинку, а возвращает новую. Новый размер мы должны указать в виде кортежа ‘(ширина, высота)’. Сохранить картинку можно через метод ‘save’:
from PIL import Image image_path = 'F:/hello.png' img = Image.open(image_path) # изменяем размер new_image = img.resize((200, 385)) new_image.show() # сохранение картинки new_image.save('F:/hello2.png')
На примере выше видно, что картинка меняется не пропорционально. Это можно изменить двумя способами:
Учет соотношения сторон
Что бы создать пропорциональную картинку вам нужно определиться с размером одно из сторон. В примере ниже указана фиксированная ширина, но вы можете немного изменить скрипт и указать высоту. Мы должны вычислить процентное соотношение старой ширины к новой, а затем умножить ее на высоту:
from PIL import Image image_path = 'F:/hello.png' # указываем фиксированный размер стороны fixed_width = 200 img = Image.open(image_path) # получаем процентное соотношение # старой и новой ширины width_percent = (fixed_width / float(img.size[0])) # на основе предыдущего значения # вычисляем новую высоту height_size = int((float(img.size[0]) * float(width_percent))) # меняем размер на полученные значения new_image = img.resize((fixed_width, height_size)) new_image.show() new_image.save('F:/hello2.png')
Создание эскиза thumbnail
Есть еще один способ выполнить предыдущие шаги автоматически — он называется ‘thumbnail’. Его отличие от resize() в том, что он не может увеличить размер изображения. Если с помощью resize() вы можете изменить размер 200х200 на 400х400, то метод thumbnail() оставит исходный.
В методе ‘thumbnail()’ создается кортеж с 2-мя числами: максимальная ширина и высота. Понятие «максимальный» нужно оценивать как значение, которое можно менять в меньшую сторону. Если вы возьмете картинку размером 100х100 и захотите ее уменьшить до 100х50, то Pillow высчитает оптимальны размер как 50х50.
from PIL import Image image_path = 'F:/hello.png' img = Image.open(image_path) # пропорциональное изменение картинки img.thumbnail(size=(350,400)) img.show() img.save('F:/hello3.png')
Обрезание (cropping) картинки
Для обрезания ненужных частей картинки используется метод ‘crop()’. Внутри этого метода помещается кортеж со значениями (отступами) соответствующие сторонам, которые нужно обрезать. Стороны можно определить следующими переменными:
(x1,y1,x2,y2)Оси x1 и y1 находятся в левой верхней части изображения, а оси x2 и y2 в правой нижней. Левая верхняя часть имеет координаты 0 и 0, а правая нижняя соответствует ширине и высоте изображения. Картинка, которую я использовал в предыдущих примерах, имеет размер 401х385. Если распределить все координаты, соответствующие этой картинке, получится следующий результат:
(0,0,401,385)
Представим, что нам нужно обрезать название на картинке — это примерно 60px. Мы должны вычесть (вырезать) это значение из нижнего правого угла (высоты):
from PIL import Image image_path = 'F:/hello.png' img = Image.open(image_path) size = img.size width, height = img.size # обрезаем картинку new_image = img.crop((0,0,width,height-60)) new_image.show() new_image.save('F:/hello3.png')
Если бы мы хотели оставить только название, то нужно было бы изменить значение y1 (2-ой индекс):
(0,height-60,width,height)
Создание границ картинки и ее увеличение за счет новой области
Увеличить размер изображения, не растягивая ее (как делает resize()), можно тремя методами.
Первый, который так же обсуждался в предыдущей части статьи, увеличит изображение без возможности изменения фона (в зависимости от изображения он может быть черным/прозрачным). В примере ниже мы добавим по 50px к каждому углу:
(-50,-50,width+50,height+50)
Второй способ — за счет создания нового изображения и вставки в него старого.
Для создания нового изображения нужно использовать метод ‘Image.new()’. В этом методе мы должны указать тип картинки, ее ширину и высоту, а так же цвет. Что бы вставить изображение — используется метод ‘paste()’. В нем указывается отступ формата ‘(верх, лево)’ либо вы можете использовать координаты аналогичные методу ‘crop()’.
В следующем примере мы создадим изображение, которое будет на 50px больше и вставим в него старую картинку. Картинка будет располагаться в 25px от верхнего и левого края:
from PIL import Image image_path = 'F:/hello.png' old_img = Image.open(image_path) # создание нового изображения new_image = Image.new(old_img.mode, (old_img.size[0]+50, old_img.size[1]+50), 'white') # вставляем старой изображение в новое new_image.paste(old_img, (25, 25)) new_image.show() new_image.save('F:/hello3.png')
Создание границ изображения с ImageOps.expand
Создать границы картинки (расширить) так же можно через метод ImageOps.expand(). Вообще через модуль ‘ImageOps’ можно проделать все шаги описанные выше, но он может не работать с какими-то типами изображений.
В метод ‘expand()’ мы должны передать объект ‘Image’, размер границы и цвет. Пример с результатом аналогичным предыдущему:
from PIL import Image from PIL import ImageOps image_path = 'F:/hello.png' old_img = Image.open(image_path) # создание нового изображения с белым фоном new_image = ImageOps.expand(old_img, border=25, fill=(255,255,255)) new_image.show() new_image.save('F:/hello3.png')Изменение размера изображения в Python
Для начала установим PIL. Обратите внимание, что PIL, больше не поддерживается, вместо него сейчас можно найти «дружеское ответвление» Pillow. Чтобы установить PIL на Debian, выполните следующую команду в терминале от root’a:
aptitude install python-imaging
Я использовал PIL для строгово изменения размера изображения 64х64 для аватаров пользователей.
from PIL import Image
img = Image.open('image.png')
width = 64 height = 64 resized_img = img.resize((width, height), Image.ANTIALIAS)
resized_img.save(image.png)Вот так очень просто мы поменяли размер изображения на 64×64.
Так же мне в дальнейшем мне понадобилось изменять размер изображения с сохранение пропорций. И тут также мне на помощь пришел PIL.
Код для изменения размера изображения с сохранением пропорций:
from PIL import Image
width = 750
img = Image.open('image.jpg')
ratio = (basewidth / float(img.size[0]))
height = int((float(img.size[1]) * float(ratio)))
img = img.resize((basewidth, height), PIL.Image.ANTIALIAS)
img.save('resized_image.jpg')Вот так с помощью PIL мы в несколько строк изменили размер изображения (image.jpg) до ширины в 750 пикселей. Данную ширину мы установили в переменной width. Высота, пропорциональная ширине вычисляется путем определения, соотношения оригинальной ширины изображения (img.size [0]) к величине указанной в переменной width (в нашем случае 300px), а затем умножением этой величины на исходную высоту изображения (img.size [1]). Полученное значение высоты хранится в переменной height.
Итак управляя переменной width, можно получать любые другие размеры итогового изображения. Так же обратите внимание, что я сохранил исходное изображение по именем resized_image.jpg, в случае необходимости его дальнейшего использования. В случае если исходное изображение больше не нужно — можно перезаписать полученное изображение с таким же именем.
Чтобы оставить высоту изображения фиксированной и пропорционально изменять ее ширину, немного изменим код.
height = 300
img = Image.open('image.jpg')
ratio = (baseheight / float(img.size[1]))
width = int((float(img.size[0]) * float(hpercent)))
img = img.resize((width, height), PIL.Image.ANTIALIAS)
img.save('resized_image.jpg')Обратите внимание. Здесь для вычисления соотношения высоты мы обращаемся не к img.size [ 0 ], а к img.size [ 1 ]. Атрибут size является кортежем хранящим ширину в первом элементе [0] и высоту во втором [1].
Вот и все. И это далеко не все возможности PIL. В дальнейшем я расскажу о других полезных возможностях этой замечательной либы. Эти посты можно найти под тэгом PIL
Как сжать изображение в Python
Сегодня мы поговорим про то, как сжать изображение в Python. Вы узнаете, как уменьшить размер файла, сжимая и изменяя размер изображения с помощью библиотеки Pillow.
Сжатие изображения — это процесс уменьшения веса картинки без ухудшения ее качества. Есть много онлайн-инструментов, которые предлагают эту услугу. Большинство из них являются отличным вариантом, если вы хотите быстро и надежно уменьшить вес изображения. Но не всегда это лучшее решение. Поэтому в этой статье мы расскажем, как уменьшать размер файла изображения в Python с помощью библиотеки Pillow.
Кроме того, вы можете свободно использовать код из этого руководства. Например, вы можете создать вокруг него API для пакетного уменьшения размеров изображений вместо использования стороннего API, который будет стоить вам денег.
Мы сделали код для данного урока максимально гибким. Вы можете сжать изображение и изменить его размер с коэффициентом масштабирования или точной шириной и высотой. Более того, вы также можете указать желаемое качество.
Начало работы
Приступим! Для начала нужно установить библиотеку Pillow:
$ pip install Pillow
Теперь откройте новый файл Python и импортируйте нашу библиотеку следующим образом:
import os from PIL import Image
Прежде чем углубиться в сжатие изображений, давайте напишем функцию для получения размера файла в удобном для нас формате:
def get_size_format(b, factor=1024, suffix="B"): """ Scale bytes to its proper byte format e.g: 1253656 => '1.20MB' 1253656678 => '1.17GB' """ for unit in ["", "K", "M", "G", "T", "P", "E", "Z"]: if b < factor: return f"" b /= factor return f"Y"
А теперь создадим нашу основную функцию для сжатия изображений. Выглядеть она будет следующим образом:
def compress_img(image_name, new_size_ratio=0.9, quality=90, width=None, height=None, to_jpg=True): # load the image to memory img = Image.open(image_name) # print the original image shape print("[*] Image shape:", img.size) # get the original image size in bytes image_size = os.path.getsize(image_name) # print the size before compression/resizing print("[*] Size before compression:", get_size_format(image_size)) if new_size_ratio < 1.0: # if resizing ratio is below 1.0, then multiply width & height with this ratio to reduce image size img = img.resize((int(img.size[0] * new_size_ratio), int(img.size[1] * new_size_ratio)), Image.ANTIALIAS) # print new image shape print("[+] New Image shape:", img.size) elif width and height: # if width and height are set, resize with them instead img = img.resize((width, height), Image.ANTIALIAS) # print new image shape print("[+] New Image shape:", img.size) # split the filename and extension filename, ext = os.path.splitext(image_name) # make new filename appending _compressed to the original file name if to_jpg: # change the extension to JPEG new_filename = f"_compressed.jpg" else: # retain the same extension of the original image new_filename = f"_compressed" try: # save the image with the corresponding quality and optimize set to True img.save(new_filename, quality=quality, optimize=True) except OSError: # convert the image to RGB mode first img = img.convert("RGB") # save the image with the corresponding quality and optimize set to True img.save(new_filename, quality=quality, optimize=True) print("[+] New file saved:", new_filename) # get the new image size in bytes new_image_size = os.path.getsize(new_filename) # print the new size in a good format print("[+] Size after compression:", get_size_format(new_image_size)) # calculate the saving bytes saving_diff = new_image_size - image_size # print the saving percentage print(f"[+] Image size change: % of the original image size.")Какая-то гигантская функция, которая делает много всего. Жуть, не правда ли? Но не переживайте. Сейчас мы рассмотрим ее подробнее и всё станет понятно.
- Мы используем метод Image.open() для загрузки изображения в память. Далее мы получаем размер файла изображения с помощью функции os.path.getsize() . Мы делаем это для того, чтобы позже иметь возможность сравнить этот размер с размером нового сгенерированного файла.
- Если значение new_size_ratio меньше 1.0 , то необходимо изменить размер. Это число находится в диапазоне от 0 до 1 и умножается на ширину и высоту исходного изображения, чтобы получить изображение с более низким разрешением. Это подходящий параметр, если вы хотите еще больше уменьшить размер изображения. Вы также можете установить его на 0,95 или 0,9, чтобы уменьшить размер изображения с минимальными изменениями разрешения.
- Если значение new_size_ratio равно 1.0 , но заданы ширина и высота, мы изменяем размер до этих новых значений ширины и высоты. Убедитесь, что они меньше исходной ширины и высоты!
- Если для to_jpg установлено значение True , мы меняем расширение исходного изображения на JPEG. Это значительно уменьшит размер изображения, особенно для изображений PNG. Если возникнет ошибка OSError , преобразование формата изображения в RGB решит данную проблему.
- И наконец, мы используем метод save() для записи оптимизированного изображения. Мы передаем в качестве параметров имя нового файла, желаемое качество и optimize со значением True . После этого мы получаем размер нового изображения. Его мы сравниваем с размером исходного изображения, который получили в самом начале.
Сжатие изображений на примерах
Теперь, когда у нас есть основная функция, давайте воспользуемся модулем argparse , чтобы интегрировать ее с аргументами командной строки. Сделаем это следующим образом:
if __name__ == "__main__": import argparse parser = argparse.ArgumentParser(description="Simple Python script for compressing and resizing images") parser.add_argument("image", help="Target image to compress and/or resize") parser.add_argument("-j", "--to-jpg", action="store_true", help="Whether to convert the image to the JPEG format") parser.add_argument("-q", "--quality", type=int, help="Quality ranging from a minimum of 0 (worst) to a maximum of 95 (best). Default is 90", default=90) parser.add_argument("-r", "--resize-ratio", type=float, help="Resizing ratio from 0 to 1, setting to 0.5 will multiply width & height of the image by 0.5. Default is 1.0", default=1.0) parser.add_argument("-w", "--width", type=int, help="The new width image, make sure to set it with the `height` parameter") parser.add_argument("-hh", "--height", type=int, help="The new height for the image, make sure to set it with the `width` parameter") args = parser.parse_args() # print the passed arguments print("="*50) print("[*] Image:", args.image) print("[*] To JPEG:", args.to_jpg) print("[*] Quality:", args.quality) print("[*] Resizing ratio:", args.resize_ratio) if args.width and args.height: print("[*] Width:", args.width) print("[*] Height:", args.height) print(" https://github.com/x4nth055/pythoncode-tutorials/blob/master/python-for-multimedia/compress-image/sample-satellite-images.png" target="_blank" rel="noreferrer noopener">этой ссылке.Для начала применим наш скрипт без каких-либо параметров. Это будет выглядеть так:
$ python compress_image.py sample-satellite-images.pngИ вот какой результат мы получим:
================================================== [*] Image: sample-satellite-images.png [*] To JPEG: False [*] Quality: 90 [*] Resizing ratio: 1.0 ================================================== [*] Image shape: (953, 496) [*] Size before compression: 425.65KB [+] New file saved: sample-satellite-images_compressed.png [+] Size after compression: 379.25KB [+] Image size change: -10.90% of the original image size.
Вес изображения уменьшен с 425,65 КБ до 379,25 КБ. Это примерно 11%. Не много, но всё-таки. Далее попробуем передать -j для преобразования нашего изображения из формата PNG в JPEG:
$ python compress_image.py sample-satellite-images.png -j
Запустим наш код и получим следующий результат:
================================================== [*] Image: sample-satellite-images.png [*] To JPEG: True [*] Quality: 90 [*] Resizing ratio: 1.0 ================================================== [*] Image shape: (953, 496) [*] Size before compression: 425.65KB [+] New file saved: sample-satellite-images_compressed.jpg [+] Size after compression: 100.07KB [+] Image size change: -76.49% of the original image size.
Примечание. Получить образец данного изображения вы можете здесь.
Это просто фантастика! Как мы видим, вес уменьшился на 76,5%! Теперь немного уменьшим качество с помощью такой команды:
$ python compress_image.py sample-satellite-images.png -j -q 75
И получим следующий вывод:
================================================== [*] Image: sample-satellite-images.png [*] To JPEG: True [*] Quality: 75 [*] Resizing ratio: 1.0 ================================================== [*] Image shape: (953, 496) [*] Size before compression: 425.65KB [+] New file saved: sample-satellite-images_compressed.jpg [+] Size after compression: 64.95KB [+] Image size change: -84.74% of the original image size.
Около 85% уменьшения файла без изменения исходного разрешения изображения! Впечатляет, не правда ли? Что ж, давайте попробуем умножить ширину и высоту изображения на 0,9:
$ python compress_image.py sample-satellite-images.png -j -q 75 -r 0.9
И вот что у нас получится:
================================================== [*] Image: sample-satellite-images.png [*] To JPEG: True [*] Quality: 75 [*] Resizing ratio: 0.9 ================================================== [*] Image shape: (953, 496) [*] Size before compression: 425.65KB [+] New Image shape: (857, 446) [+] New file saved: sample-satellite-images_compressed.jpg [+] Size after compression: 56.94KB [+] Image size change: -86.62% of the original image size.
Теперь последний штрих. Давайте установим точные значения ширины и высоты:
$ python compress_image.py sample-satellite-images.png -j -q 75 -w 800 -hh 400
Запустим и получим такой результат:
================================================== [*] Image: sample-satellite-images.png [*] To JPEG: True [*] Quality: 75 [*] Resizing ratio: 1.0 [*] Width: 800 [*] Height: 400 ================================================== [*] Image shape: (953, 496) [*] Size before compression: 425.65KB [+] New Image shape: (800, 400) [+] New file saved: sample-satellite-images_compressed.jpg [+] Size after compression: 49.73KB [+] Image size change: -88.32% of the original image size.
Потрясающе! Размер изображения уменьшился на 88%! Это прекрасный результат!
Заключение
Итак, теперь вы знаете, как сжать изображение в Python! Мы рассмотрели примеры и смогли уменьшить вес картинки на 88% без ухудшения разрешения. Невероятно! Что ж, теперь вы можете попробовать настроить параметры в соответствии с вашими потребностями.
Мы надеемся, что эта статья была для вас полезна, а данный скрипт будет удобным в использовании и поможет вам в ваших дальнейших проектах!
Полную версию кода можно получить по следующей ссылке.
Сжать изображения в Python

Сжатие изображений — широко используемый метод, позволяющий уменьшить размер файлов изображений при сохранении их визуального качества. Удаляя избыточные или ненужные данные, методы сжатия изображений позволяют ускорить загрузку, снизить требования к хранилищу и улучшить использование полосы пропускания. При программной обработке изображений часто возникает необходимость уменьшить их размеры. Итак, в этой статье вы узнаете, как легко сжимать изображения в приложении Python.
- Библиотека сжатия изображений Python
- Сжать изображения в Python
- Онлайн-инструмент для сжатия изображений
Библиотека сжатия изображений Python#
Для сжатия изображений в Python мы будем использовать Aspose.Imaging for Python. Это мощная библиотека обработки изображений, предлагающая ряд функций для обработки изображений и управления ими из ваших приложений Python. Вы можете либо скачать библиотеку, либо установить ее с помощью следующей команды.
> pip install aspose-imaging-python-netСжать изображение в Python#
Чтобы сжать изображение, вы можете установить значение уровня сжатия от 0 до 9. Значение 9 представляет максимальное сжатие, а 0 — режим сохранения. Ниже приведены шаги для сжатия изображения PNG в Python.
- Сначала загрузите изображение с помощью класса Image.
- Затем создайте объект класса PngOptions.
- После этого установите уровень сжатия с помощью свойства PngOptions.compressionlevel.
- Наконец, сохраните сжатое изображение с помощью метода Image.save(String, PngOptions).
В следующем примере кода показано, как сжать изображение в Python.
from aspose.imaging.fileformats.png import PngColorType from aspose.imaging.imageoptions import PngOptions from aspose.imaging import ColorPaletteHelper, Image import os if 'TEMPLATE_DIR' in os.environ: templates_folder = os.environ['TEMPLATE_DIR'] else: templates_folder = r"C:\Users\USER\Downloads\templates" delete_output = 'SAVE_OUTPUT' not in os.environ def compress_png(): # Пути входных и выходных файлов input_file = os.path.join(templates_folder, "template.png") output_file = os.path.join(templates_folder, "compressed_png.png") # Загрузить изображение with Image.load(input_file) as image: obj_init = PngOptions() # Установить уровень сжатия obj_init.compression_level = 9 obj_init.progressive = True obj_init.color_type = PngColorType.INDEXED_COLOR obj_init.palette = ColorPaletteHelper.get_close_image_palette(image, 1Для сжатия изображений других форматов мы будем использовать соответствующий класс ImageOption. Например, для сжатия изображений JPG мы будем использовать JpegOptions, а для изображений Tiff мы будем использовать TiffOptions .
Получите бесплатную библиотеку сжатия изображений#
Вы можете получить бесплатную временную лицензию и сжимать изображения в своих приложениях Python без каких-либо оценочных ограничений.
Сжать изображения онлайн#
Мы также создали веб-инструмент бесплатный компрессор изображений для сжатия изображений в Интернете. Вы можете использовать этот инструмент для сжатия любого количества изображений без создания учетной записи.
Заключение#
В этой статье вы найдете эффективное решение для сжатия изображений в Python. С помощью шагов и примера кода вы научились легко сжимать изображение. Кроме того, мы представили вам бесплатный онлайн-инструмент для сжатия изображений, основанный на Aspose.Imaging for Python. Вы можете использовать инструмент из любого места без создания учетной записи.
Вы можете узнать больше о нашей библиотеке обработки изображений Python, используя документацию. Кроме того, вы можете поделиться с нами своими отзывами через наш форум.
Смотрите также#
- Объединение нескольких изображений в Python
- Добавить водяной знак к изображениям в Python
- Aspose.Imaging Product Family
- compress images python
- compress jpg python
- compress png python
- compress tiff python
- python image library
- python image processing library
