简体   繁体   English

使用ReportLab(Python)的PDF文档中的PDF图像

[英]PDF image in PDF document using ReportLab (Python)

I saved some plots from matplotlib into a pdf format because it seems to offer a better quality. 我将matplotlib中的一些图表保存为pdf格式,因为它似乎提供了更好的质量。 How do I include the PDF image into a PDF document using ReportLab? 如何使用ReportLab将PDF图像包含到PDF文档中? The convenience method Image(filepath) does not work for this format. 便捷方法Image(filepath)不适用于此格式。

Thank you. 谢谢。

According to ReportLab's FAQ this is only possible with ReportLab PLUS: 根据ReportLab的常见问题解答,这只适用于ReportLab PLUS:

Can I use vector graphics in my PDFs? 我可以在PDF中使用矢量图形吗?

No, the Open Source package doesn't do this. 不,开源软件包不会这样做。 PageCatcher (see the previous answer) allows you to easily incorporate any vector image by saving it as a PDF and then using it exactly as you would an image file, and Report Markup Language accepts PDF files along with JPG, GIF and PNG. PageCatcher(参见上一个答案)允许您通过将任何矢量图像保存为PDF,然后像使用图像文件一样使用它来轻松合并任何矢量图像,并且报告标记语言接受PDF文件以及JPG,GIF和PNG。

Update : I haven't looked into this for a while but on the page of pdfrw it says: 更新 :我有一段时间没有看过这个,但在pdfrw页面上说:

pdfrw can read and write PDF files, and can also be used to read in PDFs which can then be used inside reportlab. pdfrw可以读取和写入PDF文件,也​​可以用于读取PDF,然后可以在reportlab中使用。

You can use the wonderful pdfrw package together with reportlab and use it to pass file-like objects of matplotlib figures directly into a flowable: 您可以将精美的pdfrw包与reportlab一起使用,并使用它将matplotlib图形的文件对象直接传递给flowable:

This was answered before, but I want to give a minimal example here, please also look here: https://stackoverflow.com/a/13870512/4497962 之前已经回答了,但我想在这里给出一个最小的例子,请看这里: 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()

You can use svg export from matplotlib and use svglib python library to include vector graphics in reportlab generated PDF files. 您可以使用matplotlib中的svg导出并使用svglib python库在reportlab生成的PDF文件中包含矢量图形。 svglib takes a svg file and makes a drawing object that can be directly used in reportlab. svglib获取一个svg文件并生成一个可以直接在reportlab中使用的绘图对象。

See also this question for more details: Generating PDFs from SVG input 有关更多详细信息,请参阅此问题: 从SVG输入生成PDF

使用来自reportlab.graphics导入renderPDF

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM