12

是否可以使用ReportLab (python)在 PDF 中创建渐变填充?

4

3 回答 3

7

ReportLab 现在支持 PDF 渐变。

2012 年 8 月 6 日,Peter Johnson将一个梯度支持补丁发布到 ReportLab 邮件列表,并在第二天添加到源中。我无法在ReportLab 2.6 的发行说明中发现任何内容,但自从 2012 年 10 月 1 日发布以来,它大概就在那里。它肯定存在于 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()

这将输出六个页面,其中包含各种渐变以及渐变方法调用和显示端点和停止位置的线条/圆圈:

在页面上延伸的基本线性渐变 限制在端点内的线性梯度 具有多个停靠点的线性渐变 在页面上延伸的基本径向渐变 径向梯度限制在半径内 具有多个停靠点的径向渐变

于 2013-04-13T13:43:04.843 回答
3

[我的答案不再正确,Reportlab 中现在可以使用渐变,有关详细信息,请参阅此页面上的其他答案。]

很抱歉重新提出这个问题,但我偶然发现它并没有得到正确的回答。

答案是否定的,截至今天,当前版本的 ReportLab 不支持渐变。然而,PDF 支持渐变。如果您查看 ReportLab 的 Canvas 类,您会发现它的许多方法都是围绕底层 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。但是,它缺少 reportlabs 更高级别的结构(例如页面布局)。

于 2010-05-09T21:21:49.817 回答
2

您想用渐变而不是纯色填充矩形(或其他路径)?

没问题。使用剪辑将渐变绑定/限制到路径。请记住在设置渐变之前设置剪辑路径。(并将其包裹在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

于 2013-12-12T14:58:32.143 回答