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

何が悪いのですか?

回答:


299

私はあなたの質問を理解しているのかわかりません。私はあなたが次のように何かをしていると思います:

import base64

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

もちろん、最初にファイルを開いてその内容を読み取る必要があります。単にパスをエンコード関数に渡すことはできません。

編集: わかりました。元の質問を編集した後の更新です。

まず最初に、Windowsでパス区切り文字を使用する場合は、生の文字列(文字列の先頭に 'r'を付ける)を使用して、誤ってエスケープ文字にヒットしないようにしてください。次に、PILのImage.openは、ファイル名またはファイルのようなものを受け入れます(つまり、オブジェクトはread、seek、tellメソッドを提供する必要があります)。

つまり、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
おかげで、デコードした画像を印刷するときにもう1つの問題が発生し、文字列「ÿØÿà」が表示されます。ただし、これをデータの代わりとして単独で実行すると、エラーが発生します。エンコードされた文字列は、比較のためにはるかに長くなります。なので画像データを保存していると思います。デコードされた文字列は、エンコードされた文字列を単に参照するだけですか?データの保存には短すぎるようです。
rectangletangle

印刷された出力は、必ずしも実際の内容と同じであるとは限りません。それは、印刷方法と場所によって異なります。
ジムブリソム

8
私の場合、デコードする必要があります:base64.b64encode(fh.read()).decode()HTMLファイルで使用される文字列を取得します。
2014

1
base64.b64encode(fh.read())。decode()は微妙ですが、@ qedも必要でした。違いは、バイトと他の文字列を返すことです...そして、私のSOAPサーバーは、デコードせずにそれを飲み込まないでしょう!
zzart 2014


12

最初の答えは、接頭辞b 'が付いた文字列を出力します。つまり、文字列は次のようになりますb'your_string 'この問題を解決するには、次のコード行を追加してください。

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

2
これは良い答えのように見えますが、目的があなたのウェブサイトを宣伝することである場合は投稿しないでください。ただし、リンクをプロファイルに追加することはできます。
2019

1
(それは「最初の答え」のようなコメントを避けて価値があるのでところで、解答の順序は、ここに頼っていたことができない最初の時間とともに変化する表示されます1。。 :-)
halfer

この回答の元のバージョンでは、自分のサイトまたは提携しているサイトにリンクしているようです。そのようなサイトにリンクする場合は、それが自分のサイトであることを開示する必要あります。アフィリエーションを開示しないと、スパムと見なされます。参照:「良い」自己宣伝を意味するものは何ですか?そして、自己宣伝のヘルプセンター。開示は明確である必要がありますが、正式である必要はありません。それがあなた自身の個人的なコンテンツであるとき、それはちょうど「私のサイトで…」、「私のブログで…」などのようなものであることができます
Makyen

@Makyenの提案に感謝します私はそれが私のサイトであることを開示します。自分のサイトであることを開示するために今すぐ回答を編集することは合法ですか?それとも編集しないでください。
CodeSpeedy

9

前の質問で述べたように、文字列をbase64エンコードする必要はありません。プログラムを遅くするだけです。reprを使用するだけ

>>> 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))
...

これで、イメージが Start a fresh interpreter image_dataというファイルに呼び出される変数として保存されimage.py、image_dataがインポートされます。

>>> from image import image_data
>>>

ここでrepr()がどのように役立つのか、実際にはわかりません。
Ivo van der Wijk

6
@ Ivo、Anteaterは画像をPythonファイルに保存できるようにしたいと考えています。モジュールが読み込まれるたびにデータをデコードする必要があるため、base64の使用は逆効果であることを指摘しています。使い方のreprではなく、文字列リテラルはありませんfurthur処理とする.pycファイルにそのまま使用することができ保存されている意味
ジョン・ラ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でコンパイルしてクールにします。この方法では、すべてのグラフィックを1つのモジュールにバンドルできます。


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
この答えは本当に一番上にあるはずです...最高の答え-ありがとう!
ルター
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.