Сообщить об ошибке.

Добавление картинок в PDF-документ, модуль fpdf2 в Python

Добавление картинок в PDF-документ и их компоновка, обрезка и т.д

Содержание:


Вставка картинки в PDF-документ.

При добавлении изображения в создаваемый PDF-документ, его размер на странице можно указать несколькими способами:

  • явно ширина w и высота h картинки, указываются в единицах, заданных в конструкторе класса FPDF (по умолчанию миллиметры);
  • явно задать величину одной из сторон картинки. В этом случае, другая сторона вычисляется автоматически, чтобы сохранить исходные пропорции;
  • без явного указания величин, и в этом случае изображение будет иметь разрешение 72 dpi.

Обратите внимание, что если изображение отображается несколько раз, то в PDF-файл вставляется только одна копия.

Простой пример вставка картинки:

from fpdf import FPDF

pdf = FPDF()
pdf.add_page()
pdf.image("image/logo.png", x=20, y=60)
pdf.output("pdf-with-image.pdf")

Компоновка нескольких изображений на одном листе PDF-документа.

Модуль fpdf2 может быть простым решением для компоновки нескольких изображений на одном листе PDF-документа.

Следующий код предоставляет пример сборки двух картинок на одну страницу в PDF-файл.

Примечание к коду ниже:

  • атрибут pdf.eph возвращает полную высоту страницы PDF-документа.
  • атрибут pdf.epw возвращает полную ширину страницы PDF-документа.
from fpdf import FPDF

#  в конструкторе, указываем ориентацию страницы
pdf = FPDF(orientation="landscape")
# указываем одинаковый отступ  
pdf.set_margin(0)
# добавляем страницу
pdf.add_page()
# Добавляем imgA.png 
# h=pdf.eph полная высота страницы, 
# w=pdf.epw/2 ширина половины страницы
pdf.image("imgA.png", h=pdf.eph, w=pdf.epw/2)

# установим курсор по оси `y` на 0
pdf.set_y(0)
# Добавляем imgB.png 
# h=pdf.eph - полная высота страницы, 
# w=pdf.epw/2 половина ширины страницы, 
# x=pdf.epw/2 курсор на правой половине страницы
pdf.image("imgB.jpg", h=pdf.eph, w=pdf.epw/2, x=pdf.epw/2)

pdf.output("side-by-side.pdf")

Альтернативное описание картинки в PDF-документ.

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

from fpdf import FPDFАльтернативное описание добавленной картинки в PDF-документ.

pdf = FPDF()
pdf.add_page()
pdf.image("image/logo.png", x=20, y=60, alt_text="Логотип змеи языка Python"))
pdf.output("pdf-with-image.pdf")

Вставка изображения из интернета по URL-адресу.

URL-адреса изображений могут быть напрямую переданы методу FPDF.image():

from fpdf import FPDF

pdf = FPDF()
pdf.add_page()
img_url = "https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png"
pdf.image(img_url, w=40, x=15, y=15, alt_text="Логотип")
pdf.output("pdf-with-image.pdf")

Как повернуть вставленные картинки?

from fpdf import FPDF

pdf = FPDF()
pdf.add_page()
img_url = "https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png"
x=15
y=50
with pdf.rotation(angle=45, x=x, y=y):
    pdf.image(img_url, w=40, x=x, y=y, alt_text="Логотип")
pdf.output("pdf-with-image.pdf")

FPDF.rotation(angle, x=None, y=None):

Метод FPDF.rotation() позволяет выполнять вращение вокруг заданного центра. Он должен использоваться в качестве контекстного менеджера:

with pdf.rotation(angle=90, x=x, y=y):
    pdf.something()

Поворот влияет на все элементы, которые выводятся в PDF-документ внутри контекста with (за исключением кликабельных областей).

Аргументы:

  • angle: float, угол поворота в градусах;
  • x: float, абсцисса центра вращенияж
  • y: float, ордината центра вращения.

Примечание:

Меняется только рендеринг. Методы FPDF.get_x() и FPDF.get_y() не затрагиваются, как и механизм автоматического разрыва страницы. Вращение также устанавливает локальное состояние графики, так что любые настройки состояния графики, измененные внутри, не повлияют на операции, вызываемые после его завершения.

Отключение прозрачности в добавляемых PNG картинках.

По умолчанию прозрачность изображений сохраняется: альфа-каналы извлекаются и конвертируются во встроенный SMask. Это можно отключить, установив атрибут FPDF.allow_images_transparency = False, например чтобы обеспечить соответствие PDF/A-1:

from fpdf import FPDF

pdf = FPDF()
# директория где лежат системные шрифты OS Linux
font_dir = '/usr/share/fonts/truetype/freefont'
# добавляем TTF-шрифты, поддерживающие кириллицу.
pdf.add_font("Serif", style="", fname=f"{font_dir}/FreeSerif.ttf", uni=True)
pdf.add_page()
# Установка шрифта по умолчанию
pdf.set_font("Serif", size=11)
# печатаем текст
pdf.cell(w=pdf.epw, h=30, txt="Текст сзади. " * 6)
# Отключение прозрачности
pdf.allow_images_transparency = False
# накладываем картинку на текст
img_url = "https://www.python.org/static/img/psf-logo.png"
pdf.image(img_url, w=pdf.epw/2, x=15, y=15, alt_text="Логотип сайта Python")

