ReportLab 和 Python 成像库内存中的图像问题

发布于 2024-08-20 22:31:57 字数 635 浏览 11 评论 0原文

我遇到了一个 PIL 和 reportlab 似乎无法解决的问题。具体来说,我想使用 PIL Image 对象在reportlab 的画布上使用drawImage。

过去,我使用原始数据、StringIO 和 reportlab 的 ImageReader 类将图像从网络插入到 reportlab 文档中。不幸的是,ImageReader 采用文件名或文件缓冲区之类的对象。

最终目标是能够将 QR 代码(即 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)

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

饮惑 2024-08-27 22:31:57

虽然它看起来确实应该起作用,但实际上不起作用。我终于找到了问题所在,它出现在 _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 对象中)请告诉我!

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!

倦话 2024-08-27 22:31:57

查看 ReportLab 2.4 的源代码,ImageReader 似乎会接受 PIL Image 对象作为“文件名”。


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)

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)
太傻旳人生 2024-08-27 22:31:57

奇怪的
文档声称drawImage和drawInlineImage的工作方式相同,但它可以直接与drawInlineImage一起使用,并且不能在drawImage中工作

weired
the documentation claims that drawImage and drawInlineImage work the same way, but it works with drawInlineImage out of the box, and do not work in drawImage

夏尔 2024-08-27 22:31:57

这就是我使用plotly、BytesIO 和reportlab 所做的。它将内存中的图像放入 pdf 中,而无需先将其保存在磁盘上。

import io
import plotly.graph_objects as go
from reportlab.platypus import SimpleDocTemplate, Image

image_in_memory = io.BytesIO()
figure = go.Figure(data=data)  # as it's not part of the question I'm leaving data out
figure.write_image(image_in_memory, scale=5, width=1000, height=400)
pdf_image = Image(image_in_memory, width=400, height=160)
pdf_document = SimpleDocTemplate(path, title='Title')
pdf_document.multiBuild([pdf_image])

This is what I did, using plotly, BytesIO and reportlab. It puts an image in the pdf from memory, without having to save it on disk first.

import io
import plotly.graph_objects as go
from reportlab.platypus import SimpleDocTemplate, Image

image_in_memory = io.BytesIO()
figure = go.Figure(data=data)  # as it's not part of the question I'm leaving data out
figure.write_image(image_in_memory, scale=5, width=1000, height=400)
pdf_image = Image(image_in_memory, width=400, height=160)
pdf_document = SimpleDocTemplate(path, title='Title')
pdf_document.multiBuild([pdf_image])
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文