views:

605

answers:

2

I've run into an issue I can't seem to figure out with PIL and reportlab. Specifically, I would like to use drawImage on a canvas in reportlab using a PIL Image object.

In the past I've inserted images into reportlab documents from the web using raw data, StringIO and reportlab's ImageReader class. Unfortunately, ImageReader takes a file name or a file buffer like object.

The ultimate goal is to be able to put QR codes, (which are PIL objects) into the reportlab PDFs. One thing that does work is the following:

    size, qrcode = PyQrcodec.encode('http://www.google.com')
    qrcode.save("img.jpeg")
    self.pdf.drawImage(ImageReader("img.jpeg"), 25, 25, width=125, height=125)
    self.pdf.showPage()

This saves the image and then reads it into the pdf. Obviously doing it like this doesn't make sense.

My efforts are compounded by the relatively long development history of reportlab which makes finding the answers relevant to the latest version (2.4).

Thanks for the help.

(By the way, I'm using 1.1.6 PIL)

+1  A: 

Looking at the source for ReportLab 2.4, it seems that ImageReader will accept a PIL Image object as "filename".


def _isPILImage(im):
    try:
        return isinstance(im,Image.Image)
    except ImportError:
        return 0

class ImageReader(object):
    "Wraps up either PIL or Java to get data from bitmaps"
    _cache={}
    def __init__(self, fileName):
        if isinstance(fileName,ImageReader):
            self.__dict__ = fileName.__dict__   #borgize
            return
        #start wih lots of null private fields, to be populated by
        #the relevant engine.
        self.fileName = fileName
        self._image = None
        self._width = None
        self._height = None
        self._transparent = None
        self._data = None
        if _isPILImage(fileName):
            self._image = fileName
            self.fp = getattr(fileName,'fp',None)
            try:
                self.fileName = self._image.fileName
            except AttributeError:
                self.fileName = 'PILIMAGE_%d' % id(self)
MattH
So `self.pdf.drawImage(ImageReader(qrcode), 25, 25, width=125, height=125)` ought to work, assuming the rest of the arguments to `drawImage` are appropriate.
MattH
A: 

Although it does look like it should work, it really doesn't. I finally was able to track down the problem, and it was in the _isPILImage() function. The problem is that "Image.Image" is actually "from PIL import Image" whereas my object is actually just from Image. I would have assumed they were the same, but in any case isinstance doesn't evaluate them as the same. My hack solution was to change _isPILImage(fileName): ... to

519 def _isPILImage(im):
520     import Image as PIL_Image
521     try:
522         return isinstance(im,Image.Image) or isinstance(im, PIL_Image.Image)
523     except ImportError:
524         return 0

That solves my error. Since you pointed me in the right direction I originally tried to post this as a comment then accept your answer, but it doesn't allow enough characters.

Thank you for the input! If you can think of a more elegant way to fix this... (I tried to wrap the Image.Image object in a PIL Image object) let me know!

philipk
By the way, the function above is in lib/utils.py in reportlab.
philipk