Python сжатие изображения через TinyPng. Сэкономьте гигабайты места на сервере (python tiny png compressing)

304
0
304

Возникла задача оптимизации места. Да думаю эта задача типична для всех, кто работает с объемами данных, даже не обязательно большими. Все таки 1-5 гигабайт на сервере только для картинок — это уже весомо.

Решил написать простой скрипт для компрессии и желательно без потери качества. Я думал на каком ЯП это сделать. Php — не хотелось. Node.js — прикольно, много на нем написал, но так лень ставить скобочки ). Поэтому я выбрал python. Да и питон стоит почти на всех серверах рядом с php.

Tiny PNG

Уже лет 5ть. когда еще только начинал программировать я активно использовал отличный сервис TinyPng. Каждый раз захожу и это панда поднимает мне настроение 🙂

У них все понятно и отличная документация дл разных языков.
Для начала надо зарегистрироваться и получить API ключ. Это делается просто и понятно

Скрипт

Для начал заводим виртуальное окружение. Устанавливаем модуль tiny png для python

pip install --upgrade tinify

Я сразу вставлю весь скрипт с понятными комментариями. Я лишь объясню порядок. Сначала естественно ипортируем необходимы библиотеки. Все стандартные для питона 3ей версии.
Дале проставляем переменны api ключа, целевую директорию, и размер картинки начиная с которого производить компрессию.

Есть функции:

tinify_img() — сжатие с помощью библиотеки TinyPng
copy_and_overwrite() — копирования директории для того, чтобы при записи не было ошибок, на директорию которой не существует. Так же это будет удобно посмотреть результат а потом, просто скопировать результат заменив все исходные данные.

И собственно сам цикл рекурсивного перебора папки. Проверяем на то, чтобы были файлы, чтобы они были именно формата картинок и соответственно делаем проверку на установленный лимит картинки.

import tinify
# from os import walk
import os
import imghdr
import shutil
from pathlib import Path

# TinyPNG apikey
tinify.key = "YOU_API_KEY"
# targetdir
root_dir = 'test_folder'
# the maximum size(in bytes) of the image the ones above are compressed
img_size_limit = 1000000  

# tynyfy by tinypng
def tinyfy_img(path):
    source = tinify.from_file(path)
    source.to_file("./tinyfied/" + path)
    print("tiny to " + "./tinyfied/" + path)

# copy dir
def copy_and_overwrite(from_path, to_path):
    if os.path.exists(to_path):
        shutil.rmtree(to_path)
    shutil.copytree(from_path, to_path)
    print(f"dir {from_path} copied to {to_path}")

print("======== PATH RECOURSIVE ==========")

# copy root dir
copy_and_overwrite(root_dir, './tinyfied/' + root_dir)

paths = Path(root_dir).glob('**/*')
for path in paths:
    # because path is object not string
    path_in_str = str(path)
    if os.path.isfile(path):
        file_image_type = imghdr.what(path_in_str)
        if file_image_type != None:
            if (os.path.getsize(path_in_str) > img_size_limit ):
                print(path_in_str)
                tinyfy_img(path_in_str)
                print("============")

print("Tinyfied done ???!")

На этом собственно все. Надеюсь гайд был полезен ☺️.
Ссылка на гитхаб https://github.com/alexTitakoff/tinyfy-py

0