2025, Nov 01 06:17
Как правильно масштабировать логотип PNG в ReportLab для PDF
Почему PNG‑логотип в ReportLab выходит полноразмерным и как это исправить: задайте width и height в drawImage для точного масштабирования на страницах PDF.
Добавлять небольшой логотип или шеврон на каждую страницу PDF — обычная практика при генерации отчётов. Трудности начинаются, когда исходный PNG имеет большой размер, а наивная попытка изменить масштаб прямо в вызове отрисовки не срабатывает: вместо уменьшенной версии на каждой странице оказывается полноразмерное изображение.
Пример, показывающий проблему
Ниже видно, как логотип добавляется на каждую страницу, но попытки ограничить его размер не работают. Картинка продолжает выводиться в исходных габаритах.
def paint_sheet(sheet, dossier, pagesize=A4):
pg_no = sheet.getPageNumber()
emblem = Image('/opt/rspro/home/e8409/projects/CRAMM logo.png')
emblem._restrictSize(1 * inch, 2 * inch)
sheet.drawImage(emblem, 0, 0)
sheet.showPage()
from reportlab.platypus import PageTemplate
upright_tpl = PageTemplate(
id='upright',
frames=upright_frame,
onPage=paint_sheet,
pagesize=A4)
from reportlab.platypus import BaseDocTemplate
pdf_doc = BaseDocTemplate(
'report.pdf',
pageTemplates=[
upright_tpl
]
)
Что происходит
Масштаб пытаются задать через ограничение размера, но отрисовка выполняется методом, который это ограничение не наследует. Вызов draw использует исходные размеры изображения, если явно не переданы width и height. В итоге логотип снова и снова появляется в полном размере на каждой странице.
Решение
Укажите целевые размеры прямо в вызове отрисовки. При необходимости сначала прочитайте изображение и посмотрите его габариты, затем передайте нужные значения при выводе — так масштабирование будет таким, как задумано.
from reportlab.lib.utils import ImageReader
def render_stamp(canvas_ctx, doc_ctx, pagesize=A4):
logo_path = '/opt/rspro/home/e8409/projects/CRAMM logo.png'
img_reader = ImageReader(logo_path)
orig_w, orig_h = img_reader.getSize()
target_w = desired_width
target_h = desired_height
canvas_ctx.drawImage(
logo_path,
0,
0,
width=target_w,
height=target_h,
preserveAspectRatio=True
)
Такой подход оставляет работу с изображением в том же месте, где формируется PDF. Дополнительная предварительная обработка PNG не требуется. Из практики ещё одно наблюдение: если вы запускаете код в среде с исполняемыми ячейками, выполнение шагов не по порядку может скрыть эффект ваших правок.
Почему это важно
Стабильное и предсказуемое масштабирование критично при размещении брендинга или любых фиксированных графических элементов на многих страницах. Без явного задания размеров крупный исходник «забьёт» холст, нарушит компоновку и вытеснит контент. Управление габаритами в самом вызове отрисовки гарантирует одинаковый результат на каждой странице отчёта.
Итог
При добавлении повторяющихся изображений в PDF контролируйте масштаб параметрами width и height метода отрисовки и, при необходимости, сохраняйте пропорции. Если нужно узнать исходные размеры, прочитайте изображение, а затем выводите его на каждой странице с явными габаритами. Если результат по‑прежнему выглядит странно, убедитесь, что выполняются нужные участки кода и в правильной последовательности.
Статья основана на вопросе на StackOverflow от vashts85 и ответе от RCDevs Security.