能否从图像对象创建编码的base64 URL?

17

我希望创建图像的base64内联编码数据,以便在表格中使用画布进行显示。 Python 动态生成并创建网页。现在,Python 使用 Image 模块创建缩略图。在创建所有缩略图之后,Python 生成每个缩略图的 base64 数据,并将 b64 数据放入用户网页上的隐藏 span 中。然后用户通过单击与其兴趣相关的每个缩略图旁边的复选标记来选择它们。然后他们通过单击生成 pdf 按钮,创建包含所选图像的 pdf 文件。JavaScript 使用 jsPDF 生成隐藏的 span b64 数据以创建 pdf 文件中的图像文件,然后最终生成 pdf 文件。

我希望能够在脚本执行时在内存中生成缩略图的 base64 数据,以希望减少 Python 脚本执行时间并最小化一些磁盘 I/O 操作。

以下是我想要实现的示例。

import os, sys
import Image
size = 128, 128
    im = Image.open("/original/image/1.jpeg")
    im.thumbnail(size)
    thumb = base64.b64encode(im)

很遗憾,这不起作用,会出现TypeErorr错误 -

TypeError: must be string or buffer, not instance
任何想法如何实现这一点?
4个回答

31

您需要首先将图像以JPEG格式重新保存;否则使用im.tostring()方法将返回浏览器无法识别的原始图像数据:

from io import BytesIO  
output = BytesIO()
im.save(output, format='JPEG')
im_data = output.getvalue()

然后,您可以将其编码为base64:

image_data = base64.b64encode(im_data)
if not isinstance(image_data, str):
    # Python 3, decode from bytes to string
    image_data = image_data.decode()
data_url = 'data:image/jpg;base64,' + image_data

我用这种方法做出了这个:

data:image/jpg;base64,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

不幸的是,Markdown解析器不能将此作为实际图像使用,但您可以在代码片段中查看它:

<img src="data:image/jpg;base64,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"/>


提供的两个答案都适用于我想要做的事情,但这个更符合我的程序的要求,也更流畅 :) 所以我会选择你的建议!我希望我能接受两个答案,因为我会从两者中借鉴,但StringIO 对我来说效果非常好!谢谢大家! - 0xhughes

3
在Python 3中,您可能需要使用BytesIO
from io import BytesIO

...

outputBuffer = BytesIO()
bg.save(outputBuffer, format='JPEG')
bgBase64Data = outputBuffer.getvalue()

# https://dev59.com/pmQn5IYBdhLWcg3wiXqd
return 'data:image/jpeg;base64,' + base64.b64encode(bgBase64Data).decode()

2
 thumb = base64.b64encode(im.tostring())

我认为这会起作用


不行,那样做不行,因为im.tostring()返回的是原始图像矩阵,而不是JPEG编码数据。 - Martijn Pieters
但是它是否适用于“Image.fromtext(b64decode(my_encoded_raw))”?还是这是个谎言(我没有尝试过)?... - Joran Beasley
实际上,我的阅读理解也需要提高,看起来OP确实想要往返旅行,而不是将它们显示为数据URL。糟糕。不过,我认为jsPDF或画布可能会使用JPEG。 - Martijn Pieters
是的,说实话我不知道你可以这样使用URL(很棒的技巧) - Joran Beasley
谢谢大家的建议,我在测试中尝试了tostring()方法,并得到了一些有趣的结果。但是在我的各种测试中,我似乎无法很好地让b64编码的数据在jsPDF中工作,我将继续调试,因为我注意到不同的库对于如何呈现b64数据都很挑剔! - 0xhughes

2

当我保存到缓冲区时,我使用PNG格式。使用JPEG格式时,numpy数组会有一些不同。

import base64
import io

import numpy as np
from PIL import Image

image_path = 'dog.jpg'

img2 = np.array(Image.open(image_path))

# Numpy -> b64
buffered = io.BytesIO()
Image.fromarray(img2).save(buffered, format="PNG")
b64image = base64.b64encode(buffered.getvalue())

# b64 -> Numpy
img = np.array(Image.open(io.BytesIO(base64.b64decode(b64image))))

print(img.shape)
np.testing.assert_almost_equal(img, img2)

请注意,它会变慢。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接