Возникла задача оптимизации места. Да думаю эта задача типична для всех, кто работает с объемами данных, даже не обязательно большими. Все таки 1-5 гигабайт на сервере только для картинок — это уже весомо.
Решил написать простой скрипт для компрессии и желательно без потери качества. Я думал на каком ЯП это сделать. Php — не хотелось. Node.js — прикольно, много на нем написал, но так лень ставить скобочки ). Поэтому я выбрал python. Да и питон стоит почти на всех серверах рядом с php.
Tiny PNG
Уже лет 5ть. когда еще только начинал программировать я активно использовал отличный сервис TinyPng. Каждый раз захожу и это панда поднимает мне настроение 🙂
Скрипт
Для начал заводим виртуальное окружение. Устанавливаем модуль 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