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

时间:2021-08-06 09:46:50

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

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

3 个解决方案

#1


ReportLab now supports PDF gradients.

ReportLab现在支持PDF渐变。

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.

2012年8月6日,Peter Johnson在ReportLab邮件列表中发布了梯度支持补丁,并在第二天添加到源代码中。我无法在ReportLab 2.6的发行说明中发现任何内容,但自从2012年10月1日发布以来,它可能就在那里。它绝对存在于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:

可以指定具有多个停止的线性和径向渐变。在文档中搜索术语渐变并没有出现任何问题。但是,带有第一个版本补丁的消息有几个例子,它们是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()

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

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

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

#2


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

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

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.

答案是否定的,截至今天,当前版本的ReportLab不支持渐变。但是,PDF支持渐变。如果你查看ReportLab的Canvas类,你会发现它的许多方法都是基础PDF代码生成的相对较小的包装器。要访问RL中的渐变,您需要扩展Canvas类并添加其他方法以生成正确的PDF代码。这是可行的,但显然不是微不足道的,这意味着你必须阅读PDF规范。

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.

例如。不幸的是,使渐变平滑需要很多矩形,这可能会导致PDF变大并且渲染速度很慢。使用光栅方法你会更好。

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.

最后,您可以考虑使用PyCairo。这样可以更好地支持大量图形元素,并可以渲染为PDF或PNG。然而,它缺乏reportlabs更高的杠杆结构(例如页面布局)。

#3


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

没问题。使用裁剪将渐变限制/限制为路径。只需记住在设置渐变之前设置剪辑路径。 (并将其包装在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))

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

对于径向渐变,将extend关键字参数设置为False可能就足够了。

#1


ReportLab now supports PDF gradients.

ReportLab现在支持PDF渐变。

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.

2012年8月6日,Peter Johnson在ReportLab邮件列表中发布了梯度支持补丁,并在第二天添加到源代码中。我无法在ReportLab 2.6的发行说明中发现任何内容,但自从2012年10月1日发布以来,它可能就在那里。它绝对存在于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:

可以指定具有多个停止的线性和径向渐变。在文档中搜索术语渐变并没有出现任何问题。但是,带有第一个版本补丁的消息有几个例子,它们是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()

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

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

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

#2


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

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

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.

答案是否定的,截至今天,当前版本的ReportLab不支持渐变。但是,PDF支持渐变。如果你查看ReportLab的Canvas类,你会发现它的许多方法都是基础PDF代码生成的相对较小的包装器。要访问RL中的渐变,您需要扩展Canvas类并添加其他方法以生成正确的PDF代码。这是可行的,但显然不是微不足道的,这意味着你必须阅读PDF规范。

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.

例如。不幸的是,使渐变平滑需要很多矩形,这可能会导致PDF变大并且渲染速度很慢。使用光栅方法你会更好。

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.

最后,您可以考虑使用PyCairo。这样可以更好地支持大量图形元素,并可以渲染为PDF或PNG。然而,它缺乏reportlabs更高的杠杆结构(例如页面布局)。

#3


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

没问题。使用裁剪将渐变限制/限制为路径。只需记住在设置渐变之前设置剪辑路径。 (并将其包装在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))

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

对于径向渐变,将extend关键字参数设置为False可能就足够了。