[英]Including base64-encoded image in ReportLab-generated PDF
I am trying to decode base64-encoded image and put it into PDF I generate using ReportLab. 我正在尝试解码base64编码的图像并将其放入我使用ReportLab生成的PDF中。 I currently do it like that (
image_data
is base64-encoded image, story
is already a ReportLab's story): 我目前这样做(
image_data
是base64编码的图像, story
已经是ReportLab的故事):
# There is some "story" I append every element
img_height = 1.5 * inch # max image height
img_file = tempfile.NamedTemporaryFile(mode='wb', suffix='.png')
img_file.seek(0)
img_file.write(image_data.decode('base64'))
img_file.seek(0)
img_size = ImageReader(img_file.name).getSize()
img_ratio = img_size[0] / float(img_size[1])
img = Image(img_file.name,
width=img_ratio * img_height,
height=img_height,
)
story.append(img)
and it works (although still looks ugly to me). 它工作(虽然看起来仍然丑陋)。 I thought about getting rid of the temporary file (shouldn't file-like object do the trick?).
我想要摆脱临时文件(不应该像文件一样的对象吗?)。
To get rid of the temporary file I tried to use StringIO
module, to create file-like object and pass it instead of file name: 为了摆脱我试图使用
StringIO
模块的临时文件,创建类文件对象并传递它而不是文件名:
# There is some "story" I append every element
img_height = 1.5 * inch # max image height
img_file = StringIO.StringIO()
img_file.seek(0)
img_file.write(image_data.decode('base64'))
img_file.seek(0)
img_size = ImageReader(img_file).getSize()
img_ratio = img_size[0] / float(img_size[1])
img = Image(img_file,
width=img_ratio * img_height,
height=img_height,
)
story.append(img)
But this gives me IOError with the following message: " cannot identify image file ". 但这给了我IOError以及以下消息:“ 无法识别图像文件 ”。
I know ReportLab uses PIL to read images different than jpg, but is there any way I can avoid creating named temporary files and do this only with file-like objects, without writing files to the disk? 我知道ReportLab使用PIL来读取不同于jpg的图像,但是有什么方法可以避免创建命名的临时文件,并且只对文件类对象执行此操作,而无需将文件写入磁盘?
You should wrap StringIO() by PIL.Image.open
, so simply img_size = ImageReader(PIL.Image.open(img_file)).getSize()
. 你应该换StringIO的()
PIL.Image.open
,所以干脆img_size = ImageReader(PIL.Image.open(img_file)).getSize()
Its actually a thin wrapper around Image.size, as Tommaso's answer suggests. 正如Tommaso的回答所暗示的,它实际上是Image.size的一个薄包装器。 Also, there is actually no need to calculate the desc size on your own,
bound
mode of reportlab.Image could do it for you: 而且,实际上是没有必要来计算自己的递减尺寸
bound
reportlab.Image的模式,可以为你做到这一点:
img_height = 1.5 * inch # max image height
img_file = StringIO.StringIO(image_data.decode('base64'))
img_file.seek(0)
img = Image(PIL.Image.open(img_file),
width=float('inf'),
height=img_height,
kind='bound')
)
story.append(img)
This code is working for me without PIL, as the image is already a JPEG: raw just pulls the base64 string out of a dictionary. 这段代码对我来说没有PIL,因为图像已经是JPEG:raw只是将base64字符串从字典中拉出来。 I just wrap the decoded "string" in a StringIO.
我只是将解码后的“字符串”包装在StringIO中。
raw = element['photographs'][0]['jpeg']
photo = base64.b64decode(raw)
c.drawImage(ImageReader(StringIO.StringIO(photo)), 0.5*inch, self.y, height = self.PHOTOHEIGHT, preserveAspectRatio = True)
This solution works for me. 这个解决方案适合我。 I'm using Flask with Google App Engine.
我正在使用Flask和Google App Engine。
from reportlab.platypus import Image
from reportlab.lib.units import mm
import cStringIO
from base64 import b64decode
story=[]
encoded_image = "...."
decoded_img = b64decode(encoded_image)
img_string = cStringIO.StringIO(decoded_img)
img_string.seek(0)
im = Image(img_string, 180*mm, 100*mm, kind='bound')
story.append(im)
I have received the image from the client and saved in the database: 我从客户端收到了图像并保存在数据库中:
from base64 import b64decode
image = request.files['image'].read()
encoded_image = b64encode(image)
I am not familiar with ReportLab but if you can use PIL directly this will work: 我不熟悉ReportLab,但如果你可以直接使用PIL,这将有效:
...
img = Image.open(img_file)
width, height = img.size
...
you can have a look here for PIL Image class references 您可以在这里查看PIL Image类引用
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.