PythonでGUIアプリを開発していて、最終的にpyinstallerでexe化して配布する必要があり、画像ファイルをexeファイルに埋め込む必要があったので、そのやり方を簡単にまとめてみました。
動作環境
- os: win11
- python: 3.9
- customtkinter: 5.2.0
- Pillow: 10.1.0
- pyinstaller: 6.0.0
困ったこと
コマンドのオプションで同梱するファイルを指定したり、pyinstaller用のspecファイルのdatasに同梱するファイルを追記するなどの記事を見つけたので試したのですが、うまくいきませんでした。(参照する画像ファイルがデバイス上に存在しないと「ファイルが見つからない」とエラーが出る)
解決方法
コマンドオプションかspecファイルの書き換えでなんとかなるかもしれないですが、今回開発しているのは小規模のアプリで、参照する画像ファイルも少ないのでpyファイルに直接埋め込めばいいのかなと思いました。
画像ファイルをbase64でエンコードする
下記のように、画像ファイルをbase64でエンコードし、base64_imgという変数に格納します。
(今回はcustomtkinterというGUIライブラリを使います)
例
import base64
import io
import customtkinter
from PIL import Image
app = customtkinter.CTk()
app.geometry("800x600")
base64_img = "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDA...(省略)...Qh3xB4g="
image_data = base64.b64decode(base64_img)
pil_image = Image.open(io.BytesIO(image_data))
ctk_image = customtkinter.CTkImage(pil_image, size=(800, 600))
image_label = customtkinter.CTkLabel(app, image=ctk_image, text="")
image_label.pack()
app.mainloop()
ちなみにファイルをバイナリで取り込むこともできます。
例
import io
import customtkinter
from PIL import Image
app = customtkinter.CTk()
app.geometry("800x600")
binary_img = b"\xff\xd8\xff\xe0\x00(省略)..."
pil_image = Image.open(io.BytesIO(binary_img))
ctk_image = customtkinter.CTkImage(pil_image, size=(800, 600))
image_label = customtkinter.CTkLabel(app, image=ctk_image, text="")
image_label.pack()
app.mainloop()
exe化後、(デバイス上に参照する画像ファイルがなくても)exeファイル単体で実行できるようになります。