2011-01-14 19 views
13

Matplotlib grafiklerini doğrudan ReportLab tarafından oluşturulan PDF'lere gömmek istiyorum - yani önce PNG olarak kaydetme ve ardından PNG'yi PDF'ye gömme (daha kaliteli çıktı alacağımı düşünüyorum).ReportLab için akıcı bir matplotlib var mı?

RaporLab için akıcı bir matplotlib olup olmadığını bilen var mı?

Teşekkür

+3

Başka bir seçenek pdf veya eps (veya başka vektör formatında) olarak rakam kaydetmek olabilir ve daha sonra pdf vektör versiyonunu gömmek olacaktır. Bu en azından kalite sorunları etrafında olsun ... Matplotlib vektör formatları yanı sıra raster .png's, vb kaydetme iyi bir iş yapar –

+0

svg olarak matplotlib şekil kaydetmeyi düşünün; daha sonra [bu yanıt] 'da (https://stackoverflow.com/questions/5835795/generating-pdfs-from-svg-input) ayrıntılı olarak açıklandığı şekilde 'reportlab' içinde kullanmak için' svglib' kullanma. – ImportanceOfBeingErnest

cevap

3

Bir tane değil, ama aynı zamanda PIL kullanmak zorunda kalmamak için ne ReportLab ile Matplotlib benim kendi kullanımında yapmak PNGs PNGs oluşturmak ve sonra gömmek etmektir. Ancak, PIL kullanırsanız, MatPlotLib ve ReportLab kullanarak EPS oluşturup gömebilmeniz gerektiğine inanıyorum.

3

Ücretsiz PDFRW kitaplığı, PDF'leri rapor dosyasına yerleştirmek için uygundur. Aslında, bu sorunu Matplotlib PDF'leriyle tam olarak çözmüş olan birinden PDFRW guestbook'da bir not bulunmaktadır. Belki sen miydin?

19

İşte çözüm kullanarak pdfrw var:

#!/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

Aynı konuyla ilgili yeni bir soru [ve yanıt] (http://stackoverflow.com/a/31910275/3577601) farkettim ve [değiştirilene kadar] farketmedim (http://stackoverflow.com/a/32021013/3577601) ki bu kodun kendisi bu kodun değiştirilmiş bir sürümüydi. Bunu daha dikkatli okumalıydım - üstteki vectorpdf nesnelerine baktım ve okumayı bıraktım ... –

+0

Sadece kısa bir not: Bu cevap Python3 ve PyPI'deki mevcut pdrw ile bozuldu. – Oz123

İlgili konular