Frage

I'd like to put an image (a barcode more precisely) in a pdf doc generated by reportlab. I can put it in a table. That works perfectly with createBarcodeDrawing().

The point is that I'd like the barcode to change on each page. Thus, I want to put it in a canvasmaker.

Whatever method I use (drawImage(), drawInLineImage(),...), I always have an error. I even tried to use CustomImage from Reportlab [ Platypus ] - Image does not render without any success. Consequently, my question is how can I draw an image in a canvas.Canvas ?

Can anybody help ? Thank you in advance Dom (I am not a professional)

Following a remark I read on http://www.tylerlesmann.com/2009/jan/28/writing-pdfs-python-adding-images/, I tried:

img = 'apple-logo.jpg'
self.drawInlineImage('C:\\'+img,20,20)

This works, while 'C:\apple-logo.jpg' doesn't !! Nevertheless, I still don't know how to draw my barcode without writing it to a file before! If someone manages to do it, I would really appreciate. Bye

from reportlab.pdfgen import canvas
from reportlab.lib.units import mm


class NumberedCanvas(canvas.Canvas):
def __init__(self, *args, **kwargs):
    canvas.Canvas.__init__(self, *args, **kwargs)
    self._saved_page_states = []

def showPage(self):
    self._saved_page_states.append(dict(self.__dict__))
    self._startPage()

def save(self):
    """add page info to each page (page x of y)"""
    num_pages = len(self._saved_page_states)
    for state in self._saved_page_states:
        self.__dict__.update(state)
        page_num = self._pageNumber
        mybarcode = createBarcodeDrawing('QR', value= 'www.mousevspython.com - Page %s'%page_num)
        self.drawInlineImage(mybarcode,20,20)
        canvas.Canvas.showPage(self)
    canvas.Canvas.save(self)

def main():
import sys
import urllib2
from cStringIO import StringIO
from reportlab.platypus import SimpleDocTemplate, Image, Paragraph, PageBreak
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet

#This is needed because ReportLab accepts the StringIO as a file-like object,
#but doesn't accept urllib2.urlopen's return value
def get_image(url):
    u = urllib2.urlopen(url)
    return StringIO(u.read())

styles = getSampleStyleSheet()
styleN = ParagraphStyle(styles['Normal'])

# build doc

if len(sys.argv) > 1:
    fn = sys.argv[1]
else:
    fn = "filename.pdf"
doc = SimpleDocTemplate(open(fn, "wb"))
elements = [
    Paragraph("Hello,", styleN),
    Image(get_image("http://www.red-dove.com/images/rdclogo.gif")),
    PageBreak(),
    Paragraph("world!", styleN),
    Image(get_image("http://www.python.org/images/python-logo.gif")),
]
doc.build(elements, canvasmaker=NumberedCanvas)

if __name__ == "__main__":
main()
War es hilfreich?

Lösung

You were nearly there. Just replace self.drawImage(mybarcode,20,20) with mybarcode.drawOn(self, 20, 20). The barcode is not really an image, more an barcode object which you can export to an image. As a side note: You are using the NumberedCanvas which is kind of a hack to get the total page count. As i see it you don't really need it, as you are just using the current page number. If you don't need the total page count, you can just define a canvas drawing function which draws the barcode on each page. For this you would do something like this:

def draw_barcode(canvas, doc):
    canvas.saveState()
    page_num = canvas._pageNumber
    mybarcode = createBarcodeDrawing('QR', value= 'www.mousevspython.com - Page %s'%page_num)
    mybarcode.drawOn(canvas, 20, 20)
    canvas.restoreState()

[...]

# doc.build(elements, canvasmaker=NumberedCanvas)
doc.build(elements, onFirstPage=draw_barcode, onLaterPages=draw_barcode)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top