Практический Python-инструмент из личной библиотеки решений. Используется для быстрой сборки одного PDF-файла из набора изображений без создания дополнительных папок и промежуточной структуры.
Обновление от 18.02.2026
pypdf для стабильной записи Author, Subject, KeywordsПредыдущая версия корректно записывала только Title. В обновлении устранено ограничение Pillow и реализована полноценная запись свойств документа.
1. Скрипт помещается в папку с изображениями.
2. Выполняется команда python images_to_pdf.py.
3. В этой же папке автоматически создаётся PDF-файл.
Решение применяется для документооборота, архивирования сканов, подготовки отчётов и систематизации материалов.
Любая_папка/
│
├─ 001.jpg
├─ 002.jpg
├─ 003.png
├─ images_to_pdf.py
└─ Любая_папка.pdf # создаётся автоматически
Дополнительные каталоги не требуются.
# ---# coding: utf-8
from pathlib import Path
from PIL import Image
from tqdm import tqdm
from pypdf import PdfReader, PdfWriter
ALLOWED_EXTENSIONS = (".webp", ".jpg", ".jpeg", ".png", ".tif", ".tiff")
JPEG_QUALITY = 65
PDF_RESOLUTION = 300
OPTIMIZE = True
SITE_URL = "https://ipd.by/knowledge/software/photo-to-pdf"
AUTHOR = "Алексей Гапеев"
PRODUCT_NAME = "Photo to PDF v2026"
PDF_METADATA = {
"/Title": "Сканированные документы",
"/Author": AUTHOR,
"/Subject": f"Создано с помощью {PRODUCT_NAME}",
"/Keywords": "photo-to-pdf, ipd.by, скан, архив, документы",
"/Creator": f"{PRODUCT_NAME} | {SITE_URL}",
"/Producer": "ipd.by"
}
def get_sorted_images(folder: Path):
files = [f for f in folder.iterdir() if f.suffix.lower() in ALLOWED_EXTENSIONS]
return sorted(files, key=lambda x: x.name)
def prepare_image(path: Path):
img = Image.open(path)
if img.mode in ("RGBA", "P"):
img = img.convert("RGB")
return img
def write_metadata(pdf_path: Path, metadata: dict):
reader = PdfReader(pdf_path)
writer = PdfWriter()
for page in reader.pages:
writer.add_page(page)
writer.add_metadata(metadata)
with open(pdf_path, "wb") as f:
writer.write(f)
def images_to_pdf():
current_dir = Path(__file__).parent
images_paths = get_sorted_images(current_dir)
if not images_paths:
raise RuntimeError("В текущей папке нет изображений")
images = [prepare_image(path) for path in tqdm(images_paths)]
output_pdf_name = f"{current_dir.name}.pdf"
output_path = current_dir / output_pdf_name
images[0].save(
output_path,
"PDF",
save_all=True,
append_images=images[1:],
resolution=PDF_RESOLUTION,
quality=JPEG_QUALITY,
optimize=OPTIMIZE,
)
write_metadata(output_path, PDF_METADATA)
if __name__ == "__main__":
images_to_pdf()
В архиве — обновлённый скрипт (версия 18.02.2026) и инструкция.
Скачать ZIP-архив