2011-01-14 2 views
13

ReportLab에서 직접 생성 한 PDF에 matplotlib 차트를 삽입하고 싶습니다. 즉, 먼저 PNG로 저장하지 않고 PNG를 PDF에 임베드하지 마십시오. 더 나은 출력을 얻을 수 있습니다.ReportLab 용 유동 가능한 matplotlib가 있습니까?

ReportLab 용 유동적 인 matplotlib가 있다면 누구에게 알 수 있습니까?

감사

+3

또 다른 옵션은 PDF 또는 EPS (또는 다른 벡터 형식)으로 그림을 저장하고 다음 PDF의 벡터 버전을 포함한다. Matplotlib은 벡터 형식뿐만 아니라 래스터 .png 등을 저장하는 좋은 일을합니다. –

+0

matplotlib 그림을 svg로 저장하는 것이 좋습니다. 그런 다음 [this answer] (https://stackoverflow.com/questions/5835795/generating-pdfs-from-svg-input)에 설명 된대로 'svglib'을 사용하여 'reportlab'에 사용하십시오. – ImportanceOfBeingErnest

답변

3

가 아니다, 그러나 나는 또한 PIL을 사용하지 않도록 제가 ReportLab과 함께하기 matplotlib 내 자신의 사용을 수행하면 PNG 파일을 PNG 파일을 생성 한 후 삽입하는 것입니다. 그러나 PIL을 사용하는 경우 MatPlotLib 및 ReportLab을 사용하여 EPS를 생성하고 포함 할 수 있어야합니다.

3

무료 PDFRW 라이브러리는 PDF를 reportlab에 배치하는 데 적합합니다. 사실 에는 Matplotlib PDF로이 문제를 정확히 해결 한 사람의 쪽지가 있습니다. 아마 너 였어?

19

는 여기에 솔루션을 사용하여 pdfrw입니다 :

#!/usr/bin/env python 
# encoding: utf-8 
"""matplotlib_example.py 
    An simple example of how to insert matplotlib generated figures 
    into a ReportLab platypus document. 
""" 

import matplotlib 
matplotlib.use('PDF') 
import matplotlib.pyplot as plt 
import cStringIO 

from pdfrw import PdfReader 
from pdfrw.buildxobj import pagexobj 
from pdfrw.toreportlab import makerl 

from reportlab.platypus import Flowable 
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT 
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer 
from reportlab.lib.styles import getSampleStyleSheet 
from reportlab.rl_config import defaultPageSize 
from reportlab.lib.units import inch 

PAGE_HEIGHT=defaultPageSize[1]; PAGE_WIDTH=defaultPageSize[0] 
styles = getSampleStyleSheet() 

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

    def __init__(self, filename_or_object, width=None, height=None, kind='direct'): 
     from reportlab.lib.units import inch 
     # If using StringIO buffer, set pointer to begining 
     if hasattr(filename_or_object, 'read'): 
      filename_or_object.seek(0) 
     page = PdfReader(filename_or_object, decompress=False).pages[0] 
     self.xobj = pagexobj(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, aW, aH): 
     return self.drawWidth, self.drawHeight 

    def drawOn(self, canv, x, y, _sW=0): 
     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 = self.xobj 
     xobj_name = makerl(canv._doc, xobj) 

     xscale = self.drawWidth/self._w 
     yscale = self.drawHeight/self._h 

     x -= xobj.BBox[0] * xscale 
     y -= xobj.BBox[1] * yscale 

     canv.saveState() 
     canv.translate(x, y) 
     canv.scale(xscale, yscale) 
     canv.doForm(xobj_name) 
     canv.restoreState() 

Title = "Hello world" 
pageinfo = "platypus example" 
def myFirstPage(canvas, doc): 
    canvas.saveState() 
    canvas.setFont('Times-Bold',16) 
    canvas.drawCentredString(PAGE_WIDTH/2.0, PAGE_HEIGHT-108, Title) 
    canvas.setFont('Times-Roman',9) 
    canvas.drawString(inch, 0.75 * inch, "First Page/%s" % pageinfo) 
    canvas.restoreState() 


def myLaterPages(canvas, doc): 
    canvas.saveState() 
    canvas.setFont('Times-Roman',9) 
    canvas.drawString(inch, 0.75 * inch, "Page %d %s" % (doc.page, pageinfo)) 
    canvas.restoreState() 

def go(): 
    fig = plt.figure(figsize=(4, 3)) 
    plt.plot([1,2,3,4]) 
    plt.ylabel('some numbers') 
    imgdata = cStringIO.StringIO() 
    fig.savefig(imgdata,format='PDF') 
    doc = SimpleDocTemplate("document.pdf") 
    Story = [Spacer(1,2*inch)] 
    style = styles["Normal"] 
    for i in range(5): 
     bogustext = ("This is Paragraph number %s. " % i) *20 
     p = Paragraph(bogustext, style) 
     Story.append(p) 
     Story.append(Spacer(1,0.2*inch)) 
     pi = PdfImage(imgdata) 
     Story.append(pi) 
     Story.append(Spacer(1,0.2*inch)) 
    doc.build(Story, onFirstPage=myFirstPage, onLaterPages=myLaterPages) 


if __name__ == '__main__': 
    go() 
+0

나는 같은 주제에 대해 새로운 질문 [and answer] (http://stackoverflow.com/a/31910275/3577601)을 발견했고, 내가 [수정] 될 때까지 깨닫지 못했다. (http://stackoverflow.com/a/32021013/3577601)는이 코드 자체가이 코드의 수정 된 버전임을 나타냅니다. 나는 이것을 더 조심스럽게 읽었어야했다. 나는 그냥 위쪽의 vectorpdf를보고 멈추었다. ... –

+0

그냥 잠깐.이 대답은 Python3과 현재의 PyPI의 pdrw에서 깨진다. – Oz123

관련 문제