Создание градиентной заливки в файле PDF с использованием reportlab - PullRequest
10 голосов
/ 17 января 2009

Можно ли создать PDF-градиентную заливку с помощью ReportLab (python)?

Ответы [ 3 ]

6 голосов
/ 13 апреля 2013

ReportLab теперь поддерживает PDF-градиенты.

Исправление для поддержки градиента было опубликовано в списке рассылки ReportLab Питером Джонсоном 6 августа 2012 года и было добавлено в источник на следующий день. Я не могу ничего найти в примечаниях к выпуску ReportLab 2.6 , но, поскольку он был выпущен 1 октября 2012 года, вероятно, он там. Это определенно присутствует в 2.7.

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

from reportlab.pdfgen.canvas import Canvas
from reportlab.lib.colors import red, yellow, green
from reportlab.lib.units import mm

c = Canvas("gradient.pdf")

# Linear gradient with the endpoints extending over the page.
c.linearGradient(105*mm, 200*mm, 180*mm, 100*mm, (red, yellow))
c.drawString(5*mm, 290*mm, "c.linearGradient(105*mm, 200*mm, 180*mm, 100*mm, (red, yellow))")
c.line(105*mm, 200*mm, 180*mm, 100*mm)
c.showPage()

# Linear gradient constrained within the endpoints.
c.linearGradient(105*mm, 200*mm, 180*mm, 100*mm, (red, yellow), extend=False)
c.drawString(5*mm, 290*mm, "c.linearGradient(105*mm, 200*mm, 180*mm, 100*mm, (red, yellow), extend=False)")
c.line(105*mm, 200*mm, 180*mm, 100*mm)
c.showPage()

# Linear gradient with multiple stops.
c.linearGradient(105*mm, 200*mm, 180*mm, 100*mm, (red, yellow, green), (0, 0.8, 1), extend=False)
c.drawString(5*mm, 290*mm, "c.linearGradient(105*mm, 200*mm, 180*mm, 100*mm, (red, yellow, green), (0, 0.8, 1), extend=False)")
c.line(105*mm, 200*mm, 180*mm, 100*mm)
c.line(141*mm, 102*mm, 189*mm, 138*mm)
c.showPage()

# Radial gradient with the endpoint extending over the page.
c.radialGradient(105*mm, 200*mm, 60*mm, (red, yellow))
c.drawString(5*mm, 290*mm, "c.radialGradient(105*mm, 200*mm, 60*mm, (red, yellow))")
c.circle(105*mm, 200*mm, 60*mm)
c.showPage()

# Radial gradient constrained within the circle.
c.radialGradient(105*mm, 200*mm, 60*mm, (red, yellow), extend=False)
c.drawString(5*mm, 290*mm, "c.radialGradient(105*mm, 200*mm, 60*mm, (red, yellow), extend=False)")
c.circle(105*mm, 200*mm, 60*mm)
c.showPage()

# Radial gradient with multiple stops.
c.radialGradient(105*mm, 200*mm, 60*mm, (red, yellow, green), (0, 0.8, 1))
c.drawString(5*mm, 290*mm, "c.radialGradient(105*mm, 200*mm, 60*mm, (red, yellow, green), (0, 0.8, 1))")
c.circle(105*mm, 200*mm, 48*mm)
c.circle(105*mm, 200*mm, 60*mm)
c.showPage()

c.save()

Это приводит к выводу шести страниц с различными градиентами, а также вызовом метода градиента и линиями / кругами, показывающими, где находятся конечные точки и остановки:

Basic linear gradient extending over page Linear gradient constrained within endpoints Linear gradient with multiple stops Basic radial gradient extending over page Radial gradient constrained within radius Radial gradient with multiple stops

3 голосов
/ 10 мая 2010

[Мой ответ больше не верен, теперь в Reportlab доступны градиенты, подробности см. В другом ответе на этой странице.]

Извините, что решил этот вопрос, но я наткнулся на него, и на него не было правильного ответа.

Ответ - нет, на сегодняшний день текущая версия ReportLab не поддерживает градиенты. Градиенты поддерживаются PDF, однако. Если вы заглянете в класс Canvas ReportLab, то увидите, что многие из его методов являются относительно небольшими обертками для генерации базового кода PDF. Чтобы получить доступ к градиентам в RL, вам нужно расширить класс Canvas и добавить дополнительные методы для генерации правильного кода PDF. Это выполнимо, но, очевидно, не тривиально, и это означает, что вам придется ознакомиться со спецификацией PDF.

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

start_color = (1,0,0)
end_color = (0,1,0)
for i in range(100):
    p = i * 0.01
    canvas.setFillColorRGB(*[start_color[i]*(1.0-p)+end_color[i]*p for i in range(3)])
    canvas.rect(i, 0, 2, 100)

Например. К сожалению, для получения градиента сглаживания требуется много прямоугольников, и это может привести к тому, что PDF будет большим и медленно рендериться. Вам лучше с растровым подходом.

Наконец, вы можете рассмотреть возможность использования PyCairo. Это имеет лучшую поддержку для множества графических элементов и может отображать в PDF или PNG. Однако в нем отсутствуют элементы отчета с более высокими рычагами (например, макет страницы).

0 голосов
/ 12 декабря 2013

Вы хотите заполнить прямоугольник (или другой путь) градиентом вместо сплошной цвет?

Нет проблем. Используйте отсечение, чтобы связать / ограничить градиент по пути. Просто не забудьте установить путь клипа перед установкой градиента. (И оберните его внутри saveState() / restoreState(), чтобы сбросить клип и градиент после этого.)

c = canvas.Canvas (filename)
#c.translate (8*cm, 8*cm)  # use this to move the rectangle
p = c.beginPath()
p.rect (0,0 , 5*cm,5*cm)
c.clipPath (p, stroke=0)
c.linearGradient (0,0 , 5*cm, 5*cm , (red, yellow))

Для радиальных градиентов может быть достаточно установить для параметра ключевого слова extend значение False.

...