ReportLab与Python Imaging Library内存中图像问题

11 投票
4 回答
7559 浏览
提问于 2025-04-15 19:03

我遇到了一个问题,搞不清楚怎么用PIL和reportlab一起工作。具体来说,我想在reportlab的画布上用drawImage来插入一个PIL的图像对象。

以前我通过原始数据、StringIO和reportlab的ImageReader类从网上插入图片到reportlab文档中。不过,ImageReader需要一个文件名或者类似文件的对象。

我的最终目标是把二维码(这些是PIL对象)放进reportlab生成的PDF里。有一种方法是这样的:

    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()

这个方法是先保存图片,然后再把它读进PDF里。显然,这样做不太合理。

我遇到的困难还因为reportlab的发展历史比较长,找最新版本(2.4)相关的答案比较麻烦。

谢谢大家的帮助。

(顺便说一下,我用的是1.1.6版本的PIL)

4 个回答

0

奇怪的是,文档上说 drawImage 和 drawInlineImage 的工作方式是一样的,但实际上 drawInlineImage 可以直接用,而 drawImage 却不行。

2

查看ReportLab 2.4的源代码,似乎ImageReader可以把PIL图像对象当作“文件名”来使用。


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)
5

虽然看起来应该可以正常工作,但实际上并没有。我终于找到了问题所在,问题出在 _isPILImage() 这个函数里。问题是“Image.Image”实际上是“from PIL import Image”,而我的对象其实只是从 Image 导入的。我本来以为它们是一样的,但无论如何,isinstance 并不把它们当作相同的东西。我的临时解决办法是把 _isPILImage(fileName): ... 改成

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

这样就解决了我的错误。因为你给了我正确的方向,我本来想把这个作为评论发出去,然后接受你的回答,但字符数不够。

谢谢你的建议!如果你能想到更优雅的解决办法……(我试着把 Image.Image 对象包装成一个 PIL Image 对象)请告诉我!

撰写回答