Python 从PIL image或StringIO将图像插入Reportlab
我正在尝试将条形码图像插入Reportlab。我知道在这方面有很多问题要问,但是所有问题都假定您已经在目录或文件系统中拥有映像文件 由于Reportlab与EAN13条形码存在问题,我决定使用另一个名为pyBarcode的包为我生成图像 最初,我将图像保存在一个StringIO实例中,并将其直接传递给Python 从PIL image或StringIO将图像插入Reportlab,python,python-imaging-library,reportlab,Python,Python Imaging Library,Reportlab,我正在尝试将条形码图像插入Reportlab。我知道在这方面有很多问题要问,但是所有问题都假定您已经在目录或文件系统中拥有映像文件 由于Reportlab与EAN13条形码存在问题,我决定使用另一个名为pyBarcode的包为我生成图像 最初,我将图像保存在一个StringIO实例中,并将其直接传递给reportlab.platypus.flowables.image,但这似乎不起作用。然后我阅读了文档: 支持PIL/Java1.4(Python/JavaImaging库)支持的格式 这是否意味
reportlab.platypus.flowables.image
,但这似乎不起作用。然后我阅读了文档:
支持PIL/Java1.4(Python/JavaImaging库)支持的格式
这是否意味着,如果我通过一个PIL图像,这应该工作?我尝试以下操作时出现异常:
>>> import PIL
>>> from reportlab.platypus.flowables import Image
>>> fp = StringIO(the_barcode.getvalue())
>>> barcode_image = PIL.Image.open(fp)
>>> doc = SimpleDocTemplate('barcode.pdf')
>>> story = [Image(barcode_image)]
>>> Traceback (most recent call last):
File "create.py", line 57, in <module>
main()
File "create.py", line 24, in main
save_pdf(fp, STYLE, ART, COLOR, SIZE)
File "create.py", line 28, in save_pdf
fp = StringIO(fp.getvalue())
File "/home/mark/.virtualenvs/barcode/local/lib/python2.7/site-packages/reportlab-2.6-py2.7-linux-i686.egg/reportlab/platypus/flowables.py", line 402, in __init__
if not fp and os.path.splitext(filename)[1] in ['.jpg', '.JPG', '.jpeg', '.JPEG']:
File "/home/mark/.virtualenvs/barcode/lib/python2.7/posixpath.py", line 95, in splitext
return genericpath._splitext(p, sep, altsep, extsep)
File "/home/mark/.virtualenvs/barcode/lib/python2.7/genericpath.py", line 91, in _splitext
sepIndex = p.rfind(sep)
File "/home/mark/.virtualenvs/barcode/local/lib/python2.7/site-packages/PIL/Image.py", line 512, in __getattr__
raise AttributeError(name)
AttributeError: rfind
导入PIL
>>>从reportlab.platypus.flowables导入图像
>>>fp=StringIO(条形码.getvalue())
>>>条形码\图像=完整图像打开(fp)
>>>doc=SimpleDoctTemplate('barcode.pdf')
>>>故事=[图像(条形码图像)]
>>>回溯(最近一次呼叫最后一次):
文件“create.py”,第57行,在
main()
文件“create.py”,第24行,在main中
保存pdf(fp、样式、艺术、颜色、大小)
保存pdf中的文件“create.py”,第28行
fp=StringIO(fp.getvalue())
文件“/home/mark/.virtualenvs/barcode/local/lib/python2.7/site packages/reportlab-2.6-py2.7-linux-i686.egg/reportlab/platypus/flowables.py”,第402行,在__
如果在['.jpg'、'.jpg'、'.jpeg'、'.jpeg']中没有fp和os.path.splitext(文件名)[1]:
splitext中第95行的文件“/home/mark/.virtualenvs/barcode/lib/python2.7/posixpath.py”
返回genericpath.\u splitext(p,sep,altsep,extsep)
文件“/home/mark/.virtualenvs/barcode/lib/python2.7/genericpath.py”,第91行,在拆分文本中
sepIndex=p.rfind(sep)
文件“/home/mark/.virtualenvs/barcode/local/lib/python2.7/site packages/PIL/Image.py”,第512行,在__
提升属性错误(名称)
属性错误:rfind
不知何故,PIL图像似乎也不起作用。如果我没有图像的文件名(因为我的图像是在内存中创建的),我应该将什么作为第一个参数传递给Reportlab的图像函数?我相信PIL文档的意思是它在内部使用PIL来处理图像数据 从我在源代码中看到的情况来看,您可以直接传递文件对象,因此,使用
read()
方法:
我想你可以用某种方式将原始图像数据包装成一个类似文件的对象(StringIO或类似的)
编辑:我想这就是你以前做的,对不起。无论如何,这似乎是正确的方法。如果您告诉我们在这种情况下出现了什么问题,我们也许可以解决它。重复声明“支持PIL/Java 1.4(Python/Java图像库)支持的格式”仅仅意味着
PIL
支持的数据格式受reportlab
支持(因为它使用PIL
读取它们)
现在,通过查看reportlab.platypus.flowables.Image
code,可以看到它接受文件名或文件对象作为输入。前者不是你想要的,所以让我们关注后者。你说StringIO似乎不起作用,但如果你小心一点,它会起作用。您可能对它做了一些错误的操作,下面是使用StringIO
的两种正确方法:
import sys
import PIL
from cStringIO import StringIO
from reportlab.platypus.flowables import Image
# Method 1
data = open(sys.argv[1]).read()
img1 = StringIO(data)
# Method 2
img2 = StringIO()
PIL.Image.open(sys.argv[2]).save(img2, 'PNG')
img2.seek(0)
# Method 3 (fails)
img3 = StringIO(PIL.Image.open(sys.argv[2]).tostring())
story = [Image(img1), Image(img2)]
#Image(img3)
方法3失败,因为img3
现在保存图像的原始数据,因此它不知道该数据的实际格式。没有理由尝试将此方法用于此任务
如果您有原始数据,并且您知道数据的图像模式(“L”、“RGB”等)及其宽度和高度,那么您可以使用基于
PIL.image.fromstring(…).save(mystrio,'someformat')的第四种(正确)方法。
我对所建议的方法不太了解
检查pdfdoc.py中的代码表明,AttributeError是将StringIO作为文件名处理的结果:
if source is None:
pass # use the canned one.
elif hasattr(source,'jpeg_fh'):
self.loadImageFromSRC(source) #it is already a PIL Image
else:
# it is a filename
进一步检查源代码,会发现jpeg_fh是reportlab.lib.utils中ImageReader类的一个属性。ImageReader同时接受StringIO和PIL图像
因此,在ImageReader中包装StringIO解决了我的问题:
import PIL
from reportlab.lib.utils import ImageReader
io_img = StringIO(data)
pil_img = PIL.Image.open(StringIO(data))
reportlab_io_img = ImageReader(io_img)
reportlab_pil_img = ImageReader(pil_img)
canvas.drawImage(reportlab_io_img, ...)
canvas.drawImage(reportlab_pil_img, ...)
在Python3中,使用“from io import BytesIO”而不是“from cStringIO import StringIO”。和“img2=BytesIO()”而不是“img2=StringIO()”
Image()
也可以采用来自requests.get()
的“类似文件的响应对象表示法”。现在允许Image()filename参数可以是“类似文件的对象”。所以,呸,这不是一个未记录的特性。Image(requests.get(“http://example.com/foo.png,stream=True)。例如,原始、w、h)
。