使用reportlab在PDF文件中创建渐变填充

发布于 2024-07-12 03:55:12 字数 104 浏览 12 评论 0原文

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

Is it possible to create a gradient fill in a PDF using ReportLab (python)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

天气好吗我好吗 2024-07-19 03:55:12

ReportLab 现在支持 PDF 渐变。

渐变支持补丁已发布到 ReportLab 邮件列表 由 Peter Johnson 于 2012 年 8 月 6 日发布,并于第二天添加到源。 我在 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()

这输出了具有各种渐变的六个页面,加上渐变方法调用和显示端点和停止位置的线/圆:

基本线性渐变延伸到页面
端点内约束的线性渐变
具有多个停止点的线性渐变
基本径向渐变延伸到页面
径向渐变限制在半径内
具有多个停止点的径向渐变

ReportLab now supports PDF gradients.

A patch for gradient support was posted to the ReportLab mailing list by Peter Johnson on 6 August 2012 and was added to the source the next day. I cannot spot anything in the release notes for ReportLab 2.6 but since that was released on the 1st of October 2012 presumably it is in there. It is definitely present in 2.7.

Both linear and radial gradients with multiple stops can be specified. Searching the documentation for the term gradient doesn't turn up anything. However, the message with the first version of the patch has a couple of examples which are the basis of some tests in the ReportLab source. Based on this I've worked up a quick demo script:

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()

This outputs six pages with various gradients plus the gradient method call and lines/circles showing where the endpoints and stops are:

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

后eg是否自 2024-07-19 03:55:12

[我的答案不再正确,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 更高水平的结构(例如页面布局)。

[My answer is no longer correct, gradients are now available in Reportlab, see the other answer on this page for details.]

Sorry to ressurect this question, but I stumbled across it and it hadn't been correctly answered.

The answer is no, as of today, the current version of ReportLab does not support gradients. Gradients are supported by PDF, however. If you look in ReportLab's Canvas class you'll see that many of its methods are relatively small wrappers around the underlying PDF code generation. To access gradients in RL you'd need to extend the Canvas class and add additional methods to generate the correct PDF code. This is doable, but obviously not trivial, and it means you'd have to read up on the PDF spec.

There are two alternatives. Firstly generate the gradient as a raster image and use that, secondly generate the gradient by drawing a whole series of rectangles in different colors.

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)

For example. Unfortunately getting the gradient smooth takes a lot of rectangles, and this can cause the PDF to be large and render slowly. You're better off with the raster approach.

Finally, you might consider using PyCairo. This has better support for lots of graphical elements, and can render to a PDF or PNG. It lacks reportlabs higher lever constructs (such as page layout), however.

还在原地等你 2024-07-19 03:55:12

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

没问题。 使用裁剪将渐变绑定/限制为路径。 只需记住在设置渐变之前设置剪辑路径即可。 (并将其包装在 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< /code> 关键字参数为 False

You want to fill a rectangle (or other path) with a gradient instead of
a solid color?

No problem. Use clipping to bound/limit the gradient to a path. Just remember to set the clip path before setting the gradient. (And wrap it inside saveState()/restoreState() to reset the clip and gradient afterwards.)

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))

For radial gradients it might be enough to set the extend keyword parameter to False.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文