pdf.output("pdf-with-image.pdf")

Использование модуля Pillow при добавлении картинки.

При установке модуля fpdf2, модуль Pillow устанавливается автоматически, так что дополнительно ставить ничего не надо. С помощью библиотеки Pillow можно выполнять подготовительные манипуляции с изображениями перед добавлением и легко вставлять результат:

from fpdf import FPDF
from PIL import Image

pdf = FPDF()
pdf.add_page()
# открываем изображение при помощи PIL
img = Image.open("img/logo.png")
# манипуляции с изображениями перед добавлением
img = img.crop((10, 10, 490, 490)).resize((96, 96), resample=Image.NEAREST)
# добавляем в PDF-документ
pdf.image(img, x=80, y=100)
pdf.output("pdf-with-image.pdf")

Сжатие вставленных изображений в PDF-документ.

По умолчанию модуль fpdf2 избегает изменения вставленных изображений: преобразование изображений из/в PNG/JPEG не выполняется.

Чтобы уменьшить размер PDF-файла, можно легко указать модулю fpdf2 преобразовывать и вставлять все изображения в форматы JPEG:

from fpdf import FPDF

pdf = FPDF()
pdf.set_image_filter("DCTDecode")
pdf.add_page()
pdf.image("img/logo.png", x=20, y=60)
pdf.output("pdf-with-image.pdf")

Помните, что при "сглаживании" изображений, альфа-каналы преобразуются в черный цвет.

Обнаружение больших изображений и уменьшение их масштаба.

Если вас беспокоит размер полученного PDF-файла, то можно проверить, не являются ли некоторые вставленные изображения слишком большими, что их разрешение неоправданно велико, учитывая размер, в котором они отображаются.

Существует способ включить этот механизм обнаружения в модуле fpdf2:

pdf.oversized_images = "WARN"

После установки этого свойства, будет отображаться предупреждение всякий раз, когда вставляется изображение слишком большого размера.

Модуль fpdf2 также может автоматически уменьшать масштаб таких изображений:

pdf.oversized_images = "DOWNSCALE"

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

OVERSIZED: Generated new low-res image with name=lowres-test.png dims=(319, 451) id=2

Для более точного управления можно установить атрибут pdf.oversized_images_ratio, который определяет порог, при котором изображение считается слишком большим.

Метод FPDF.image() модуля fpdf2.

Синтаксис:

FPDF.image(name, x=None, y=None, 
           w=0, h=0, link='', 
           title=None, alt_text=None)

Справочные сведения по методу FPDF.image().

Метод FPDF.image() вставляет изображение на страницу создаваемого PDF-документа, при этом указатель/курсор переносится на следующую строку под картинкой.

Размер изображения на странице можно указать по-разному:

  • явно ширина w и высота h картинки, указываются в единицах, заданных в конструкторе класса FPDF (по умолчанию миллиметры);
  • явно задать величину одной из сторон картинки. В этом случае, другая сторона вычисляется автоматически, чтобы сохранить исходные пропорции;
  • без явного указания величин, и в этом случае изображение будет иметь размеры при разрешении 72 dpi.

Примечания:

  • если изображение используется несколько раз, в файл вставляется только одна копия.
  • при использовании анимированного GIF используется только первый кадр.

Принимаемые аргументы:

  • name: это либо строка, представляющая путь к файлу изображения, или URL-адрес изображения, или io.BytesIO или экземпляр PIL.Image.Image;
  • x=None: необязательное положение вставляемого изображения на листе по горизонтали. Если не указано или равно None, то используется текущая абсцисса (положение курсора);
  • y=None: необязательное положение вставляемого изображения на листе по вертикали. Если не указано или равно None, то используется текущая абсцисса (положение курсора) После вызова текущая ордината перемещается в нижнюю часть изображения;
  • w=0: необязательная ширина изображения. Если не указана или равна нулю, то автоматически рассчитывается по размеру изображения. При передаче pdf.epw масштабирует изображение по горизонтали до полной ширины листа;
  • h=0: необязательная высота изображения. Если не указана или равна нулю, то автоматически рассчитывается по размеру изображения. При передаче pdf.eph масштабирует изображение по вертикали до полной высоты листа;
  • link='': необязательная ссылка для добавления к изображению, может быть внутренняя (идентификатор, возвращаемый FPDF.add_link() или внешний URL;
  • title=None: необязательный. В настоящее время, похоже, никогда не отображается PDF-читалками;
  • alt_text=None: необязательный альтернативный текст, описывающий изображение, для удобства. Отображается некоторыми программами чтения PDF-файлов при наведении курсора.