【问题标题】:PDF image in PDF document using ReportLab (Python)使用 ReportLab (Python) 的 PDF 文档中的 PDF 图像
【发布时间】:2011-03-27 18:37:49
【问题描述】:

我将 matplotlib 中的一些绘图保存为 pdf 格式,因为它似乎提供了更好的质量。如何使用 ReportLab 将 PDF 图像包含到 PDF 文档中?便捷方法 Image(filepath) 不适用于这种格式。

谢谢。

【问题讨论】:

    标签: python image pdf reportlab


    【解决方案1】:

    使用 from reportlab.graphics 导入 renderPDF

    【讨论】:

    • 这是不正确的。 renderPDF 获取现有文档并生成 PDF。与海报想要的完全相反。
    【解决方案2】:

    根据ReportLab's FAQ,这只能通过 ReportLab PLUS 实现:

    我可以在我的 PDF 中使用矢量图形吗?

    不,开源包不支持 这。 PageCatcher(见上 答案)让您轻松 通过保存合并任何矢量图像 它作为PDF,然后完全使用它 就像图像文件一样,然后报告 标记语言接受 PDF 文件 以及 JPG、GIF 和 PNG。

    更新:我已经有一段时间没有研究这个了,但是on the page of pdfrw 它说:

    pdfrw可以读写PDF文件,也​​可以用来读取PDF,然后在reportlab内部使用。

    【讨论】:

    • 没错。在 pdfrw 页面和questions 这里有几个使用 pdfrw 的示例
    • 如果您可以获取矢量数据本身,您可以在reportlab 画布上进行绘制。生成没有图像的漂亮图形
    • 这个答案不正确,请参阅我在 2017 年 1 月 23 日的回答
    【解决方案3】:

    您可以将精彩的pdfrw包与reportlab一起使用,并使用它将matplotlib图形的类文件对象直接传递到flowable中:

    这个问题之前回答过,但是我想在这里举个小例子,也请看这里:https://stackoverflow.com/a/13870512/4497962

    from io import BytesIO
    import matplotlib.pyplot as plt
    from pdfrw import PdfReader, PdfDict
    from pdfrw.buildxobj import pagexobj
    from pdfrw.toreportlab import makerl
    from reportlab.platypus import Flowable
    from reportlab.lib.enums import TA_JUSTIFY,TA_LEFT,TA_CENTER,TA_RIGHT
    
    class PdfImage(Flowable):
        """
        PdfImage wraps the first page from a PDF file as a Flowable
        which can be included into a ReportLab Platypus document.
        Based on the vectorpdf extension in rst2pdf (http://code.google.com/p/rst2pdf/)
    
        This can be used from the place where you want to return your matplotlib image
        as a Flowable:
    
            img = BytesIO()
    
            fig, ax = plt.subplots(figsize=(canvaswidth,canvaswidth))
    
            ax.plot([1,2,3],[6,5,4],antialiased=True,linewidth=2,color='red',label='a curve')
    
            fig.savefig(img,format='PDF')
    
            return(PdfImage(img))
    
        """
    
        def __init__(self, filename_or_object, width=None, height=None, kind='direct'):
            # If using StringIO buffer, set pointer to begining
            if hasattr(filename_or_object, 'read'):
                filename_or_object.seek(0)
                #print("read")
            self.page = PdfReader(filename_or_object, decompress=False).pages[0]
            self.xobj = pagexobj(self.page)
    
            self.imageWidth = width
            self.imageHeight = height
            x1, y1, x2, y2 = self.xobj.BBox
    
            self._w, self._h = x2 - x1, y2 - y1
            if not self.imageWidth:
                self.imageWidth = self._w
            if not self.imageHeight:
                self.imageHeight = self._h
            self.__ratio = float(self.imageWidth)/self.imageHeight
            if kind in ['direct','absolute'] or width==None or height==None:
                self.drawWidth = width or self.imageWidth
                self.drawHeight = height or self.imageHeight
            elif kind in ['bound','proportional']:
                factor = min(float(width)/self._w,float(height)/self._h)
                self.drawWidth = self._w*factor
                self.drawHeight = self._h*factor
    
        def wrap(self, availableWidth, availableHeight):
            """
            returns draw- width and height
    
            convenience function to adapt your image 
            to the available Space that is available
            """
            return self.drawWidth, self.drawHeight
    
        def drawOn(self, canv, x, y, _sW=0):
            """
            translates Bounding Box and scales the given canvas
            """
            if _sW > 0 and hasattr(self, 'hAlign'):
                a = self.hAlign
                if a in ('CENTER', 'CENTRE', TA_CENTER):
                    x += 0.5*_sW
                elif a in ('RIGHT', TA_RIGHT):
                    x += _sW
                elif a not in ('LEFT', TA_LEFT):
                    raise ValueError("Bad hAlign value " + str(a))
    
            #xobj_name = makerl(canv._doc, self.xobj)
            xobj_name = makerl(canv, self.xobj)
    
            xscale = self.drawWidth/self._w
            yscale = self.drawHeight/self._h
    
            x -= self.xobj.BBox[0] * xscale
            y -= self.xobj.BBox[1] * yscale
    
            canv.saveState()
            canv.translate(x, y)
            canv.scale(xscale, yscale)
            canv.doForm(xobj_name)
            canv.restoreState()
    

    【讨论】:

    • 这正是我所需要的!非常感谢您的代码!
    • 如果你喜欢这个,你可能还想看看这个:pypi.python.org/pypi/autobasedoc
    • 感谢代码!我在尝试使用 drawOn 方法设置图像的位置时遇到了一些麻烦我应该将什么传递给它的第一个参数?
    • 奥拉穆里洛,tudo bem?它是画布对象:image.drawOn(canv, x, y),参见Canvas类中的reportlab/pdfgen/canvas.py
    【解决方案4】:

    您可以使用 svg 从 matplotlib 导出并使用 svglib python 库在 reportlab 生成的 PDF 文件中包含矢量图形。 svglib 获取一个svg文件,制作一个可以直接在reportlab中使用的绘图对象。

    有关更多详细信息,另请参阅此问题:Generating PDFs from SVG input

    【讨论】:

    • 以上是首选方式,因为你不必对存储进行文件操作,顺便说一下,svglib使用pdfrw...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-13
    • 2012-03-19
    • 2021-04-19
    • 1970-01-01
    • 2018-10-07
    • 2016-02-22
    • 2017-07-31
    相关资源
    最近更新 更多