使用画布绘制图像并使用SimpleDocTemplate

slo*_*thy 6 python django reportlab

我正在使用reportlab在django视图中编写pdf,它们非常简单,标题,内容和页脚.

我正在使用非常适合的SimpleDocTemplate,在内容中绘制表格,页脚和标题是drwan使用:

build([data], onFirstPage=drawPageFrame, onLaterPages=drawPageFrame).
Run Code Online (Sandbox Code Playgroud)

我的问题是,如何使用Canvas.drawImage(...)绘制图像?我需要一个"浮动"图像...位于我想要的文本上,而使用SimpleDocTemplate我没有Canvas对象来执行此操作.

搜索我发现了这个:

鸭嘴兽布局的东西使用flowables.当包装,拆分或绘制时,包装工通常将属性canv设置到每个flowable上,即围绕wrap,split和draw方法.在这些方法中,您可以使用self的canv属性访问画布.

怎么用这个?

嗯,更多要测试的东西:

flowables.Macro
flowables.CallerMacro
Run Code Online (Sandbox Code Playgroud)
# -*- coding: utf-8 -*-
from reportlab.lib.pagesizes import A4, landscape, portrait
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import Table, Flowable, SimpleDocTemplate, Paragraph, Spacer, Image
from reportlab.lib import randomtext
from reportlab import platypus

import os,random

styles = getSampleStyleSheet()
path = os.path.realpath(os.path.dirname(__file__))

def drawPageFrame(canvas, doc):
    canvas.saveState()
    canvas.drawImage(path+"/ujiPDF.jpg",50,50,57,57)
    canvas.restoreState()

doc = SimpleDocTemplate("salida.pdf",pagesize=A4)

elementos = []

com = 'canvas.drawImage("'+path+'/ujiPDF.jpg",100,100,57,57)'
print com
elementos.append(platypus.flowables.Macro('canvas.saveState()'))
print platypus.flowables.Macro(com)
elementos.append(platypus.flowables.Macro(com))
elementos.append(platypus.flowables.Macro('canvas.restoreState()'))

para = Paragraph(randomtext.randomText(randomtext.PYTHON,20), styles["Normal"])
elementos.append(para)

doc.build(elementos,onFirstPage=drawPageFrame, onLaterPages=drawPageFrame)

这是宏方法...干净退出但没有第二个图像.

cyb*_*olt 6

鸭嘴兽中有Image类。只要使用from reportlab.platypus import Image ,你就可以访问这个类。它像内部的其他类一样工作,smth.append(Image(filename))并将图像附加到您需要构建到 pdf 的对象上。创立于Tyler Lessman 个人网站


Eze*_*ick 6

如果我理解正确的话,您不需要将整个文档模板作为子类,您只需要一个可以放入INTO SimpleDocTemplate的可流动对象即可。您可以使用Flowable本身的非常简单的子类来实现这一点。

->特别是由于人们经常询问如何将matplotlib对象放入reportlab,因此我将展示如何使用matplotlib生成图,然后使用修改后的flowable将该图放入SimpleDocTemplate(而不将文件保存到磁盘)。该概念适用于任何文件或可以馈入cStringIO的任何内容

->在下面的DOES中,您可以将图形放在文本上方(将高度从负值更改为正值,以将其推到绘图所在部分顶部的假想线上方)

关键概念是每个Flowable本身都包含我们可以在其上绘制的画布。

import matplotlib.pyplot as plt
import cStringIO
from reportlab.lib.units import inch, cm
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image, Table
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
import reportlab.lib, reportlab.platypus

class flowable_fig(reportlab.platypus.Flowable):
    def __init__(self, imgdata):
        reportlab.platypus.Flowable.__init__(self)
        self.img = reportlab.lib.utils.ImageReader(imgdata)

    def draw(self):
        self.canv.drawImage(self.img, 0, 0, height = -2*inch, width=4*inch)
        # http://www.reportlab.com/apis/reportlab/2.4/pdfgen.html
                            
doc = SimpleDocTemplate(("report.pdf"),pagesize=letter,
                    rightMargin=72,leftMargin=72,
                    topMargin=72,bottomMargin=18)
Story=[]
styles=getSampleStyleSheet()
ptext = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi massa dolor, vulputate quis elit sed, sagittis consectetur erat. Sed lobortis nisi eros, eu maximus enim iaculis ac. Vestibulum sagittis urna nec interdum aliquam. Pellentesque ornare velit ut ante ullamcorper, vulputate accumsan nisi vulputate. Fusce consectetur dolor quam. Phasellus hendrerit, ligula vel consectetur pretium, lorem neque dapibus eros, ornare suscipit ipsum dolor id nisl. Sed vel orci id leo efficitur lobortis sit amet id risus. Nullam euismod, ipsum a posuere scelerisque, ante lorem ultrices nibh, ut feugiat metus ex congue enim. Nam lobortis, metus id pellentesque feugiat, arcu orci rutrum felis, quis luctus urna nisl at nulla. Donec eu eros pharetra dolor congue facilisis at ac magna. Nullam eu ultricies metus. Sed sodales, libero viverra pellentesque tempus, magna purus convallis nibh, eu condimentum tortor erat tincidunt turpis. Vestibulum scelerisque tincidunt egestas. Nullam commodo diam nisl, sed consequat ex sagittis eu.'
Story.append(Paragraph(ptext, styles["Normal"]))

fig = plt.figure(figsize=(10, 3))
plt.plot([1,2,3,4])
plt.ylabel('This is a boring plot')
imgdata = cStringIO.StringIO()
fig.savefig(imgdata, format='png')
imgdata.seek(0)  # rewind the data

pic = flowable_fig(imgdata)
Story.append(pic)
doc.build(Story)
Run Code Online (Sandbox Code Playgroud)

您可以扩展此最小化的代码片段,以完成所需的操作,还可以向Story变量中添加尽可能多的片段(实际上这只是可流动对象的列表)。神奇之处在于,我们正在为文档构建器提供一个Flowable,该Flowable使用Flowable自己的画布绘制图形。

编辑:我几乎忘记了,因为这给了我们对drawImage的完全访问权限,我们还可以使图片或绘图具有透明度,以便可以通过它看到其他事物。drawImage上的文档具有详细信息。

  • 我还必须使用`from io import BytesIO` (2认同)

G G*_*III 3

最好的选择是创建 SimpleDocTemplate 或 BaseDocTemplate 的子类。在构建方法中,您将可以访问画布。如果您想利用 SimpleDocTemplate 所做的一切,您可以尝试直接从site-packages/reportlab/platypus/doctemplate.py.