使用base64编码图像文件


161

我想使用base64模块将图像编码为字符串。不过我遇到了一个问题。如何指定要编码的图像?我尝试对图像使用目录,但这只会导致目录被编码。我希望对实际的图像文件进行编码。

编辑

我尝试了以下代码段:

with open("C:\Python26\seriph1.BMP", "rb") as f:
    data12 = f.read()
    UU = data12.encode("base64")
    UUU = base64.b64decode(UU)

    print UUU

    self.image = ImageTk.PhotoImage(Image.open(UUU))

但出现以下错误:

Traceback (most recent call last):
  File "<string>", line 245, in run_nodebug
  File "C:\Python26\GUI1.2.9.py", line 473, in <module>
    app = simpleapp_tk(None)
  File "C:\Python26\GUI1.2.9.py", line 14, in __init__
    self.initialize()
  File "C:\Python26\GUI1.2.9.py", line 431, in initialize
    self.image = ImageTk.PhotoImage(Image.open(UUU))
  File "C:\Python26\lib\site-packages\PIL\Image.py", line 1952, in open
    fp = __builtin__.open(fp, "rb")
TypeError: file() argument 1 must be encoded string without NULL bytes, not str

我究竟做错了什么?

Answers:


299

我不确定我是否理解您的问题。我假设您正在按照以下方式进行操作:

import base64

with open("yourfile.ext", "rb") as image_file:
    encoded_string = base64.b64encode(image_file.read())

当然,您必须首先打开文件并读取其内容-您不能简单地将路径传递给encode函数。

编辑: 好的,在您编辑完原始问题之后,这是一个更新。

首先,在Windows上使用路径定界符时,请记住使用原始字符串(在字符串前加上'r'),以防止意外击中转义字符。其次,PIL的Image.open要么接受文件名,要么接受类似文件的文件(也就是说,该对象必须提供读取,查找和告诉方法)。

话虽如此,您可以使用cStringIO从内存缓冲区创建这样的对象:

import cStringIO
import PIL.Image

# assume data contains your decoded image
file_like = cStringIO.StringIO(data)

img = PIL.Image.open(file_like)
img.show()

1
谢谢,当我打印解码图像时又遇到一个问题,我得到了字符串“ÿØÿà”。但是,当我单独运行它代替数据时,会出现错误。编码后的字符串比较长。因此,我认为这可能会存储图像数据。解码后的字符串是否仅引用编码后的字符串或其他内容?对于数据存储来说似乎太短了。
rectangletangle

打印的输出不一定等于实际的内容-它取决于打印方式和打印位置。
吉姆·布里索

8
就我而言,我需要解码:base64.b64encode(fh.read()).decode()以获取要在html文件中使用的字符串。
2014年

1
base64.b64encode(fh.read())。decode()有点微妙,但我也需要@qed,谢谢。区别在于一个返回字节和其他字符串……而我的SOAP服务器不会不解码就不会吞下它!
zzart 2014年

57

使用python 2.x,您可以使用.encode进行简单编码:

with open("path/to/file.png", "rb") as f:
    data = f.read()
    print data.encode("base64")

12

第一个答案将打印带有前缀b'的字符串。这意味着您的字符串将如下所示:b'your_string'要解决此问题,请添加以下代码行。

encoded_string= base64.b64encode(img_file.read())
print(encoded_string.decode('utf-8'))

2
这看起来是一个很好的答案,但是如果目的是推广您的网站,请不要发布。但是,欢迎您将链接添加到个人资料中。
Halfer '19

1
(顺便说一句,此处不能依靠答案顺序,因此,有必要避免使用诸如“第一个答案”之类的评论。最先出现的答案可能会随着时间而改变。:-)
Halfer

在此答案的原始版本中,您似乎已链接到自己的网站或与之关联的网站。如果您确实链接到这样的网站,则必须披露它是您的网站。如果您不透露从属关系,则将其视为垃圾邮件。请参阅:什么表示“良好”的自我提升?帮助中心则是自我促进。披露必须是明确的,但不必是正式的。当是您自己的个人内容时,可能只是“在我的网站上……”,“在我的博客上……”之类的
东西。– Makyen

感谢@Makyen的建议,我将透露这是我的网站。现在编辑答案以披露它是我的网站是否合法?否则我不应该编辑它。
CodeSpeedy

9

正如我在上一个问题中所说的那样,无需对字符串进行base64编码,只会使程序变慢。只需使用代表

>>> with open("images/image.gif", "rb") as fin:
...  image_data=fin.read()
...
>>> with open("image.py","wb") as fout:
...  fout.write("image_data="+repr(image_data))
...

现在,图像作为变量存储image_data在名为“ image.py 启动新的解释器” 的文件中,并导入image_data

>>> from image import image_data
>>>

我真的不知道repr()在这里有什么用。
伊万·范德·维克

6
@ Ivo,Aeateater希望能够将图像存储在python文件中。我指出使用base64会适得其反,因为每次加载模块时都需要对数据进行解码。使用再版,而不是指字面字符串在.pyc文件文件立即使用,没有furthur处理存储准备
约翰·拉ROOY

7

借鉴Ivo van der Wijkgnibbler的较早开发成果,这是一个动态解决方案

import cStringIO
import PIL.Image

image_data = None

def imagetopy(image, output_file):
    with open(image, 'rb') as fin:
        image_data = fin.read()

    with open(output_file, 'w') as fout:
        fout.write('image_data = '+ repr(image_data))

def pytoimage(pyfile):
    pymodule = __import__(pyfile)
    img = PIL.Image.open(cStringIO.StringIO(pymodule.image_data))
    img.show()

if __name__ == '__main__':
    imagetopy('spot.png', 'wishes.py')
    pytoimage('wishes')

然后,您可以决定使用Cython编译输出图像文件,以使其更酷。使用这种方法,您可以将所有图形捆绑到一个模块中。


7
import base64
from PIL import Image
from io import BytesIO

with open("image.jpg", "rb") as image_file:
    data = base64.b64encode(image_file.read())

im = Image.open(BytesIO(base64.b64decode(data)))
im.save('image1.png', 'PNG')

1
这个答案确实应该是最重要的……最好的答案-谢谢!
路德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.